major update: naming and features upgrade pass, support for Linux (w/ linker script build step), & shrink dependencies

main
Allen Webster 2026-02-22 18:47:21 -08:00
parent cc1522760f
commit e1fc795db4
25 changed files with 9781 additions and 2598 deletions

15
build.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash
root_path="$PWD"
build_path="$root_path/build"
src_path="$root_path/src"
mkdir -p $build_path
cd $build_path
rm *
clang -o sy.ld_meta $src_path/symbol_set.ld_meta.c -I$src_path/mr4th
clang -c -o example1.o $src_path/example1.c
./sy.ld_meta --out:example1_sy.ld example1.o
clang -o example1 example1.o -T example1_sy.ld

View File

@ -1,62 +0,0 @@
////////////////////////////////
// Functions
#if OS_WINDOWS
# include <Windows.h>
# include <userenv.h>
# include <psapi.h>
#endif
static String8
str8(U8 *str, U64 size){
String8 result = {str, size};
return(result);
}
static B32
str8_match(String8 a, String8 b, U32 flags){
B32 result = 0;
if (a.size == b.size){
U64 size = a.size;
result = 1;
for (U64 i = 0; i < size; i += 1){
U8 ac = a.str[i];
U8 bc = b.str[i];
if (ac != bc){
result = 0;
break;
}
}
}
return(result);
}
#if OS_WINDOWS
// see: https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
static void*
os_this_image(void){
extern U8 __ImageBase[];
void *result = __ImageBase;
return(result);
}
#else
# error os_this_image not implemented for this OS
#endif
#if OS_WINDOWS
# include "binary/pe/mr4th_pe.h"
# include "binary/pe/mr4th_pe.img_get_section.c"
static RangePtr
self_img_get_section(void *image, String8 name){
RangePtr result = pe_img_get_section(image, name);
return(result);
}
#else
# error selfimg_get_section not implemented for this OS
#endif

View File

