diff --git a/src/dwarf/dwarf_parse_elf.c b/src/dwarf/dwarf_parse_elf.c index a837c483..89b76f65 100644 --- a/src/dwarf/dwarf_parse_elf.c +++ b/src/dwarf/dwarf_parse_elf.c @@ -52,11 +52,11 @@ dw_raw_from_elf_bin(Arena *arena, String8 data, ELF_Bin *bin) // rjf: read compressed-section header ELF_Chdr64 chdr64 = {0}; U64 chdr_size = 0; - if(ELF_HdrIs64Bit(bin->hdr.e_ident)) + if(bin->hdr.e_ident[ELF_Identifier_Class] == ELF_Class_64) { chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr64); } - else if(ELF_HdrIs32Bit(bin->hdr.e_ident)) + else if(bin->hdr.e_ident[ELF_Identifier_Class] == ELF_Class_32) { ELF_Chdr32 chdr32 = {0}; chdr_size = str8_deserial_read_struct(section_data__maybe_compressed, 0, &chdr32); diff --git a/src/elf/elf.c b/src/elf/elf.c index 4bb43547..c92ac9c6 100644 --- a/src/elf/elf.c +++ b/src/elf/elf.c @@ -122,46 +122,65 @@ elf_auxv64_from_auxv32(ELF_Auxv32 auxv32) } //////////////////////////////// - -internal String8 -elf_string_from_class(Arena *arena, ELF_Class v) -{ - switch (v) { - case ELF_Class_None: return str8_lit("None"); - case ELF_Class_32: return str8_lit("32Bit"); - case ELF_Class_64: return str8_lit("64Bit"); - } - return push_str8f(arena, "%#x", v); -} - -//////////////////////////////// +//~ rjf: ELF -> Codebase enum Conversions internal Arch arch_from_elf_machine(ELF_MachineKind e_machine) { Arch arch = Arch_Null; - switch (e_machine) { - case ELF_MachineKind_None: arch = Arch_Null; break; - case ELF_MachineKind_AARCH64: arch = Arch_arm32; break; - case ELF_MachineKind_ARM: arch = Arch_arm32; break; - case ELF_MachineKind_386: arch = Arch_x86; break; - case ELF_MachineKind_X86_64: arch = Arch_x64; break; - default: NotImplemented; break; + switch((ELF_MachineKindEnum)e_machine) + { + default:{}break; + case ELF_MachineKind_None: {arch = Arch_Null;}break; + case ELF_MachineKind_AARCH64: {arch = Arch_arm32;}break; + case ELF_MachineKind_ARM: {arch = Arch_arm32;}break; + case ELF_MachineKind_386: {arch = Arch_x86;}break; + case ELF_MachineKind_X86_64: {arch = Arch_x64;}break; } return arch; } //////////////////////////////// +//~ rjf: ELF Class -> Structure Size + +internal U64 +elf_hdr_size_from_class(ELF_Class elf_class) +{ + U64 result = 0; + switch((ELF_ClassEnum)elf_class) + { + case ELF_Class_COUNT: + case ELF_Class_None:{}break; + case ELF_Class_32:{result = sizeof(ELF_Hdr32);} break; + case ELF_Class_64:{result = sizeof(ELF_Hdr64);} break; + } + return result; +} internal U64 elf_phdr_size_from_class(ELF_Class elf_class) { U64 result = 0; - switch (elf_class) { - case ELF_Class_None: break; - case ELF_Class_32: { result = sizeof(ELF_Phdr32); } break; - case ELF_Class_64: { result = sizeof(ELF_Phdr64); } break; - default: { NotImplemented; } break; + switch((ELF_ClassEnum)elf_class) + { + case ELF_Class_COUNT: + case ELF_Class_None:{}break; + case ELF_Class_32:{result = sizeof(ELF_Phdr32);} break; + case ELF_Class_64:{result = sizeof(ELF_Phdr64);} break; + } + return result; +} + +internal U64 +elf_shdr_size_from_class(ELF_Class elf_class) +{ + U64 result = 0; + switch((ELF_ClassEnum)elf_class) + { + case ELF_Class_COUNT: + case ELF_Class_None:{}break; + case ELF_Class_32:{result = sizeof(ELF_Shdr32);} break; + case ELF_Class_64:{result = sizeof(ELF_Shdr64);} break; } return result; } @@ -170,124 +189,149 @@ internal U64 elf_dyn_size_from_class(ELF_Class elf_class) { U64 result = 0; - switch (elf_class) { - case ELF_Class_None: break; - case ELF_Class_32: { result = sizeof(ELF_Dyn32); } break; - case ELF_Class_64: { result = sizeof(ELF_Dyn64); } break; - default: { NotImplemented; } break; + switch((ELF_ClassEnum)elf_class) + { + case ELF_Class_COUNT: + case ELF_Class_None:{}break; + case ELF_Class_32:{result = sizeof(ELF_Dyn32);}break; + case ELF_Class_64:{result = sizeof(ELF_Dyn64);}break; + } + return result; +} + +internal U64 +elf_sym_size_from_class(ELF_Class elf_class) +{ + U64 result = 0; + switch((ELF_ClassEnum)elf_class) + { + case ELF_Class_COUNT: + case ELF_Class_None:{}break; + case ELF_Class_32:{result = sizeof(ELF_Sym32);}break; + case ELF_Class_64:{result = sizeof(ELF_Sym64);}break; } return result; } //////////////////////////////// +//~ rjf: Optional Class Conversion Readers -internal MachineOpResult -elf_read_ehdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Hdr64 *ehdr_out) +internal ELF_Hdr64 +elf_hdr64_from_class_data(ELF_Class elf_class, String8 data) { - U8 e_ident[ELF_Identifier_Max] = {0}; - MachineOpResult result = mem_read(addr, &e_ident, sizeof(e_ident), mem_read_ud); - if (result == MachineOpResult_Ok) { - if (str8_match(str8_prefix(str8_array_fixed(e_ident), elf_magic_string.size), elf_magic_string, 0)) { - switch (e_ident[ELF_Identifier_Class]) { - default: { InvalidPath; }break; - case ELF_Class_None: { }break; - case ELF_Class_32: { - ELF_Hdr32 ehdr32 = {0}; - result = mem_read(addr, &ehdr32, sizeof(ehdr32), mem_read_ud); - if (result == MachineOpResult_Ok) { - *ehdr_out = elf_hdr64_from_hdr32(ehdr32); - } - } break; - case ELF_Class_64: { - result = mem_read(addr, ehdr_out, sizeof(*ehdr_out), mem_read_ud); - } break; - } + ELF_Hdr64 result = {0}; + U64 needed_size = elf_hdr_size_from_class(elf_class); + if(data.size >= needed_size) + { + switch(elf_class) + { + default:{}break; + case ELF_Class_32: + { + ELF_Hdr32 result32 = *(ELF_Hdr32 *)data.str; + result = elf_hdr64_from_hdr32(result32); + }break; + case ELF_Class_64: + { + result = *(ELF_Hdr64 *)data.str; + }break; } } return result; } -internal MachineOpResult -elf_read_phdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out) +internal ELF_Phdr64 +elf_phdr64_from_class_data(ELF_Class elf_class, String8 data) { - MachineOpResult result = MachineOpResult_Fail; - switch (elf_class) { - case ELF_Class_None: break; - case ELF_Class_32: { - ELF_Phdr32 phdr32 = {0}; - result = mem_read(addr, &phdr32, sizeof(phdr32), mem_read_ud); - if (result == MachineOpResult_Ok) { - *phdr_out = elf_phdr64_from_phdr32(phdr32); - } - } break; - case ELF_Class_64: { - result = mem_read(addr, phdr_out, sizeof(*phdr_out), mem_read_ud); - } break; - default: { NotImplemented; } break; + ELF_Phdr64 result = {0}; + U64 needed_size = elf_phdr_size_from_class(elf_class); + if(data.size >= needed_size) + { + switch(elf_class) + { + default:{}break; + case ELF_Class_32: + { + ELF_Phdr32 result32 = *(ELF_Phdr32 *)data.str; + result = elf_phdr64_from_phdr32(result32); + }break; + case ELF_Class_64: + { + result = *(ELF_Phdr64 *)data.str; + }break; + } } return result; } -internal MachineOpResult -elf_read_shdr(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out) +internal ELF_Shdr64 +elf_shdr64_from_class_data(ELF_Class elf_class, String8 data) { - MachineOpResult result = MachineOpResult_Fail; - switch (elf_class) { - case ELF_Class_None: break; - case ELF_Class_32: { - ELF_Shdr32 shdr32 = {0}; - result = mem_read(addr, &shdr32, sizeof(shdr32), mem_read_ud); - if (result == MachineOpResult_Ok) { - *shdr_out = elf_shdr64_from_shdr32(shdr32); - } - } break; - case ELF_Class_64: { - result = mem_read(addr, shdr_out, sizeof(*shdr_out), mem_read_ud); - } break; - default: { NotImplemented; } break; + ELF_Shdr64 result = {0}; + U64 needed_size = elf_shdr_size_from_class(elf_class); + if(data.size >= needed_size) + { + switch(elf_class) + { + default:{}break; + case ELF_Class_32: + { + ELF_Shdr32 result32 = *(ELF_Shdr32 *)data.str; + result = elf_shdr64_from_shdr32(result32); + }break; + case ELF_Class_64: + { + result = *(ELF_Shdr64 *)data.str; + }break; + } } return result; } -internal MachineOpResult -elf_read_dyn(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out) +internal ELF_Dyn64 +elf_dyn64_from_class_data(ELF_Class elf_class, String8 data) { - MachineOpResult result = MachineOpResult_Fail; - switch (elf_class) { - case ELF_Class_None: {} break; - case ELF_Class_32: { - ELF_Dyn32 dyn32 = {0}; - result = mem_read(addr, &dyn32, sizeof(dyn32), mem_read_ud); - if (result == MachineOpResult_Fail) { - *dyn_out = elf_dyn64_from_dyn32(dyn32); - } - } break; - case ELF_Class_64: { - result = mem_read(addr, dyn_out, sizeof(*dyn_out), mem_read_ud); - } break; - default: { NotImplemented; } break; + ELF_Dyn64 result = {0}; + U64 needed_size = elf_dyn_size_from_class(elf_class); + if(data.size >= needed_size) + { + switch(elf_class) + { + default:{}break; + case ELF_Class_32: + { + ELF_Dyn32 result32 = *(ELF_Dyn32 *)data.str; + result = elf_dyn64_from_dyn32(result32); + }break; + case ELF_Class_64: + { + result = *(ELF_Dyn64 *)data.str; + }break; + } } return result; } -internal MachineOpResult -elf_read_symbol(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out) +internal ELF_Sym64 +elf_sym64_from_class_data(ELF_Class elf_class, String8 data) { - MachineOpResult result = MachineOpResult_Fail; - switch (elf_class) { - case ELF_Class_None: {} break; - case ELF_Class_32: { - ELF_Sym32 symbol32 = {0}; - result = mem_read(addr, &symbol32, sizeof(symbol32), mem_read_ud); - if (result == MachineOpResult_Ok) { - *symbol_out = elf_sym64_from_sym32(symbol32); - } - }break; - case ELF_Class_64: { - result = mem_read(addr, symbol_out, sizeof(*symbol_out), mem_read_ud); - }break; - default: { NotImplemented; } break; + ELF_Sym64 result = {0}; + U64 needed_size = elf_sym_size_from_class(elf_class); + if(data.size >= needed_size) + { + switch(elf_class) + { + default:{}break; + case ELF_Class_32: + { + ELF_Sym32 result32 = *(ELF_Sym32 *)data.str; + result = elf_sym64_from_sym32(result32); + }break; + case ELF_Class_64: + { + result = *(ELF_Sym64 *)data.str; + }break; + } } return result; } - diff --git a/src/elf/elf.h b/src/elf/elf.h index 1a32fbce..fb4e343e 100644 --- a/src/elf/elf.h +++ b/src/elf/elf.h @@ -4,17 +4,21 @@ #ifndef ELF_H #define ELF_H +//////////////////////////////// +//~ rjf: Primary ELF File enums/structures + typedef U8 ELF_Class; -enum +typedef enum ELF_ClassEnum { ELF_Class_None = 0, ELF_Class_32 = 1, ELF_Class_64 = 2, - ELF_Class_Count = 3 -}; + ELF_Class_COUNT = 3 +} +ELF_ClassEnum; typedef U8 ELF_OsAbi; -enum +typedef enum ELF_OsAbiEnum { ELF_OsAbi_None, ELF_OsAbi_SYSV, @@ -28,17 +32,19 @@ enum ELF_OsAbi_TRU64, ELF_OsAbi_ARM = 97, ELF_OsAbi_STANDALONE = 255, -}; +} +ELF_OsAbiEnum; typedef U8 ELF_Version; -enum +typedef enum ELF_VersionEnum { ELF_Version_None, ELF_Version_Current, -}; +} +ELF_VersionEnum; typedef U16 ELF_MachineKind; -enum +typedef enum ELF_MachineKindEnum { ELF_MachineKind_None = 0, ELF_MachineKind_M32 = 1, @@ -96,18 +102,20 @@ enum ELF_MachineKind_K1OM = 181, ELF_MachineKind_RISCV = 243, ELF_MachineKind_S390_OLD = 0xA390, -}; +} +ELF_MachineKindEnum; typedef U8 ELF_Data; -enum +typedef enum ELF_DataEnum { ELF_Data_None = 0, ELF_Data_2LSB = 1, ELF_Data_2MSB = 2, -}; +} +ELF_DataEnum; typedef U16 ELF_Type; -enum +typedef enum ELF_TypeEnum { ELF_Type_None = 0, ELF_Type_Rel = 1, @@ -118,10 +126,11 @@ enum ELF_Type_HiOs = 0xff00, ELF_Type_LoProc = 0xff00, ELF_Type_HiProc = 0xffff -}; +} +ELF_TypeEnum; typedef U32 ELF_PType; -enum +typedef enum ELF_PTypeEnum { ELF_PType_Null = 0, ELF_PType_Load = 1, @@ -141,18 +150,20 @@ enum ELF_PType_GnuStack = ELF_PType_LoOs + 0x474e551, // frame unwind information ELF_PType_GnuRelro = ELF_PType_LoOs + 0x474e552, // stack flags ELF_PType_GnuProperty = ELF_PType_LoOs + 0x474e553, // read-only after relocations -}; +} +ELF_PTypeEnum; typedef U32 ELF_PFlag; -enum +typedef enum ELF_PFlagEnum { ELF_PFlag_Exec = (1 << 0), ELF_PFlag_Write = (1 << 1), ELF_PFlag_Read = (1 << 2), -}; +} +ELF_PFlagEnum; typedef U32 ELF_ShType; -enum +typedef enum ELF_ShTypeEnum { ELF_ShType_Null = 0, ELF_ShType_ProgBits = 1, @@ -187,10 +198,11 @@ enum ELF_ShType_GNU_versym = ELF_ShType_SUNW_versym, ELF_ShType_Proc, ELF_ShType_User, -}; +} +ELF_ShTypeEnum; typedef U32 ELF_SectionIndex; -enum +typedef enum ELF_SectionIndexEnum { ELF_SectionIndex_Undef = 0, // Symbol with section index is undefined and must be resolved by the link editor @@ -214,7 +226,8 @@ enum ELF_SectionIndex_TIC6X_Common = ELF_SectionIndex_LoReserve, ELF_SectionIndex_MIPS_SUndefined = 0xff04, -}; +} +ELF_SectionIndexEnum; typedef U32 ELF_SectionFlags; enum @@ -240,7 +253,7 @@ enum #define ELF_SectionFlag_Extract_MaskOs(f) (U8)(((f) >> ELF_SectionFlag_MaskOs_Shift) & ELF_SectionFlag_MaskOs_Mask) #define ELF_SectionFlag_Extract_MaskProc(f) (U8)(((f) >> ELF_SectionFlag_MaskProc_shift) & ELF_SectionFlag_MaskProc_Mask) typedef U32 ELF_AuxType; -enum +typedef enum ELF_AuxTypeEnum { ELF_AuxType_Null = 0, ELF_AuxType_Phdr = 3, // program headers @@ -276,10 +289,11 @@ enum ELF_AuxType_L2_CacheGeometry = 45, ELF_AuxType_L3_CacheSize = 46, ELF_AuxType_L3_CacheGeometry = 47, -}; +} +ELF_AuxTypeEnum; typedef U32 ELF_DynTag; -enum +typedef enum ELF_DynTagEnum { ELF_DynTag_Null = 0, @@ -358,7 +372,8 @@ enum ELF_DynTag_VerSym = 0x6ffffff0, ELF_DynTag_LoProc = 0x70000000, ELF_DynTag_HiProc = 0x7fffffff, -}; +} +ELF_DynTagEnum; typedef U32 ELF_DynFlag; enum @@ -532,9 +547,6 @@ enum ELF_NoteType_STapSdt = 3, // System Tap probes }; -#define ELF_HdrIs64Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_64) -#define ELF_HdrIs32Bit(e_ident) (e_ident[ELF_Identifier_Class] == ELF_Class_32) - typedef enum ELF_Identifier { ELF_Identifier_Mag0 = 0, @@ -547,76 +559,82 @@ typedef enum ELF_Identifier ELF_Identifier_OsAbi = 7, ELF_Identfiier_AbiBersion = 8, ELF_Identifier_Max = 16, -} ELF_Identifier; +} +ELF_Identifier; read_only global U8 elf_magic[] = {0x7f, 'E', 'L', 'F'}; read_only global String8 elf_magic_string = {elf_magic, sizeof(elf_magic)}; -typedef struct ELF_Hdr64 +typedef struct ELF_Hdr64 ELF_Hdr64; +struct ELF_Hdr64 { - U8 e_ident[ELF_Identifier_Max]; - ELF_Type e_type; + U8 e_ident[ELF_Identifier_Max]; + ELF_Type e_type; ELF_MachineKind e_machine; - U32 e_version; - U64 e_entry; - U64 e_phoff; - U64 e_shoff; - U32 e_flags; - U16 e_ehsize; - U16 e_phentsize; - U16 e_phnum; - U16 e_shentsize; - U16 e_shnum; - U16 e_shstrndx; -} ELF_Hdr64; + U32 e_version; + U64 e_entry; + U64 e_phoff; + U64 e_shoff; + U32 e_flags; + U16 e_ehsize; + U16 e_phentsize; + U16 e_phnum; + U16 e_shentsize; + U16 e_shnum; + U16 e_shstrndx; +}; -typedef struct ELF_Hdr32 +typedef struct ELF_Hdr32 ELF_Hdr32; +struct ELF_Hdr32 { - U8 e_ident[ELF_Identifier_Max]; - ELF_Type e_type; + U8 e_ident[ELF_Identifier_Max]; + ELF_Type e_type; ELF_MachineKind e_machine; - U32 e_version; - U32 e_entry; - U32 e_phoff; - U32 e_shoff; - U32 e_flags; - U16 e_ehsize; - U16 e_phentsize; - U16 e_phnum; - U16 e_shentsize; - U16 e_shnum; - U16 e_shstrndx; -} ELF_Hdr32; + U32 e_version; + U32 e_entry; + U32 e_phoff; + U32 e_shoff; + U32 e_flags; + U16 e_ehsize; + U16 e_phentsize; + U16 e_phnum; + U16 e_shentsize; + U16 e_shnum; + U16 e_shstrndx; +}; -typedef struct ELF_Shdr64 +typedef struct ELF_Shdr64 ELF_Shdr64; +struct ELF_Shdr64 { - U32 sh_name; + U32 sh_name; ELF_ShType sh_type; - U64 sh_flags; - U64 sh_addr; - U64 sh_offset; - U64 sh_size; - U32 sh_link; - U32 sh_info; - U64 sh_addralign; - U64 sh_entsize; -} ELF_Shdr64; + U64 sh_flags; + U64 sh_addr; + U64 sh_offset; + U64 sh_size; + U32 sh_link; + U32 sh_info; + U64 sh_addralign; + U64 sh_entsize; +}; -typedef struct ELF_Shdr32 +typedef struct ELF_Shdr32 ELF_Shdr32; +struct ELF_Shdr32 { - U32 sh_name; + U32 sh_name; ELF_ShType sh_type; - U32 sh_flags; - U32 sh_addr; - U32 sh_offset; - U32 sh_size; - U32 sh_link; - U32 sh_info; - U32 sh_addralign; - U32 sh_entsize; -} ELF_Shdr32; + U32 sh_flags; + U32 sh_addr; + U32 sh_offset; + U32 sh_size; + U32 sh_link; + U32 sh_info; + U32 sh_addralign; + U32 sh_entsize; +}; -typedef struct ELF_Phdr64 +typedef struct ELF_Phdr64 ELF_Phdr64; +struct ELF_Phdr64 { U32 p_type; U32 p_flags; @@ -626,9 +644,10 @@ typedef struct ELF_Phdr64 U64 p_filesz; U64 p_memsz; U64 p_align; -} ELF_Phdr64; +}; -typedef struct ELF_Phdr32 +typedef struct ELF_Phdr32 ELF_Phdr32; +struct ELF_Phdr32 { U32 p_type; U32 p_offset; @@ -638,46 +657,53 @@ typedef struct ELF_Phdr32 U32 p_memsz; U32 p_flags; U32 p_align; -} ELF_Phdr32; +}; //////////////////////////////// -// Auxiliary Vectors - +//~ Auxiliary Vectors +// // these appear in /proc//auxv of a process, they are not in elf files +// -typedef struct ELF_Auxv32 +typedef struct ELF_Auxv32 ELF_Auxv32; +struct ELF_Auxv32 { U32 a_type; U32 a_val; -} ELF_Auxv32; +}; -typedef struct ELF_Auxv64 +typedef struct ELF_Auxv64 ELF_Auxv64; +struct ELF_Auxv64 { U64 a_type; U64 a_val; -} ELF_Auxv64; +}; //////////////////////////////// -// Dynamic Structures - +//~ Dynamic Structures +// // these appear in the virtual address space of a process, they are not in elf files +// -typedef struct ELF_Dyn32 +typedef struct ELF_Dyn32 ELF_Dyn32; +struct ELF_Dyn32 { U32 tag; U32 val; -} ELF_Dyn32; +}; -typedef struct ELF_Dyn64 +typedef struct ELF_Dyn64 ELF_Dyn64; +struct ELF_Dyn64 { U64 tag; U64 val; -} ELF_Dyn64; +}; //////////////////////////////// -// Imports and Exports +//~ Imports and Exports -typedef struct +typedef struct ELF_Sym32 ELF_Sym32; +struct ELF_Sym32 { U32 st_name; // Holds index into files string table. U32 st_value; // Depending on the context, this may be address, size, etc. @@ -685,9 +711,10 @@ typedef struct U8 st_info; // Contains symbols type and binding. U8 st_other; // Reserved for future use, currenly zero. U16 st_shndx; // Section index to which symbol is relevant. -} ELF_Sym32; +}; -typedef struct +typedef struct ELF_Sym64 ELF_Sym64; +struct ELF_Sym64 { U32 st_name; U8 st_info; @@ -695,38 +722,42 @@ typedef struct U16 st_shndx; U64 st_value; U64 st_size; -} ELF_Sym64; +}; #define ELF_ST_INFO(b,t) (((b) << 4) + ((t) & 0xF)) #define ELF_ST_BIND(x) ((x) >> 4) #define ELF_ST_TYPE(x) ((x) & 0xF) #define ELF_ST_VISIBILITY(v) ((v) & 0x3) -typedef struct +typedef struct ELF_Rel32 ELF_Rel32; +struct ELF_Rel32 { U32 r_offset; U32 r_info; -} ELF_Rel32; +}; -typedef struct +typedef struct ELF_Rela32 ELF_Rela32; +struct ELF_Rela32 { U32 r_offset; U32 r_info; S32 r_addend; -} ELF_Rela32; +}; -typedef struct +typedef struct ELF_Rel64 ELF_Rel64; +struct ELF_Rel64 { U64 r_offset; U64 r_info; -} ELF_Rel64; +}; -typedef struct +typedef struct ELF_Rela64 ELF_Rela64; +struct ELF_Rela64 { U64 r_offset; U64 r_info; S64 r_addend; -} ELF_Rela64; +}; #define ELF32_R_SYM(x) ((x) >> 8) #define ELF32_R_TYPE(x) ((x) & 0xFF) @@ -740,7 +771,8 @@ typedef struct #define ELF_EXTERNAL_VERSYM_MASK 0x7FFF // Appears in .gnu.verdef (SHT_GNU_verdef) -typedef struct +typedef struct ELF_ExternalVerdef ELF_ExternalVerdef; +struct ELF_ExternalVerdef { U16 vd_version; U16 vd_flags; @@ -749,43 +781,47 @@ typedef struct U32 vd_hash; U32 vd_aux; U32 vd_next; -} ELF_ExternalVerdef; +}; // Appears in .gnu.verdef (SHT_GNU_verdef) -typedef struct +typedef struct ELF_ExternalVerdaux ELF_ExternalVerdaux; +struct ELF_ExternalVerdaux { U32 vda_name; U32 vda_next; -} ELF_ExternalVerdaux; +}; // Appears in .gnu.verneed (SHT_GNU_verneed) -typedef struct +typedef struct ELF_ExternalVerneed ELF_ExternalVerneed; +struct ELF_ExternalVerneed { U16 vn_version; U16 vn_cnt; U32 vn_file; U32 vn_aux; U32 vn_next; -} ELF_ExternalVerneed; +}; // Appears in .gnu.verneed (SHT_GNU_verneed) -typedef struct +typedef struct ELF_ExternalVernaux ELF_ExternalVernaux; +struct ELF_ExternalVernaux { U32 vna_hash; U16 vna_flags; U16 vna_other; U32 vna_name; U32 vna_next; -} ELF_ExternalVernaux; +}; // Appears in .gnu.version (SHT_GNU_versym) -typedef struct +typedef struct ELF_ExternalVersym ELF_ExternalVersym; +struct ELF_ExternalVersym { U16 vs_vers; -} ELF_ExternalVersym; +}; //////////////////////////////// -// Extensions +//~ Extensions typedef U8 ELF_CompressType; enum ELF_CompressTypeEnum @@ -801,53 +837,57 @@ enum ELF_CompressTypeEnum ELF_CompressType_HiProc = 0x7fffffff, }; -typedef struct ELF_Chdr32 +typedef struct ELF_Chdr32 ELF_Chdr32; +struct ELF_Chdr32 { U32 ch_type; U32 ch_size; U32 ch_addr_align; -} ELF_Chdr32; +}; -typedef struct ELF_Chdr64 +typedef struct ELF_Chdr64 ELF_Chdr64; +struct ELF_Chdr64 { U32 ch_type; U32 ch_reserved; U64 ch_size; U64 ch_addr_align; -} ELF_Chdr64; +}; //////////////////////////////// +//~ rjf: 32 => 64 bit conversions internal ELF_Hdr64 elf_hdr64_from_hdr32(ELF_Hdr32 h32); internal ELF_Shdr64 elf_shdr64_from_shdr32(ELF_Shdr32 h32); internal ELF_Phdr64 elf_phdr64_from_phdr32(ELF_Phdr32 h32); -internal ELF_Dyn64 elf_dyn64_from_dyn32 (ELF_Dyn32 h32); -internal ELF_Sym64 elf_sym64_from_sym32 (ELF_Sym32 sym32); -internal ELF_Rel64 elf_rel64_from_rel32 (ELF_Rel32 rel32); +internal ELF_Dyn64 elf_dyn64_from_dyn32(ELF_Dyn32 h32); +internal ELF_Sym64 elf_sym64_from_sym32(ELF_Sym32 sym32); +internal ELF_Rel64 elf_rel64_from_rel32(ELF_Rel32 rel32); internal ELF_Rela64 elf_rela64_from_rela32(ELF_Rela32 rela32); internal ELF_Chdr64 elf_chdr64_from_chdr32(ELF_Chdr32 chdr32); internal ELF_Auxv64 elf_auxv64_from_auxv32(ELF_Auxv32 auxv32); //////////////////////////////// - -internal String8 elf_string_from_class(Arena *arena, ELF_Class v); - -//////////////////////////////// +//~ rjf: ELF -> Codebase enum Conversions internal Arch arch_from_elf_machine(ELF_MachineKind machine); //////////////////////////////// +//~ rjf: ELF Class -> Structure Size +internal U64 elf_hdr_size_from_class(ELF_Class elf_class); internal U64 elf_phdr_size_from_class(ELF_Class elf_class); +internal U64 elf_shdr_size_from_class(ELF_Class elf_class); internal U64 elf_dyn_size_from_class(ELF_Class elf_class); +internal U64 elf_sym_size_from_class(ELF_Class elf_class); //////////////////////////////// -//~ Compat Readers +//~ rjf: Optional Class Conversion Readers -internal MachineOpResult elf_read_ehdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Hdr64 *ehdr_out); -internal MachineOpResult elf_read_phdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Phdr64 *phdr_out); -internal MachineOpResult elf_read_shdr (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Shdr64 *shdr_out); -internal MachineOpResult elf_read_dyn (MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Dyn64 *dyn_out); -internal MachineOpResult elf_read_symbol(MachineOp_MemRead *mem_read, void *mem_read_ud, U64 addr, ELF_Class elf_class, ELF_Sym64 *symbol_out); +internal ELF_Hdr64 elf_hdr64_from_class_data(ELF_Class elf_class, String8 data); +internal ELF_Phdr64 elf_phdr64_from_class_data(ELF_Class elf_class, String8 data); +internal ELF_Shdr64 elf_shdr64_from_class_data(ELF_Class elf_class, String8 data); +internal ELF_Dyn64 elf_dyn64_from_class_data(ELF_Class elf_class, String8 data); +internal ELF_Sym64 elf_sym64_from_class_data(ELF_Class elf_class, String8 data); #endif // ELF_H diff --git a/src/elf/elf_parse.c b/src/elf/elf_parse.c index 297965ff..a77820db 100644 --- a/src/elf/elf_parse.c +++ b/src/elf/elf_parse.c @@ -172,8 +172,8 @@ internal ELF_NoteList elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineKind e_machine) { ELF_NoteList result = {0}; - - for (U64 cursor = 0; cursor < raw_note.size; ) { + for(U64 cursor = 0; cursor < raw_note.size; ) + { U32 owner_size; U64 owner_size_size = str8_deserial_read_struct(raw_note, cursor, &owner_size); if (owner_size_size == 0) { goto exit; } @@ -206,9 +206,6 @@ elf_parse_note(Arena *arena, String8 raw_note, ELF_Class elf_class, ELF_MachineK SLLQueuePush(result.first, result.last, n); result.count += 1; } - exit:; return result; } - - diff --git a/src/linux/demon/linux_demon.c b/src/linux/demon/linux_demon.c index b23e5876..fd50fe08 100644 --- a/src/linux/demon/linux_demon.c +++ b/src/linux/demon/linux_demon.c @@ -40,6 +40,16 @@ lnx_dmn_write(int memory_fd, Rng1U64 range, void *src) return is_written; } +internal String8 +lnx_dmn_data_from_memory_range(Arena *arena, int memory_fd, Rng1U64 range) +{ + String8 result = {0}; + result.size = dim_1u64(range); + result.str = push_array(arena, U8, result.size); + lnx_dmn_read(memory_fd, range, result.str); + return result; +} + internal String8 lnx_dmn_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size) { @@ -340,21 +350,24 @@ lnx_dmn_set_trap(Arena *arena, DMN_Trap *trap) } //////////////////////////////// -//~ rjf: ELF/GNU Parsing +//~ rjf: In-Memory ELF Parsing Helpers internal Rng1U64 -lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum) +lnx_dmn_vaddr_range_from_phdrs(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum) { - Rng1U64 result = { .min = max_U64 }; - - for(U64 ph_cursor = e_phaddr, ph_opl = (e_phaddr + e_phentsize * e_phnum); ph_cursor < ph_opl; ph_cursor += e_phentsize) + Rng1U64 result = {.min = max_U64}; + for(U64 ph_cursor = e_phaddr, ph_opl = (e_phaddr + e_phentsize * e_phnum); + ph_cursor < ph_opl; + ph_cursor += e_phentsize) { ELF_Phdr64 phdr = {0}; - if(elf_read_phdr(lnx_dmn_machine_op_mem_read, &memory_fd, ph_cursor, elf_class, &phdr) != MachineOpResult_Ok) { - Assert(0 && "unable to read a program header"); + Temp scratch = scratch_begin(0, 0); + U64 phdr_size = elf_phdr_size_from_class(elf_class); + String8 phdr_data = lnx_dmn_data_from_memory_range(scratch.arena, memory_fd, r1u64(ph_cursor, ph_cursor+phdr_size)); + phdr = elf_phdr64_from_class_data(elf_class, phdr_data); + scratch_end(scratch); } - if(phdr.p_type == ELF_PType_Load) { U64 min = rebase + phdr.p_vaddr; @@ -363,7 +376,6 @@ lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 result.max = Max(result.max, max); } } - return result; } @@ -458,14 +470,25 @@ lnx_dmn_module_alloc(LNX_DMN_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 //- rjf: load this module if it's not already loaded if(module == 0) { - // parse out module's ELF header + Temp scratch = scratch_begin(0, 0); + + // rjf: read module's ELF identifier + U8 module_eident[ELF_Identifier_Max] = {0}; + lnx_dmn_read(memory_fd, r1u64(base_vaddr, base_vaddr + sizeof(module_eident)), module_eident); + ELF_Class module_eclass = module_eident[ELF_Identifier_Class]; + + // rjf: read module's ELF header ELF_Hdr64 module_ehdr = {0}; - elf_read_ehdr(lnx_dmn_machine_op_mem_read, &memory_fd, base_vaddr, &module_ehdr); + { + U64 ehdr_size = elf_hdr_size_from_class(module_eclass); + String8 ehdr_data = lnx_dmn_data_from_memory_range(scratch.arena, memory_fd, r1u64(base_vaddr, base_vaddr+ehdr_size)); + module_ehdr = elf_hdr64_from_class_data(module_eclass, ehdr_data); + } // gather info about module - U64 module_rebase = module_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; - U64 module_phdr_vaddr = module_rebase + module_ehdr.e_phoff; - Rng1U64 module_vrange = lnx_dmn_compute_image_vrange(memory_fd, module_ehdr.e_ident[ELF_Identifier_Class], module_rebase, module_phdr_vaddr, module_ehdr.e_phentsize, module_ehdr.e_phnum); + U64 module_rebase = module_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; + U64 module_phdr_vaddr = module_rebase + module_ehdr.e_phoff; + Rng1U64 module_vrange = lnx_dmn_vaddr_range_from_phdrs(memory_fd, module_ehdr.e_ident[ELF_Identifier_Class], module_rebase, module_phdr_vaddr, module_ehdr.e_phentsize, module_ehdr.e_phnum); // read TLS index and TLS offset U64 tls_index = max_U64; @@ -505,6 +528,8 @@ lnx_dmn_module_alloc(LNX_DMN_ProcessCtx *ctx, int memory_fd, U64 base_vaddr, U64 { DLLPushBack_NP(ctx->module_slots[slot_idx].first, ctx->module_slots[slot_idx].last, module, hash_next, hash_prev); } + + scratch_end(scratch); } return module; } @@ -2475,25 +2500,42 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) Arch arch = arch_from_elf_machine(exe_ehdr.e_machine); U64 base_vaddr = (auxv.phdr & ~(auxv.pagesz-1)); U64 rebase = exe_ehdr.e_type == ELF_Type_Dyn ? base_vaddr : 0; - Rng1U64 image_vrange = lnx_dmn_compute_image_vrange(new_process->fd, exe_ehdr.e_ident[ELF_Identifier_Class], rebase, auxv.phdr, auxv.phent, auxv.phnum); + Rng1U64 image_vrange = lnx_dmn_vaddr_range_from_phdrs(new_process->fd, exe_ehdr.e_ident[ELF_Identifier_Class], rebase, auxv.phdr, auxv.phent, auxv.phnum); Arena *ctx_arena = arena_alloc(); + //- rjf: read dynamically loaded ELF identifier + U8 dl_eident[ELF_Identifier_Max] = {0}; + lnx_dmn_read(new_process->fd, r1u64(auxv.base, auxv.base+sizeof(dl_eident)), dl_eident); + ELF_Class dl_class = dl_eident[ELF_Identifier_Class]; + //- rjf: read dynamically loaded ELF header ELF_Hdr64 dl_ehdr = {0}; - elf_read_ehdr(lnx_dmn_machine_op_mem_read, &new_process->fd, auxv.base, &dl_ehdr); - ELF_Class dl_class = dl_ehdr.e_ident[ELF_Identifier_Class]; + { + U64 ehdr_size = elf_hdr_size_from_class(dl_class); + String8 ehdr_data = lnx_dmn_data_from_memory_range(scratch.arena, new_process->fd, r1u64(auxv.base, auxv.base+ehdr_size)); + dl_ehdr = elf_hdr64_from_class_data(dl_class, ehdr_data); + } //- rjf: compute rdebug vaddr U64 rdebug_vaddr = 0; { Temp scratch = scratch_begin(0, 0); - // load DL's header - ELF_Hdr64 ehdr = {0}; - elf_read_ehdr(lnx_dmn_machine_op_mem_read, &new_process->fd, auxv.base, &ehdr); + // rjf: load DL's elf identifier + U8 eident[ELF_Identifier_Max] = {0}; + lnx_dmn_read(new_process->fd, r1u64(auxv.base, auxv.base+sizeof(eident)), eident); + ELF_Class elf_class = eident[ELF_Identifier_Class]; + // rjf: load DL's header + ELF_Hdr64 ehdr = {0}; + { + U64 ehdr_size = elf_hdr_size_from_class(elf_class); + String8 ehdr_data = lnx_dmn_data_from_memory_range(scratch.arena, new_process->fd, r1u64(auxv.base, auxv.base+ehdr_size)); + ehdr = elf_hdr64_from_class_data(elf_class, ehdr_data); + } + + // rjf: unpack header U64 rebase = dl_ehdr.e_type == ELF_Type_Dyn ? auxv.base : 0; - ELF_Class elf_class = ehdr.e_ident[ELF_Identifier_Class]; // rjf: find dynamic program header U64 dynamic_vaddr = 0; @@ -2502,7 +2544,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) for(U64 ph_cursor = phdr_vaddr, ph_opl = (phdr_vaddr + ehdr.e_phentsize * ehdr.e_phentsize); ph_cursor < ph_opl; ph_cursor += ehdr.e_phentsize) { ELF_Phdr64 phdr = {0}; - elf_read_phdr(lnx_dmn_machine_op_mem_read, &new_process->fd, ph_cursor, elf_class, &phdr); + { + Temp scratch = scratch_begin(0, 0); + U64 phdr_size = elf_phdr_size_from_class(elf_class); + String8 phdr_data = lnx_dmn_data_from_memory_range(scratch.arena, new_process->fd, r1u64(ph_cursor, ph_cursor+phdr_size)); + phdr = elf_phdr64_from_class_data(elf_class, phdr_data); + scratch_end(scratch); + } if(phdr.p_type == ELF_PType_Dynamic) { dynamic_vaddr = rebase + phdr.p_vaddr; @@ -2521,7 +2569,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) { // rjf: read next dyn entry ELF_Dyn64 dyn = {0}; - if(elf_read_dyn(lnx_dmn_machine_op_mem_read, &new_process->fd, dynamic_cursor, elf_class, &dyn) != MachineOpResult_Ok) { Assert(0 && "unable to read dynamic"); } + { + Temp scratch = scratch_begin(&arena, 1); + U64 dyn_size = elf_dyn_size_from_class(elf_class); + String8 dyn_data = lnx_dmn_data_from_memory_range(scratch.arena, new_process->fd, r1u64(dynamic_cursor, dynamic_cursor+dyn_size)); + dyn = elf_dyn64_from_class_data(elf_class, dyn_data); + scratch_end(scratch); + } // rjf: break on zero if(dyn.tag == ELF_DynTag_Null) { break; } @@ -2626,10 +2680,13 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) for EachIndex(symbol_idx, symbol_count) { ELF_Sym64 symbol = {0}; - if(elf_read_symbol(lnx_dmn_machine_op_mem_read, &new_process->fd, dynamic_info.symtab_vaddr + symbol_idx * dynamic_info.symtab_entry_size, elf_class, &symbol) != MachineOpResult_Ok) { - Assert(0 && "failed to read symbol table"); - break; + Temp temp = temp_begin(scratch.arena); + U64 sym_size = elf_sym_size_from_class(elf_class); + U64 sym_vaddr = dynamic_info.symtab_vaddr + symbol_idx*dynamic_info.symtab_entry_size; + String8 sym_data = lnx_dmn_data_from_memory_range(temp.arena, new_process->fd, r1u64(sym_vaddr, sym_vaddr+sym_size)); + symbol = elf_sym64_from_class_data(elf_class, sym_data); + temp_end(temp); } Temp temp = temp_begin(scratch.arena); @@ -2776,12 +2833,29 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) if(dl_fd >= 0) { U64 offset = 0; - ELF_Hdr64 ehdr = {0}; - if(elf_read_ehdr(lnx_dmn_machine_op_mem_read, &dl_fd, offset, &ehdr) != MachineOpResult_Ok) { goto exit; } - U64 strtab_shdr_offset = offset + ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize; - ELF_Shdr64 strtab_shdr = {0}; - if(elf_read_shdr(lnx_dmn_machine_op_mem_read, &dl_fd, strtab_shdr_offset, ehdr.e_ident[ELF_Identifier_Class], &strtab_shdr) != MachineOpResult_Ok) { goto exit; } + U8 eident[ELF_Identifier_Max] = {0}; + lnx_dmn_read(dl_fd, r1u64(offset, offset+sizeof(eident)), eident); + ELF_Class eclass = eident[ELF_Identifier_Class]; + + ELF_Hdr64 ehdr = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + U64 ehdr_size = elf_hdr_size_from_class(eclass); + String8 ehdr_data = lnx_dmn_data_from_memory_range(scratch.arena, dl_fd, r1u64(offset, offset+ehdr_size)); + ehdr = elf_hdr64_from_class_data(eclass, ehdr_data); + scratch_end(scratch); + } + + U64 strtab_shdr_offset = offset + ehdr.e_shoff + ehdr.e_shstrndx * ehdr.e_shentsize; + ELF_Shdr64 strtab_shdr = {0}; + { + Temp scratch = scratch_begin(&arena, 1); + U64 shdr_size = elf_shdr_size_from_class(eclass); + String8 shdr_data = lnx_dmn_data_from_memory_range(scratch.arena, dl_fd, r1u64(strtab_shdr_offset, strtab_shdr_offset+shdr_size)); + strtab_shdr = elf_shdr64_from_class_data(eclass, shdr_data); + scratch_end(scratch); + } B32 found_probes = 0; B32 found_probes_base = 0; @@ -2790,9 +2864,16 @@ dmn_ctrl_run(Arena *arena, DMN_CtrlCtx *ctx, DMN_RunCtrls *ctrls) ELF_Shdr64 stapsdt_shdr = {0}; for(U64 shdr_off = offset + ehdr.e_shoff, shdr_opl = shdr_off + ehdr.e_shentsize * ehdr.e_shnum; shdr_off < shdr_opl; - shdr_off += ehdr.e_shentsize) { + shdr_off += ehdr.e_shentsize) + { ELF_Shdr64 shdr = {0}; - if(elf_read_shdr(lnx_dmn_machine_op_mem_read, &dl_fd, shdr_off, ehdr.e_ident[ELF_Identifier_Class], &shdr) != MachineOpResult_Ok) { goto exit; } + { + Temp scratch = scratch_begin(&arena, 1); + U64 shdr_size = elf_shdr_size_from_class(eclass); + String8 shdr_data = lnx_dmn_data_from_memory_range(scratch.arena, dl_fd, r1u64(shdr_off, shdr_off+shdr_size)); + strtab_shdr = elf_shdr64_from_class_data(eclass, shdr_data); + scratch_end(scratch); + } if(shdr.sh_type == ELF_ShType_Note) { diff --git a/src/linux/demon/linux_demon.h b/src/linux/demon/linux_demon.h index f0010032..797dd998 100644 --- a/src/linux/demon/linux_demon.h +++ b/src/linux/demon/linux_demon.h @@ -398,6 +398,7 @@ thread_static B32 lnx_dmn_ctrl_thread = 0; internal U64 lnx_dmn_read(int memory_fd, Rng1U64 range, void *dst); internal B32 lnx_dmn_write(int memory_fd, Rng1U64 range, void *src); +internal String8 lnx_dmn_data_from_memory_range(Arena *arena, int memory_fd, Rng1U64 range); internal String8 lnx_dmn_read_string_capped(Arena *arena, int memory_fd, U64 base_vaddr, U64 cap_size); internal String8 lnx_dmn_read_string(Arena *arena, int memory_fd, U64 base_vaddr); #define lnx_dmn_read_struct(fd, vaddr, ptr) lnx_dmn_read((fd), r1u64((vaddr), (vaddr)+sizeof(*(ptr))), (ptr)) @@ -414,9 +415,9 @@ internal DMN_ModuleInfo *lnx_dmn_module_info_from_process_module(Arena *arena, p internal LNX_DMN_ActiveTrap *lnx_dmn_set_trap(Arena *arena, DMN_Trap *trap); //////////////////////////////// -//~ rjf: ELF/GNU Parsing +//~ rjf: In-Memory ELF Parsing Helpers -internal Rng1U64 lnx_dmn_compute_image_vrange(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum); +internal Rng1U64 lnx_dmn_vaddr_range_from_phdrs(int memory_fd, ELF_Class elf_class, U64 rebase, U64 e_phaddr, U64 e_phentsize, U64 e_phnum); //////////////////////////////// //~ rjf: Entity Functions diff --git a/src/radbin/radbin.c b/src/radbin/radbin.c index a89b0fb8..43d735f2 100644 --- a/src/radbin/radbin.c +++ b/src/radbin/radbin.c @@ -259,7 +259,7 @@ rb_thread_entry_point(void *p) identifier_maybe[ELF_Identifier_Mag3] == 'F'); if(is_elf_magic) { - file_format = ELF_HdrIs64Bit(identifier_maybe) ? RB_FileFormat_ELF64 : RB_FileFormat_ELF32; + file_format = (identifier_maybe[ELF_Identifier_Class] == ELF_Class_64) ? RB_FileFormat_ELF64 : RB_FileFormat_ELF32; } }