merge
commit
32ce56df78
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue