main
Allen Webster 2026-06-29 17:23:29 -07:00
commit 32ce56df78
14 changed files with 10480 additions and 89 deletions

5861
mr4th/mr4th_base.c Normal file

File diff suppressed because it is too large Load Diff

1891
mr4th/mr4th_base.h Normal file

File diff suppressed because it is too large Load Diff

294
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
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
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);
}

710
mr4th/mr4th_elf.h Normal file
View File

@ -0,0 +1,710 @@
#ifndef MR4TH_ELF_H
#define MR4TH_ELF_H
/*
** ELF total layout summary:
**
** TODO
*/
////////////////////////////////
// Types: ELF
// identification
#define ELF_NUM_IDENT 16
#define ELF_IdentificationIdx_XList(X)\
X(MAG0, 0)\
X(MAG1, 1)\
X(MAG2, 2)\
X(MAG3, 3)\
X(CLASS, 4)\
X(DATA, 5)\
X(VERSION, 6)\
X(OSABI, 7)\
X(ABIVERSION, 8)\
X(PAD0, 9)\
X(PAD1, 10)\
X(PAD2, 11)\
X(PAD3, 12)\
X(PAD4, 13)\
X(PAD5, 14)\
X(PAD6, 15)
typedef enum ELF_IdentificationIdx{
#define X(N,C) ELF_IdentificationIdx_##N = C,
ELF_IdentificationIdx_XList(X)
#undef X
} ELF_IdentificationIdx;
#define ELF_Magic_Byte0 0x7F
#define ELF_Magic_Byte1 'E'
#define ELF_Magic_Byte2 'L'
#define ELF_Magic_Byte3 'F'
// elf class
#define ELF_Class_XList(X)\
X(NONE, 0)\
X(32, 1)\
X(64, 2)
typedef enum ELF_Class{
#define X(N,C) ELF_Class_##N = C,
ELF_Class_XList(X)
#undef X
} ELF_Class;
// elf encoding
#define ELF_Encoding_XList(X)\
X(NONE, 0)\
X(2LSB, 1)\
X(2MSB, 2)
typedef enum ELF_Encoding{
#define X(N,C) ELF_Encoding_##N = C,
ELF_Encoding_XList(X)
#undef X
} ELF_Encoding;
// elf os/abi extension
#define ELF_OsAbiExtension_XList(X)\
X(NONE, 0)\
X(HPUX, 1)\
X(NETBSD, 2)\
X(GNU, 3)\
X(SOLARIS, 6)\
X(AIX, 7)\
X(IRIX, 8)\
X(FREEBSD, 9)\
X(TRU64, 10)\
X(MODESTO, 11)\
X(OPENBSD, 12)\
X(OPENVMS, 13)\
X(NSK, 14)\
X(AROS, 15)\
X(FENIXOS, 16)\
X(CLOUDABI, 17)\
X(OPENVOS, 18)
typedef enum ELF_OsAbiExtension{
#define X(N,C) ELF_OsAbiExtension_##N = C,
ELF_OsAbiExtension_XList(X)
#undef X
} ELF_OsAbiExtension;
// file type
#define ELF_FileType_XList(X)\
X(NONE, 0)\
X(REL, 1)\
X(EXEC, 2)\
X(DYN, 3)\
X(CORE, 4)\
X(LOOS, 0xfe00)\
X(HIOS, 0xfeff)\
X(LOPROC, 0xff00)\
X(HIPROC, 0xffff)
typedef U16 ELF_FileType;
enum{
#define X(N,C) ELF_FileType_##N = C,
ELF_FileType_XList(X)
#undef X
};
// machine type
#define ELF_MachineType_XList(X)\
X(NONE, 0)\
X(M32, 1)\
X(SPARC, 2)\
X(386, 3)\
X(68K, 4)\
X(88K, 5)\
X(IAMCU, 6)\
X(860, 7)\
X(MIPS, 8)\
X(S370, 9)\
X(MIPS_RS3_LE, 10)\
X(PARISC, 15)\
X(VPP500, 17)\
X(SPARC32PLUS, 18)\
X(960, 19)\
X(PPC, 20)\
X(PPC64, 21)\
X(S390, 22)\
X(SPU, 23)\
X(V800, 36)\
X(FR20, 37)\
X(RH32, 38)\
X(RCE, 39)\
X(ARM, 40)\
X(ALPHA, 41)\
X(SH, 42)\
X(SPARCV9, 43)\
X(TRICORE, 44)\
X(ARC, 45)\
X(H8_300, 300)\
X(H8S, 48)\
X(H8_500, 49)\
X(IA_64, 50)\
X(MIPS_X, 51)\
X(COLDFIRE, 52)\
X(68HC12, 53)\
X(MMA, 54)\
X(PCP, 55)\
X(NCPU, 56)\
X(NDR1, 57)\
X(STARCORE, 58)\
X(ME16, 59)\
X(ST100, 60)\
X(TINYJ, 61)\
X(X86_64, 62)\
X(PDSP, 63)\
X(PDP10, 64)\
X(PDP11, 65)\
X(FX66, 66)\
X(ST9PLUS, 67)\
X(ST7, 68)\
X(68HC16, 69)\
X(68HC11, 70)\
X(68HC08, 71)\
X(68HC05, 72)\
X(SVX, 73)\
X(ST19, 74)\
X(VAX, 75)\
X(CRIS, 76)\
X(JAVELIN, 77)\
X(FIREPATH, 78)\
X(ZSP, 79)\
X(MMIX, 80)\
X(HUANY, 81)\
X(PRISM, 82)\
X(AVR, 83)\
X(FR30, 84)\
X(D10V, 85)\
X(D30V, 86)\
X(V850, 87)\
X(M32R, 88)\
X(MN10300, 89)\
X(MN10200, 90)\
X(PJ, 91)\
X(OPENRISC, 92)\
X(ARC_COMPACT, 93)\
X(XTENSA, 94)\
X(VIDEOCORE, 95)\
X(TMM_GPP, 96)\
X(NS32K, 97)\
X(TPC, 98)\
X(SNP1K, 99)\
X(ST200, 100)\
X(IP2K, 101)\
X(MAX, 102)\
X(CR, 103)\
X(F2MC16, 104)\
X(MSP430, 105)\
X(BLACKFIN, 106)\
X(SE_C33, 107)\
X(SEP, 108)\
X(ARCA, 109)\
X(UNICORE, 110)\
X(EXCESS, 111)\
X(DXP, 112)\
X(ALTERA_NIOS2, 113)\
X(CRX, 114)\
X(XGATE, 115)\
X(C166, 116)\
X(M16C, 117)\
X(DSPIC30F, 118)\
X(CE, 119)\
X(M32C, 120)\
X(TSK3000, 131)\
X(RS08, 132)\
X(SHARC, 133)\
X(ECOG2, 134)\
X(SCORE7, 135)\
X(DSP24, 136)\
X(VIDEOCORE3, 137)\
X(LATTICEMICO32, 138)\
X(SE_C17, 139)\
X(TI_C6000, 140)\
X(TI_C2000, 141)\
X(TI_C5500, 142)\
X(TI_ARP32, 143)\
X(TI_PRU, 144)\
X(MMDSP_PLUS, 160)\
X(CYPRESS_M8C, 161)\
X(R32C, 162)\
X(TRIMEDIA, 163)\
X(QDSP6, 164)\
X(8051, 165)\
X(STXP7X, 166)\
X(NDS32, 167)\
X(ECOG1, 168)\
X(MAXQ30, 169)\
X(XIMO16, 170)\
X(MANIK, 171)\
X(CRAYNV2, 172)\
X(RX, 173)\
X(METAG, 174)\
X(MCST_ELBRUS, 175)\
X(ECOG16, 176)\
X(CR16, 177)\
X(ETPU, 178)\
X(SLE9X, 179)\
X(L10M, 180)\
X(K10M, 181)\
X(AARCH64, 183)\
X(AVR32, 185)\
X(STM8, 186)\
X(TILE64, 187)\
X(TILEPRO, 188)\
X(MICROBLAZE, 189)\
X(CUDA, 190)\
X(TILEGX, 191)\
X(CLOUDSHIELD, 192)\
X(COREA_1ST, 193)\
X(COREA_2ND, 194)\
X(ARC_COMPACT2, 195)\
X(OPEN8, 196)\
X(RL78, 197)\
X(VIDEOCORE5, 198)\
X(78KOR, 199)\
X(56800EX, 200)\
X(BA1, 201)\
X(BA2, 202)\
X(XCORE, 203)\
X(MCHP_PIC, 204)\
X(INTEL205, 205)\
X(INTEL206, 206)\
X(INTEL207, 207)\
X(INTEL208, 208)\
X(INTEL209, 209)\
X(KM32, 210)\
X(KMX32, 211)\
X(KMX16, 212)\
X(KMX8, 213)\
X(KVARC, 214)\
X(CDP, 215)\
X(COGE, 216)\
X(COOL, 217)\
X(NORC, 218)\
X(CSR_KALIMBA, 219)\
X(Z80, 220)\
X(VISIUM, 221)\
X(FT32, 222)\
X(MOXIE, 223)\
X(AMDGPU, 224)\
X(RISCV, 243)
typedef U16 ELF_MachineType;
enum{
#define X(N,C) ELF_MachineType_##N = C,
ELF_MachineType_XList(X)
#undef X
};
// elf header
typedef struct ELF_Header32{
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U32 entry;
U32 segment_table_foff;
U32 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
} ELF_Header32;
typedef struct ELF_Header64{
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U64 entry;
U64 segment_table_foff;
U64 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
} ELF_Header64;
// elf section type
#define ELF_SectionType_XList(X)\
X(NULL, 0)\
X(PROGBITS, 1)\
X(SYMTAB, 2)\
X(STRTAB, 3)\
X(RELA, 4)\
X(HASH, 5)\
X(DYNAMIC, 6)\
X(NOTE, 7)\
X(NOBITS, 8)\
X(REL, 9)\
X(SHLIB, 10)\
X(DYNSYM, 11)\
X(INIT_ARRAY, 14)\
X(FINI_ARRAY, 15)\
X(PREINIT_ARRAY, 16)\
X(GROUP, 17)\
X(SYMTAB_SHNDX, 18)\
X(LOOS, 0x60000000)\
X(HIOS, 0x6fffffff)\
X(LOPROC, 0x70000000)\
X(HIPROC, 0x7fffffff)\
X(LOUSER, 0x80000000)\
X(HIUSER, 0xffffffff)
typedef U32 ELF_SectionType;
enum{
#define X(N,C) ELF_SectionType_##N = C,
ELF_SectionType_XList(X)
#undef X
};
// elf section flags
#define ELF_SectionFlags_XList(X)\
X(WRITE, 0x1)\
X(ALLOC, 0x2)\
X(EXECINSTR, 0x4)\
X(MERGE, 0x10)\
X(STRINGS, 0x20)\
X(INFO_LINK, 0x40)\
X(LINK_ORDER, 0x80)\
X(OS_NONCONFORMING, 0x100)\
X(GROUP, 0x200)\
X(TLS, 0x400)\
X(COMPRESSED, 0x800)\
X(MASKOS, 0x0ff00000)\
X(MASKPROC, 0xf0000000)
enum{
#define X(N,C) ELF_SectionFlag_##N = C,
ELF_SectionFlags_XList(X)
#undef X
};
// elf section indexes
#define ELF_SectionIndex_XList(X)\
X(UNDEF, 0)\
X(LORESERVE, 0xff00)\
X(LOPROC, 0xff00)\
X(HIPROC, 0xff1f)\
X(LOOS, 0xff20)\
X(HIOS, 0xff3f)\
X(ABS, 0xfff1)\
X(COMMON, 0xfff2)\
X(XINDEX, 0xffff)\
X(HIRESERVE, 0xffff)
typedef enum ELF_SectionIndex{
#define X(N,C) ELF_SectionIndex_##N = C,
ELF_SectionIndex_XList(X)
#undef X
} ELF_SectionIndex;
// elf section
typedef struct ELF_Section32{
U32 name;
ELF_SectionType type;
U32 flags;
U32 addr;
U32 offset;
U32 size;
U32 link;
U32 info;
U32 addralign;
U32 entsize;
} ELF_Section32;
typedef struct ELF_Section64{
U32 name;
ELF_SectionType type;
U64 flags;
U64 addr;
U64 offset;
U64 size;
U32 link;
U32 info;
U64 addralign;
U64 entsize;
} ELF_Section64;
// elf compression type
#define ELF_CompressionType_XList(X)\
X(ZLIB, 1)\
X(LOOS, 0x60000000)\
X(HIOS, 0x6fffffff)\
X(LOPROC, 0x70000000)\
X(HIPROC, 0x7fffffff)
typedef enum ELF_CompressionType{
#define X(N,C) ELF_CompressionType_##N = C,
ELF_CompressionType_XList(X)
#undef X
} ELF_CompressionType;
// elf compression header
typedef struct ELF_CompressionHeader32{
ELF_CompressionType type;
U32 size;
U32 addralign;
} ELF_CompressionHeader32;
typedef struct ELF_CompressionHeader64{
ELF_CompressionType type;
U32 reserved;
U64 size;
U64 addralign;
} ELF_CompressionHeader64;
// elf section group flags
#define ELF_SectionGroupFlags_XList(X)\
X(COMDAT, 0x1)\
X(MASKOS, 0x0ff00000)\
X(MASKPROC, 0xf0000000)
typedef U32 ELF_SectionGroupFlags;
enum{
#define X(N,C) ELF_SectionGroupFlag_##N = C,
ELF_SectionGroupFlags_XList(X)
#undef X
};
// elf symbol
typedef struct ELF_Symbol32{
U32 name;
U32 value;
U32 size;
U8 info;
U8 other;
U16 section_index;
} ELF_Symbol32;
typedef struct ELF_Symbol64{
U32 name;
U8 info;
U8 other;
U16 section_index;
U64 value;
U64 size;
} ELF_Symbol64;
#define ELF_Symbol_BindFromInfo(inf) ((inf)>>4)
#define ELF_Symbol_TypeFromInfo(inf) ((inf)&0xF)
#define ELF_Symbol_InfoFromBindType(bin,typ) (((bin)<<4)|((type)&0xF))
#define ELF_Symbol_VisFromOther(oth) ((oth)&0x3)
#define ELF_Symbol_OtherFromVis(vis) (((vis)&0x3))
// elf symbol binding
#define ELF_SymbolBinding_XList(X)\
X(LOCAL, 0)\
X(GLOBAL, 1)\
X(WEAK, 2)\
X(LOOS, 10)\
X(HIOS, 12)\
X(LOPROC, 13)\
X(HIPROC, 15)
typedef enum ELF_SymbolBinding{
#define X(N,C) ELF_SymbolBinding_##N = C,
ELF_SymbolBinding_XList(X)
#undef X
} ELF_SymbolBinding;
// elf symbol types
#define ELF_SymbolType_XList(X)\
X(NOTYPE, 0)\
X(OBJECT, 1)\
X(FUNC, 2)\
X(SECTION, 3)\
X(FILE, 4)\
X(COMMON, 5)\
X(TLS, 6)\
X(LOOS, 10)\
X(HIOS, 12)\
X(LOPROC, 13)\
X(HIPROC, 15)
typedef enum ELF_SymbolType{
#define X(N,C) ELF_SymbolType_##N = C,
ELF_SymbolType_XList(X)
#undef X
} ELF_SymbolType;
// elf symbol visibility
#define ELF_SymbolVis_XList(X)\
X(DEFAULT, 0)\
X(INTERNAL, 1)\
X(HIDDEN, 2)\
X(PROTECTED, 3)
typedef enum ELF_SymbolVis{
#define X(N,C) ELF_SymbolVis_##N = C,
ELF_SymbolVis_XList(X)
#undef X
} ELF_SymbolVis;
// elf relocations
typedef struct ELF_Relocation32{
U32 offset;
U32 info;
} ELF_Relocation32;
typedef struct ELF_RelocationAdd32{
U32 offset;
U32 info;
S32 addend;
} ELF_RelocationAdd32;
typedef struct ELF_Relocation64{
U64 offset;
U64 info;
} ELF_Relocation64;
typedef struct ELF_RelocationAdd64{
U64 offset;
U64 info;
S64 addend;
} ELF_RelocationAdd64;
// elf segment type
#define ELF_SegmentType_XList(X)\
X(NULL, 0)\
X(LOAD, 1)\
X(DYNAMIC, 2)\
X(INTERP, 3)\
X(NOTE, 4)\
X(SHLIB, 5)\
X(PHDR, 6)\
X(TLS, 7)\
X(LOOS, 0x60000000)\
X(HIOS, 0x6fffffff)\
X(LOPROC, 0x70000000)\
X(HIPROC, 0x7fffffff)
typedef U32 ELF_SegmentType;
enum{
#define X(N,C) ELF_SegmentType_##N = C,
ELF_SegmentType_XList(X)
#undef X
};
// elf segment flags
#define ELF_SegmentFlags_XList(X)\
X(X, 0x1)\
X(W, 0x2)\
X(R, 0x4)\
X(MASKOS, 0x0ff00000)\
X(MASKPROC, 0xf0000000)\
typedef U32 ELF_SegmentFlags;
enum{
#define X(N,C) ELF_SegmentFlag_##N = C,
ELF_SegmentFlags_XList(X)
#undef X
};
// elf segment
typedef struct ELF_Segment32{
ELF_SegmentType type;
U32 offset;
U32 vaddr;
U32 paddr;
U32 file_size;
U32 memory_size;
ELF_SegmentFlags flags;
U32 align;
} ELF_Segment32;
typedef struct ELF_Segment64{
ELF_SegmentType type;
ELF_SegmentFlags flags;
U64 offset;
U64 vaddr;
U64 paddr;
U64 file_size;
U64 memory_size;
U64 align;
} ELF_Segment64;
////////////////////////////////
// Functions: ELF
// normalizing
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_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_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_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_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_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_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_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_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_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
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;
}
}
}

