Commit: 42e1d79f4da4706e6047d66795b1673fcfd8d892
Parent: a42d40b02ffe7269c267c5bb0e9e46986e65bc76
Author: Randy Palamar
Date: Sun, 27 Apr 2025 11:12:00 -0600
section header parsing
Diffstat:
M | elfinspect.c | | | 151 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
M | main_posix.c | | | 19 | +++++++++++++++++-- |
2 files changed, 151 insertions(+), 19 deletions(-)
diff --git a/elfinspect.c b/elfinspect.c
@@ -4,9 +4,13 @@
/* TODO(rnp) platform specific */
#define ASSERT(c) do { if (!(c)) asm("int3"); } while (0)
+#define TODO(c) ASSERT(c)
#define countof(a) (sizeof(a) / sizeof(*a))
+#define KB(a) ((u64)a << 10ULL)
+#define MB(a) ((u64)a << 20ULL)
+
typedef struct {u8 *beg, *end;} Arena;
#define str8(s) (str8){.len = countof(s) - 1, .data = (u8 *)s}
@@ -37,17 +41,17 @@ typedef struct { u8 identifier[16]; ELF_HEADER_MEMBERS(u64) } ELFHeader64;
#undef X
typedef enum {
- EHK_NONE = 0x00,
- EHK_32 = 0x01,
- EHK_64 = 0x02,
-} ELFHeaderKind;
+ EK_NONE = 0x00,
+ EK_32 = 0x01,
+ EK_64 = 0x02,
+} ELFKind;
typedef struct {
union {
ELFHeader64 eh64;
ELFHeader32 eh32;
- } u;
- ELFHeaderKind kind;
+ };
+ ELFKind kind;
} ELFHeader;
typedef enum {
@@ -56,6 +60,91 @@ typedef enum {
EEK_BIG = 0x02,
} ELFEndianKind;
+/* X(ctype, name) */
+#define ELF_SECTION_HEADER_MEMBERS(ptrsize) \
+ X(u32, name_table_offset) \
+ X(u32, kind) \
+ X(ptrsize, flags) \
+ X(ptrsize, addr) \
+ X(ptrsize, offset) \
+ X(ptrsize, size) \
+ X(u32, link) \
+ X(u32, info) \
+ X(ptrsize, addralign) \
+ X(ptrsize, entsize)
+
+#define X(ctype, name) ctype name;
+typedef struct {ELF_SECTION_HEADER_MEMBERS(u32)} ELFSectionHeader32;
+typedef struct {ELF_SECTION_HEADER_MEMBERS(u64)} ELFSectionHeader64;
+#undef X
+
+typedef struct {
+ str8 name;
+ union {
+ ELFSectionHeader64 sh64;
+ ELFSectionHeader32 sh32;
+ };
+} ELFSectionHeader;
+
+typedef enum {
+ ESK_NULL = 0,
+ ESK_PROGBITS = 1,
+ ESK_SYMBOL_TABLE = 2,
+ ESK_STR_TABLE = 3,
+ ESK_RELA = 4,
+ ESK_HASH = 5,
+ ESK_DYNAMIC = 6,
+ ESK_NOTE = 7,
+ ESK_NOBITS = 8,
+ ESK_REL = 9,
+ ESK_SHLIB = 10,
+ ESK_DYNSYM = 11,
+ ESK_INIT_ARRAY = 14,
+ ESK_FINI_ARRAY = 15,
+ ESK_PREINIT_ARR = 16,
+ ESK_GROUP = 17,
+ ESK_SYMTAB_SHND = 18,
+ ESK_RELR = 19,
+ ESK_NUM = 20,
+ ESK_LOPROC = 0x70000000,
+ ESK_HIPROC = 0x7fffffff,
+ ESK_LOUSER = 0x80000000,
+ ESK_HIUSER = 0x8fffffff,
+} ELFSectionKind;
+
+#define zero_struct(s) mem_clear(s, 0, sizeof(*s));
+function void *
+mem_clear(void *restrict _s, u8 byte, iz size)
+{
+ u8 *s = _s;
+ for (iz i = 0; i < size; i++)
+ s[i] = byte;
+ return s;
+}
+
+#define alloc(a, t, c) (t *)alloc_(a, _Alignof(t), sizeof(t), c)
+function void *
+alloc_(Arena *a, iz alignment, iz size, iz count)
+{
+ iz capacity = a->end - a->beg;
+ iz padding = -(uintptr_t)a->beg & alignment;
+ if ((capacity - padding) / size < count) {
+ ASSERT(0 && "OOM: buy more ram lol");
+ }
+ u8 *result = a->beg + padding;
+ a->beg += padding + size * count;
+ return mem_clear(result, 0, size * count);
+}
+
+function str8
+c_str_to_str8(u8 *c_str)
+{
+ str8 result = {.data = c_str};
+ if (c_str) while (*c_str) c_str++;
+ result.len = c_str - result.data;
+ return result;
+}
+
function void
print_u64(u64 v)
{
@@ -68,18 +157,18 @@ function void print_u32(u32 v) { print_u64(v); }
function void
print_elf_header_32(ELFHeader *eh)
{
- ASSERT(eh->kind == EHK_32);
+ ASSERT(eh->kind == EK_32);
printf("TODO: print 32 bit elf header\n");
}
function void
print_elf_header_64(ELFHeader *eh)
{
- ASSERT(eh->kind == EHK_64);
+ ASSERT(eh->kind == EK_64);
printf("ELF Header:\nidentifier: 0x");
- for (u32 i = 0; i < countof(eh->u.eh64.identifier); i++)
- printf(" %02x", eh->u.eh64.identifier[i]);
- #define X(ctype, name) printf("\n"); printf(#name ": "); print_##ctype(eh->u.eh64.name);
+ for (u32 i = 0; i < countof(eh->eh64.identifier); i++)
+ printf(" %02x", eh->eh64.identifier[i]);
+ #define X(ctype, name) printf("\n"); printf(#name ": "); print_##ctype(eh->eh64.name);
ELF_HEADER_MEMBERS(u64)
#undef X
printf("\n");
@@ -89,8 +178,8 @@ function void
print_elf_header(ELFHeader *eh)
{
switch (eh->kind) {
- case EHK_32: print_elf_header_32(eh); break;
- case EHK_64: print_elf_header_64(eh); break;
+ case EK_32: print_elf_header_32(eh); break;
+ case EK_64: print_elf_header_64(eh); break;
default: printf("invalid elf header\n"); break;
}
}
@@ -111,23 +200,51 @@ elf_header_from_file(str8 file)
{
ELFHeader result = {0};
ASSERT(file.len > sizeof(ELFHeader64));
- ASSERT(file.data[4] == EHK_64);
+ ASSERT(file.data[4] == EK_64);
ASSERT(file.data[5] == EEK_LITTLE);
- result.u.eh64 = *(ELFHeader64 *)file.data;
- result.kind = file.data[4];
+ result.eh64 = *(ELFHeader64 *)file.data;
+ result.kind = file.data[4];
+
+ return result;
+}
+
+function ELFSectionHeader *
+elf_extract_section_headers(Arena *a, str8 file, ELFHeader *eh)
+{
+ TODO(eh->kind == EK_64);
+ TODO(eh->eh64.identifier[5] == EEK_LITTLE);
+ TODO(file.len >= eh->eh64.shoff + eh->eh64.shentsize * eh->eh64.shnum);
+ u32 sections = eh->eh64.shnum;
+ ELFSectionHeader *result = alloc(a, ELFSectionHeader, sections);
+ for (u32 i = 0; i < sections; i++) {
+ iz offset = eh->eh64.shoff + eh->eh64.shentsize * i;
+ result[i].sh64 = *(ELFSectionHeader64 *)(file.data + offset);
+ }
+
+ u8 *str_tab = file.data + result[eh->eh64.shstrndx].sh64.offset;
+ for (u32 i = 0; i < sections; i++)
+ result[i].name = c_str_to_str8(str_tab + result[i].sh64.name_table_offset);
return result;
}
function b32
-elfinspect(str8 file)
+elfinspect(Arena arena, str8 file)
{
b32 result = 0;
if (is_elf(file)) {
ELFHeader header = elf_header_from_file(file);
+ ELFSectionHeader *sections = elf_extract_section_headers(&arena, file, &header);
print_elf_header(&header);
+ printf("\nSections:\n");
+ for (u32 i = 0; i < header.eh64.shnum; i++) {
+ printf("[%u]:", i);
+ str8 name = sections[i].name;
+ if (name.len) printf(" %.*s", (s32)name.len, name.data);
+ printf("\n");
+ }
result = 1;
}
diff --git a/main_posix.c b/main_posix.c
@@ -21,6 +21,20 @@ typedef ptrdiff_t iz;
#include <sys/stat.h>
#include <unistd.h>
+function Arena
+os_arena_new(iz size)
+{
+ Arena result = {0};
+ iz page_size = sysconf(_SC_PAGESIZE);
+ if (size % page_size) size += page_size - (size % page_size);
+ u8 *mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ if (mem != MAP_FAILED) {
+ result.beg = mem;
+ result.end = mem + size;
+ }
+ return result;
+}
+
function str8
os_map_file(u8 *name)
{
@@ -39,7 +53,8 @@ os_map_file(u8 *name)
s32
main(s32 argc, char *argv[])
{
- str8 file = os_map_file((u8 *)argv[0]);
- elfinspect(file);
+ Arena arena = os_arena_new(MB(32));
+ str8 file = os_map_file((u8 *)argv[0]);
+ elfinspect(arena, file);
return 0;
}