linux_demon: more helper flattening / elimination

This commit is contained in:
Ryan Fleury committed 2026-08-11 11:01:58 -07:00
1 parent b8679b4a9a
commit 1770d85308
7 files changed
+459 -296

No files matched your search

+2 -2
View File
@@ -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);
+159 -115
View File
@@ -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;
}
+178 -138
View File
@@ -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/<pid>/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
+2 -5
View File
@@ -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;
}
+114 -33
View File
@@ -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)
{
+3 -2
View File
@@ -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
+1 -1
View File
@@ -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;
}
}