49
mr4th/mr4th_elf.parse.h Normal file
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
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 README 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

31
symbol_set.define.h Normal file
View File

@ -0,0 +1,31 @@
#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 section(SY__GLUE(SYMBOL_SET_DEFINE,_section),read,write)
#endif
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

308
symbol_set.h Normal file
View File

@ -0,0 +1,308 @@
/***********************************************************
** 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 README to get started.
*/
#ifndef SYMBOL_SET_H
#define SYMBOL_SET_H
/*********************
** Context Cracking **
*********************/
/* 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
# 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
#elif defined(_MSC_VER)
# define SY__COMPILER_CL 1
# if defined(_WIN32)
# define SY__OS_WINDOWS 1
# else
# error missing OS detection
# endif
# 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
#elif defined(__GNUC__)
# define SY__COMPILER_GCC 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
# 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
#else
# error no context cracking for this compiler
#endif
#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
/* language */
#if defined(__cplusplus)
# define SY__LANG_CXX 1
#else
# define SY__LANG_C 1
#endif
#if !defined(SY__LANG_CXX)
# define SY__LANG_CXX 0
#endif
#if !defined(SY__LANG_C)
# define SY__LANG_C 0
#endif
/**********
** Types **
**********/
#include <stdint.h>
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))
/*************
** 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 */