@ -1,252 +0,0 @@
////////////////////////////////
// Context Cracking
// untangle compiler, os, & architecture
#if defined(__clang__)
# define COMPILER_CLANG 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__gnu_linux__)
# define OS_LINUX 1
# elif defined(__APPLE__) && defined(__MACH__)
# define OS_MAC 1
# else
# error missing OS detection
# endif
# if defined(__amd64__)
# define ARCH_X64 1
// TODO(allen): verify this works on clang
# elif defined(__i386__)
# define ARCH_X86 1
// TODO(allen): verify this works on clang
# elif defined(__arm__)
# define ARCH_ARM 1
// TODO(allen): verify this works on clang
# elif defined(__aarch64__)
# define ARCH_ARM64 1
# else
# error missing ARCH detection
# endif
#elif defined(_MSC_VER)
# define COMPILER_CL 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# else
# error missing OS detection
# endif
# if defined(_M_AMD64)
# define ARCH_X64 1
# elif defined(_M_I86)
# define ARCH_X86 1
# elif defined(_M_ARM)
# define ARCH_ARM 1
// TODO(allen): ARM64?
# else
# error missing ARCH detection
# endif
#elif defined(__GNUC__)
# define COMPILER_GCC 1
# if defined(_WIN32)
# define OS_WINDOWS 1
# elif defined(__gnu_linux__)
# define OS_LINUX 1
# elif defined(__APPLE__) && defined(__MACH__)
# define OS_MAC 1
# else
# error missing OS detection
# endif
# if defined(__amd64__)
# define ARCH_X64 1
# elif defined(__i386__)
# define ARCH_X86 1
# elif defined(__arm__)
# define ARCH_ARM 1
# elif defined(__aarch64__)
# define ARCH_ARM64 1
# else
# error missing ARCH detection
# endif
#else
# error no context cracking for this compiler
#endif
#if !defined(COMPILER_CL)
# define COMPILER_CL 0
#endif
#if !defined(COMPILER_CLANG)
# define COMPILER_CLANG 0
#endif
#if !defined(COMPILER_GCC)
# define COMPILER_GCC 0
#endif
#if !defined(OS_WINDOWS)
# define OS_WINDOWS 0
#endif
#if !defined(OS_LINUX)
# define OS_LINUX 0
#endif
#if !defined(OS_MAC)
# define OS_MAC 0
#endif
#if !defined(ARCH_X64)
# define ARCH_X64 0
#endif
#if !defined(ARCH_X86)
# define ARCH_X86 0
#endif
#if !defined(ARCH_ARM)
# define ARCH_ARM 0
#endif
#if !defined(ARCH_ARM64)
# define ARCH_ARM64 0
#endif
// language
#if defined(__cplusplus)
# define LANG_CXX 1
#else
# define LANG_C 1
#endif
#if !defined(LANG_CXX)
# define LANG_CXX 0
#endif
#if !defined(LANG_C)
# define LANG_C 0
#endif
////////////////////////////////
// GLUE(a,b) STRIFY(s)
#define GLUE__(a,b) a##b
#define GLUE_(a,b) GLUE__(a,b)
#define GLUE(a,b) GLUE_(a,b)
#define STRIFY__(s) #s
#define STRIFY_(s) STRIFY__(s)
#define STRIFY(s) STRIFY_(s)
////////////////////////////////
// SECTION(<section-name>) <Decl>
#if COMPILER_CLANG || COMPILER_GCC
# define SECTION(N) __attribute__((__section__(N)))
#elif COMPILER_CL
# define SECTION(N) __declspec(allocate(N))
#else
# error SECTION not defined for this compiler
#endif
// for CL users: #pragma section(<section>,read,write)
////////////////////////////////
// BEFORE_MAIN(){ <...> }
#if OS_WINDOWS
# pragma section(".CRT$XCU", read)
# if LANG_CXX
# define BEFORE_MAIN_NAMED(n) \
static void n(void); \
__declspec(allocate(".CRT$XCU")) \
__pragma(comment(linker,"/include:" #n "__")) \
extern "C" void (*n##__)(void); \
void (*n##__)(void) = n; \
static void n(void)
# else
# define BEFORE_MAIN_NAMED(n) \
static void n(void); \
__declspec(allocate(".CRT$XCU")) \
__pragma(comment(linker,"/include:" #n "__")) \
void (*n##__)(void) = n; \
static void n(void)
# endif
#elif OS_LINUX
# define BEFORE_MAIN_NAMED(n) \
__attribute__((constructor)) static void n(void)
#else
# error BEFORE_MAIN missing for this OS
#endif
#define BEFORE_MAIN_(n) BEFORE_MAIN_NAMED(n)
#define BEFORE_MAIN() BEFORE_MAIN_(GLUE(beforemain,__COUNTER__))
////////////////////////////////
// DO_NOT_ELIMINATE
#if OS_WINDOWS
# define DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N))
# define DO_NOT_ELIMINATE__S1(N) DO_NOT_ELIMINATE__S0(N)
# define DO_NOT_ELIMINATE(N) DO_NOT_ELIMINATE__S1(N)
#else
# define DO_NOT_ELIMINATE(N)
#endif
////////////////////////////////
// Types
#include <stdint.h>
typedef int8_t S8;
typedef int16_t S16;
typedef int32_t S32;
typedef int64_t S64;
typedef uint8_t U8;
typedef uint16_t U16;
typedef uint32_t U32;
typedef uint64_t U64;
typedef S8 B8;
typedef S16 B16;
typedef S32 B32;
typedef S64 B64;
typedef float F32;
typedef double F64;
typedef struct RangePtr{
U8 *first;
U8 *opl;
} RangePtr;
typedef struct String8{
U8 *str;
U64 size;
} String8;
#define str8_lit(str) str8((U8*)(str), sizeof(str) - 1)
#define str8_lit_const(str) { (U8*)(str), sizeof(str) - 1 }
#define str8_expand(s) ((int)((s).size)), ((s).str)
////////////////////////////////
// Functions
static String8 str8(U8 *str, U64 size);
static B32 str8_match(String8 a, String8 b, U32 flags);
static void* os_this_image(void);
static RangePtr self_img_get_section(void *image, String8 name);

View File

@ -1,518 +0,0 @@
////////////////////////////////
// Functions: ELF
// normalizing
MR4TH_SYM_COMPTIME U16
elf_u16_decode(void *ptr, B32 flip){
U16 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = buf[1] | (buf[0] << 8);
}
else{
result = *(U16*)ptr;
}
return(result);
}
MR4TH_SYM_COMPTIME U32
elf_u32_decode(void *ptr, B32 flip){
U32 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);
}
else{
result = *(U32*)ptr;
}
return(result);
}
MR4TH_SYM_COMPTIME U64
elf_u64_decode(void *ptr, B32 flip){
U64 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = ((((U64)buf[7]) << 0) | (((U64)buf[6]) << 8) |
(((U64)buf[5]) << 16) | (((U64)buf[4]) << 24) |
(((U64)buf[3]) << 32) | (((U64)buf[2]) << 40) |
(((U64)buf[1]) << 48) | (((U64)buf[0]) << 56));
}
else{
result = *(U64*)ptr;
}
return(result);
}
MR4TH_SYM_COMPTIME void
elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
MemoryCopyArray(dst->ident, src->ident);
dst->type = elf_u16_decode(&src->type, flip_order);
dst->machine = elf_u16_decode(&src->machine, flip_order);
dst->version = elf_u32_decode(&src->version, flip_order);
dst->entry = (U64)elf_u32_decode(&src->entry, flip_order);
dst->segment_table_foff = (U64)elf_u32_decode(&src->segment_table_foff, flip_order);
dst->section_table_foff = (U64)elf_u32_decode(&src->section_table_foff, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->header_size = elf_u16_decode(&src->header_size, flip_order);
dst->segment_size = elf_u16_decode(&src->segment_size, flip_order);
dst->segment_count = elf_u16_decode(&src->segment_count, flip_order);
dst->section_size = elf_u16_decode(&src->section_size, flip_order);
dst->section_count = elf_u16_decode(&src->section_count, flip_order);
dst->string_section_index = elf_u16_decode(&src->string_section_index, flip_order);
}
MR4TH_SYM_COMPTIME void
elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
MemoryCopyArray(dst->ident, src->ident);
dst->type = elf_u16_decode(&src->type, 1);
dst->machine = elf_u16_decode(&src->machine, 1);
dst->version = elf_u32_decode(&src->version, 1);
dst->entry = elf_u32_decode(&src->entry, 1);
dst->segment_table_foff = elf_u32_decode(&src->segment_table_foff, 1);
dst->section_table_foff = elf_u32_decode(&src->section_table_foff, 1);
dst->flags = elf_u32_decode(&src->flags, 1);
dst->header_size = elf_u16_decode(&src->header_size, 1);
dst->segment_size = elf_u16_decode(&src->segment_size, 1);
dst->segment_count = elf_u16_decode(&src->segment_count, 1);
dst->section_size = elf_u16_decode(&src->section_size, 1);
dst->section_count = elf_u16_decode(&src->section_count, 1);
dst->string_section_index = elf_u16_decode(&src->string_section_index, 1);
}
}
MR4TH_SYM_COMPTIME void
elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->name = elf_u32_decode(&src->name, flip_order);
dst->type = elf_u32_decode(&src->type, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->addr = elf_u32_decode(&src->addr, flip_order);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->size = elf_u32_decode(&src->size, flip_order);
dst->link = elf_u32_decode(&src->link, flip_order);
dst->info = elf_u32_decode(&src->info, flip_order);
dst->addralign = elf_u32_decode(&src->addralign, flip_order);
dst->entsize = elf_u32_decode(&src->entsize, flip_order);
}
MR4TH_SYM_COMPTIME void
elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->name = elf_u32_decode(&src->name, 1);
dst->type = elf_u32_decode(&src->type, 1);
dst->flags = elf_u64_decode(&src->flags, 1);
dst->addr = elf_u64_decode(&src->addr, 1);
dst->offset = elf_u64_decode(&src->offset, 1);
dst->size = elf_u64_decode(&src->size, 1);
dst->link = elf_u32_decode(&src->link, 1);
dst->info = elf_u32_decode(&src->info, 1);
dst->addralign = elf_u64_decode(&src->addralign, 1);
dst->entsize = elf_u64_decode(&src->entsize, 1);
}
}
MR4TH_SYM_COMPTIME void
elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->type = elf_u32_decode(&src->type, flip_order);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->vaddr = elf_u32_decode(&src->vaddr, flip_order);
dst->paddr = elf_u32_decode(&src->paddr, flip_order);
dst->file_size = elf_u32_decode(&src->file_size, flip_order);
dst->memory_size = elf_u32_decode(&src->memory_size, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->align = elf_u32_decode(&src->align, flip_order);
}
MR4TH_SYM_COMPTIME void
elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->type = elf_u32_decode(&src->type, 1);
dst->flags = elf_u32_decode(&src->flags, 1);
dst->offset = elf_u64_decode(&src->offset, 1);
dst->vaddr = elf_u64_decode(&src->vaddr, 1);
dst->paddr = elf_u64_decode(&src->paddr, 1);
dst->file_size = elf_u64_decode(&src->file_size, 1);
dst->memory_size = elf_u64_decode(&src->memory_size, 1);
dst->align = elf_u64_decode(&src->align, 1);
}
}
MR4TH_SYM_COMPTIME void
elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->name = elf_u32_decode(&src->name, flip_order);
dst->value = elf_u32_decode(&src->value, flip_order);
dst->size = elf_u32_decode(&src->size, flip_order);
dst->info = src->info;
dst->other = src->other;
dst->section_index = elf_u16_decode(&src->section_index, flip_order);
}
MR4TH_SYM_COMPTIME void
elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->name = elf_u32_decode(&src->name, 1);
dst->info = src->info;
dst->other = src->other;
dst->section_index = elf_u16_decode(&src->section_index, 1);
dst->value = elf_u64_decode(&src->value, 1);
dst->size = elf_u64_decode(&src->size, 1);
}
}
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
elf_reloca64_from_reloc32(Arena *arena, ELF_Relocation32 *src, U64 count, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
{
ELF_Relocation32 *srcptr = src;
ELF_RelocationAdd64 *dstptr = dst;
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
dstptr->offset = elf_u32_decode(&srcptr->offset, flip_order);
dstptr->info = elf_u32_decode(&srcptr->info, flip_order);
}
}
return(dst);
}
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
elf_reloca64_from_reloc64(Arena *arena, ELF_Relocation64 *src, U64 count, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
{
ELF_Relocation64 *srcptr = src;
ELF_RelocationAdd64 *dstptr = dst;
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
dstptr->offset = elf_u64_decode(&srcptr->offset, flip_order);
dstptr->info = elf_u64_decode(&srcptr->info, flip_order);
}
}
return(dst);
}
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
elf_reloca64_from_reloca32(Arena *arena, ELF_RelocationAdd32 *src, U64 count, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
{
ELF_RelocationAdd32 *srcptr = src;
ELF_RelocationAdd64 *dstptr = dst;
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
dstptr->offset = elf_u32_decode(&srcptr->offset, flip_order);
dstptr->info = elf_u32_decode(&srcptr->info, flip_order);
dstptr->addend = (S32)elf_u32_decode(&srcptr->addend, flip_order);
}
}
return(dst);
}
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
elf_reloca64_from_reloca64(Arena *arena, ELF_RelocationAdd64 *src, U64 count, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
{
ELF_RelocationAdd64 *srcptr = src;
ELF_RelocationAdd64 *dstptr = dst;
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
dstptr->offset = elf_u64_decode(&srcptr->offset, flip_order);
dstptr->info = elf_u64_decode(&srcptr->info, flip_order);
dstptr->addend = (S64)elf_u64_decode(&srcptr->addend, flip_order);
}
}
return(dst);
}
// strings
MR4TH_SYM_COMPTIME String8
elf_str8_from_identification_idx(ELF_IdentificationIdx idx){
String8 result = str8_lit("ERROR");
switch (idx){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_IdentificationIdx_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_class(ELF_Class elf_class){
String8 result = str8_lit("ERROR");
switch (elf_class){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_Class_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_encoding(ELF_Encoding elf_encoding){
String8 result = str8_lit("ERROR");
switch (elf_encoding){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_Encoding_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi){
String8 result = str8_lit("ERROR");
switch (elf_osabi){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_OsAbiExtension_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_file_type(ELF_FileType file_type){
String8 result = str8_lit("ERROR");
switch (file_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_FileType_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_machine_type(ELF_FileType machine_type){
String8 result = str8_lit("ERROR");
switch (machine_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_MachineType_XList(X)
#undef X
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_section_type(ELF_SectionType section_type){
String8 result = str8_lit("ERROR");
if (ELF_SectionType_LOOS <= section_type &&
section_type <= ELF_SectionType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SectionType_LOPROC <= section_type &&
section_type <= ELF_SectionType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else if (ELF_SectionType_LOUSER <= section_type &&
section_type <= ELF_SectionType_HIUSER){
result = str8_lit("USER-CUSTOM-TYPE");
}
else{
switch (section_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SectionType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYM_COMPTIME void
elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags){
U32 f = 1;
for (U32 i = 0; i < 20; i += 1){
if ((flags & f) != 0){
switch (f){
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
ELF_SectionFlags_XList(X)
#undef X
}
}
f <<= 1;
}
if ((flags & ELF_SectionFlag_MASKOS) != 0){
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
}
if ((flags & ELF_SectionFlag_MASKPROC) != 0){
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
}
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_section_flags(Arena *arena, U32 flags){
ArenaTemp scratch = arena_get_scratch(&arena, 1);
String8List list = {0};
elf_str8list_from_section_flags(scratch.arena, &list, flags);
String8 result = str8_join_flags(arena, &list);
arena_release_scratch(&scratch);
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_segment_type(ELF_SegmentType segment_type){
String8 result = str8_lit("ERROR");
if (ELF_SegmentType_LOOS <= segment_type &&
segment_type <= ELF_SegmentType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SegmentType_LOPROC <= segment_type &&
segment_type <= ELF_SegmentType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (segment_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SegmentType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYM_COMPTIME void
elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags){
U32 f = 1;
for (U32 i = 0; i < 20; i += 1){
if ((flags & f) != 0){
switch (f){
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
ELF_SegmentFlags_XList(X)
#undef X
}
}
f <<= 1;
}
if ((flags & ELF_SegmentFlag_MASKOS) != 0){
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
}
if ((flags & ELF_SegmentFlag_MASKPROC) != 0){
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
}
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags){
ArenaTemp scratch = arena_get_scratch(&arena, 1);
String8List list = {0};
elf_str8list_from_segment_flags(scratch.arena, &list, flags);
String8 result = str8_join_flags(arena, &list);
arena_release_scratch(&scratch);
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_symbol_binding(ELF_SymbolBinding bind){
String8 result = str8_lit("ERROR");
if (ELF_SymbolBinding_LOOS <= bind &&
bind <= ELF_SymbolBinding_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SymbolBinding_LOPROC <= bind &&
bind <= ELF_SymbolBinding_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (bind){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolBinding_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_symbol_type(ELF_SymbolType type){
String8 result = str8_lit("ERROR");
if (ELF_SymbolType_LOOS <= type &&
type <= ELF_SymbolType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SymbolType_LOPROC <= type &&
type <= ELF_SymbolType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYM_COMPTIME String8
elf_str8_from_symbol_vis(ELF_SymbolVis vis){
String8 result = str8_lit("ERROR");
switch (vis){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolVis_XList(X)
#undef X
}
return(result);
}

View File

@ -1,567 +0,0 @@
/*
** ELF File Dumper
*/
#include "mr4th_base.h"
#include "mr4th_base.stdio.h"
#include "mr4th_keywords.h"
#include "mr4th_elf.h"
#include "mr4th_elf.dump.h"
#include "mr4th_base.c"
#include "mr4th_elf.c"
////////////////////////////////
// ELF DUMP Arguments Functions
function ELFDUMP_Arguments*
elfdump_args(Arena *arena, String8List *command_line_args){
// parse
CMDLN *cmdln = cmdln_from_args(arena, command_line_args);
// setup args
ELFDUMP_Arguments *args = push_array(arena, ELFDUMP_Arguments, 1);
// get input file name
args->input_file_name = cmdln_input_from_idx(cmdln, 0);
return(args);
}
////////////////////////////////
// Entry Point
int main(int argc, char **argv){
os_main_init(argc, argv);
Arena *arena = arena_alloc();
// arguments
String8List command_line_args = os_command_line_arguments();
ELFDUMP_Arguments *args = elfdump_args(arena, &command_line_args);
// load input file
String8 input_data = os_file_read(arena, args->input_file_name);
/////////////////
///// PARSE /////
/////////////////
// magic check
B32 elf_magic = 0;
ELF_Class elf_class = ELF_Class_NONE;
ELF_Encoding elf_encoding = ELF_Encoding_NONE;
U32 elf_version = 0;
ELF_OsAbiExtension elf_ext = ELF_OsAbiExtension_NONE;
if (input_data.size >= ELF_NUM_IDENT){
if (input_data.str[0] == ELF_Magic_Byte0 &&
input_data.str[1] == ELF_Magic_Byte1 &&
input_data.str[2] == ELF_Magic_Byte2 &&
input_data.str[3] == ELF_Magic_Byte3){
elf_magic = 1;
}
elf_class = input_data.str[ELF_IdentificationIdx_CLASS];
elf_encoding = input_data.str[ELF_IdentificationIdx_DATA];
elf_version = input_data.str[ELF_IdentificationIdx_VERSION];
elf_ext = input_data.str[ELF_IdentificationIdx_OSABI];
}
B32 elf_header_good = 1;
if (!elf_magic || elf_class == 0 || elf_encoding == 0 || elf_version != 1){
elf_header_good = 0;
}
// elf header
ELF_Header32 *hdr32_raw = 0;
ELF_Header64 *hdr64_raw = 0;
if (elf_header_good){
// 32-bit
if (elf_class == ELF_Class_32){
if (sizeof(*hdr32_raw) <= input_data.size){
hdr32_raw = (ELF_Header32*)input_data.str;
}
}
// 64-bit
if (elf_class == ELF_Class_64){
if (sizeof(*hdr64_raw) <= input_data.size){
hdr64_raw = (ELF_Header64*)input_data.str;
}
}
}
// normalize header
ELF_Header64 hdr = {0};
if (hdr32_raw != 0){
elf_header64_from_header32(&hdr, hdr32_raw, elf_encoding);
}
else if (hdr64_raw != 0){
elf_header64_from_header64(&hdr, hdr64_raw, elf_encoding);
}
else{
elf_header_good = 0;
}
// sections
ELF_Section32 *sec32_raw = 0;
ELF_Section64 *sec64_raw = 0;
if (elf_header_good){
U64 foff = hdr.section_table_foff;
U64 opl_foff = foff + hdr.section_count*hdr.section_size;
if (opl_foff <= input_data.size){
// 32-bit
if (elf_class == ELF_Class_32){
sec32_raw = (ELF_Section32*)(input_data.str + foff);
}
// 64-bit
if (elf_class == ELF_Class_64){
sec64_raw = (ELF_Section64*)(input_data.str + foff);
}
}
}
// normalize sections
B32 sections_good = 1;
ELF_Section64 *sections = 0;
if (sec32_raw != 0){
sections = push_array(arena, ELF_Section64, hdr.section_count);
for (U32 i = 0; i < hdr.section_count; i += 1){
elf_section64_from_section32(sections + i, sec32_raw + i, elf_encoding);
}
}
else if (sec64_raw != 0){
sections = push_array(arena, ELF_Section64, hdr.section_count);
for (U32 i = 0; i < hdr.section_count; i += 1){
elf_section64_from_section64(sections + i, sec64_raw + i, elf_encoding);
}
}
else{
sections_good = 0;
}
// segments
ELF_Segment32 *seg32_raw = 0;
ELF_Segment64 *seg64_raw = 0;
if (elf_header_good){
U64 foff = hdr.segment_table_foff;
U64 opl_foff = foff + hdr.segment_count*hdr.segment_size;
if (opl_foff <= input_data.size){
// 32-bit
if (elf_class == ELF_Class_32){
seg32_raw = (ELF_Segment32*)(input_data.str + foff);
}
// 64-bit
if (elf_class == ELF_Class_64){
seg64_raw = (ELF_Segment64*)(input_data.str + foff);
}
}
}
// normalize segments
B32 segments_good = 1;
ELF_Segment64 *segments = 0;
if (seg32_raw != 0){
segments = push_array(arena, ELF_Segment64, hdr.segment_count);
for (U32 i = 0; i < hdr.segment_count; i += 1){
elf_segment64_from_segment32(segments + i, seg32_raw + i, elf_encoding);
}
}
else if (seg64_raw != 0){
segments = push_array(arena, ELF_Segment64, hdr.segment_count);
for (U32 i = 0; i < hdr.segment_count; i += 1){
elf_segment64_from_segment64(segments + i, seg64_raw + i, elf_encoding);
}
}
else{
segments_good = 0;
}
// find symtab section
ELF_Section64 *symtab_section = 0;
for (U32 i = 0; i < hdr.section_count; i += 1){
ELF_Section64 *section = sections + i;
if (section->type == ELF_SectionType_SYMTAB){
symtab_section = section;
break;
}
}
// find dynsym section
ELF_Section64 *dynsym_section = 0;
for (U32 i = 0; i < hdr.section_count; i += 1){
ELF_Section64 *section = sections + i;
if (section->type == ELF_SectionType_DYNSYM){
dynsym_section = section;
break;
}
}
// decode symol tables
ELFDUMP_SymbolTable symbol_tables[2] = {0};
ELF_Section64 *symbol_table_sections[2];
symbol_table_sections[0] = symtab_section;
symbol_table_sections[1] = dynsym_section;
for (U32 k = 0; k < 2; k += 1){
ELF_Section64 *symbol_section = symbol_table_sections[k];
ELF_Symbol32 *sym32_raw = 0;
ELF_Symbol64 *sym64_raw = 0;
U8 *string_table_first = 0;
U8 *string_table_opl = 0;
U32 symbol_count = 0;
if (symbol_section != 0){
// extract symbol string table
if (symbol_section->link < hdr.section_count){
ELF_Section64 *string_table = sections + symbol_section->link;
string_table_first = input_data.str + string_table->offset;
string_table_opl = string_table_first + string_table->size;
}
// extract raw symbol array
U64 foff = symbol_section->offset;
U64 opl_foff = foff + symbol_section->size;
U64 symbol_count_cap = 0;
if (opl_foff <= input_data.size){
// 32-bit
if (elf_class == ELF_Class_32){
sym32_raw = (ELF_Symbol32*)(input_data.str + foff);
symbol_count_cap = symbol_section->size/sizeof(*sym32_raw);
}
// 64-bit
if (elf_class == ELF_Class_64){
sym64_raw = (ELF_Symbol64*)(input_data.str + foff);
symbol_count_cap = symbol_section->size/sizeof(*sym64_raw);
}
}
// extract symbol count
symbol_count = symbol_section->info;
symbol_count = ClampTop(symbol_count, symbol_count_cap);
}
// normalize symbol table
ELF_Symbol64 *symbols = 0;
if (sym32_raw != 0){
symbols = push_array(arena, ELF_Symbol64, symbol_count);
for (U32 i = 0; i < symbol_count; i += 1){
elf_symbol64_from_symbol32(symbols + i, sym32_raw + i, elf_encoding);
}
}
else if (sym64_raw != 0){
symbols = push_array(arena, ELF_Symbol64, symbol_count);
for (U32 i = 0; i < symbol_count; i += 1){
elf_symbol64_from_symbol64(symbols + i, sym64_raw + i, elf_encoding);
}
}
// fill symbol table
if (symbols != 0){
ELFDUMP_SymbolTable *symbol_table = &symbol_tables[k];
symbol_table->symbols = symbols;
symbol_table->count = symbol_count;
symbol_table->string_table_first = string_table_first;
symbol_table->string_table_opl = string_table_opl;
}
}
// relocations
ELFDUMP_Relocs *first_relocs = 0;
ELFDUMP_Relocs *last_relocs = 0;
if (sections_good){
for (U32 i = 0; i < hdr.section_count; i += 1){
ELF_RelocationAdd64 *relocs = 0;
U64 reloc_count = 0;
ELF_Section64 *section = sections + i;
void *section_data = input_data.str + section->offset;
switch (section->type){
case ELF_SectionType_REL:
{
if (elf_class == ELF_Class_32){
ELF_Relocation32 *reloc32 = (ELF_Relocation32*)section_data;
reloc_count = section->size/sizeof(*reloc32);
relocs = elf_reloca64_from_reloc32(arena, reloc32, reloc_count, elf_encoding);
}
else{
ELF_Relocation64 *reloc64 = (ELF_Relocation64*)section_data;
reloc_count = section->size/sizeof(*reloc64);
relocs = elf_reloca64_from_reloc64(arena, reloc64, reloc_count, elf_encoding);
}
}break;
case ELF_SectionType_RELA:
{
if (elf_class == ELF_Class_32){
ELF_RelocationAdd32 *reloca32 = (ELF_RelocationAdd32*)section_data;
reloc_count = section->size/sizeof(*reloca32);
relocs = elf_reloca64_from_reloca32(arena, reloca32, reloc_count, elf_encoding);
}
else{
ELF_RelocationAdd64 *reloca64 = (ELF_RelocationAdd64*)section_data;
reloc_count = section->size/sizeof(*reloca64);
relocs = elf_reloca64_from_reloca64(arena, reloca64, reloc_count, elf_encoding);
}
}break;
}
if (reloc_count > 0){
ELFDUMP_Relocs *r = push_array(arena, ELFDUMP_Relocs, 1);
SLLQueuePush(first_relocs, last_relocs, r);
r->section_idx = i;
r->symbol_table_section_idx = section->link;
r->target_section_idx = section->info;
r->relocs = relocs;
r->count = reloc_count;
}
}
}
////////////////
///// DUMP /////
////////////////
if (!elf_header_good){
m4_printf("Unsuccessful parse\n");
}
if (elf_header_good){
ArenaTemp scratch = arena_get_scratch(0, 0);
// elf header
{
for (U32 i = 0; i < ELF_NUM_IDENT; i += 1){
String8 ident_string = elf_str8_from_identification_idx(i);
String8 val_string = {0};
switch (i){
case ELF_IdentificationIdx_CLASS:
{
val_string = elf_str8_from_class(hdr.ident[i]);
}break;
case ELF_IdentificationIdx_DATA:
{
val_string = elf_str8_from_encoding(hdr.ident[i]);
}break;
case ELF_IdentificationIdx_OSABI:
{
val_string = elf_str8_from_osabi(hdr.ident[i]);
}break;
default:
{
val_string = str8_pushf(scratch.arena, "0x%02x", hdr.ident[i]);
}break;
}
m4_printf("elf_header.ident[%10S] = %S\n", &ident_string, &val_string);
}
String8 type_string = elf_str8_from_file_type(hdr.type);
String8 machine_string = elf_str8_from_machine_type(hdr.machine);
m4_printf("elf_header.type = %S\n", &type_string);
m4_printf("elf_header.machine = %S\n", &machine_string);
m4_printf("elf_header.version = %u\n", hdr.version);
m4_printf("elf_header.entry = 0x%08llx\n", hdr.entry);
m4_printf("elf_header.segment_table_foff = 0x%08llx\n", hdr.segment_table_foff);
m4_printf("elf_header.section_table_foff = 0x%08llx\n", hdr.section_table_foff);
// TODO(allen): flags pneumonics
m4_printf("elf_header.flags = 0x%08x\n", hdr.flags);
m4_printf("elf_header.header_size = %u\n", hdr.header_size);
m4_printf("elf_header.segment_size = %u\n", hdr.segment_size);
m4_printf("elf_header.segment_count = %u\n", hdr.segment_count);
m4_printf("elf_header.section_size = %u\n", hdr.section_size);
m4_printf("elf_header.section_count = %u\n", hdr.section_count);
m4_printf("elf_header.string_section_index = %u\n", hdr.string_section_index);
m4_printf("\n");
arena_release_scratch(&scratch);
}
// sections
if (sections_good){
// get the section name string table
U8 *string_table_first = 0;
U8 *string_table_opl = 0;
{
ELF_Section64 *string_table = 0;
if (hdr.string_section_index != ELF_SectionIndex_UNDEF &&
hdr.string_section_index != ELF_SectionIndex_XINDEX){
string_table = sections + hdr.string_section_index;
}
else if (hdr.string_section_index == ELF_SectionIndex_XINDEX){
U32 string_section_index = sections[0].link;
string_table = sections + string_section_index;
}
if (string_table != 0){
string_table_first = input_data.str + string_table->offset;
string_table_opl = string_table_first + string_table->size;
}
}
// dump each section
for (U32 i = 0; i < hdr.section_count; i += 1){
ELF_Section64 *section = sections + i;
String8 name = str8_cstring_capped(string_table_first + section->name,
string_table_opl);
String8 type_string = elf_str8_from_section_type(section->type);
String8 flags_string =
elf_str8_from_section_flags(scratch.arena, section->flags);
m4_printf("section[%u] = {\n"
" name = \"%S\",\n"
" type = %S (0x%x),\n"
" flags = %S,\n"
" addr = 0x%08llx,\n"
" size = %$llu,\n"
" link = %u,\n"
" info = %u,\n"
" addralign = %llu,\n"
" entsize = %$llu,\n"
"}\n",
i, &name,
&type_string, section->type,
&flags_string,
section->addr,
section->size,
section->link,
section->info,
section->addralign,
section->entsize);
}
m4_printf("\n");
}
// segments
if (segments_good){
for (U32 i = 0; i < hdr.segment_count; i += 1){
ELF_Segment64 *segment = segments + i;
String8 type_string = elf_str8_from_segment_type(segment->type);
String8 flags_string =
elf_str8_from_segment_flags(scratch.arena, segment->flags);
m4_printf("segment[%u] = {\n"
" type = %S (0x%x),\n"
" flags = %S,\n"
" offset = 0x%08llx,\n"
" vaddr = 0x%08llx,\n"
" paddr = 0x%08llx,\n"
" file_size = %$llu,\n"
" memory_size = %$llu,\n"
" align = %llu,\n"
"}\n",
i,
&type_string, segment->type,
&flags_string,
segment->offset,
segment->vaddr,
segment->paddr,
segment->file_size,
segment->memory_size,
segment->align);
}
m4_printf("\n");
}
// symbol tables
String8 symbol_table_name[2];
symbol_table_name[0] = str8_lit("symtab");
symbol_table_name[1] = str8_lit("dynsym");
for (U32 k = 0; k < 2; k += 1){
ELFDUMP_SymbolTable *symbol_table = &symbol_tables[k];
if (symbol_table->symbols != 0){
for (U32 i = 0; i < symbol_table->count; i += 1){
ELF_Symbol64 *symbol = symbol_table->symbols + i;
String8 name =
str8_cstring_capped(symbol_table->string_table_first + symbol->name,
symbol_table->string_table_opl);
ELF_SymbolBinding bind = ELF_Symbol_BindFromInfo(symbol->info);
ELF_SymbolType type = ELF_Symbol_TypeFromInfo(symbol->info);
ELF_SymbolVis vis = ELF_Symbol_VisFromOther(symbol->other);
String8 bind_string = elf_str8_from_symbol_binding(bind);
String8 type_string = elf_str8_from_symbol_type(type);
String8 vis_string = elf_str8_from_symbol_vis(vis);
m4_printf("%S[%u] = {\n"
" name = \"%S\",\n"
" info = bind: %S, type: %S,\n"
" other = vis: %S,\n"
" section_index = %u,\n"
" value = %llu,\n"
" size = %$llu,\n"
"}\n",
&symbol_table_name[k], i,
&name,
&bind_string, &type_string,
&vis_string,
symbol->section_index,
symbol->value,
symbol->size);
}
m4_printf("\n");
}
}
// relocations
for (ELFDUMP_Relocs *relocs = first_relocs;
relocs != 0;
relocs = relocs->next){
m4_printf("relocations(%u) = {\n", relocs->section_idx);
U32 count = relocs->count;
ELF_RelocationAdd64 *relocptr = relocs->relocs;
for (U32 i = 0; i < count; i += 1, relocptr += 1){
m4_printf(" { offset = %llu,\n"
" info = %llu,\n"
" addend = %lld,\n"
" },\n", relocptr->offset, relocptr->info, relocptr->addend);
}
m4_printf("}\n\n");
}
}
return(0);
}

View File

@ -1,40 +0,0 @@
#ifndef MR4TH_ELF_DUMP_H
#define MR4TH_ELF_DUMP_H
////////////////////////////////
// ELF DUMP Arguments Types
typedef struct ELFDUMP_Arguments{
String8 input_file_name;
} ELFDUMP_Arguments;
////////////////////////////////
// ELF DUMP Types
typedef struct ELFDUMP_SymbolTable{
ELF_Symbol64 *symbols;
U32 count;
U8 *string_table_first;
U8 *string_table_opl;
} ELFDUMP_SymbolTable;
typedef struct ELFDUMP_Relocs{
struct ELFDUMP_Relocs *next;
U32 section_idx;
U32 symbol_table_section_idx;
U32 target_section_idx;
U32 count;
ELF_RelocationAdd64 *relocs;
} ELFDUMP_Relocs;
////////////////////////////////
// ELF DUMP Arguments Functions
function ELFDUMP_Arguments* elfdump_args(Arena *arena, String8List *args);
////////////////////////////////
// Entry Point
int main(int argc, char **argv);
#endif //MR4TH_ELF_DUMP_H

View File

@ -1,831 +0,0 @@
#ifndef MR4TH_PE_H
#define MR4TH_PE_H
/*
** PE/COFF total layout summary:
**
** MS-DOS Stub [image only]
** *****************
** ptr> PE Signature [image only]
** COFF Header
** Optional Header [image only]
** Section Table
*/
////////////////////////////////
// Types: COFF / PE
#pragma pack(push,1)
// MS-DOS Stub
// located at offset=0 in valid executables
#define PE_MSDOS_MAGIC 0x5A4D
typedef struct PE_DosHeader{
U16 magic;
U16 last_page_size;
U16 page_count;
U16 reloc_count;
U16 paragraph_header_size;
U16 min_paragraph;
U16 max_paragraph;
U16 init_ss;
U16 init_sp;
U16 checksum;
U16 init_ip;
U16 init_cs;
U16 reloc_table_file_off;
U16 overlay_number;
U16 reserved[4];
U16 oem_id;
U16 oem_info;
U16 reserved2[10];
U32 coff_file_offset;
} PE_DosHeader;
// pe signature
#define PE_SIGNATURE 0x00004550
// coff header
#define PE_MachineType_XList(X)\
X(UNKNOWN, 0x0)\
X(ALPHA, 0x184)\
X(ALPHA64, 0x284)\
X(AM33, 0x1d3)\
X(AMD64, 0x8664)\
X(ARM, 0x1c0)\
X(ARM64, 0xaa64)\
X(ARMNT, 0x1c4)\
X(EBC, 0xebc)\
X(I386, 0x14c)\
X(IA64, 0x200)\
X(LOONGARCH32, 0x6232)\
X(LOONGARCH64, 0x6264)\
X(M32R, 0x9041)\
X(MIPS16, 0x266)\
X(MIPSFPU, 0x366)\
X(MIPSFPU16, 0x466)\
X(POWERPC, 0x1f0)\
X(POWERPCFP, 0x1f1)\
X(R4000, 0x166)\
X(RISCV32, 0x5032)\
X(RISCV64, 0x5064)\
X(RISCV128, 0x5128)\
X(SH3, 0x1a2)\
X(SH3DSP, 0x1a3)\
X(SH4, 0x1a6)\
X(SH5, 0x1a8)\
X(THUMB, 0x1c2)\
X(WCEMIPSV2, 0x169)
typedef U16 PE_MachineType;
enum{
#define X(N,C) PE_MachineType_##N = C,
PE_MachineType_XList(X)
#undef X
};
#define PE_Flags_XList(X)\
X(RELOCS_STRIPPED, 0x0001)\
X(EXECUTABLE_IMAGE, 0x0002)\
X(LINE_NUMS_STRIPPED, 0x0004)\
X(LOCAL_SYMS_STRIPPED, 0x0008)\
X(AGGRESSIVE_WS_TRIM, 0x0010)\
X(LARGE_ADDRESS_AWARE, 0x0020)\
X(RESERVED, 0x0040)\
X(BYTES_REVERSED_LO, 0x0080)\
X(32BIT_MACHINE, 0x0100)\
X(DEBUG_STRIPPED, 0x0200)\
X(REMOVABLE_RUN_FROM_SWAP, 0x0400)\
X(NET_RUN_FROM_SWAP, 0x0800)\
X(SYSTEM, 0x1000)\
X(DLL, 0x2000)\
X(UP_SYSTEM_ONLY, 0x4000)\
X(BYTES_REVERSED_HI, 0x8000)\
typedef U16 PE_Flags;
enum{
#define X(N,C) PE_Flag_##N = C,
PE_Flags_XList(X)
#undef X
};
typedef struct PE_CoffHeader{
PE_MachineType machine_type;
U16 section_count;
U32 time_stamp;
U32 symbol_table_foff;
U32 symbol_count;
U16 optional_header_size;
PE_Flags flags;
} PE_CoffHeader;
// optional headers
#define PE_OptionalHeaderMagic_XList(X)\
X(ROM, 0x107)\
X(PE32, 0x10B)\
X(PE32Plus, 0x20B)
typedef U16 PE_OptionalHeaderMagic;
enum{
#define X(N,C) PE_OptionalHeaderMagic_##N = C,
PE_OptionalHeaderMagic_XList(X)
#undef X
};
#define PE_WindowsSubsystem_XList(X)\
X(UNKNOWN, 0)\
X(NATIVE, 1)\
X(WINDOWS_GUI, 2)\
X(WINDOWS_CUI, 3)\
X(OS2_CUI, 5)\
X(POSIX_CUI, 7)\
X(NATIVE_WINDOWS, 8)\
X(WINDOWS_CE_GUI, 9)\
X(EFI_APPLICATION, 10)\
X(EFI_BOOT_SERVICE_DRIVER, 11)\
X(EFI_RUNTIME_DRIVER, 12)\
X(EFI_ROM, 13)\
X(XBOX, 14)\
X(WINDOWS_BOOT_APPLICATION, 16)
typedef U16 PE_WindowsSubsystem;
enum{
#define X(N,C) PE_WindowsSubsystem_##N = C,
PE_WindowsSubsystem_XList(X)
#undef X
};
#define PE_DLLFlags_XList(X)\
X(RESERVED0, 0x0001)\
X(RESERVED1, 0x0002)\
X(RESERVED2, 0x0004)\
X(RESERVED3, 0x0008)\
X(HIGH_ENTROPY_VA, 0x0020)\
X(DYNAMIC_BASE, 0x0040)\
X(FORCE_INTEGRITY, 0x0080)\
X(NX_COMPAT, 0x0100)\
X(NO_ISOLATION, 0x0200)\
X(NO_SEH, 0x0400)\
X(NO_BIND, 0x0800)\
X(APPCONTAINER, 0x1000)\
X(WDM_DRIVER, 0x2000)\
X(GUARD_CF, 0x4000)\
X(TERMINAL_SERVER_AWARE, 0x8000)
typedef U16 PE_DLLFlags;
enum{
#define X(N,C) PE_DLLFlag_##N = C,
PE_DLLFlags_XList(X)
#undef X
};
typedef struct PE_OptionalHeader32{
PE_OptionalHeaderMagic magic;
U8 linker_version_major;
U8 linker_version_minor;
U32 total_size_text; // 'text' means executable code here
U32 total_size_inited_data;
U32 total_size_zeroed_data;
U32 entry_point_voff;
U32 text_voff;
U32 data_voff;
U32 image_base_vaddr;
U32 section_alignment;
U32 file_alignment;
U16 os_version_major;
U16 os_version_minor;
U16 image_version_major;
U16 image_version_minor;
U16 subsystem_version_major;
U16 subsystem_version_minor;
U32 reserved0;
U32 image_size;
U32 headers_size;
U32 checksum;
PE_WindowsSubsystem subsystem;
PE_DLLFlags dll_flags;
U32 stack_size_reserve;
U32 stack_size_commit;
U32 heap_size_reserve;
U32 heap_size_commit;
U32 reserved1;
U32 data_directory_count;
} PE_OptionalHeader32;
typedef struct PE_OptionalHeader32Plus{
U16 magic;
U8 linker_version_major;
U8 linker_version_minor;
U32 total_size_text; // 'text' means executable code here
U32 total_size_inited_data;
U32 total_size_zeroed_data;
U32 entry_point_voff;
U32 text_voff;
U64 image_base_vaddr;
U32 section_alignment;
U32 file_alignment;
U16 os_version_major;
U16 os_version_minor;
U16 image_version_major;
U16 image_version_minor;
U16 subsystem_version_major;
U16 subsystem_version_minor;
U32 reserved0;
U32 image_size;
U32 headers_size;
U32 checksum;
PE_WindowsSubsystem subsystem;
PE_DLLFlags dll_flags;
U64 stack_size_reserve;
U64 stack_size_commit;
U64 heap_size_reserve;
U64 heap_size_commit;
U32 reserved1;
U32 data_directory_count;
} PE_OptionalHeader32Plus;
typedef struct PE_DataDirectory{
U32 voff;
U32 size;
} PE_DataDirectory;
#define PE_DataDirectoryIdx_XList(X)\
X(ExportTable, "Export Table", 0)\
X(ImportTable, "Import Table", 1)\
X(ResourceTable, "Resource Table", 2)\
X(ExceptionTable, "Exception Table", 3)\
X(CertificateTable, "Certificate Table", 4)\
X(BaseRelocationTable, "Base Relocation Table", 5)\
X(Debug, "Debug Directories", 6)\
X(Architecture, "Architecture", 7)\
X(GlobalPtr, "Global Ptr", 8)\
X(TLSTable, "TLS Table", 9)\
X(LoadConfigTable, "Load Config Table", 10)\
X(BoundImport, "Bound Import", 11)\
X(IAT, "IAT", 12)\
X(DelayImportDescriptor, "Delay Import Descriptor", 13)\
X(CLRRuntimeHeader, "CLR Runtime Header", 14)\
X(Reserved, "Reserved", 15)
typedef U32 PE_DataDirectoryIdx;
enum{
#define X(N,D,C) PE_DataDirectoryIdx_##N = C,
PE_DataDirectoryIdx_XList(X)
#undef X
PE_DataDirectoryIdx_COUNT
};
// section table
#define PE_SectionFlags_XList(X)\
X(TYPE_NO_PAD, 0x00000008)\
X(CNT_CODE, 0x00000020)\
X(CNT_INITIALIZED_DATA, 0x00000040)\
X(CNT_UNINITIALIZED_DATA, 0x00000080)\
X(LNK_OTHER, 0x00000100)\
X(LNK_INFO, 0x00000200)\
X(LNK_REMOVE, 0x00000800)\
X(LNK_COMDAT, 0x00001000)\
X(GPREL, 0x00008000)\
X(MEM_16BIT, 0x00020000)\
X(MEM_LOCKED, 0x00040000)\
X(MEM_PRELOAD, 0x00080000)\
X(LNK_NRELOC_OVFL, 0x01000000)\
X(MEM_DISCARDABLE, 0x02000000)\
X(MEM_NOT_CACHED, 0x04000000)\
X(MEM_NOT_PAGED, 0x08000000)\
X(MEM_SHARED, 0x10000000)\
X(MEM_EXECUTE, 0x20000000)\
X(MEM_READ, 0x40000000)\
X(MEM_WRITE, 0x80000000)
#define PE_SectionAlignFromSectionFlags(f) ((f)&0x00F00000)
#define PE_SectionAlign_XList(X)\
X(1, 0x00100000)\
X(2, 0x00200000)\
X(4, 0x00300000)\
X(8, 0x00400000)\
X(16, 0x00500000)\
X(32, 0x00600000)\
X(64, 0x00700000)\
X(128, 0x00800000)\
X(256, 0x00900000)\
X(512, 0x00A00000)\
X(1024, 0x00B00000)\
X(2048, 0x00C00000)\
X(4096, 0x00D00000)\
X(8192, 0x00E00000)
typedef U32 PE_SectionFlags;
enum{
#define X(N,C) PE_SectionFlag_##N = C,
PE_SectionFlags_XList(X)
#undef X
#define X(N,C) PE_SectionAlign_##N = C,
PE_SectionAlign_XList(X)
#undef X
};
typedef struct PE_SectionHeader{
U8 name[8];
U32 vsize;
U32 voff;
U32 fsize;
U32 foff;
U32 relocations_foff;
U32 line_numbers_foff;
U16 relocation_count;
U16 line_number_count;
PE_SectionFlags flags;
} PE_SectionHeader;
// coff relocations
// TODO(allen): these are just the "x64" values
// generalize PE_CoffRelocationType to all machines
#define PE_CoffRelocationType_XList(X)\
X(ABSOLUTE, 0x0000)\
X(ADDR64, 0x0001)\
X(ADDR32, 0x0002)\
X(ADDR32NB, 0x0003)\
X(REL32, 0x0004)\
X(REL32_1, 0x0005)\
X(REL32_2, 0x0006)\
X(REL32_3, 0x0007)\
X(REL32_4, 0x0008)\
X(REL32_5, 0x0009)\
X(SECTION, 0x000A)\
X(SECREL, 0x000B)\
X(SECREL7, 0x000C)\
X(TOKEN, 0x000D)\
X(SREL32, 0x000E)\
X(PAIR, 0x000F)\
X(SSPAN32, 0x0010)
typedef U16 PE_CoffRelocationType;
enum{
#define X(N,C) PE_CoffRelocationType_##N = C,
PE_CoffRelocationType_XList(X)
#undef X
};
typedef struct PE_CoffRelocation{
U32 off;
U32 symbol_idx;
PE_CoffRelocationType type;
} PE_CoffRelocation;
// coff symbol table
#define PE_CoffSymbolStorageClass_XList(X)\
X(END_OF_FUNCTION, 0xFF)\
X(NULL, 0)\
X(AUTOMATIC, 1)\
X(EXTERNAL, 2)\
X(STATIC, 3)\
X(REGISTER, 4)\
X(EXTERNAL_DEF, 5)\
X(LABEL, 6)\
X(UNDEFINED_LABEL, 7)\
X(MEMBER_OF_STRUCT, 8)\
X(ARGUMENT, 9)\
X(STRUCT_TAG, 10)\
X(MEMBER_OF_UNION, 11)\
X(UNION_TAG, 12)\
X(TYPE_DEFINITION, 13)\
X(UNDEFINED_STATIC, 14)\
X(ENUM_TAG, 15)\
X(MEMBER_OF_ENUM, 16)\
X(REGISTER_PARAM, 17)\
X(BIT_FIELD, 18)\
X(BLOCK, 100)\
X(FUNCTION, 101)\
X(END_OF_STRUCT, 102)\
X(FILE, 103)\
X(SECTION, 104)\
X(WEAK_EXTERNAL, 105)\
X(CLR_TOKEN, 107)
typedef U8 PE_CoffSymbolStorageClass;
enum{
#define X(N,C) PE_CoffSymbolStorageClass_##N = C,
PE_CoffSymbolStorageClass_XList(X)
#undef X
};
#define PE_CoffSymbolTypeLo_XList(X)\
X(NULL, 0)\
X(VOID, 1)\
X(CHAR, 2)\
X(SHORT, 3)\
X(INT, 4)\
X(LONG, 5)\
X(FLOAT, 6)\
X(DOUBLE, 7)\
X(STRUCT, 8)\
X(UNION, 9)\
X(ENUM, 10)\
X(MOE, 11)\
X(BYTE, 12)\
X(WORD, 13)\
X(UINT, 14)\
X(DWORD, 15)
enum{
#define X(N,C) PE_CoffSymbolTypeLo_##N = C,
PE_CoffSymbolTypeLo_XList(X)
#undef X
};
#define PE_CoffSymbolTypeHi_XList(X)\
X(NULL, 0)\
X(POINTER, 1)\
X(FUNCTION, 2)\
X(ARRAY, 3)
enum{
#define X(N,C) PE_CoffSymbolTypeHi_##N = C,
PE_CoffSymbolTypeHi_XList(X)
#undef X
};
typedef U16 PE_CoffSymbolType;
typedef struct PE_CoffSymbolRecord{
union{
U8 raw[8];
struct{
U32 zero;
U32 string_table_off;
};
} name;
U32 val;
S16 sec_number;
PE_CoffSymbolType type;
PE_CoffSymbolStorageClass storage_class;
U8 aux_symbol_count;
} PE_CoffSymbolRecord;
// TODO(allen): COFF Line Numbers (Deprecated)
// TODO(allen): Attribute Certificate Table
// TODO(allen): Delay-Load Import Tables
// export data
typedef struct PE_ExportDirectoryTable{
U32 reserved0;
U32 time_stamp;
U16 version_major;
U16 version_minor;
U32 binary_name_voff;
U32 ordinal_base;
U32 export_count;
U32 ordinal_count;
U32 export_voff;
U32 name_voff;
U32 ordinal_voff;
/*
** NOTE(allen): Additional Structure Information
** export : [ export_count] U32;
** name : [ordinal_count] U32;
** ordinal : [ordinal_count] U16;
**
** for i in [0,ordinal_count):
** name[i] : voff to a cstring
** export[ordinal[i]] : voff to a symbol OR voff to forwarding string
** (voffs in export range are fowarding strings)
** ordinal[i] : "unbiased ordinal"
** ordinal[i] + ordinal_base : "ordinal"
*/
} PE_ExportDirectoryTable;
// import data
typedef struct PE_ImportDirectoryTable{
U32 import_lookup_table_voff;
U32 time_stamp;
U32 first_forwarder_idx;
U32 name_voff;
U32 import_address_table_voff;
/*
** NOTE(allen): Additional Structure Information
** IF PE32:
** import_lookup_table : null-terminated [] U32;
** IF PE32Plus:
** import_lookup_table : null-terminated [] U64;
**
** WHEN lookup = import_lookup_table[i]
** if (HighBits1(lookup)){
** ordinal = LowBits16(lookup)
** }
** else{
** hint_voff = LowBits31(lookup)
** hint : { U16, null-terminated-cstring }
** }
*/
} PE_ImportDirectoryTable;
// exception handling
#if 0
// NOTE(allen): untested - from documentation
typedef struct PE_ExceptionHandler_MIPS{
U32 begin_vaddr;
U32 end_vaddr;
U32 handler_vaddr;
U32 handler_data;
U32 prolog_end_vaddr;
} PE_ExceptionHandler_MIPS;
#endif
#if 0
// NOTE(allen): untested - from documentation
typedef struct PE_ExceptionHandler_ARM{
U32 begin_vaddr;
U32 info;
} PE_ExceptionHandler_ARM;
#define PE_ExceptionHandler_ARMInfo_PrologLength(i) (((i) >> 0)&0xFF)
#define PE_ExceptionHandler_ARMInfo_FuncLength(i) (((i) >> 8)&0x3FFFFF)
#define PE_ExceptionHandler_ARMInfo_32Bit(i) (((i) >> 30)&0x1)
#define PE_ExceptionHandler_ARMInfo_ExceptionFlag(i) (((i) >> 31)&0x1)
#endif
typedef struct PE_ExceptionHandler_X86{
U32 begin_voff;
U32 end_voff;
U32 unwind_voff;
} PE_ExceptionHandler_X86;
typedef struct PE_UnwindInfo{
U8 header;
U8 prolog_size;
U8 code_count;
U8 frame;
} PE_UnwindInfo;
#define PE_UnwindInfo_VersionFromHeader(x) ((x)&7)
#define PE_UnwindInfo_FlagsFromHeader(x) (((x)>>3)&0x1F)
#define PE_UnwindInfoFlags_XList(X)\
X(EHANDLER, (1 << 0))\
X(UHANDLER, (1 << 1))\
X(CHAINED, (1 << 2))
typedef U8 PE_UnwindInfoFlags;
enum{
#define X(N,C) PE_UnwindInfoFlag_##N = C,
PE_UnwindInfoFlags_XList(X)
#undef X
};
#define PE_UnwindInfo_RegFromFrame(x) ((x)&0xF)
#define PE_UnwindInfo_OffFromFrame(x) (((x) >> 4)&0xF)
#define PE_UnwindOpCode_XList(X)\
X(PUSH_NONVOL, 0)\
X(ALLOC_LARGE, 1)\
X(ALLOC_SMALL, 2)\
X(SET_FPREG, 3)\
X(SAVE_NONVOL, 4)\
X(SAVE_NONVOL_FAR, 5)\
X(EPILOG, 6)\
X(SPARE, 7)\
X(SAVE_XMM128, 8)\
X(SAVE_XMM128_FAR, 9)\
X(PUSH_MACHFRAME, 10)
typedef U8 PE_UnwindOpCode;
enum{
#define X(N,C) PE_UnwindOpCode_##N = C,
PE_UnwindOpCode_XList(X)
#undef X
};
#define PE_UnwindCode_GetOffset(x) (((x) >> 0)&0xFF)
#define PE_UnwindCode_GetOpCode(x) (((x) >> 8)&0x0F)
#define PE_UnwindCode_GetOpInfo(x) (((x) >> 12)&0x0F)
#define PE_UnwindCode_FromOffsetOpCodeInfo(off,opcode,opinfo) \
(((off)&0xFF) | (((opcode)&0xF) << 8) | (((opinfo)&0xF) << 12))
#define PE_UnwindRegX64_XList(X)\
X(RAX, 0)\
X(RCX, 1)\
X(RDX, 2)\
X(RBX, 3)\
X(RSP, 4)\
X(RBP, 5)\
X(RSI, 6)\
X(RDI, 7)\
X(R8, 8)\
X(R9, 9)\
X(R10, 10)\
X(R11, 11)\
X(R12, 12)\
X(R13, 13)\
X(R14, 14)\
X(R15, 15)
typedef U8 PE_UnwindRegX64;
enum{
#define X(N,C) PE_UnwindRegX64_##N = C,
PE_UnwindRegX64_XList(X)
#undef X
};
// base relocations
typedef struct PE_BaseRelocationBlock{
U32 page_voff;
U32 block_size;
} PE_BaseRelocationBlock;
typedef U16 PE_BaseRelocationTypeOffset;
#define PE_BaseRelocationType_XList(X)\
X(ABSOLUTE, 0)\
X(HIGH, 1)\
X(LOW, 2)\
X(HIGHLOW, 3)\
X(HIGHADJ, 4)\
X(SPLIT1, 5)\
X(SPLIT2, 7)\
X(SPLIT3, 8)\
X(MIPS_JMPADDR16, 9)\
X(DIR64, 10)
typedef U8 PE_BaseRelocationType;
enum{
#define X(N,C) PE_BaseRelocationType_##N = C,
PE_BaseRelocationType_XList(X)
#undef X
};
// SPLIT1: MIPS -> JMPADDR, ARM -> MOV32, RISCV -> HIGH20
// SPLIT2: THUMB -> MOV32, RISCV -> LOW12I
// SPLIT3: RISCV -> LOW12S, LOONGARCH32 -> MARK_LA, LOONGARCH64 -> MARK_LA
#define PE_BaseRelocationTypeOffset_GetType(X) (((X) >> 12)&0xF)
#define PE_BaseRelocationTypeOffset_GetOff(X) (((X) >> 0)&0xFFF)
// debug
#define PE_DebugType_XList(X)\
X(UNKNOWN, 0)\
X(COFF, 1)\
X(CODEVIEW, 2)\
X(FPO, 3)\
X(MISC, 4)\
X(EXCEPTION, 5)\
X(OMAP_TO_SRC, 7)\
X(OMAP_FROM_SRC, 8)\
X(BORLAND, 9)\
X(RESERVED10, 10)\
X(CLSID, 11)\
X(VC_FEATURE, 12)\
X(POGO, 13)\
X(ILTCG, 14)\
X(MPX, 15)\
X(REPRO, 16)\
X(EMBEDDED, 17)\
X(CRYPTOHASH, 19)\
X(EX_DLLCHARACTERISTICS, 20)
typedef U32 PE_DebugType;
enum{
#define X(N,C) PE_DebugType_##N = C,
PE_DebugType_XList(X)
#undef X
};
typedef struct PE_DebugDirectory{
U32 reserved0;
U32 time_stamp;
U16 version_major;
U16 version_minor;
PE_DebugType type;
U32 size;
U32 voff;
U32 foff;
} PE_DebugDirectory;
/* TODO(allen):
** [ ] Can we gather information about debug info types besides CODEVIEW ?
** [ ] What are the first 24 bytes of the CODEVIEW data range?
*/
// tls table
typedef U32 PE_TlsDirectoryFlags;
#define PE_TLSDirectoryFlags_GetAlign(X) ((X)&0x00F00000)
typedef struct PE_TLSDirectory32{
U32 raw_data_start_vaddr;
U32 raw_data_end_vaddr;
U32 tls_index_vaddr;
U32 tls_callback_array_vaddr;
U32 zero_fill_size;
PE_TlsDirectoryFlags flags;
} PE_TLSDirectory32;
typedef struct PE_TLSDirectory32Plus{
U64 raw_data_start_vaddr;
U64 raw_data_end_vaddr;
U64 tls_index_vaddr;
U64 tls_callback_array_vaddr;
U32 zero_fill_size;
PE_TlsDirectoryFlags flags;
} PE_TLSDirectory32Plus;
// load config table
/* TODO(allen): pneumonics for load config that are missing
** [ ] global flags
** [ ] process affinity mask
** [ ] process heap flags
** [ ] control flow guard flags
*/
typedef struct PE_LoadConfig32{
U32 reserved0;
U32 time_stamp;
U16 version_major;
U16 version_minor;
U32 global_flags_clear;
U32 global_flags_set;
U32 default_critical_section_timeout;
U32 decommit_free_block_threshold;
U32 decommit_total_free_threshold;
U32 lock_prefix_table_vaddr;
U32 maximum_allocation_size;
U32 virtual_memory_threshold;
U32 process_affinity_mask;
U32 process_heap_flags;
U16 csd_version;
U16 reserved1;
U32 reserved2;
U32 security_cookie_vaddr;
U32 seh_table_vaddr;
U32 seh_count;
U32 control_flow_guard_check_function_vaddr;
U32 control_flow_guard_dispatch_function_vaddr;
U32 control_flow_guard_function_table_vaddr;
U32 control_flow_guard_function_count;
U32 control_flow_guard_flags;
U8 code_integrity[12];
U32 guard_address_taken_iat_table_vaddr;
U32 guard_address_taken_iat_count;
U32 guard_long_jump_target_table_vaddr;
U32 guard_long_jump_target_count;
} PE_LoadConfig32;
typedef struct PE_LoadConfig64{
U32 reserved0;
U32 time_stamp;
U16 version_major;
U16 version_minor;
U32 global_flags_clear;
U32 global_flags_set;
U32 default_critical_section_timeout;
U64 decommit_free_block_threshold;
U64 decommit_total_free_threshold;
U64 lock_prefix_table_vaddr;
U64 maximum_allocation_size;
U64 virtual_memory_threshold;
U64 process_affinity_mask;
U32 process_heap_flags;
U16 csd_version;
U16 reserved1;
U64 reserved2;
U64 security_cookie_vaddr;
U64 seh_table_vaddr;
U64 seh_count;
U64 control_flow_guard_check_function_vaddr;
U64 control_flow_guard_dispatch_function_vaddr;
U64 control_flow_guard_function_table_vaddr;
U64 control_flow_guard_function_count;
U32 control_flow_guard_flags;
U8 code_integrity[12];
U64 guard_address_taken_iat_table_vaddr;
U64 guard_address_taken_iat_count;
U64 guard_long_jump_target_table_vaddr;
U64 guard_long_jump_target_count;
} PE_LoadConfig64;
#pragma pack(pop)
#endif //MR4TH_PE_H

View File

@ -1,68 +0,0 @@
////////////////////////////////
// PE Get Section Function
static RangePtr
pe_img_get_section(void *image_raw, String8 name){
U8 *image = (U8*)image_raw;
// dos header
PE_DosHeader *dos_header = (PE_DosHeader*)(image);
if (dos_header->magic != PE_MSDOS_MAGIC){
dos_header = 0;
}
// coff header
PE_CoffHeader *coff_header = 0;
U64 after_coff_header_offset = 0;
if (dos_header != 0){
U64 pe_signature_offset = dos_header->coff_file_offset;
U64 coff_header_offset = pe_signature_offset + sizeof(U32);
U32 pe_signature = *(U32*)(image + pe_signature_offset);
if (pe_signature == PE_SIGNATURE){
coff_header = (PE_CoffHeader*)(image + coff_header_offset);
after_coff_header_offset = coff_header_offset + sizeof(*coff_header);
}
}
// section table offset & count
U32 section_table_offset = 0;
U32 section_count = 0;
if (coff_header != 0){
section_table_offset = ( after_coff_header_offset
+ coff_header->optional_header_size);
section_count = coff_header->section_count;
}
// scan section table
PE_SectionHeader *match = 0;
{
PE_SectionHeader *sec = (PE_SectionHeader*)(image + section_table_offset);
for (U32 i = 0; i < section_count; i += 1, sec += 1){
U8 *secptr = sec->name;
U8 *secopl = sec->name + sizeof(sec->name);
U8 *keyptr = name.str;
U8 *keyopl = name.str + name.size;
B32 string_match = 1;
for (;*secptr != 0 && secptr < secopl && keyptr < keyopl;
secptr += 1, keyptr += 1){
if (*secptr != *keyptr){
string_match = 0;
break;
}
}
if (string_match){
match = sec;
break;
}
}
}
// fill result
RangePtr result = {0};
if (match != 0){
result.first = image + match->voff;
result.opl = result.first + match->vsize;
}
return(result);
}

View File

@ -1,9 +0,0 @@
#ifndef MR4TH_PE_IMG_GET_SECTION_H
#define MR4TH_PE_IMG_GET_SECTION_H
////////////////////////////////
// PE Get Section Function
static RangePtr pe_img_get_section(void *image, String8 name);
#endif //MR4TH_PE_IMG_GET_SECTION_H

View File

@ -2,66 +2,54 @@
** C Scripting Example #1
*/
#include "base.h"
#include "symbol_set.h"
#include "example1.h"
#include "base.c"
#include <stdio.h>
COMMAND_SCRIPT(foo, "Generates foo and increments the foo counter"){
printf("foo, ");
ctx->foo += 1;
#include "symbol_set.c"
EX1_COMMAND_DEF(Hello, "Increments and prints the counter"){
ctx->counter += 1;
printf("Hello World! (%d)\n", ctx->counter);
}
COMMAND_SCRIPT(bar, "Generates bar and decrements the foo counter"){
printf("bar, ");
ctx->foo -= 1;
EX1_COMMAND_DEF(Goodbye, "Prints and decrements the counter"){
printf("Goodbye! (%d)\n", ctx->counter);
ctx->counter -= 1;
}
COMMAND_SCRIPT(baz,
"Generates 2 bars if the foo counter is positive, "
"generates 2 foos if the foo counter is negative, "
"otherwise generates baz"){
if (ctx->foo > 0){
printf("bar, bar, ");
}
else if (ctx->foo < 0){
printf("foo, foo, ");
}
else{
printf("baz, ");
}
EX1_COMMAND_DEF(UntilNextTime, "Resets the counter and prints"){
ctx->counter = 0;
printf("Until next time...\n");
}
int main(void){
// init sequence
U32 command_ids[] = {
COMMAND_ID(foo), COMMAND_ID(foo), COMMAND_ID(baz),
COMMAND_ID(bar), COMMAND_ID(baz), COMMAND_ID(bar),
COMMAND_ID(foo), COMMAND_ID(bar), COMMAND_ID(baz),
};
// display the legend of rules
printf("RULES:\n");
{
EX1_Command *commands = SymbolBasePtr(EX1_CommandSymbols);
U64 count = SymbolCount(EX1_CommandSymbols);
for (U64 i = 0; i < count; i += 1){
EX1_Command *command = commands + i;
printf("%.*s -> %.*s\n",
str8_expand(command->name),
str8_expand(command->description));
}
for (SyEach(EX1_COMMAND, command)){
printf("%s -> %s\n", command->name, command->description);
}
printf("\n");
// init the sequence
Sy_U32 sequence[] = {
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Hello),
SyID(EX1_COMMAND, UntilNextTime),
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Goodbye),
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Goodbye),
SyID(EX1_COMMAND, UntilNextTime),
SyID(EX1_COMMAND, Goodbye), SyID(EX1_COMMAND, Goodbye),
SyID(EX1_COMMAND, Goodbye), SyID(EX1_COMMAND, Hello),
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Hello),
};
// display the sequence
printf("SEQUENCE:\n");
for (U32 i = 0; i < sizeof(command_ids)/sizeof(command_ids[0]); i += 1){
U32 id = command_ids[i];
EX1_Command *command = COMMAND_METADATA_FROM_ID(id);
printf("%.*s, ", str8_expand(command->name));
for (Sy_U32 i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i += 1){
Sy_U32 id = sequence[i];
EX1_Command *command = SyAddressFromID(EX1_COMMAND, id);
printf("%s, ", command->name);
}
printf("\n\n");
@ -69,13 +57,12 @@ int main(void){
printf("OUTPUT:\n");
{
EX1_Ctx ctx = {0};
for (U32 i = 0; i < sizeof(command_ids)/sizeof(command_ids[0]); i += 1){
U32 id = command_ids[i];
EX1_Command *command = COMMAND_METADATA_FROM_ID(id);
for (Sy_U32 i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i += 1){
Sy_U32 id = sequence[i];
EX1_Command *command = SyAddressFromID(EX1_COMMAND, id);
command->hook(&ctx);
}
}
printf("\n\n");
return(0);
}

View File

@ -5,29 +5,26 @@
// Setup a Symbol Set
typedef struct EX1_Ctx{
S64 foo;
int counter;
} EX1_Ctx;
typedef void EX1_Hook(EX1_Ctx *ctx);
typedef struct EX1_Command{
String8 name;
String8 description;
char *name;
char *description;
EX1_Hook *hook;
} EX1_Command;
#define SYMBOL_SET_DEFINE EX1_CommandSymbols
#define EX1_CommandSymbols_Type EX1_Command
#define EX1_CommandSymbols_section ".ex1CMD"
#define SYMBOL_SET_DEFINE EX1_COMMAND
#define EX1_COMMAND_Type EX1_Command
#define EX1_COMMAND_section ".sy.x1cm"
#define EX1_COMMAND_marker x1cm
#include "symbol_set.define.h"
#define COMMAND_ID(N) SymbolID(EX1_CommandSymbols, N)
#define COMMAND_DECL(N) SymbolDeclare(EX1_CommandSymbols, N)
#define COMMAND_METADATA_FROM_ID(id) SymbolMetadataFromID(EX1_CommandSymbols, id)
#define EX1_COMMAND_DEF(N,desc) \
void ex1cmd_##N(EX1_Ctx *ctx); \
SyDefine(EX1_COMMAND, N) = { #N, desc, ex1cmd_##N };\
void ex1cmd_##N(EX1_Ctx *ctx)
#define COMMAND_SCRIPT(N,desc) \
void cmdhook_##N(EX1_Ctx *ctx); \
SymbolDefine(EX1_CommandSymbols, N) = { str8_lit_const(#N), str8_lit_const(desc), cmdhook_##N };\
void cmdhook_##N(EX1_Ctx *ctx)
#endif //EXAMPLE1_H
#endif /* EXAMPLE1_H */

5861
src/mr4th/mr4th_base.c Normal file

File diff suppressed because it is too large Load Diff

1891
src/mr4th/mr4th_base.h Normal file

File diff suppressed because it is too large Load Diff

294
src/mr4th/mr4th_cmdln.c Normal file
View File

@ -0,0 +1,294 @@
////////////////////////////////
// Functions: Command Line Parsing
MR4TH_SYMBOL MR4TH_READ_ONLY
CMDLN_Params cmdln__params_nil = {0};
#define cmdln_params_nil (CMDLN_Params*)(&cmdln__params_nil)
MR4TH_SYMBOL CMDLN*
cmdln_from_args(Arena *arena, String8List *args){
CMDLN *cmdln = push_array(arena, CMDLN, 1);
cmdln->raw = str8_list_copy(arena, args);
String8Node *node = cmdln->raw.first;
// first string is 'program'
if (node != 0){
cmdln->program = node->string;
node = node->next;
}
// consume string nodes
B32 forced_input = 0;
for (;node != 0;){
String8 string = str8_skip_chop_whitespace(node->string);
node = node->next;
// check if argument is a flag
B32 is_flag = 0;
if (!forced_input){
is_flag = (string.size != 0 && string.str[0] == '-');
}
// parse flag
if (is_flag){
// long flag
B32 is_long_flag = (string.size > 1 && string.str[1] == '-');
if (is_long_flag){
// end 'normal' mode
B32 double_dash = (string.size == 2);
if (double_dash){
forced_input = 1;
}
// parse long flag
if (!double_dash){
String8 flag_whole = str8_skip(string, 2);
// parameter delimter
U64 delim = flag_whole.size;
for (U8 *ptr = flag_whole.str, *opl = flag_whole.str + flag_whole.size;
ptr < opl; ptr += 1){
if (*ptr == '=' || *ptr == ':'){
delim = (U64)(ptr - flag_whole.str);
break;
}
}
// split flag at delimiter
String8 flag_name = str8_prefix(flag_whole, delim);
String8 flag_param = str8_skip(flag_whole, delim + 1);
// if have a param delimiter at end
// then use the next argument as the flag_param
if (delim == flag_whole.size - 1){
if (node != 0){
flag_param = node->string;
node = node->next;
}
}
// parse parameters
CMDLN_Params *params = cmdln_params_from_string(arena, flag_param);
// store flag node
{
CMDLN_Node *cmdlnnode = push_array(arena, CMDLN_Node, 1);
SLLQueuePush(cmdln->first, cmdln->last, cmdlnnode);
cmdlnnode->string = flag_name;
cmdlnnode->params = params;
cmdln->flag_count += 1;
}
}
}
// short flags
if (!is_long_flag){
String8 short_flags = str8_skip(string, 1);
U8 *flag = short_flags.str;
U8 *flagopl = short_flags.str + short_flags.size;
for (; flag < flagopl; flag += 1){
U8 *flagptr = flag;
// check for parameters
String8 flag_param = {0};
if (flag + 1 < flagopl &&
(flag[1] == '=' || flag[1] == ':')){
flag_param = str8_range(flag + 2, flagopl);
if (flag_param.size == 0){
if (node != 0){
flag_param = node->string;
node = node->next;
}
}
// kill the flag loop after finding parameters
flag = flagopl;
}
// parse parameters
CMDLN_Params *params = cmdln_params_from_string(arena, flag_param);
// store flag node
{
CMDLN_Node *cmdlnnode = push_array(arena, CMDLN_Node, 1);
SLLQueuePush(cmdln->first, cmdln->last, cmdlnnode);
cmdlnnode->string = str8(flagptr, 1);
cmdlnnode->params = params;
cmdln->flag_count += 1;
}
}
}
}
// parse input
if (!is_flag){
String8 input_string = string;
// store input node
{
CMDLN_Node *cmdlnnode = push_array(arena, CMDLN_Node, 1);
SLLQueuePush(cmdln->first, cmdln->last, cmdlnnode);
cmdlnnode->string = input_string;
cmdln->input_count += 1;
}
}
}
// pointer arrays
cmdln->inputs = push_array(arena, CMDLN_Node*, cmdln->input_count);
cmdln->flags = push_array(arena, CMDLN_Node*, cmdln->flag_count);
{
CMDLN_Node **inputptr = cmdln->inputs;
CMDLN_Node **flagptr = cmdln->flags;
for (CMDLN_Node *node = cmdln->first;
node != 0;
node = node->next){
if (node->params == 0){
*inputptr = node;
inputptr += 1;
}
else{
*flagptr = node;
flagptr += 1;
}
}
}
return(cmdln);
}
MR4TH_SYMBOL CMDLN_Params*
cmdln_params_from_string(Arena *arena, String8 flag_param){
CMDLN_Params *params = cmdln_params_nil;
if (flag_param.size > 0){
params = push_array(arena, CMDLN_Params, 1);
params->raw = flag_param;
params->list = str8_split(arena, flag_param, (U8*)",", 1);
}
return(params);
}
MR4TH_SYMBOL U64
cmdln_input_count(CMDLN *cmdln){
return(cmdln->input_count);
}
MR4TH_SYMBOL String8
cmdln_input_from_idx(CMDLN *cmdln, U64 idx){
String8 result = {0};
if (idx < cmdln->input_count){
result = cmdln->inputs[idx]->string;
}
return(result);
}
MR4TH_SYMBOL U64
cmdln_flag_count(CMDLN *cmdln){
return(cmdln->flag_count);
}
MR4TH_SYMBOL CMDLN_Flag*
cmdln_flag_from_idx(CMDLN *cmdln, U64 idx){
CMDLN_Flag *result = 0;
if (idx < cmdln->flag_count){
result = cmdln->flags[idx];
}
return(result);
}
MR4TH_SYMBOL CMDLN_Params*
cmdln_get_params(CMDLN *cmdln, String8 flagstr, char abbrev){
CMDLN_Params *result = 0;
for (CMDLN_Node *node = cmdln->first;
node != 0;
node = node->next){
if (node->params != 0){
if (str8_match(flagstr, node->string, 0) ||
(node->string.size == 1 && node->string.str[0] == (U8)abbrev)){
result = node->params;
break;
}
}
}
return(result);
}
MR4TH_SYMBOL B32
cmdln_has_flag(CMDLN *cmdln, String8 flagstr, char abbrev){
CMDLN_Params *params = cmdln_get_params(cmdln, flagstr, abbrev);
B32 result = (params != 0);
return(result);
}
MR4TH_SYMBOL String8
cmdln_get_str8(CMDLN *cmdln, String8 flagstr, char abbrev){
CMDLN_Params *params = cmdln_get_params(cmdln, flagstr, abbrev);
String8 result = {0};
if (params != 0){
result = params->raw;
}
return(result);
}
MR4TH_SYMBOL S64
cmdln_get_s64(CMDLN *cmdln, String8 flagstr, char abbrev){
String8 str = cmdln_get_str8(cmdln, flagstr, abbrev);
S64 result = cmdln_s64_from_str8(str);
return(result);
}
MR4TH_SYMBOL F64
cmdln_get_f64(CMDLN *cmdln, String8 flagstr, char abbrev){
String8 str = cmdln_get_str8(cmdln, flagstr, abbrev);
F64 result = cmdln_f64_from_str8(str);
return(result);
}
MR4TH_SYMBOL S64
cmdln_s64_from_str8(String8 valstr){
S64 result = s64_from_str8_c_syntax(valstr);
return(result);
}
MR4TH_SYMBOL F64
cmdln_f64_from_str8(String8 valstr){
F64 result = f64_from_str8(valstr);
return(result);
}
MR4TH_SYMBOL void
cmdln_dump(Arena *arena, String8List *out, CMDLN *cmdln, U32 indent){
// raw
str8_list_pushf(arena, out, "%Nraw:\n", indent);
for (String8Node *node = cmdln->raw.first;
node != 0;
node = node->next){
str8_list_pushf(arena, out, "%N%S\n", indent + 1, node->string);
}
// program
str8_list_pushf(arena, out, "%Nprogram: %S\n", indent, cmdln->program);
// input nodes
str8_list_pushf(arena, out, "%Nnodes:\n", indent);
for (CMDLN_Node *cmdlnnode = cmdln->first;
cmdlnnode != 0;
cmdlnnode = cmdlnnode->next){
if (cmdlnnode->params == 0){
str8_list_pushf(arena, out, "%N[input] %S\n", indent + 1, cmdlnnode->string);
}
else{
str8_list_pushf(arena, out, "%N[flag ] %S\n", indent + 1, cmdlnnode->string);
for (String8Node *node = cmdlnnode->params->list.first;
node != 0;
node = node->next){
str8_list_pushf(arena, out, "%N[param] %S\n", indent + 2, node->string);
}
}
}
}

64
src/mr4th/mr4th_cmdln.h Normal file
View File

@ -0,0 +1,64 @@
#ifndef MR4TH_CMDLN_H
#define MR4TH_CMDLN_H
////////////////////////////////
// Types: Command Line Parsing
typedef struct CMDLN_Params{
String8 raw;
String8List list;
} CMDLN_Params;
typedef struct CMDLN_Node{
struct CMDLN_Node *next;
String8 string;
CMDLN_Params *params;
// (params == 0 ) -> 'input' (not a flag)
// (params != 0 ) -> flag
// (params == nil) -> flag has no parameters
} CMDLN_Node;
typedef CMDLN_Node CMDLN_Flag;
typedef struct CMDLN{
String8List raw;
String8 program;
CMDLN_Node *first;
CMDLN_Node *last;
U64 input_count;
U64 flag_count;
CMDLN_Node **inputs;
CMDLN_Node **flags;
} CMDLN;
////////////////////////////////
// Functions: Command Line Parsing
MR4TH_SYMBOL CMDLN* cmdln_from_args(Arena *arena, String8List *args);
MR4TH_SYMBOL CMDLN_Params* cmdln_params_from_string(Arena *arena, String8 flag_param);
MR4TH_SYMBOL U64 cmdln_input_count(CMDLN *cmdln);
MR4TH_SYMBOL String8 cmdln_input_from_idx(CMDLN *cmdln, U64 idx);
MR4TH_SYMBOL U64 cmdln_flag_count(CMDLN *cmdln);
MR4TH_SYMBOL CMDLN_Flag* cmdln_flag_from_idx(CMDLN *cmdln, U64 idx);
MR4TH_SYMBOL CMDLN_Params* cmdln_get_params(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL B32 cmdln_has_flag(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL String8 cmdln_get_str8(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL S64 cmdln_get_s64(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL F64 cmdln_get_f64(CMDLN *cmdln, String8 flagstr, char abbrev);
MR4TH_SYMBOL S64 cmdln_s64_from_str8(String8 valstr);
MR4TH_SYMBOL F64 cmdln_f64_from_str8(String8 valstr);
MR4TH_SYMBOL void cmdln_dump(Arena *arena, String8List *out, CMDLN *cmdln, U32 indent);
/* TODO:
** [ ] fuzz
** [ ] built in parser diagnostics
** [ ] built in misuse feedback
** [ ] help structurer
*/
#endif //MR4TH_CMDLN_H

480
src/mr4th/mr4th_elf.c Normal file
View File

@ -0,0 +1,480 @@
////////////////////////////////
// Functions: ELF
// normalizing
MR4TH_SYMBOL_STATIC U16
elf_u16_decode(void *ptr, B32 flip){
U16 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = buf[1] | (buf[0] << 8);
}
else{
result = *(U16*)ptr;
}
return(result);
}
MR4TH_SYMBOL_STATIC U32
elf_u32_decode(void *ptr, B32 flip){
U32 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);
}
else{
result = *(U32*)ptr;
}
return(result);
}
MR4TH_SYMBOL_STATIC U64
elf_u64_decode(void *ptr, B32 flip){
U64 result = 0;
if (flip){
U8 *buf = (U8*)ptr;
result = ((((U64)buf[7]) << 0) | (((U64)buf[6]) << 8) |
(((U64)buf[5]) << 16) | (((U64)buf[4]) << 24) |
(((U64)buf[3]) << 32) | (((U64)buf[2]) << 40) |
(((U64)buf[1]) << 48) | (((U64)buf[0]) << 56));
}
else{
result = *(U64*)ptr;
}
return(result);
}
MR4TH_SYMBOL_STATIC void
elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
MemoryCopyArray(dst->ident, src->ident);
dst->type = elf_u16_decode(&src->type, flip_order);
dst->machine = elf_u16_decode(&src->machine, flip_order);
dst->version = elf_u32_decode(&src->version, flip_order);
dst->entry = (U64)elf_u32_decode(&src->entry, flip_order);
dst->segment_table_foff = (U64)elf_u32_decode(&src->segment_table_foff, flip_order);
dst->section_table_foff = (U64)elf_u32_decode(&src->section_table_foff, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->header_size = elf_u16_decode(&src->header_size, flip_order);
dst->segment_size = elf_u16_decode(&src->segment_size, flip_order);
dst->segment_count = elf_u16_decode(&src->segment_count, flip_order);
dst->section_size = elf_u16_decode(&src->section_size, flip_order);
dst->section_count = elf_u16_decode(&src->section_count, flip_order);
dst->string_section_index = elf_u16_decode(&src->string_section_index, flip_order);
}
MR4TH_SYMBOL_STATIC void
elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
MemoryCopyArray(dst->ident, src->ident);
dst->type = elf_u16_decode(&src->type, 1);
dst->machine = elf_u16_decode(&src->machine, 1);
dst->version = elf_u32_decode(&src->version, 1);
dst->entry = elf_u32_decode(&src->entry, 1);
dst->segment_table_foff = elf_u32_decode(&src->segment_table_foff, 1);
dst->section_table_foff = elf_u32_decode(&src->section_table_foff, 1);
dst->flags = elf_u32_decode(&src->flags, 1);
dst->header_size = elf_u16_decode(&src->header_size, 1);
dst->segment_size = elf_u16_decode(&src->segment_size, 1);
dst->segment_count = elf_u16_decode(&src->segment_count, 1);
dst->section_size = elf_u16_decode(&src->section_size, 1);
dst->section_count = elf_u16_decode(&src->section_count, 1);
dst->string_section_index = elf_u16_decode(&src->string_section_index, 1);
}
}
MR4TH_SYMBOL_STATIC void
elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->name = elf_u32_decode(&src->name, flip_order);
dst->type = elf_u32_decode(&src->type, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->addr = elf_u32_decode(&src->addr, flip_order);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->size = elf_u32_decode(&src->size, flip_order);
dst->link = elf_u32_decode(&src->link, flip_order);
dst->info = elf_u32_decode(&src->info, flip_order);
dst->addralign = elf_u32_decode(&src->addralign, flip_order);
dst->entsize = elf_u32_decode(&src->entsize, flip_order);
}
MR4TH_SYMBOL_STATIC void
elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->name = elf_u32_decode(&src->name, 1);
dst->type = elf_u32_decode(&src->type, 1);
dst->flags = elf_u64_decode(&src->flags, 1);
dst->addr = elf_u64_decode(&src->addr, 1);
dst->offset = elf_u64_decode(&src->offset, 1);
dst->size = elf_u64_decode(&src->size, 1);
dst->link = elf_u32_decode(&src->link, 1);
dst->info = elf_u32_decode(&src->info, 1);
dst->addralign = elf_u64_decode(&src->addralign, 1);
dst->entsize = elf_u64_decode(&src->entsize, 1);
}
}
MR4TH_SYMBOL_STATIC void
elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->type = elf_u32_decode(&src->type, flip_order);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->vaddr = elf_u32_decode(&src->vaddr, flip_order);
dst->paddr = elf_u32_decode(&src->paddr, flip_order);
dst->file_size = elf_u32_decode(&src->file_size, flip_order);
dst->memory_size = elf_u32_decode(&src->memory_size, flip_order);
dst->flags = elf_u32_decode(&src->flags, flip_order);
dst->align = elf_u32_decode(&src->align, flip_order);
}
MR4TH_SYMBOL_STATIC void
elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->type = elf_u32_decode(&src->type, 1);
dst->flags = elf_u32_decode(&src->flags, 1);
dst->offset = elf_u64_decode(&src->offset, 1);
dst->vaddr = elf_u64_decode(&src->vaddr, 1);
dst->paddr = elf_u64_decode(&src->paddr, 1);
dst->file_size = elf_u64_decode(&src->file_size, 1);
dst->memory_size = elf_u64_decode(&src->memory_size, 1);
dst->align = elf_u64_decode(&src->align, 1);
}
}
MR4TH_SYMBOL_STATIC void
elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->name = elf_u32_decode(&src->name, flip_order);
dst->value = elf_u32_decode(&src->value, flip_order);
dst->size = elf_u32_decode(&src->size, flip_order);
dst->info = src->info;
dst->other = src->other;
dst->section_index = elf_u16_decode(&src->section_index, flip_order);
}
MR4TH_SYMBOL_STATIC void
elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
if (!flip_order){
MemoryCopyStruct(dst, src);
}
else{
dst->name = elf_u32_decode(&src->name, 1);
dst->info = src->info;
dst->other = src->other;
dst->section_index = elf_u16_decode(&src->section_index, 1);
dst->value = elf_u64_decode(&src->value, 1);
dst->size = elf_u64_decode(&src->size, 1);
}
}
MR4TH_SYMBOL_STATIC void
elf_reloca64_from_reloc32(ELF_RelocationAdd64 *dst, ELF_Relocation32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->info = elf_u32_decode(&src->info, flip_order);
dst->addend = 0;
}
MR4TH_SYMBOL_STATIC void
elf_reloca64_from_reloc64(ELF_RelocationAdd64 *dst, ELF_Relocation64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->offset = elf_u64_decode(&src->offset, flip_order);
dst->info = elf_u64_decode(&src->info, flip_order);
dst->addend = 0;
}
MR4TH_SYMBOL_STATIC void
elf_reloca64_from_reloca32(ELF_RelocationAdd64 *dst, ELF_RelocationAdd32 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->offset = elf_u32_decode(&src->offset, flip_order);
dst->info = elf_u32_decode(&src->info, flip_order);
dst->addend = (S32)elf_u32_decode(&src->addend, flip_order);
}
MR4TH_SYMBOL_STATIC void
elf_reloca64_from_reloca64(ELF_RelocationAdd64 *dst, ELF_RelocationAdd64 *src, ELF_Encoding src_encoding){
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
dst->offset = elf_u64_decode(&src->offset, flip_order);
dst->info = elf_u64_decode(&src->info, flip_order);
dst->addend = (S64)elf_u64_decode(&src->addend, flip_order);
}
// strings
MR4TH_SYMBOL_STATIC String8
elf_str8_from_identification_idx(ELF_IdentificationIdx idx){
String8 result = str8_lit("ERROR");
switch (idx){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_IdentificationIdx_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_class(ELF_Class elf_class){
String8 result = str8_lit("ERROR");
switch (elf_class){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_Class_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_encoding(ELF_Encoding elf_encoding){
String8 result = str8_lit("ERROR");
switch (elf_encoding){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_Encoding_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi){
String8 result = str8_lit("ERROR");
switch (elf_osabi){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_OsAbiExtension_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_file_type(ELF_FileType file_type){
String8 result = str8_lit("ERROR");
switch (file_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_FileType_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_machine_type(ELF_FileType machine_type){
String8 result = str8_lit("ERROR");
switch (machine_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_MachineType_XList(X)
#undef X
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_section_type(ELF_SectionType section_type){
String8 result = str8_lit("ERROR");
if (ELF_SectionType_LOOS <= section_type &&
section_type <= ELF_SectionType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SectionType_LOPROC <= section_type &&
section_type <= ELF_SectionType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else if (ELF_SectionType_LOUSER <= section_type &&
section_type <= ELF_SectionType_HIUSER){
result = str8_lit("USER-CUSTOM-TYPE");
}
else{
switch (section_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SectionType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYMBOL_STATIC void
elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags){
U32 f = 1;
for (U32 i = 0; i < 20; i += 1){
if ((flags & f) != 0){
switch (f){
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
ELF_SectionFlags_XList(X)
#undef X
}
}
f <<= 1;
}
if ((flags & ELF_SectionFlag_MASKOS) != 0){
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
}
if ((flags & ELF_SectionFlag_MASKPROC) != 0){
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
}
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_section_flags(Arena *arena, U32 flags){
ArenaTemp scratch = arena_get_scratch(&arena, 1);
String8List list = {0};
elf_str8list_from_section_flags(scratch.arena, &list, flags);
String8 result = str8_join_flags(arena, &list);
arena_release_scratch(&scratch);
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_segment_type(ELF_SegmentType segment_type){
String8 result = str8_lit("ERROR");
if (ELF_SegmentType_LOOS <= segment_type &&
segment_type <= ELF_SegmentType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SegmentType_LOPROC <= segment_type &&
segment_type <= ELF_SegmentType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (segment_type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SegmentType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYMBOL_STATIC void
elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags){
U32 f = 1;
for (U32 i = 0; i < 20; i += 1){
if ((flags & f) != 0){
switch (f){
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
ELF_SegmentFlags_XList(X)
#undef X
}
}
f <<= 1;
}
if ((flags & ELF_SegmentFlag_MASKOS) != 0){
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
}
if ((flags & ELF_SegmentFlag_MASKPROC) != 0){
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
}
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags){
ArenaTemp scratch = arena_get_scratch(&arena, 1);
String8List list = {0};
elf_str8list_from_segment_flags(scratch.arena, &list, flags);
String8 result = str8_join_flags(arena, &list);
arena_release_scratch(&scratch);
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_symbol_binding(ELF_SymbolBinding bind){
String8 result = str8_lit("ERROR");
if (ELF_SymbolBinding_LOOS <= bind &&
bind <= ELF_SymbolBinding_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SymbolBinding_LOPROC <= bind &&
bind <= ELF_SymbolBinding_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (bind){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolBinding_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_symbol_type(ELF_SymbolType type){
String8 result = str8_lit("ERROR");
if (ELF_SymbolType_LOOS <= type &&
type <= ELF_SymbolType_HIOS){
result = str8_lit("OS-CUSTOM-TYPE");
}
else if (ELF_SymbolType_LOPROC <= type &&
type <= ELF_SymbolType_HIPROC){
result = str8_lit("PROC-CUSTOM-TYPE");
}
else{
switch (type){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolType_XList(X)
#undef X
}
}
return(result);
}
MR4TH_SYMBOL_STATIC String8
elf_str8_from_symbol_vis(ELF_SymbolVis vis){
String8 result = str8_lit("ERROR");
switch (vis){
#define X(N,C) case C: result = str8_lit(#N); break;
ELF_SymbolVis_XList(X)
#undef X
}
return(result);
}

View File

@ -660,46 +660,46 @@ typedef struct ELF_Segment64{
// normalizing
MR4TH_SYM_COMPTIME U16 elf_u16_decode(void *ptr, B32 flip);
MR4TH_SYM_COMPTIME U32 elf_u32_decode(void *ptr, B32 flip);
MR4TH_SYM_COMPTIME U64 elf_u64_decode(void *ptr, B32 flip);
MR4TH_SYMBOL_STATIC U16 elf_u16_decode(void *ptr, B32 flip);
MR4TH_SYMBOL_STATIC U32 elf_u32_decode(void *ptr, B32 flip);
MR4TH_SYMBOL_STATIC U64 elf_u64_decode(void *ptr, B32 flip);
MR4TH_SYM_COMPTIME void elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME void elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloc32(Arena *arena, ELF_Relocation32 *src, U64 count, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloc64(Arena *arena, ELF_Relocation64 *src, U64 count, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloca32(Arena *arena, ELF_RelocationAdd32 *src, U64 count, ELF_Encoding src_encoding);
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloca64(Arena *arena, ELF_RelocationAdd64 *src, U64 count, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloc32(ELF_RelocationAdd64 *dst, ELF_Relocation32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloc64(ELF_RelocationAdd64 *dst, ELF_Relocation64 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloca32(ELF_RelocationAdd64 *dst, ELF_RelocationAdd32 *src, ELF_Encoding src_encoding);
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloca64(ELF_RelocationAdd64 *dst, ELF_RelocationAdd64 *src, ELF_Encoding src_encoding);
// strings
MR4TH_SYM_COMPTIME String8 elf_str8_from_identification_idx(ELF_IdentificationIdx idx);
MR4TH_SYM_COMPTIME String8 elf_str8_from_class(ELF_Class elf_class);
MR4TH_SYM_COMPTIME String8 elf_str8_from_encoding(ELF_Encoding elf_encoding);
MR4TH_SYM_COMPTIME String8 elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi);
MR4TH_SYM_COMPTIME String8 elf_str8_from_file_type(ELF_FileType file_type);
MR4TH_SYM_COMPTIME String8 elf_str8_from_machine_type(ELF_FileType machine_type);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_identification_idx(ELF_IdentificationIdx idx);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_class(ELF_Class elf_class);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_encoding(ELF_Encoding elf_encoding);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_file_type(ELF_FileType file_type);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_machine_type(ELF_FileType machine_type);
MR4TH_SYM_COMPTIME String8 elf_str8_from_section_type(ELF_SectionType section_type);
MR4TH_SYM_COMPTIME void elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags);
MR4TH_SYM_COMPTIME String8 elf_str8_from_section_flags(Arena *arena, U32 flags);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_section_type(ELF_SectionType section_type);
MR4TH_SYMBOL_STATIC void elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_section_flags(Arena *arena, U32 flags);
MR4TH_SYM_COMPTIME String8 elf_str8_from_segment_type(ELF_SegmentType segment_type);
MR4TH_SYM_COMPTIME void elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags);
MR4TH_SYM_COMPTIME String8 elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_segment_type(ELF_SegmentType segment_type);
MR4TH_SYMBOL_STATIC void elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags);
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_binding(ELF_SymbolBinding bind);
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_type(ELF_SymbolType type);
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_vis(ELF_SymbolVis vis);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_binding(ELF_SymbolBinding bind);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_type(ELF_SymbolType type);
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_vis(ELF_SymbolVis vis);
#endif //MR4TH_ELF_H

422
src/mr4th/mr4th_elf.parse.c Normal file
View File

@ -0,0 +1,422 @@
////////////////////////////////
// Elf Parse Functions
MR4TH_SYMBOL ELF_Parse*
elfp_begin(Arena *arena, String8 data){
// magic check
B32 elf_magic = 0;
ELF_Class elf_class = ELF_Class_NONE;
ELF_Encoding elf_encoding = ELF_Encoding_NONE;
U32 elf_version = 0;
ELF_OsAbiExtension elf_ext = ELF_OsAbiExtension_NONE;
B32 good_headers = 0;
if (data.size >= ELF_NUM_IDENT){
elf_class = data.str[ELF_IdentificationIdx_CLASS];
elf_encoding = data.str[ELF_IdentificationIdx_DATA];
elf_version = data.str[ELF_IdentificationIdx_VERSION];
elf_ext = data.str[ELF_IdentificationIdx_OSABI];
if (data.str[0] == ELF_Magic_Byte0 &&
data.str[1] == ELF_Magic_Byte1 &&
data.str[2] == ELF_Magic_Byte2 &&
data.str[3] == ELF_Magic_Byte3 &&
elf_version == 1 &&
(elf_class == ELF_Class_32 || elf_class == ELF_Class_64) &&
(elf_encoding == ELF_Encoding_2LSB ||
elf_encoding == ELF_Encoding_2MSB)){
good_headers = 1;
}
}
// header
void *header = 0;
U64 section_table_foff = 0;
U16 section_count = 0;
U16 section_size = 0;
U64 segment_table_foff = 0;
U16 segment_count = 0;
U16 segment_size = 0;
U16 string_section_index = 0;
if (good_headers){
switch (elf_class){
default:break;
case ELF_Class_32: {
if (sizeof(ELF_Header32) <= data.size){
header = data.str;
ELF_Header32 *h = (ELF_Header32*)header;
section_table_foff = h->section_table_foff;
section_count = h->section_count;
section_size = h->section_size;
segment_table_foff = h->segment_table_foff;
segment_count = h->segment_count;
segment_size = h->segment_size;
string_section_index = h->string_section_index;
}
}break;
case ELF_Class_64: {
if (sizeof(ELF_Header64) <= data.size){
header = data.str;
ELF_Header64 *h = (ELF_Header64*)header;
section_table_foff = h->section_table_foff;
section_count = h->section_count;
section_size = h->section_size;
segment_table_foff = h->segment_table_foff;
segment_count = h->segment_count;
segment_size = h->segment_size;
string_section_index = h->string_section_index;
}
}break;
}
}
// sections
void *sections = 0;
if (section_count > 0 && section_table_foff + section_count*section_size <= data.size){
sections = data.str + section_table_foff;
}
// segments
void *segments = 0;
if (segment_count > 0 && segment_table_foff + segment_count*segment_size <= data.size){
segments = data.str + segment_table_foff;
}
// string table
U8 *section_strtable_first = 0;
U8 *section_strtable_opl = 0;
{
U32 index = 0;
if (string_section_index != ELF_SectionIndex_UNDEF &&
string_section_index != ELF_SectionIndex_XINDEX){
index = string_section_index;
}
else if (string_section_index == ELF_SectionIndex_XINDEX){
switch (elf_class){
default:break;
case ELF_Class_32: index = ((ELF_Section32*)sections)->link; break;
case ELF_Class_64: index = ((ELF_Section64*)sections)->link; break;
}
}
if (index > 0){
U64 offset = 0;
U64 size = 0;
switch (elf_class){
default:break;
case ELF_Class_32:
{
offset = ((ELF_Section32*)sections)[index].offset;
size = ((ELF_Section32*)sections)[index].size;
}break;
case ELF_Class_64:
{
offset = ((ELF_Section64*)sections)[index].offset;
size = ((ELF_Section64*)sections)[index].size;
}break;
}
if (offset < data.size && offset + size < data.size){
section_strtable_first = data.str + offset;
section_strtable_opl = data.str + offset + size;
}
}
}
// find symtab & dynsym sections
void *symbols[ELFP_SYMBOL_TABLE_COUNT] = {0};
U32 symbol_count[ELFP_SYMBOL_TABLE_COUNT] = {0};
U8 *symbol_strtable_first[ELFP_SYMBOL_TABLE_COUNT] = {0};
U8 *symbol_strtable_opl[ELFP_SYMBOL_TABLE_COUNT] = {0};
if (sections != 0){
for (U32 i = 0; i < section_count; i += 1){
ELF_SectionType type = 0;
U64 foff = 0;
U64 opl = 0;
switch (elf_class){
default:break;
case ELF_Class_32: {
ELF_Section32 *sec32 = (ELF_Section32*)sections + i;
type = sec32->type;
foff = sec32->offset;
opl = foff + sec32->size;
}break;
case ELF_Class_64: {
ELF_Section64 *sec64 = (ELF_Section64*)sections + i;
type = sec64->type;
foff = sec64->offset;
opl = foff + sec64->size;
}break;
}
U32 idx = ELFP_SYMBOL_TABLE_COUNT;
switch (type){
case ELF_SectionType_SYMTAB: idx = ELFP_SYMBOL_TABLE_symtab; break;
case ELF_SectionType_DYNSYM: idx = ELFP_SYMBOL_TABLE_dynsym; break;
}
if (idx < ELFP_SYMBOL_TABLE_COUNT &&
foff < data.size && opl < data.size){
U32 link = 0;
//U32 info = 0;
U32 count = 0;
switch (elf_class){
default:break;
case ELF_Class_32: {
ELF_Section32 *sec32 = (ELF_Section32*)sections + i;
link = sec32->link;
//info = sec32->info;
count = sec32->size/sizeof(ELF_Symbol32);
}break;
case ELF_Class_64: {
ELF_Section64 *sec64 = (ELF_Section64*)sections + i;
link = sec64->link;
//info = sec64->info;
count = sec64->size/sizeof(ELF_Symbol64);
}break;
}
symbols[idx] = data.str + foff;
symbol_count[idx] = count;
if (link < section_count){
U64 strtable_off = 0;
U64 strtable_size = 0;
switch (elf_class){
default:break;
case ELF_Class_32: {
ELF_Section32 *sec32 = (ELF_Section32*)sections + link;
strtable_off = sec32->offset;
strtable_size = sec32->size;
}break;
case ELF_Class_64: {
ELF_Section64 *sec64 = (ELF_Section64*)sections + link;
strtable_off = sec64->offset;
strtable_size = sec64->size;
}break;
}
if (strtable_off < data.size &&
strtable_off + strtable_size < data.size){
symbol_strtable_first[idx] = data.str + strtable_off;
symbol_strtable_opl[idx] = data.str + strtable_off + strtable_size;
}
}
}
}
}
// fill result
ELF_Parse *elf = 0;
if (header != 0){
elf = push_array(arena, ELF_Parse, 1);
elf->elf_class = elf_class;
elf->encoding = elf_encoding;
elf->section_count = section_count;
elf->segment_count = segment_count;
elf->header = header;
elf->size = data.size;
elf->sections = sections;
elf->segments = segments;
elf->section_strtable_first = section_strtable_first;
elf->section_strtable_opl = section_strtable_opl;
MemoryCopyArray(elf->symbols, symbols);
MemoryCopyArray(elf->symbol_count, symbol_count);
MemoryCopyArray(elf->symbol_strtable_first, symbol_strtable_first);
MemoryCopyArray(elf->symbol_strtable_opl, symbol_strtable_opl);
}
return(elf);
}
MR4TH_SYMBOL void
elfp_header_read(ELF_Parse *elf, ELF_Header64 *out){
if (elf->header != 0){
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
elf_header64_from_header32(out, (ELF_Header32*)elf->header, elf->encoding);
}break;
case ELF_Class_64: {
elf_header64_from_header64(out, (ELF_Header64*)elf->header, elf->encoding);
}break;
}
}
}
MR4TH_SYMBOL U32
elfp_section_count(ELF_Parse *elf){
U32 result = elf->section_count;
return(result);
}
MR4TH_SYMBOL void
elfp_section_read(ELF_Parse *elf, U32 idx, ELF_Section64 *out){
if (elf->sections != 0 && idx < elf->section_count){
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
elf_section64_from_section32(out, (ELF_Section32*)elf->sections + idx, elf->encoding);
}break;
case ELF_Class_64: {
elf_section64_from_section64(out, (ELF_Section64*)elf->sections + idx, elf->encoding);
}break;
}
}
}
MR4TH_SYMBOL String8
elfp_section_name(ELF_Parse *elf, U32 idx){
String8 result = {0};
if (elf->sections != 0 && idx < elf->section_count){
U32 name = 0;
switch (elf->elf_class){
default:break;
case ELF_Class_32: name = ((ELF_Section32*)elf->sections)[idx].name; break;
case ELF_Class_64: name = ((ELF_Section64*)elf->sections)[idx].name; break;
}
result = str8_cstring_capped(elf->section_strtable_first + name,
elf->section_strtable_opl);
}
return(result);
}
MR4TH_SYMBOL U32
elfp_segment_count(ELF_Parse *elf){
U32 result = elf->segment_count;
return(result);
}
MR4TH_SYMBOL void
elfp_segment_read(ELF_Parse *elf, U32 idx, ELF_Segment64 *out){
if (elf->segments != 0 && idx < elf->segment_count){
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
elf_segment64_from_segment32(out, (ELF_Segment32*)elf->segments + idx, elf->encoding);
}break;
case ELF_Class_64: {
elf_segment64_from_segment64(out, (ELF_Segment64*)elf->segments + idx, elf->encoding);
}break;
}
}
}
MR4TH_SYMBOL U32
elfp_symbol_count(ELF_Parse *elf, U32 table){
U32 result = 0;
if (table < ELFP_SYMBOL_TABLE_COUNT){
result = elf->symbol_count[table];
}
return(result);
}
MR4TH_SYMBOL void
elfp_symbol_read(ELF_Parse *elf, U32 table, U32 idx, ELF_Symbol64 *out){
if (table < ELFP_SYMBOL_TABLE_COUNT){
void *symbols = elf->symbols[table];
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
elf_symbol64_from_symbol32(out, (ELF_Symbol32*)symbols + idx, elf->encoding);
}break;
case ELF_Class_64: {
elf_symbol64_from_symbol64(out, (ELF_Symbol64*)symbols + idx, elf->encoding);
}break;
}
}
}
MR4TH_SYMBOL String8
elfp_symbol_name(ELF_Parse *elf, U32 table, U32 idx){
String8 result = {0};
if (table < ELFP_SYMBOL_TABLE_COUNT){
void *s = elf->symbols[table];
U8 *string_table_first = elf->symbol_strtable_first[table];
U8 *string_table_opl = elf->symbol_strtable_opl[table];
U32 name = 0;
switch (elf->elf_class){
default:break;
case ELF_Class_32: name = ((ELF_Symbol32*)s)[idx].name; break;
case ELF_Class_64: name = ((ELF_Symbol64*)s)[idx].name; break;
}
if (string_table_first != 0){
result = str8_cstring_capped(string_table_first + name,
string_table_opl);
}
}
return(result);
}
MR4TH_SYMBOL U32
elfp_relocs_count(ELF_Parse *elf, U32 secidx){
U32 result = 0;
if (elf->sections != 0 && secidx < elf->section_count){
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
ELF_Section32 *sec32 = ((ELF_Section32*)elf->sections) + secidx;
switch (sec32->type){
case ELF_SectionType_REL:
result = sec32->size/sizeof(ELF_Relocation32); break;
case ELF_SectionType_RELA:
result = sec32->size/sizeof(ELF_RelocationAdd32); break;
}
}break;
case ELF_Class_64: {
ELF_Section64 *sec64 = ((ELF_Section64*)elf->sections) + secidx;
switch (sec64->type){
case ELF_SectionType_REL:
result = sec64->size/sizeof(ELF_Relocation64); break;
case ELF_SectionType_RELA:
result = sec64->size/sizeof(ELF_RelocationAdd64); break;
}
}break;
}
}
return(result);
}
MR4TH_SYMBOL void
elfp_relocs_read(ELF_Parse *elf, U32 secidx, U32 relocidx, ELF_RelocationAdd64 *out){
if (elf->sections != 0 && secidx < elf->section_count){
switch (elf->elf_class){
default:break;
case ELF_Class_32: {
ELF_Section32 *sec32 = ((ELF_Section32*)elf->sections) + secidx;
U64 opl = ClampTop(sec32->offset + sec32->size, elf->size);
U64 size = opl - sec32->offset;
switch (sec32->type){
case ELF_SectionType_REL: {
ELF_Relocation32 *relocs = (ELF_Relocation32*)((U8*)elf->header + sec32->offset);
U32 count = sec32->size/sizeof(*relocs);
if (relocidx < count){
elf_reloca64_from_reloc32(out, relocs + relocidx, elf->encoding);
}
}break;
case ELF_SectionType_RELA: {
ELF_RelocationAdd32 *relocs = (ELF_RelocationAdd32*)((U8*)elf->header + sec32->offset);
U32 count = sec32->size/sizeof(*relocs);
if (relocidx < count){
elf_reloca64_from_reloca32(out, relocs + relocidx, elf->encoding);
}
}break;
}
}break;
case ELF_Class_64: {
ELF_Section64 *sec64 = ((ELF_Section64*)elf->sections) + secidx;
U64 opl = ClampTop(sec64->offset + sec64->size, elf->size);
U64 size = opl - sec64->offset;
switch (sec64->type){
case ELF_SectionType_REL: {
ELF_Relocation64 *relocs = (ELF_Relocation64*)((U8*)elf->header + sec64->offset);
U32 count = sec64->size/sizeof(*relocs);
if (relocidx < count){
elf_reloca64_from_reloc64(out, relocs + relocidx, elf->encoding);
}
}break;
case ELF_SectionType_RELA: {
ELF_RelocationAdd64 *relocs = (ELF_RelocationAdd64*)((U8*)elf->header + sec64->offset);
U32 count = sec64->size/sizeof(*relocs);
if (relocidx < count){
elf_reloca64_from_reloca64(out, relocs + relocidx, elf->encoding);
}
}break;
}
}break;
}
}
}

View File

@ -0,0 +1,49 @@
#ifndef MR4TH_ELF_PARSE_H
#define MR4TH_ELF_PARSE_H
////////////////////////////////
// Elf Parse Types
#define ELFP_SYMBOL_TABLE_symtab 0
#define ELFP_SYMBOL_TABLE_dynsym 1
#define ELFP_SYMBOL_TABLE_COUNT 2
typedef struct ELF_Parse{
ELF_Class elf_class;
ELF_Encoding encoding;
U32 section_count;
U32 segment_count;
void *header;
U64 size;
void *sections;
void *segments;
U8 *section_strtable_first;
U8 *section_strtable_opl;
void *symbols[ELFP_SYMBOL_TABLE_COUNT];
U32 symbol_count[ELFP_SYMBOL_TABLE_COUNT];
U8 *symbol_strtable_first[ELFP_SYMBOL_TABLE_COUNT];
U8 *symbol_strtable_opl[ELFP_SYMBOL_TABLE_COUNT];
} ELF_Parse;
////////////////////////////////
// Elf Parse Functions
MR4TH_SYMBOL ELF_Parse* elfp_begin(Arena *arena, String8 data);
MR4TH_SYMBOL void elfp_header_read(ELF_Parse *elf, ELF_Header64 *out);
MR4TH_SYMBOL U32 elfp_section_count(ELF_Parse *elf);
MR4TH_SYMBOL void elfp_section_read(ELF_Parse *elf, U32 idx, ELF_Section64 *out);
MR4TH_SYMBOL String8 elfp_section_name(ELF_Parse *elf, U32 idx);
MR4TH_SYMBOL U32 elfp_segment_count(ELF_Parse *elf);
MR4TH_SYMBOL void elfp_segment_read(ELF_Parse *elf, U32 idx, ELF_Segment64 *out);
MR4TH_SYMBOL U32 elfp_symbol_count(ELF_Parse *elf, U32 table);
MR4TH_SYMBOL void elfp_symbol_read(ELF_Parse *elf, U32 table, U32 idx, ELF_Symbol64 *out);
MR4TH_SYMBOL String8 elfp_symbol_name(ELF_Parse *elf, U32 table, U32 idx);
MR4TH_SYMBOL U32 elfp_relocs_count(ELF_Parse *elf, U32 secidx);
MR4TH_SYMBOL void elfp_relocs_read(ELF_Parse *elf, U32 secidx, U32 relocidx, ELF_RelocationAdd64 *out);
#endif //MR4TH_ELF_PARSE_H

91
src/symbol_set.c Normal file
View File

@ -0,0 +1,91 @@
/***********************************************************
** symbol_set - A public domain C modifier library
** by Allen Webster, "Mr. 4th", allenw@mr4th.com
**
** No warranty implied; use at your own risk
**
** Read symbol_set.intro.h to get started.
*/
#if SY__OS_WINDOWS
#pragma pack(push,1)
#define SY__DOS_MAGIC 0x5A4D
typedef struct Sy__DosHeader{
Sy_U16 magic;
Sy_U16 last_page_size;
Sy_U16 page_count;
Sy_U16 reloc_count;
Sy_U16 paragraph_header_size;
Sy_U16 min_paragraph;
Sy_U16 max_paragraph;
Sy_U16 init_ss;
Sy_U16 init_sp;
Sy_U16 checksum;
Sy_U16 init_ip;
Sy_U16 init_cs;
Sy_U16 reloc_table_file_off;
Sy_U16 overlay_number;
Sy_U16 reserved[4];
Sy_U16 oem_id;
Sy_U16 oem_info;
Sy_U16 reserved2[10];
Sy_U32 coff_offset;
} Sy__DosHeader;
typedef struct Sy__CoffHeader{
Sy_U16 machine_type;
Sy_U16 section_count;
Sy_U32 time_stamp;
Sy_U32 symbol_table_foff;
Sy_U32 symbol_count;
Sy_U16 optional_header_size;
Sy_U16 flags;
} Sy__CoffHeader;
typedef struct Sy_CoffSection{
Sy_U8 name[8];
Sy_U32 vsize;
Sy_U32 voff;
Sy_U32 fsize;
Sy_U32 foff;
Sy_U32 relocations_foff;
Sy_U32 line_numbers_foff;
Sy_U16 relocation_count;
Sy_U16 line_number_count;
Sy_U32 flags;
} Sy_CoffSection;
#pragma pack(pop)
void
sy__section_init(char *name, Sy_U32 name_size, void **first_out, void **opl_out){
if (name_size <= 8){
extern Sy_U8 __ImageBase[];
Sy_U8 *base = __ImageBase;
Sy__DosHeader *dos = (Sy__DosHeader*)base;
if (dos_header->magic == SY__DOS_MAGIC){
Sy__CoffHeader *coff = (Sy__CoffHeader*)(base + dos->coff_offset);
Sy_U32 sections_offset = (dos->coff_offset + sizeof(*coff) +
coff->optional_header_size);
Sy_U32 section_count = coff->section_count;
Sy_CoffSection *section = (Sy_CoffSection*)(base + sections_offset);
for (Sy_U32 i = 0; i < section_count; i += 1, section += 1){
int match = 1;
for (Sy_U32 j = 0; j < 8; j += 1){
if (name[j] != section->name[j]){
match = 0;
break;
}
if (name[j] == 0){
break;
}
}
if (match){
*first_out = base + section->voff;
*opl_out = base + section->voff + section->vsize;
break;
}
}
}
}
}
#endif

View File

@ -1,13 +1,31 @@
static U64 SymbolCount(SYMBOL_SET_DEFINE) = 0;
static SYMBOL__TYPE(SYMBOL_SET_DEFINE) * SymbolBasePtr(SYMBOL_SET_DEFINE) = 0;
static SYMBOL__TYPE(SYMBOL_SET_DEFINE) SYMBOL__SYM(SYMBOL_SET_DEFINE,0);
#if SY__OS_LINUX
int spider;
extern SyType(SYMBOL_SET_DEFINE) SY__FIRST(SYMBOL_SET_DEFINE);
extern SyType(SYMBOL_SET_DEFINE) SY__OPL(SYMBOL_SET_DEFINE);
// (these symbols are resolved in the linker script)
#elif SY__OS_WINDOWS
#if COMPILER_CL
# pragma SYMBOL__CL_PRAGMA
# pragma section(SY__GLUE(SYMBOL_SET_DEFINE,_section),read,write)
#endif
BEFORE_MAIN(){
void *image = os_this_image();
RangePtr range = self_img_get_section(image, str8_lit(GLUE(SYMBOL_SET_DEFINE,_section)));
SymbolCount(SYMBOL_SET_DEFINE) = (range.opl - range.first)/sizeof(SYMBOL__TYPE(SYMBOL_SET_DEFINE));
SymbolBasePtr(SYMBOL_SET_DEFINE) = (SYMBOL__TYPE(SYMBOL_SET_DEFINE)*)(range.first);
SyType(SYMBOL_SET_DEFINE) *SY__FIRST(SYMBOL_SET_DEFINE) = 0;
SyType(SYMBOL_SET_DEFINE) *SY__OPL(SYMBOL_SET_DEFINE) = 0;
SY__BEFORE_MAIN(SY__GLUE(SYMBOL_SET_DEFINE,__init)){
int size = sizeof(SY__GLUE(SYMBOL_SET_DEFINE,_section)) - 1;
void *first = 0;
void *opl = 0;
sy__section_init(SY__GLUE(SYMBOL_SET_DEFINE,_section), size,
(void**)&SY__FIRST(SYMBOL_SET_DEFINE),
(void**)&SY__OPL(SYMBOL_SET_DEFINE));
}
#else
# error symbol_set.define not implemented for this OS
#endif
#undef SYMBOL_SET_DEFINE

View File

@ -1,78 +1,308 @@
/*
** Symbol Set
/***********************************************************
** symbol_set - A public domain C modifier library
** by Allen Webster, "Mr. 4th", allenw@mr4th.com
**
** No warranty implied; use at your own risk
**
** Read symbol_set.intro.h to get started.
*/
#ifndef SYMBOL_SET_H
#define SYMBOL_SET_H
////////////////////////////////
// Copy-Pastable
#if 0
/*********************
** Context Cracking **
*********************/
// To define a Symbol Set
#define SYMBOL_SET_DEFINE example_name
#define example_name_Type ExampleType
#define example_name_section ".exmpl"
#include "symbol_set.define.h"
// Common wrappers to put around a Symbol Set (after defining it)
#define EXAMPLE_ID(N) SymbolID(example_name, N)
#define EXAMPLE_RAW(N) SymbolRaw(example_name, N)
#define EXAMPLE_DECL(N) SymbolDeclare(example_name, N)
/* untangle compiler, os, & architecture */
#if defined(__clang__)
# define SY__COMPILER_CLANG 1
# if defined(_WIN32)
# define SY__OS_WINDOWS 1
# elif defined(__gnu_linux__)
# define SY__OS_LINUX 1
# elif defined(__APPLE__) && defined(__MACH__)
# define SY__OS_MAC 1
# else
# error missing OS detection
# endif
////////////////////////////////
// Symbol Set System
# if defined(__amd64__)
# define SY__ARCH_X64 1
# elif defined(__i386__)
# define SY__ARCH_X86 1
# elif defined(__arm__)
# define SY__ARCH_ARM 1
# elif defined(__aarch64__)
# define SY__ARCH_ARM64 1
# else
# error missing ARCH detection
# endif
// Symbol Set key terms:
// "count" - the total number of symbols in this set
// "baseptr" - the pointer to the base of the array of symbol data
// "oplptr" - the pointer to the spot one past the last element of the array
// "id" - the 1-based index of the symbol
// id=0 stands for the special 'nil' case
// id values in the range [1,count] stand for a symbol in the set
// "metadata" - a pointer to the slot in the array for this symbol
// "raw" - address of the metadata as an integer
#elif defined(_MSC_VER)
# define SY__COMPILER_CL 1
// user interface
# if defined(_WIN32)
# define SY__OS_WINDOWS 1
# else
# error missing OS detection
# endif
#define SymbolDeclare(E,N) \
SECTION(E##_section) extern SYMBOL__TYPE(E) SYMBOL__SYM(E,N)
# if defined(_M_AMD64)
# define SY__ARCH_X64 1
# elif defined(_M_I86)
# define SY__ARCH_X86 1
# elif defined(_M_ARM)
# define SY__ARCH_ARM 1
# else
# error missing ARCH detection
# endif
#define SymbolDefine(E,N) DO_NOT_ELIMINATE(SYMBOL__SYM(E,N)) SymbolDeclare(E,N)
#define SymbolDefineNameless(E) SymbolDefine(E,GLUE(auto,__COUNTER__))
#elif defined(__GNUC__)
# define SY__COMPILER_GCC 1
#define SymbolCount(E) GLUE(E, _count)
#define SymbolBasePtr(E) GLUE(E, _baseptr)
#define SymbolOplPtr(E) (SymbolBasePtr(E) + SymbolCount(E))
# if defined(_WIN32)
# define SY__OS_WINDOWS 1
# elif defined(__gnu_linux__)
# define SY__OS_LINUX 1
# elif defined(__APPLE__) && defined(__MACH__)
# define SY__OS_MAC 1
# else
# error missing OS detection
# endif
#define SymbolMetadata(E,N) (&SYMBOL__SYM(E,N))
#define SymbolID(E,N) SymbolIDFromMetadata(E, SymbolMetadata(E,N))
# if defined(__amd64__)
# define SY__ARCH_X64 1
# elif defined(__i386__)
# define SY__ARCH_X86 1
# elif defined(__arm__)
# define SY__ARCH_ARM 1
# elif defined(__aarch64__)
# define SY__ARCH_ARM64 1
# else
# error missing ARCH detection
# endif
#define SymbolIDFromMetadata(E,ptr) \
((SymbolBasePtr(E) <= (ptr) && (ptr) < SymbolOplPtr(E))? \
(U32)(1 + ((ptr) - SymbolBasePtr(E))):0)
#else
# error no context cracking for this compiler
#endif
#define SymbolMetadataFromID(E,id) \
((1 <= (id) && (id) <= SymbolCount(E))?\
(SymbolBasePtr(E) + (id) - 1):(&SYMBOL__SYM(E,0)))
#if !defined(SY__COMPILER_CL)
# define SY__COMPILER_CL 0
#endif
#if !defined(SY__COMPILER_CLANG)
# define SY__COMPILER_CLANG 0
#endif
#if !defined(SY__COMPILER_GCC)
# define SY__COMPILER_GCC 0
#endif
#if !defined(SY__OS_WINDOWS)
# define SY__OS_WINDOWS 0
#endif
#if !defined(SY__OS_LINUX)
# define SY__OS_LINUX 0
#endif
#if !defined(SY__OS_MAC)
# define SY__OS_MAC 0
#endif
#if !defined(SY__ARCH_X64)
# define SY__ARCH_X64 0
#endif
#if !defined(SY__ARCH_X86)
# define SY__ARCH_X86 0
#endif
#if !defined(SY__ARCH_ARM)
# define SY__ARCH_ARM 0
#endif
#if !defined(SY__ARCH_ARM64)
# define SY__ARCH_ARM64 0
#endif
#define SymbolRaw(E,N) IntFromPtr(SymbolMetadata(E,N))
#define SymbolIDFromRaw(E,raw) SymbolIDFromMetadata(E,(SYMBOL__TYPE(E)*)(PtrFromInt(raw)))
#define SymbolRawFromID(E,id) IntFromPtr(SymbolMetadataFromID(E,id))
/* language */
#if defined(__cplusplus)
# define SY__LANG_CXX 1
#else
# define SY__LANG_C 1
#endif
// internal
#if !defined(SY__LANG_CXX)
# define SY__LANG_CXX 0
#endif
#if !defined(SY__LANG_C)
# define SY__LANG_C 0
#endif
#define SYMBOL__TYPE(E) GLUE(E,_Type)
#define SYMBOL__SYM(E,N) GLUE(E, GLUE(__, N))
/**********
** Types **
**********/
#define SYMBOL__RAW_BASE(E) IntFromPtr(SymbolBasePtr(E))
#define SYMBOL__RAW_OPL(E) (SYMBOL__RAW_BASE(E) + SymbolCount(E)*sizeof(SYMBOL__TYPE(E)))
#include <stdint.h>
#define SYMBOL__BEFORE_MAIN_NAME GLUE(SYMBOL_SET_DEFINE,__init)
#define SYMBOL__CL_PRAGMA section(GLUE(SYMBOL_SET_DEFINE,_section),read,write)
typedef uint8_t Sy_U8;
typedef uint16_t Sy_U16;
typedef uint32_t Sy_U32;
typedef uint64_t Sy_U64;
#if SY__ARCH_X64 || SY__ARCH_ARM64
typedef Sy_U64 Sy_UAddress;
#else
typedef Sy_U32 Sy_UAddress;
#endif
/******************
** Macro Helpers **
******************/
#define SY__GLUE_(a,b) a##b
#define SY__GLUE(a,b) SY__GLUE_(a,b)
#define SY__STRIFY_(s) #s
#define SY__STRIFY(s) SY__STRIFY_(s)
/*****************
** Align Helper **
*****************/
#define SY__ALIGN_TO_POW2(x,a) (((x) + (a) - 1)&~((a) - 1))
/*******************
** Section Macros **
*******************/
/* IMPORTANT! On CL compiler add: #pragma section(<section>,read,write) */
#if SY__COMPILER_CLANG || SY__COMPILER_GCC
# if SY__OS_MAC
# define SY__SECTION_READONLY(N) __attribute__((__section__("__TEXT,"N))) const
# define SY__SECTION_READWRITE(N) __attribute__((__section__("__READ,"N)))
# else
# define SY__SECTION_READONLY(N) __attribute__((__section__(N))) const
# define SY__SECTION_READWRITE(N) __attribute__((__section__(N)))
# endif
#elif COMPILER_CL
# define SY__SECTION_READONLY(N) __declspec(allocate(N)) const
# define SY__SECTION_READWRITE(N) __declspec(allocate(N))
#else
# error SY__SECTION_* not defined for this compiler/OS
#endif
/****************************
** Do Not Mangle Qualifier **
****************************/
#if SY__LANG_CXX
# define SY__DO_NOT_MANGLE extern "C"
#else
# define SY__DO_NOT_MANGLE
#endif
/*******************************
** Do Not Eliminate Qualifier **
*******************************/
#if SY__OS_WINDOWS
# define SY__DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N))
# define SY__DO_NOT_ELIMINATE__S1(N) DO_NOT_ELIMINATE__S0(N)
# define SY__DO_NOT_ELIMINATE(N) DO_NOT_ELIMINATE__S1(N)
#else
# define SY__DO_NOT_ELIMINATE(N)
#endif
/********************
** Align Qualifier **
********************/
#if SY__COMPILER_CL
# define SY__ALIGN_VAR(z) __declspec(align(z))
#elif SY__COMPILER_CLANG || SY__COMPILER_GCC
# define SY__ALIGN_VAR(z) __attribute__((__aligned__(z)))
#else
# error SY__ALIGN not defined for this compiler
#endif
/*****************
** Before Mains **
*****************/
#if SY__OS_WINDOWS
# pragma section(".CRT$XCU", read)
# define SY__BEFORE_MAIN__(n) \
static void n(void); \
SY__SECTIONREADWRITE(".CRT$XCU") \
SY__DO_NOT_ELIMINATE(n##__) \
SY__DO_NOT_MANGLE void (*n##__)(void); \
void (*n##__)(void) = n; \
static void n(void)
#elif SY__OS_LINUX
# define SY__BEFORE_MAIN__(n) __attribute__((constructor)) static void n(void)
#else
# error SY__BEFORE_MAIN__ missing for this OS
#endif
#define SY__BEFORE_MAIN_(n) SY__BEFORE_MAIN__(n)
#define SY__BEFORE_MAIN(n) SY__BEFORE_MAIN_(n)
/*************************************
** Symbol Set Programming Interface **
*************************************/
#define SyType(S) SY__GLUE(S,_Type)
#define SyDeclare(S,N) SY__ALIGN_VAR(8) SY__SECTION_READWRITE(S##_section) SyType(S) SY__SYMBOL(S,N)
#define SyDefine(S,N) SY__DO_NOT_ELIMINATE(SY__SYMBOL(S,N)) SyDeclare(S,N)
#define SyDefineUnnamed(S) SyDefine(S,SY__GLUE(unnamed,__COUNTER__))
#define SyAddress(S,N) (&SY__SYMBOL(S,N))
#define SyID(S,N) SyIDFromAddress_Unchecked(S,SyAddress(S,N))
#define SyFlag(S,N) (1llu << SyID(S,N))
#define SyStride(S) SY__ALIGN_TO_POW2(sizeof(SyType(S)), 8)
#if SY__OS_WINDOWS
# define SyFirst(S) SY__FIRST(S)
# define SyOpl(S) SY__OPL(S)
#elif SY__OS_LINUX
# define SyFirst(S) (&SY__FIRST(S))
# define SyOpl(S) (&SY__OPL(S))
#else
# error missing implementation set locator for this OS
#endif
#define SyCount(S) (((Sy_U8*)SyOpl(S) - (Sy_U8*)SyFirst(S))/SyStride(S))
#define SyNext(S,addr) (SyType(S)*)((Sy_U8*)addr + SyStride(S))
#define SyEach(S,var) SyType(S)*var=SyFirst(S); var<SyOpl(S); var=SyNext(S,var)
#define SyIDFromAddress(S,addr) (SyAddressCheck(S,addr)?SyIDFromAddress_Unchecked(S,addr):0)
#define SyAddressFromID(S,id) (SyIDCheck(S,id)?SyAddressFromID_Unchecked(S,id):0)
#define SyAddressCheck(S,addr) (SyFirst(S) <= (addr) && (addr) <= SyOpl(S))
#define SyIDCheck(S,id) (1 <= (id) && (id) <= SyCount(S))
#define SyIDFromAddress_Unchecked(S,addr) ((Sy_U32)(1 + ((Sy_U8*)(addr) - (Sy_U8*)SyFirst(S))/SyStride(S)))
#define SyAddressFromID_Unchecked(S,id) ((SyType(S)*)((Sy_U8*)SyFirst(S) + ((id) - 1)*SyStride(S)))
#define SyRaw(S,N) (Sy_UAddress)(SyAddress(S,N))
#define SyIDFromRaw(S,raw) SyIDFromAddress(S,(SyType(S)*)(raw))
#define SyIDFromRaw_Unchecked(S,raw) SyIDFromAddress_Unchecked(S,(SyType(S)*)(raw))
#endif //SYMBOL_SET_H
/*************
** Internal **
*************/
#define SY__SYMBOL(S,N) SY__GLUE(S,SY__GLUE(__,N))
#define SY__FIRST_(S) SY__GLUE(syfirst__, S##_marker)
#define SY__OPL_(S) SY__GLUE(syopl__, S##_marker)
#define SY__FIRST(S) SY__FIRST_(S)
#define SY__OPL(S) SY__OPL_(S)
#if SY__OS_WINDOWS
void sy__section_init(char *name, Sy_U32 name_size, void **first_out, void **opl_out);
#endif
#endif /* SYMBOL_SET_H */

35
src/symbol_set.intro.h Normal file
View File

@ -0,0 +1,35 @@
/****** Define One Symbol Set *******/
#if 0
/* To define a symbol set, copy-paste the block below and then:
** Replace ZZZ with a name for the symbol set.
** Replace Typezz with the type of the symbol set.
** Replace secz with a unique name for the data section of the symbol set.
** IMPORTANT NOTE: you only get 4 characters for the section name if you
** want to port to Windows.
*/
#define SYMBOL_SET_DEFINE ZZZ
#define ZZZ_Type Typezz
#define ZZZ_section ".sy.secz"
#define ZZZ_marker secz
#include "symbol_set.define.h"
#endif
/****** Define One Symbol Set *******/
/****** Common Helpers For Defining Symbols *******/
#if 0
/* Defining a basic struct with a NAME */
#define ZZZ_DEF(N,...) SyDefine(ZZZ, NAME) = { ... }
/* Defining a basic struct without a name */
#define ZZZ_DEF(...) SyDefineNameless(ZZZ, NAME) = { ... }
#endif
/****** Common Helpers For Defining Symbols *******/

101
src/symbol_set.ld_meta.c Normal file
View File

@ -0,0 +1,101 @@
/*
** Symbol Set Link Script Generator for ld
*/
#include "mr4th_base.h"
#include "mr4th_cmdln.h"
#include "mr4th_elf.h"
#include "mr4th_elf.parse.h"
#include "mr4th_base.c"
#include "mr4th_cmdln.c"
#include "mr4th_elf.c"
#include "mr4th_elf.parse.c"
////////////////////////////////
// Entry Point
int main(int argc, char **argv){
os_main_init(argc, argv);
Arena *arena = arena_alloc();
// arguments
String8List command_line_args = os_command_line_arguments();
CMDLN *cmdln = cmdln_from_args(arena, &command_line_args);
String8 output_file_name = cmdln_get_str8(cmdln, str8_lit("out"), 'o');
if (output_file_name.size == 0){
output_file_name = str8_lit("sy.ld");
}
// symbol set names
String8List symbol_set_names = {0};
BUFFER buckets;
buffer_alloc(&buckets, GB(64));
hash_buckets_init(&buckets, 512);
for (U32 input_idx = 0;; input_idx += 1){
// load input file
String8 input_file_name = cmdln_input_from_idx(cmdln, input_idx);
if (input_file_name.size == 0){
break;
}
String8 input_data = os_file_read(arena, input_file_name);
// parse
ELF_Parse *parse = elfp_begin(arena, input_data);
// insert symbol sets inot symbol_set_names
U32 section_count = elfp_section_count(parse);
for (U32 i = 0; i < section_count; i += 1){
String8 secname = elfp_section_name(parse, i);
if (secname.size >= 4 &&
str8_match(secname, str8_lit(".sy."), StringMatchFlag_PrefixMatch)){
String8 syname = str8_skip(secname, 4);
U64 hash = str8_hash(syname);
B32 match = 0;
for (HASH_Node *hash_node = hash_buckets_first(&buckets, hash);
hash_node != 0;
hash_node = hash_node->next){
if (hash_node->hash == hash){
String8Node *node = (String8Node*)PtrFromInt(hash_node->val);
if (str8_match(node->string, syname, 0)){
match = 1;
break;
}
}
}
if (!match){
str8_list_push(arena, &symbol_set_names, syname);
hash_buckets_expand(&buckets, symbol_set_names.node_count);
hash_buckets_insert(arena, &buckets, hash, IntFromPtr(symbol_set_names.last));
}
}
}
}
// print output linker script
STREAM *stream = stream_new();
stream_printf(stream,
"SECTIONS {\n"
" .sy : {\n");
for (String8Node *node = symbol_set_names.first;
node != 0; node = node->next){
stream_printf(stream, " syfirst__%S = .; *(.sy.%S); syopl__%S = .;\n",
&node->string, &node->string, &node->string);
}
stream_printf(stream,
" }\n"
"}\n"
"INSERT AFTER .data;\n");
os_file_write_stream(output_file_name, stream);
return(0);
}

View File

@ -62,17 +62,12 @@ Development:
Other Upgrade Research:
[ ] Could Symbol Sets syntax be organized in such a way that it's just a data
section and type wrapped in a macro?
[ ] Could Symbol Sets syntax be organized in such a way that it's just a
data section and type wrapped in a macro?
Support Tools:
[x] see data section size and layout info
[ ] dump binary as hex from a data section
[ ] see symbols inside data sections
[ ] see symbols by name
[ ] count of symbols in symbol set
[ ] display of string and integer data in symbol from symbol set
[ ] see symbols in symbol sets from object files
[ ] size of types