101
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

@ -34,7 +34,7 @@ X(PAD6, 15)
typedef enum ELF_IdentificationIdx{
#define X(N,C) ELF_IdentificationIdx_##N = C,
ELF_IdentificationIdx_XList(X)
ELF_IdentificationIdx_XList(X)
#undef X
} ELF_IdentificationIdx;
@ -52,7 +52,7 @@ X(64, 2)
typedef enum ELF_Class{
#define X(N,C) ELF_Class_##N = C,
ELF_Class_XList(X)
ELF_Class_XList(X)
#undef X
} ELF_Class;
@ -65,7 +65,7 @@ X(2MSB, 2)
typedef enum ELF_Encoding{
#define X(N,C) ELF_Encoding_##N = C,
ELF_Encoding_XList(X)
ELF_Encoding_XList(X)
#undef X
} ELF_Encoding;
@ -92,7 +92,7 @@ X(OPENVOS, 18)
typedef enum ELF_OsAbiExtension{
#define X(N,C) ELF_OsAbiExtension_##N = C,
ELF_OsAbiExtension_XList(X)
ELF_OsAbiExtension_XList(X)
#undef X
} ELF_OsAbiExtension;
@ -112,7 +112,7 @@ X(HIPROC, 0xffff)
typedef U16 ELF_FileType;
enum{
#define X(N,C) ELF_FileType_##N = C,
ELF_FileType_XList(X)
ELF_FileType_XList(X)
#undef X
};
@ -311,37 +311,37 @@ enum{
// elf header
typedef struct ELF_Header32{
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U32 entry;
U32 segment_table_foff;
U32 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U32 entry;
U32 segment_table_foff;
U32 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
} ELF_Header32;
typedef struct ELF_Header64{
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U64 entry;
U64 segment_table_foff;
U64 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
U8 ident[ELF_NUM_IDENT];
ELF_FileType type;
ELF_MachineType machine;
U32 version;
U64 entry;
U64 segment_table_foff;
U64 section_table_foff;
U32 flags;
U16 header_size;
U16 segment_size;
U16 segment_count;
U16 section_size;
U16 section_count;
U16 string_section_index;
} ELF_Header64;
// elf section type
@ -374,7 +374,7 @@ X(HIUSER, 0xffffffff)
typedef U32 ELF_SectionType;
enum{
#define X(N,C) ELF_SectionType_##N = C,
ELF_SectionType_XList(X)
ELF_SectionType_XList(X)
#undef X
};
@ -397,7 +397,7 @@ X(MASKPROC, 0xf0000000)
enum{
#define X(N,C) ELF_SectionFlag_##N = C,
ELF_SectionFlags_XList(X)
ELF_SectionFlags_XList(X)
#undef X
};
@ -417,7 +417,7 @@ X(HIRESERVE, 0xffff)
typedef enum ELF_SectionIndex{
#define X(N,C) ELF_SectionIndex_##N = C,
ELF_SectionIndex_XList(X)
ELF_SectionIndex_XList(X)
#undef X
} ELF_SectionIndex;
@ -426,10 +426,10 @@ typedef enum ELF_SectionIndex{
typedef struct ELF_Section32{
U32 name;
ELF_SectionType type;
ELF_SectionType type;
U32 flags;
U32 addr;
U32 offset;
U32 addr;
U32 offset;
U32 size;
U32 link;
U32 info;
@ -439,10 +439,10 @@ typedef struct ELF_Section32{
typedef struct ELF_Section64{
U32 name;
ELF_SectionType type;
ELF_SectionType type;
U64 flags;
U64 addr;
U64 offset;
U64 addr;
U64 offset;
U64 size;
U32 link;
U32 info;
@ -461,23 +461,23 @@ X(HIPROC, 0x7fffffff)
typedef enum ELF_CompressionType{
#define X(N,C) ELF_CompressionType_##N = C,
ELF_CompressionType_XList(X)
ELF_CompressionType_XList(X)
#undef X
} ELF_CompressionType;
// elf compression header
typedef struct ELF_CompressionHeader32{
ELF_CompressionType type;
ELF_CompressionType type;
U32 size;
U32 addralign;
} ELF_CompressionHeader32;
typedef struct ELF_CompressionHeader64{
ELF_CompressionType type;
ELF_CompressionType type;
U32 reserved;
U64 size;
U64 addralign;
U64 size;
U64 addralign;
} ELF_CompressionHeader64;
// elf section group flags
@ -490,28 +490,28 @@ X(MASKPROC, 0xf0000000)
typedef U32 ELF_SectionGroupFlags;
enum{
#define X(N,C) ELF_SectionGroupFlag_##N = C,
ELF_SectionGroupFlags_XList(X)
ELF_SectionGroupFlags_XList(X)
#undef X
};
// elf symbol
typedef struct ELF_Symbol32{
U32 name;
U32 value;
U32 size;
U8 info;
U8 other;
U16 section_index;
U32 name;
U32 value;
U32 size;
U8 info;
U8 other;
U16 section_index;
} ELF_Symbol32;
typedef struct ELF_Symbol64{
U32 name;
U8 info;
U8 other;
U16 section_index;
U64 value;
U64 size;
U32 name;
U8 info;
U8 other;
U16 section_index;
U64 value;
U64 size;
} ELF_Symbol64;
#define ELF_Symbol_BindFromInfo(inf) ((inf)>>4)
@ -534,7 +534,7 @@ X(HIPROC, 15)
typedef enum ELF_SymbolBinding{
#define X(N,C) ELF_SymbolBinding_##N = C,
ELF_SymbolBinding_XList(X)
ELF_SymbolBinding_XList(X)
#undef X
} ELF_SymbolBinding;
@ -555,7 +555,7 @@ X(HIPROC, 15)
typedef enum ELF_SymbolType{
#define X(N,C) ELF_SymbolType_##N = C,
ELF_SymbolType_XList(X)
ELF_SymbolType_XList(X)
#undef X
} ELF_SymbolType;
@ -569,31 +569,31 @@ X(PROTECTED, 3)
typedef enum ELF_SymbolVis{
#define X(N,C) ELF_SymbolVis_##N = C,
ELF_SymbolVis_XList(X)
ELF_SymbolVis_XList(X)
#undef X
} ELF_SymbolVis;
// elf relocations
typedef struct ELF_Relocation32{
U32 offset;
U32 info;
U32 offset;
U32 info;
} ELF_Relocation32;
typedef struct ELF_RelocationAdd32{
U32 offset;
U32 info;
U32 offset;
U32 info;
S32 addend;
} ELF_RelocationAdd32;
typedef struct ELF_Relocation64{
U64 offset;
U64 info;
U64 offset;
U64 info;
} ELF_Relocation64;
typedef struct ELF_RelocationAdd64{
U64 offset;
U64 info;
U64 offset;
U64 info;
S64 addend;
} ELF_RelocationAdd64;
@ -616,7 +616,7 @@ X(HIPROC, 0x7fffffff)
typedef U32 ELF_SegmentType;
enum{
#define X(N,C) ELF_SegmentType_##N = C,
ELF_SegmentType_XList(X)
ELF_SegmentType_XList(X)
#undef X
};
@ -632,32 +632,32 @@ X(MASKPROC, 0xf0000000)\
typedef U32 ELF_SegmentFlags;
enum{
#define X(N,C) ELF_SegmentFlag_##N = C,
ELF_SegmentFlags_XList(X)
ELF_SegmentFlags_XList(X)
#undef X
};
// elf segment
typedef struct ELF_Segment32{
ELF_SegmentType type;
U32 offset;
U32 vaddr;
U32 paddr;
U32 file_size;
U32 memory_size;
ELF_SegmentFlags flags;
U32 align;
ELF_SegmentType type;
U32 offset;
U32 vaddr;
U32 paddr;
U32 file_size;
U32 memory_size;
ELF_SegmentFlags flags;
U32 align;
} ELF_Segment32;
typedef struct ELF_Segment64{
ELF_SegmentType type;
ELF_SegmentFlags flags;
U64 offset;
U64 vaddr;
U64 paddr;
U64 file_size;
U64 memory_size;
U64 align;
ELF_SegmentType type;
ELF_SegmentFlags flags;
U64 offset;
U64 vaddr;
U64 paddr;
U64 file_size;
U64 memory_size;
U64 align;
} ELF_Segment64;
////////////////////////////////

89
symbol_set.starter.h Normal file
View File

@ -0,0 +1,89 @@
/***********************************************************
** 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 README to get started.
*/
/****************************
*****************************
********** Setup **********
*****************************
****************************/
#if 0
/* In ever compilation unit, #include "symbol_set.h" once before using
** any symbol set features or defining a symbol set. */
#include "symbol_set.h"
/* In one compilation unit, #include "symbol_set.c" */
#include "symbol_set.c"
#endif
/******************************************
*******************************************
********** Define A 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: only use 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
/****************************************************
*****************************************************
********** Common Symbol Defining Macros **********
*****************************************************
****************************************************/
#if 0
/* Define a basic struct with a NAME */
#define ZZZ_DEF(N,...) SyDefine(ZZZ, NAME) = { ... }
/* Define a basic struct without a name */
#define ZZZ_DEF(...) SyDefineUnnamed(ZZZ, NAME) = { ... }
/* Define a struct with a NAME & attach a function.
** Replace zzzprefix with a unique function prefix.
** Update the parameter and return types as needed.
*/
#define ZZZ_DEF(N,...) \
void zzzprefix_##N(void); \
SyDefine(ZZZ, NAME) = { ..., zzzprefix_##N }; \
void zzzprefix_##N(void)
/* Define a struct with a NAME & attach multiple functions
** Replace zzzprefix1... with unique function prefixes.
** Update the parameter and return types as needed.
** Replace ZZZ_PREFIX1... with appropriate names.
*/
#define ZZZ_DEF(N,...) \
void zzzprefix1_##N(void); \
void zzzprefix2_##N(void); \
SyDefine(ZZZ, NAME) = { ..., zzzprefix1_##N, zzzprefix2_##N }
#define ZZZ_PREFIX1(N) void zzzprefix1_##N(void)
#define ZZZ_PREFIX2(N) void zzzprefix2_##N(void)
#endif