major update: naming and features upgrade pass, support for Linux (w/ linker script build step), & shrink dependencies
parent
cc1522760f
commit
e1fc795db4
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
|
||||
root_path="$PWD"
|
||||
build_path="$root_path/build"
|
||||
src_path="$root_path/src"
|
||||
|
||||
mkdir -p $build_path
|
||||
cd $build_path
|
||||
rm *
|
||||
|
||||
clang -o sy.ld_meta $src_path/symbol_set.ld_meta.c -I$src_path/mr4th
|
||||
|
||||
clang -c -o example1.o $src_path/example1.c
|
||||
./sy.ld_meta --out:example1_sy.ld example1.o
|
||||
clang -o example1 example1.o -T example1_sy.ld
|
||||
62
src/base.c
62
src/base.c
|
|
@ -1,62 +0,0 @@
|
|||
////////////////////////////////
|
||||
// Functions
|
||||
|
||||
|
||||
#if OS_WINDOWS
|
||||
# include <Windows.h>
|
||||
# include <userenv.h>
|
||||
# include <psapi.h>
|
||||
#endif
|
||||
|
||||
static String8
|
||||
str8(U8 *str, U64 size){
|
||||
String8 result = {str, size};
|
||||
return(result);
|
||||
}
|
||||
|
||||
static B32
|
||||
str8_match(String8 a, String8 b, U32 flags){
|
||||
B32 result = 0;
|
||||
if (a.size == b.size){
|
||||
U64 size = a.size;
|
||||
result = 1;
|
||||
for (U64 i = 0; i < size; i += 1){
|
||||
U8 ac = a.str[i];
|
||||
U8 bc = b.str[i];
|
||||
if (ac != bc){
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
#if OS_WINDOWS
|
||||
|
||||
// see: https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
|
||||
static void*
|
||||
os_this_image(void){
|
||||
extern U8 __ImageBase[];
|
||||
void *result = __ImageBase;
|
||||
return(result);
|
||||
}
|
||||
|
||||
#else
|
||||
# error os_this_image not implemented for this OS
|
||||
#endif
|
||||
|
||||
#if OS_WINDOWS
|
||||
|
||||
# include "binary/pe/mr4th_pe.h"
|
||||
# include "binary/pe/mr4th_pe.img_get_section.c"
|
||||
|
||||
static RangePtr
|
||||
self_img_get_section(void *image, String8 name){
|
||||
RangePtr result = pe_img_get_section(image, name);
|
||||
return(result);
|
||||
}
|
||||
|
||||
#else
|
||||
# error selfimg_get_section not implemented for this OS
|
||||
#endif
|
||||
252
src/base.h
252
src/base.h
|
|
@ -1,252 +0,0 @@
|
|||
////////////////////////////////
|
||||
// Context Cracking
|
||||
|
||||
// untangle compiler, os, & architecture
|
||||
#if defined(__clang__)
|
||||
# define COMPILER_CLANG 1
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__gnu_linux__)
|
||||
# define OS_LINUX 1
|
||||
# elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define OS_MAC 1
|
||||
# else
|
||||
# error missing OS detection
|
||||
# endif
|
||||
|
||||
# if defined(__amd64__)
|
||||
# define ARCH_X64 1
|
||||
// TODO(allen): verify this works on clang
|
||||
# elif defined(__i386__)
|
||||
# define ARCH_X86 1
|
||||
// TODO(allen): verify this works on clang
|
||||
# elif defined(__arm__)
|
||||
# define ARCH_ARM 1
|
||||
// TODO(allen): verify this works on clang
|
||||
# elif defined(__aarch64__)
|
||||
# define ARCH_ARM64 1
|
||||
# else
|
||||
# error missing ARCH detection
|
||||
# endif
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
# define COMPILER_CL 1
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# else
|
||||
# error missing OS detection
|
||||
# endif
|
||||
|
||||
# if defined(_M_AMD64)
|
||||
# define ARCH_X64 1
|
||||
# elif defined(_M_I86)
|
||||
# define ARCH_X86 1
|
||||
# elif defined(_M_ARM)
|
||||
# define ARCH_ARM 1
|
||||
// TODO(allen): ARM64?
|
||||
# else
|
||||
# error missing ARCH detection
|
||||
# endif
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
# define COMPILER_GCC 1
|
||||
|
||||
# if defined(_WIN32)
|
||||
# define OS_WINDOWS 1
|
||||
# elif defined(__gnu_linux__)
|
||||
# define OS_LINUX 1
|
||||
# elif defined(__APPLE__) && defined(__MACH__)
|
||||
# define OS_MAC 1
|
||||
# else
|
||||
# error missing OS detection
|
||||
# endif
|
||||
|
||||
# if defined(__amd64__)
|
||||
# define ARCH_X64 1
|
||||
# elif defined(__i386__)
|
||||
# define ARCH_X86 1
|
||||
# elif defined(__arm__)
|
||||
# define ARCH_ARM 1
|
||||
# elif defined(__aarch64__)
|
||||
# define ARCH_ARM64 1
|
||||
# else
|
||||
# error missing ARCH detection
|
||||
# endif
|
||||
|
||||
#else
|
||||
# error no context cracking for this compiler
|
||||
#endif
|
||||
|
||||
#if !defined(COMPILER_CL)
|
||||
# define COMPILER_CL 0
|
||||
#endif
|
||||
#if !defined(COMPILER_CLANG)
|
||||
# define COMPILER_CLANG 0
|
||||
#endif
|
||||
#if !defined(COMPILER_GCC)
|
||||
# define COMPILER_GCC 0
|
||||
#endif
|
||||
#if !defined(OS_WINDOWS)
|
||||
# define OS_WINDOWS 0
|
||||
#endif
|
||||
#if !defined(OS_LINUX)
|
||||
# define OS_LINUX 0
|
||||
#endif
|
||||
#if !defined(OS_MAC)
|
||||
# define OS_MAC 0
|
||||
#endif
|
||||
#if !defined(ARCH_X64)
|
||||
# define ARCH_X64 0
|
||||
#endif
|
||||
#if !defined(ARCH_X86)
|
||||
# define ARCH_X86 0
|
||||
#endif
|
||||
#if !defined(ARCH_ARM)
|
||||
# define ARCH_ARM 0
|
||||
#endif
|
||||
#if !defined(ARCH_ARM64)
|
||||
# define ARCH_ARM64 0
|
||||
#endif
|
||||
|
||||
|
||||
// language
|
||||
#if defined(__cplusplus)
|
||||
# define LANG_CXX 1
|
||||
#else
|
||||
# define LANG_C 1
|
||||
#endif
|
||||
|
||||
#if !defined(LANG_CXX)
|
||||
# define LANG_CXX 0
|
||||
#endif
|
||||
#if !defined(LANG_C)
|
||||
# define LANG_C 0
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// GLUE(a,b) STRIFY(s)
|
||||
|
||||
#define GLUE__(a,b) a##b
|
||||
#define GLUE_(a,b) GLUE__(a,b)
|
||||
#define GLUE(a,b) GLUE_(a,b)
|
||||
|
||||
#define STRIFY__(s) #s
|
||||
#define STRIFY_(s) STRIFY__(s)
|
||||
#define STRIFY(s) STRIFY_(s)
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// SECTION(<section-name>) <Decl>
|
||||
|
||||
#if COMPILER_CLANG || COMPILER_GCC
|
||||
# define SECTION(N) __attribute__((__section__(N)))
|
||||
#elif COMPILER_CL
|
||||
# define SECTION(N) __declspec(allocate(N))
|
||||
#else
|
||||
# error SECTION not defined for this compiler
|
||||
#endif
|
||||
|
||||
// for CL users: #pragma section(<section>,read,write)
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// BEFORE_MAIN(){ <...> }
|
||||
|
||||
#if OS_WINDOWS
|
||||
|
||||
# pragma section(".CRT$XCU", read)
|
||||
|
||||
# if LANG_CXX
|
||||
|
||||
# define BEFORE_MAIN_NAMED(n) \
|
||||
static void n(void); \
|
||||
__declspec(allocate(".CRT$XCU")) \
|
||||
__pragma(comment(linker,"/include:" #n "__")) \
|
||||
extern "C" void (*n##__)(void); \
|
||||
void (*n##__)(void) = n; \
|
||||
static void n(void)
|
||||
|
||||
# else
|
||||
|
||||
# define BEFORE_MAIN_NAMED(n) \
|
||||
static void n(void); \
|
||||
__declspec(allocate(".CRT$XCU")) \
|
||||
__pragma(comment(linker,"/include:" #n "__")) \
|
||||
void (*n##__)(void) = n; \
|
||||
static void n(void)
|
||||
|
||||
# endif
|
||||
|
||||
#elif OS_LINUX
|
||||
|
||||
# define BEFORE_MAIN_NAMED(n) \
|
||||
__attribute__((constructor)) static void n(void)
|
||||
|
||||
#else
|
||||
# error BEFORE_MAIN missing for this OS
|
||||
#endif
|
||||
|
||||
#define BEFORE_MAIN_(n) BEFORE_MAIN_NAMED(n)
|
||||
#define BEFORE_MAIN() BEFORE_MAIN_(GLUE(beforemain,__COUNTER__))
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// DO_NOT_ELIMINATE
|
||||
|
||||
#if OS_WINDOWS
|
||||
# define DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N))
|
||||
# define DO_NOT_ELIMINATE__S1(N) DO_NOT_ELIMINATE__S0(N)
|
||||
# define DO_NOT_ELIMINATE(N) DO_NOT_ELIMINATE__S1(N)
|
||||
#else
|
||||
|
||||
# define DO_NOT_ELIMINATE(N)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// Types
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t S8;
|
||||
typedef int16_t S16;
|
||||
typedef int32_t S32;
|
||||
typedef int64_t S64;
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef uint64_t U64;
|
||||
typedef S8 B8;
|
||||
typedef S16 B16;
|
||||
typedef S32 B32;
|
||||
typedef S64 B64;
|
||||
typedef float F32;
|
||||
typedef double F64;
|
||||
|
||||
typedef struct RangePtr{
|
||||
U8 *first;
|
||||
U8 *opl;
|
||||
} RangePtr;
|
||||
|
||||
typedef struct String8{
|
||||
U8 *str;
|
||||
U64 size;
|
||||
} String8;
|
||||
|
||||
#define str8_lit(str) str8((U8*)(str), sizeof(str) - 1)
|
||||
#define str8_lit_const(str) { (U8*)(str), sizeof(str) - 1 }
|
||||
#define str8_expand(s) ((int)((s).size)), ((s).str)
|
||||
|
||||
////////////////////////////////
|
||||
// Functions
|
||||
|
||||
static String8 str8(U8 *str, U64 size);
|
||||
static B32 str8_match(String8 a, String8 b, U32 flags);
|
||||
|
||||
static void* os_this_image(void);
|
||||
|
||||
static RangePtr self_img_get_section(void *image, String8 name);
|
||||
|
|
@ -1,518 +0,0 @@
|
|||
////////////////////////////////
|
||||
// Functions: ELF
|
||||
|
||||
// normalizing
|
||||
|
||||
MR4TH_SYM_COMPTIME U16
|
||||
elf_u16_decode(void *ptr, B32 flip){
|
||||
U16 result = 0;
|
||||
if (flip){
|
||||
U8 *buf = (U8*)ptr;
|
||||
result = buf[1] | (buf[0] << 8);
|
||||
}
|
||||
else{
|
||||
result = *(U16*)ptr;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME U32
|
||||
elf_u32_decode(void *ptr, B32 flip){
|
||||
U32 result = 0;
|
||||
if (flip){
|
||||
U8 *buf = (U8*)ptr;
|
||||
result = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);
|
||||
}
|
||||
else{
|
||||
result = *(U32*)ptr;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME U64
|
||||
elf_u64_decode(void *ptr, B32 flip){
|
||||
U64 result = 0;
|
||||
if (flip){
|
||||
U8 *buf = (U8*)ptr;
|
||||
result = ((((U64)buf[7]) << 0) | (((U64)buf[6]) << 8) |
|
||||
(((U64)buf[5]) << 16) | (((U64)buf[4]) << 24) |
|
||||
(((U64)buf[3]) << 32) | (((U64)buf[2]) << 40) |
|
||||
(((U64)buf[1]) << 48) | (((U64)buf[0]) << 56));
|
||||
}
|
||||
else{
|
||||
result = *(U64*)ptr;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
MemoryCopyArray(dst->ident, src->ident);
|
||||
dst->type = elf_u16_decode(&src->type, flip_order);
|
||||
dst->machine = elf_u16_decode(&src->machine, flip_order);
|
||||
dst->version = elf_u32_decode(&src->version, flip_order);
|
||||
dst->entry = (U64)elf_u32_decode(&src->entry, flip_order);
|
||||
dst->segment_table_foff = (U64)elf_u32_decode(&src->segment_table_foff, flip_order);
|
||||
dst->section_table_foff = (U64)elf_u32_decode(&src->section_table_foff, flip_order);
|
||||
dst->flags = elf_u32_decode(&src->flags, flip_order);
|
||||
dst->header_size = elf_u16_decode(&src->header_size, flip_order);
|
||||
dst->segment_size = elf_u16_decode(&src->segment_size, flip_order);
|
||||
dst->segment_count = elf_u16_decode(&src->segment_count, flip_order);
|
||||
dst->section_size = elf_u16_decode(&src->section_size, flip_order);
|
||||
dst->section_count = elf_u16_decode(&src->section_count, flip_order);
|
||||
dst->string_section_index = elf_u16_decode(&src->string_section_index, flip_order);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
if (!flip_order){
|
||||
MemoryCopyStruct(dst, src);
|
||||
}
|
||||
else{
|
||||
MemoryCopyArray(dst->ident, src->ident);
|
||||
dst->type = elf_u16_decode(&src->type, 1);
|
||||
dst->machine = elf_u16_decode(&src->machine, 1);
|
||||
dst->version = elf_u32_decode(&src->version, 1);
|
||||
dst->entry = elf_u32_decode(&src->entry, 1);
|
||||
dst->segment_table_foff = elf_u32_decode(&src->segment_table_foff, 1);
|
||||
dst->section_table_foff = elf_u32_decode(&src->section_table_foff, 1);
|
||||
dst->flags = elf_u32_decode(&src->flags, 1);
|
||||
dst->header_size = elf_u16_decode(&src->header_size, 1);
|
||||
dst->segment_size = elf_u16_decode(&src->segment_size, 1);
|
||||
dst->segment_count = elf_u16_decode(&src->segment_count, 1);
|
||||
dst->section_size = elf_u16_decode(&src->section_size, 1);
|
||||
dst->section_count = elf_u16_decode(&src->section_count, 1);
|
||||
dst->string_section_index = elf_u16_decode(&src->string_section_index, 1);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
dst->name = elf_u32_decode(&src->name, flip_order);
|
||||
dst->type = elf_u32_decode(&src->type, flip_order);
|
||||
dst->flags = elf_u32_decode(&src->flags, flip_order);
|
||||
dst->addr = elf_u32_decode(&src->addr, flip_order);
|
||||
dst->offset = elf_u32_decode(&src->offset, flip_order);
|
||||
dst->size = elf_u32_decode(&src->size, flip_order);
|
||||
dst->link = elf_u32_decode(&src->link, flip_order);
|
||||
dst->info = elf_u32_decode(&src->info, flip_order);
|
||||
dst->addralign = elf_u32_decode(&src->addralign, flip_order);
|
||||
dst->entsize = elf_u32_decode(&src->entsize, flip_order);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
if (!flip_order){
|
||||
MemoryCopyStruct(dst, src);
|
||||
}
|
||||
else{
|
||||
dst->name = elf_u32_decode(&src->name, 1);
|
||||
dst->type = elf_u32_decode(&src->type, 1);
|
||||
dst->flags = elf_u64_decode(&src->flags, 1);
|
||||
dst->addr = elf_u64_decode(&src->addr, 1);
|
||||
dst->offset = elf_u64_decode(&src->offset, 1);
|
||||
dst->size = elf_u64_decode(&src->size, 1);
|
||||
dst->link = elf_u32_decode(&src->link, 1);
|
||||
dst->info = elf_u32_decode(&src->info, 1);
|
||||
dst->addralign = elf_u64_decode(&src->addralign, 1);
|
||||
dst->entsize = elf_u64_decode(&src->entsize, 1);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
dst->type = elf_u32_decode(&src->type, flip_order);
|
||||
dst->offset = elf_u32_decode(&src->offset, flip_order);
|
||||
dst->vaddr = elf_u32_decode(&src->vaddr, flip_order);
|
||||
dst->paddr = elf_u32_decode(&src->paddr, flip_order);
|
||||
dst->file_size = elf_u32_decode(&src->file_size, flip_order);
|
||||
dst->memory_size = elf_u32_decode(&src->memory_size, flip_order);
|
||||
dst->flags = elf_u32_decode(&src->flags, flip_order);
|
||||
dst->align = elf_u32_decode(&src->align, flip_order);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
if (!flip_order){
|
||||
MemoryCopyStruct(dst, src);
|
||||
}
|
||||
else{
|
||||
dst->type = elf_u32_decode(&src->type, 1);
|
||||
dst->flags = elf_u32_decode(&src->flags, 1);
|
||||
dst->offset = elf_u64_decode(&src->offset, 1);
|
||||
dst->vaddr = elf_u64_decode(&src->vaddr, 1);
|
||||
dst->paddr = elf_u64_decode(&src->paddr, 1);
|
||||
dst->file_size = elf_u64_decode(&src->file_size, 1);
|
||||
dst->memory_size = elf_u64_decode(&src->memory_size, 1);
|
||||
dst->align = elf_u64_decode(&src->align, 1);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
dst->name = elf_u32_decode(&src->name, flip_order);
|
||||
dst->value = elf_u32_decode(&src->value, flip_order);
|
||||
dst->size = elf_u32_decode(&src->size, flip_order);
|
||||
dst->info = src->info;
|
||||
dst->other = src->other;
|
||||
dst->section_index = elf_u16_decode(&src->section_index, flip_order);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
if (!flip_order){
|
||||
MemoryCopyStruct(dst, src);
|
||||
}
|
||||
else{
|
||||
dst->name = elf_u32_decode(&src->name, 1);
|
||||
dst->info = src->info;
|
||||
dst->other = src->other;
|
||||
dst->section_index = elf_u16_decode(&src->section_index, 1);
|
||||
dst->value = elf_u64_decode(&src->value, 1);
|
||||
dst->size = elf_u64_decode(&src->size, 1);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
|
||||
elf_reloca64_from_reloc32(Arena *arena, ELF_Relocation32 *src, U64 count, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
|
||||
{
|
||||
ELF_Relocation32 *srcptr = src;
|
||||
ELF_RelocationAdd64 *dstptr = dst;
|
||||
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
|
||||
dstptr->offset = elf_u32_decode(&srcptr->offset, flip_order);
|
||||
dstptr->info = elf_u32_decode(&srcptr->info, flip_order);
|
||||
}
|
||||
}
|
||||
|
||||
return(dst);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
|
||||
elf_reloca64_from_reloc64(Arena *arena, ELF_Relocation64 *src, U64 count, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
|
||||
{
|
||||
ELF_Relocation64 *srcptr = src;
|
||||
ELF_RelocationAdd64 *dstptr = dst;
|
||||
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
|
||||
dstptr->offset = elf_u64_decode(&srcptr->offset, flip_order);
|
||||
dstptr->info = elf_u64_decode(&srcptr->info, flip_order);
|
||||
}
|
||||
}
|
||||
|
||||
return(dst);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
|
||||
elf_reloca64_from_reloca32(Arena *arena, ELF_RelocationAdd32 *src, U64 count, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
|
||||
{
|
||||
ELF_RelocationAdd32 *srcptr = src;
|
||||
ELF_RelocationAdd64 *dstptr = dst;
|
||||
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
|
||||
dstptr->offset = elf_u32_decode(&srcptr->offset, flip_order);
|
||||
dstptr->info = elf_u32_decode(&srcptr->info, flip_order);
|
||||
dstptr->addend = (S32)elf_u32_decode(&srcptr->addend, flip_order);
|
||||
}
|
||||
}
|
||||
|
||||
return(dst);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64*
|
||||
elf_reloca64_from_reloca64(Arena *arena, ELF_RelocationAdd64 *src, U64 count, ELF_Encoding src_encoding){
|
||||
B32 src_big_endian = (src_encoding == ELF_Encoding_2MSB);
|
||||
B32 flip_order = (src_big_endian != ARCH_BIG_ENDIAN);
|
||||
|
||||
ELF_RelocationAdd64 *dst = push_array(arena, ELF_RelocationAdd64, count);
|
||||
{
|
||||
ELF_RelocationAdd64 *srcptr = src;
|
||||
ELF_RelocationAdd64 *dstptr = dst;
|
||||
for (U64 i = 0; i < count; i += 1, srcptr += 1, dstptr += 1){
|
||||
dstptr->offset = elf_u64_decode(&srcptr->offset, flip_order);
|
||||
dstptr->info = elf_u64_decode(&srcptr->info, flip_order);
|
||||
dstptr->addend = (S64)elf_u64_decode(&srcptr->addend, flip_order);
|
||||
}
|
||||
}
|
||||
|
||||
return(dst);
|
||||
}
|
||||
|
||||
// strings
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_identification_idx(ELF_IdentificationIdx idx){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (idx){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_IdentificationIdx_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_class(ELF_Class elf_class){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (elf_class){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_Class_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_encoding(ELF_Encoding elf_encoding){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (elf_encoding){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_Encoding_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (elf_osabi){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_OsAbiExtension_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_file_type(ELF_FileType file_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (file_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_FileType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_machine_type(ELF_FileType machine_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (machine_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_MachineType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_section_type(ELF_SectionType section_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
|
||||
if (ELF_SectionType_LOOS <= section_type &&
|
||||
section_type <= ELF_SectionType_HIOS){
|
||||
result = str8_lit("OS-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else if (ELF_SectionType_LOPROC <= section_type &&
|
||||
section_type <= ELF_SectionType_HIPROC){
|
||||
result = str8_lit("PROC-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else if (ELF_SectionType_LOUSER <= section_type &&
|
||||
section_type <= ELF_SectionType_HIUSER){
|
||||
result = str8_lit("USER-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else{
|
||||
switch (section_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_SectionType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags){
|
||||
U32 f = 1;
|
||||
for (U32 i = 0; i < 20; i += 1){
|
||||
if ((flags & f) != 0){
|
||||
switch (f){
|
||||
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
|
||||
ELF_SectionFlags_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
f <<= 1;
|
||||
}
|
||||
if ((flags & ELF_SectionFlag_MASKOS) != 0){
|
||||
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
|
||||
}
|
||||
if ((flags & ELF_SectionFlag_MASKPROC) != 0){
|
||||
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_section_flags(Arena *arena, U32 flags){
|
||||
ArenaTemp scratch = arena_get_scratch(&arena, 1);
|
||||
String8List list = {0};
|
||||
elf_str8list_from_section_flags(scratch.arena, &list, flags);
|
||||
String8 result = str8_join_flags(arena, &list);
|
||||
arena_release_scratch(&scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_segment_type(ELF_SegmentType segment_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
|
||||
if (ELF_SegmentType_LOOS <= segment_type &&
|
||||
segment_type <= ELF_SegmentType_HIOS){
|
||||
result = str8_lit("OS-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else if (ELF_SegmentType_LOPROC <= segment_type &&
|
||||
segment_type <= ELF_SegmentType_HIPROC){
|
||||
result = str8_lit("PROC-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else{
|
||||
switch (segment_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_SegmentType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags){
|
||||
U32 f = 1;
|
||||
for (U32 i = 0; i < 20; i += 1){
|
||||
if ((flags & f) != 0){
|
||||
switch (f){
|
||||
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
|
||||
ELF_SegmentFlags_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
f <<= 1;
|
||||
}
|
||||
if ((flags & ELF_SegmentFlag_MASKOS) != 0){
|
||||
str8_list_pushf(arena, out, "OS-CUSTOM(%02x)", (flags >> 20)&0xFF);
|
||||
}
|
||||
if ((flags & ELF_SegmentFlag_MASKPROC) != 0){
|
||||
str8_list_pushf(arena, out, "PROC-CUSTOM(%01x)", (flags >> 28)&0xF);
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags){
|
||||
ArenaTemp scratch = arena_get_scratch(&arena, 1);
|
||||
String8List list = {0};
|
||||
elf_str8list_from_segment_flags(scratch.arena, &list, flags);
|
||||
String8 result = str8_join_flags(arena, &list);
|
||||
arena_release_scratch(&scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_symbol_binding(ELF_SymbolBinding bind){
|
||||
String8 result = str8_lit("ERROR");
|
||||
|
||||
if (ELF_SymbolBinding_LOOS <= bind &&
|
||||
bind <= ELF_SymbolBinding_HIOS){
|
||||
result = str8_lit("OS-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else if (ELF_SymbolBinding_LOPROC <= bind &&
|
||||
bind <= ELF_SymbolBinding_HIPROC){
|
||||
result = str8_lit("PROC-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else{
|
||||
switch (bind){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_SymbolBinding_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_symbol_type(ELF_SymbolType type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
|
||||
if (ELF_SymbolType_LOOS <= type &&
|
||||
type <= ELF_SymbolType_HIOS){
|
||||
result = str8_lit("OS-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else if (ELF_SymbolType_LOPROC <= type &&
|
||||
type <= ELF_SymbolType_HIPROC){
|
||||
result = str8_lit("PROC-CUSTOM-TYPE");
|
||||
}
|
||||
|
||||
else{
|
||||
switch (type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_SymbolType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
elf_str8_from_symbol_vis(ELF_SymbolVis vis){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (vis){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
ELF_SymbolVis_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
|
@ -1,567 +0,0 @@
|
|||
/*
|
||||
** ELF File Dumper
|
||||
*/
|
||||
|
||||
|
||||
#include "mr4th_base.h"
|
||||
#include "mr4th_base.stdio.h"
|
||||
#include "mr4th_keywords.h"
|
||||
|
||||
#include "mr4th_elf.h"
|
||||
|
||||
#include "mr4th_elf.dump.h"
|
||||
|
||||
#include "mr4th_base.c"
|
||||
#include "mr4th_elf.c"
|
||||
|
||||
////////////////////////////////
|
||||
// ELF DUMP Arguments Functions
|
||||
|
||||
function ELFDUMP_Arguments*
|
||||
elfdump_args(Arena *arena, String8List *command_line_args){
|
||||
// parse
|
||||
CMDLN *cmdln = cmdln_from_args(arena, command_line_args);
|
||||
|
||||
// setup args
|
||||
ELFDUMP_Arguments *args = push_array(arena, ELFDUMP_Arguments, 1);
|
||||
|
||||
// get input file name
|
||||
args->input_file_name = cmdln_input_from_idx(cmdln, 0);
|
||||
|
||||
return(args);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Entry Point
|
||||
|
||||
int main(int argc, char **argv){
|
||||
os_main_init(argc, argv);
|
||||
|
||||
Arena *arena = arena_alloc();
|
||||
|
||||
// arguments
|
||||
String8List command_line_args = os_command_line_arguments();
|
||||
ELFDUMP_Arguments *args = elfdump_args(arena, &command_line_args);
|
||||
|
||||
// load input file
|
||||
String8 input_data = os_file_read(arena, args->input_file_name);
|
||||
|
||||
|
||||
/////////////////
|
||||
///// PARSE /////
|
||||
/////////////////
|
||||
|
||||
// magic check
|
||||
B32 elf_magic = 0;
|
||||
ELF_Class elf_class = ELF_Class_NONE;
|
||||
ELF_Encoding elf_encoding = ELF_Encoding_NONE;
|
||||
U32 elf_version = 0;
|
||||
ELF_OsAbiExtension elf_ext = ELF_OsAbiExtension_NONE;
|
||||
|
||||
if (input_data.size >= ELF_NUM_IDENT){
|
||||
if (input_data.str[0] == ELF_Magic_Byte0 &&
|
||||
input_data.str[1] == ELF_Magic_Byte1 &&
|
||||
input_data.str[2] == ELF_Magic_Byte2 &&
|
||||
input_data.str[3] == ELF_Magic_Byte3){
|
||||
elf_magic = 1;
|
||||
}
|
||||
elf_class = input_data.str[ELF_IdentificationIdx_CLASS];
|
||||
elf_encoding = input_data.str[ELF_IdentificationIdx_DATA];
|
||||
elf_version = input_data.str[ELF_IdentificationIdx_VERSION];
|
||||
elf_ext = input_data.str[ELF_IdentificationIdx_OSABI];
|
||||
}
|
||||
|
||||
B32 elf_header_good = 1;
|
||||
if (!elf_magic || elf_class == 0 || elf_encoding == 0 || elf_version != 1){
|
||||
elf_header_good = 0;
|
||||
}
|
||||
|
||||
// elf header
|
||||
ELF_Header32 *hdr32_raw = 0;
|
||||
ELF_Header64 *hdr64_raw = 0;
|
||||
if (elf_header_good){
|
||||
|
||||
// 32-bit
|
||||
if (elf_class == ELF_Class_32){
|
||||
if (sizeof(*hdr32_raw) <= input_data.size){
|
||||
hdr32_raw = (ELF_Header32*)input_data.str;
|
||||
}
|
||||
}
|
||||
|
||||
// 64-bit
|
||||
if (elf_class == ELF_Class_64){
|
||||
if (sizeof(*hdr64_raw) <= input_data.size){
|
||||
hdr64_raw = (ELF_Header64*)input_data.str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize header
|
||||
ELF_Header64 hdr = {0};
|
||||
if (hdr32_raw != 0){
|
||||
elf_header64_from_header32(&hdr, hdr32_raw, elf_encoding);
|
||||
}
|
||||
else if (hdr64_raw != 0){
|
||||
elf_header64_from_header64(&hdr, hdr64_raw, elf_encoding);
|
||||
}
|
||||
else{
|
||||
elf_header_good = 0;
|
||||
}
|
||||
|
||||
// sections
|
||||
ELF_Section32 *sec32_raw = 0;
|
||||
ELF_Section64 *sec64_raw = 0;
|
||||
if (elf_header_good){
|
||||
|
||||
U64 foff = hdr.section_table_foff;
|
||||
U64 opl_foff = foff + hdr.section_count*hdr.section_size;
|
||||
|
||||
if (opl_foff <= input_data.size){
|
||||
// 32-bit
|
||||
if (elf_class == ELF_Class_32){
|
||||
sec32_raw = (ELF_Section32*)(input_data.str + foff);
|
||||
}
|
||||
|
||||
// 64-bit
|
||||
if (elf_class == ELF_Class_64){
|
||||
sec64_raw = (ELF_Section64*)(input_data.str + foff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize sections
|
||||
B32 sections_good = 1;
|
||||
ELF_Section64 *sections = 0;
|
||||
if (sec32_raw != 0){
|
||||
sections = push_array(arena, ELF_Section64, hdr.section_count);
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
elf_section64_from_section32(sections + i, sec32_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
else if (sec64_raw != 0){
|
||||
sections = push_array(arena, ELF_Section64, hdr.section_count);
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
elf_section64_from_section64(sections + i, sec64_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
else{
|
||||
sections_good = 0;
|
||||
}
|
||||
|
||||
// segments
|
||||
ELF_Segment32 *seg32_raw = 0;
|
||||
ELF_Segment64 *seg64_raw = 0;
|
||||
if (elf_header_good){
|
||||
|
||||
U64 foff = hdr.segment_table_foff;
|
||||
U64 opl_foff = foff + hdr.segment_count*hdr.segment_size;
|
||||
|
||||
if (opl_foff <= input_data.size){
|
||||
// 32-bit
|
||||
if (elf_class == ELF_Class_32){
|
||||
seg32_raw = (ELF_Segment32*)(input_data.str + foff);
|
||||
}
|
||||
|
||||
// 64-bit
|
||||
if (elf_class == ELF_Class_64){
|
||||
seg64_raw = (ELF_Segment64*)(input_data.str + foff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// normalize segments
|
||||
B32 segments_good = 1;
|
||||
ELF_Segment64 *segments = 0;
|
||||
if (seg32_raw != 0){
|
||||
segments = push_array(arena, ELF_Segment64, hdr.segment_count);
|
||||
for (U32 i = 0; i < hdr.segment_count; i += 1){
|
||||
elf_segment64_from_segment32(segments + i, seg32_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
else if (seg64_raw != 0){
|
||||
segments = push_array(arena, ELF_Segment64, hdr.segment_count);
|
||||
for (U32 i = 0; i < hdr.segment_count; i += 1){
|
||||
elf_segment64_from_segment64(segments + i, seg64_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
else{
|
||||
segments_good = 0;
|
||||
}
|
||||
|
||||
// find symtab section
|
||||
ELF_Section64 *symtab_section = 0;
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
ELF_Section64 *section = sections + i;
|
||||
if (section->type == ELF_SectionType_SYMTAB){
|
||||
symtab_section = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// find dynsym section
|
||||
ELF_Section64 *dynsym_section = 0;
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
ELF_Section64 *section = sections + i;
|
||||
if (section->type == ELF_SectionType_DYNSYM){
|
||||
dynsym_section = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// decode symol tables
|
||||
ELFDUMP_SymbolTable symbol_tables[2] = {0};
|
||||
|
||||
ELF_Section64 *symbol_table_sections[2];
|
||||
symbol_table_sections[0] = symtab_section;
|
||||
symbol_table_sections[1] = dynsym_section;
|
||||
|
||||
for (U32 k = 0; k < 2; k += 1){
|
||||
ELF_Section64 *symbol_section = symbol_table_sections[k];
|
||||
|
||||
ELF_Symbol32 *sym32_raw = 0;
|
||||
ELF_Symbol64 *sym64_raw = 0;
|
||||
U8 *string_table_first = 0;
|
||||
U8 *string_table_opl = 0;
|
||||
U32 symbol_count = 0;
|
||||
|
||||
if (symbol_section != 0){
|
||||
|
||||
// extract symbol string table
|
||||
if (symbol_section->link < hdr.section_count){
|
||||
ELF_Section64 *string_table = sections + symbol_section->link;
|
||||
string_table_first = input_data.str + string_table->offset;
|
||||
string_table_opl = string_table_first + string_table->size;
|
||||
}
|
||||
|
||||
// extract raw symbol array
|
||||
U64 foff = symbol_section->offset;
|
||||
U64 opl_foff = foff + symbol_section->size;
|
||||
|
||||
U64 symbol_count_cap = 0;
|
||||
|
||||
if (opl_foff <= input_data.size){
|
||||
// 32-bit
|
||||
if (elf_class == ELF_Class_32){
|
||||
sym32_raw = (ELF_Symbol32*)(input_data.str + foff);
|
||||
symbol_count_cap = symbol_section->size/sizeof(*sym32_raw);
|
||||
}
|
||||
|
||||
// 64-bit
|
||||
if (elf_class == ELF_Class_64){
|
||||
sym64_raw = (ELF_Symbol64*)(input_data.str + foff);
|
||||
symbol_count_cap = symbol_section->size/sizeof(*sym64_raw);
|
||||
}
|
||||
}
|
||||
|
||||
// extract symbol count
|
||||
symbol_count = symbol_section->info;
|
||||
symbol_count = ClampTop(symbol_count, symbol_count_cap);
|
||||
}
|
||||
|
||||
// normalize symbol table
|
||||
ELF_Symbol64 *symbols = 0;
|
||||
if (sym32_raw != 0){
|
||||
symbols = push_array(arena, ELF_Symbol64, symbol_count);
|
||||
for (U32 i = 0; i < symbol_count; i += 1){
|
||||
elf_symbol64_from_symbol32(symbols + i, sym32_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
else if (sym64_raw != 0){
|
||||
symbols = push_array(arena, ELF_Symbol64, symbol_count);
|
||||
for (U32 i = 0; i < symbol_count; i += 1){
|
||||
elf_symbol64_from_symbol64(symbols + i, sym64_raw + i, elf_encoding);
|
||||
}
|
||||
}
|
||||
|
||||
// fill symbol table
|
||||
if (symbols != 0){
|
||||
ELFDUMP_SymbolTable *symbol_table = &symbol_tables[k];
|
||||
symbol_table->symbols = symbols;
|
||||
symbol_table->count = symbol_count;
|
||||
symbol_table->string_table_first = string_table_first;
|
||||
symbol_table->string_table_opl = string_table_opl;
|
||||
}
|
||||
}
|
||||
|
||||
// relocations
|
||||
ELFDUMP_Relocs *first_relocs = 0;
|
||||
ELFDUMP_Relocs *last_relocs = 0;
|
||||
|
||||
if (sections_good){
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
|
||||
ELF_RelocationAdd64 *relocs = 0;
|
||||
U64 reloc_count = 0;
|
||||
|
||||
ELF_Section64 *section = sections + i;
|
||||
void *section_data = input_data.str + section->offset;
|
||||
|
||||
switch (section->type){
|
||||
case ELF_SectionType_REL:
|
||||
{
|
||||
if (elf_class == ELF_Class_32){
|
||||
ELF_Relocation32 *reloc32 = (ELF_Relocation32*)section_data;
|
||||
reloc_count = section->size/sizeof(*reloc32);
|
||||
relocs = elf_reloca64_from_reloc32(arena, reloc32, reloc_count, elf_encoding);
|
||||
}
|
||||
else{
|
||||
ELF_Relocation64 *reloc64 = (ELF_Relocation64*)section_data;
|
||||
reloc_count = section->size/sizeof(*reloc64);
|
||||
relocs = elf_reloca64_from_reloc64(arena, reloc64, reloc_count, elf_encoding);
|
||||
}
|
||||
}break;
|
||||
|
||||
case ELF_SectionType_RELA:
|
||||
{
|
||||
if (elf_class == ELF_Class_32){
|
||||
ELF_RelocationAdd32 *reloca32 = (ELF_RelocationAdd32*)section_data;
|
||||
reloc_count = section->size/sizeof(*reloca32);
|
||||
relocs = elf_reloca64_from_reloca32(arena, reloca32, reloc_count, elf_encoding);
|
||||
}
|
||||
else{
|
||||
ELF_RelocationAdd64 *reloca64 = (ELF_RelocationAdd64*)section_data;
|
||||
reloc_count = section->size/sizeof(*reloca64);
|
||||
relocs = elf_reloca64_from_reloca64(arena, reloca64, reloc_count, elf_encoding);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
||||
if (reloc_count > 0){
|
||||
ELFDUMP_Relocs *r = push_array(arena, ELFDUMP_Relocs, 1);
|
||||
SLLQueuePush(first_relocs, last_relocs, r);
|
||||
r->section_idx = i;
|
||||
r->symbol_table_section_idx = section->link;
|
||||
r->target_section_idx = section->info;
|
||||
r->relocs = relocs;
|
||||
r->count = reloc_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////
|
||||
///// DUMP /////
|
||||
////////////////
|
||||
|
||||
if (!elf_header_good){
|
||||
m4_printf("Unsuccessful parse\n");
|
||||
}
|
||||
|
||||
if (elf_header_good){
|
||||
ArenaTemp scratch = arena_get_scratch(0, 0);
|
||||
|
||||
// elf header
|
||||
{
|
||||
|
||||
for (U32 i = 0; i < ELF_NUM_IDENT; i += 1){
|
||||
String8 ident_string = elf_str8_from_identification_idx(i);
|
||||
|
||||
String8 val_string = {0};
|
||||
switch (i){
|
||||
case ELF_IdentificationIdx_CLASS:
|
||||
{
|
||||
val_string = elf_str8_from_class(hdr.ident[i]);
|
||||
}break;
|
||||
|
||||
case ELF_IdentificationIdx_DATA:
|
||||
{
|
||||
val_string = elf_str8_from_encoding(hdr.ident[i]);
|
||||
}break;
|
||||
|
||||
case ELF_IdentificationIdx_OSABI:
|
||||
{
|
||||
val_string = elf_str8_from_osabi(hdr.ident[i]);
|
||||
}break;
|
||||
|
||||
default:
|
||||
{
|
||||
val_string = str8_pushf(scratch.arena, "0x%02x", hdr.ident[i]);
|
||||
}break;
|
||||
}
|
||||
|
||||
m4_printf("elf_header.ident[%10S] = %S\n", &ident_string, &val_string);
|
||||
}
|
||||
|
||||
String8 type_string = elf_str8_from_file_type(hdr.type);
|
||||
String8 machine_string = elf_str8_from_machine_type(hdr.machine);
|
||||
|
||||
m4_printf("elf_header.type = %S\n", &type_string);
|
||||
m4_printf("elf_header.machine = %S\n", &machine_string);
|
||||
m4_printf("elf_header.version = %u\n", hdr.version);
|
||||
m4_printf("elf_header.entry = 0x%08llx\n", hdr.entry);
|
||||
m4_printf("elf_header.segment_table_foff = 0x%08llx\n", hdr.segment_table_foff);
|
||||
m4_printf("elf_header.section_table_foff = 0x%08llx\n", hdr.section_table_foff);
|
||||
// TODO(allen): flags pneumonics
|
||||
m4_printf("elf_header.flags = 0x%08x\n", hdr.flags);
|
||||
m4_printf("elf_header.header_size = %u\n", hdr.header_size);
|
||||
m4_printf("elf_header.segment_size = %u\n", hdr.segment_size);
|
||||
m4_printf("elf_header.segment_count = %u\n", hdr.segment_count);
|
||||
m4_printf("elf_header.section_size = %u\n", hdr.section_size);
|
||||
m4_printf("elf_header.section_count = %u\n", hdr.section_count);
|
||||
m4_printf("elf_header.string_section_index = %u\n", hdr.string_section_index);
|
||||
|
||||
m4_printf("\n");
|
||||
|
||||
arena_release_scratch(&scratch);
|
||||
}
|
||||
|
||||
// sections
|
||||
if (sections_good){
|
||||
|
||||
// get the section name string table
|
||||
U8 *string_table_first = 0;
|
||||
U8 *string_table_opl = 0;
|
||||
{
|
||||
ELF_Section64 *string_table = 0;
|
||||
if (hdr.string_section_index != ELF_SectionIndex_UNDEF &&
|
||||
hdr.string_section_index != ELF_SectionIndex_XINDEX){
|
||||
string_table = sections + hdr.string_section_index;
|
||||
}
|
||||
else if (hdr.string_section_index == ELF_SectionIndex_XINDEX){
|
||||
U32 string_section_index = sections[0].link;
|
||||
string_table = sections + string_section_index;
|
||||
}
|
||||
|
||||
if (string_table != 0){
|
||||
string_table_first = input_data.str + string_table->offset;
|
||||
string_table_opl = string_table_first + string_table->size;
|
||||
}
|
||||
}
|
||||
|
||||
// dump each section
|
||||
for (U32 i = 0; i < hdr.section_count; i += 1){
|
||||
ELF_Section64 *section = sections + i;
|
||||
|
||||
String8 name = str8_cstring_capped(string_table_first + section->name,
|
||||
string_table_opl);
|
||||
String8 type_string = elf_str8_from_section_type(section->type);
|
||||
String8 flags_string =
|
||||
elf_str8_from_section_flags(scratch.arena, section->flags);
|
||||
|
||||
m4_printf("section[%u] = {\n"
|
||||
" name = \"%S\",\n"
|
||||
" type = %S (0x%x),\n"
|
||||
" flags = %S,\n"
|
||||
" addr = 0x%08llx,\n"
|
||||
" size = %$llu,\n"
|
||||
" link = %u,\n"
|
||||
" info = %u,\n"
|
||||
" addralign = %llu,\n"
|
||||
" entsize = %$llu,\n"
|
||||
"}\n",
|
||||
i, &name,
|
||||
&type_string, section->type,
|
||||
&flags_string,
|
||||
section->addr,
|
||||
section->size,
|
||||
section->link,
|
||||
section->info,
|
||||
section->addralign,
|
||||
section->entsize);
|
||||
|
||||
}
|
||||
|
||||
m4_printf("\n");
|
||||
|
||||
}
|
||||
|
||||
// segments
|
||||
if (segments_good){
|
||||
for (U32 i = 0; i < hdr.segment_count; i += 1){
|
||||
ELF_Segment64 *segment = segments + i;
|
||||
|
||||
String8 type_string = elf_str8_from_segment_type(segment->type);
|
||||
String8 flags_string =
|
||||
elf_str8_from_segment_flags(scratch.arena, segment->flags);
|
||||
|
||||
m4_printf("segment[%u] = {\n"
|
||||
" type = %S (0x%x),\n"
|
||||
" flags = %S,\n"
|
||||
" offset = 0x%08llx,\n"
|
||||
" vaddr = 0x%08llx,\n"
|
||||
" paddr = 0x%08llx,\n"
|
||||
" file_size = %$llu,\n"
|
||||
" memory_size = %$llu,\n"
|
||||
" align = %llu,\n"
|
||||
"}\n",
|
||||
i,
|
||||
&type_string, segment->type,
|
||||
&flags_string,
|
||||
segment->offset,
|
||||
segment->vaddr,
|
||||
segment->paddr,
|
||||
segment->file_size,
|
||||
segment->memory_size,
|
||||
segment->align);
|
||||
}
|
||||
|
||||
m4_printf("\n");
|
||||
}
|
||||
|
||||
// symbol tables
|
||||
String8 symbol_table_name[2];
|
||||
symbol_table_name[0] = str8_lit("symtab");
|
||||
symbol_table_name[1] = str8_lit("dynsym");
|
||||
|
||||
for (U32 k = 0; k < 2; k += 1){
|
||||
ELFDUMP_SymbolTable *symbol_table = &symbol_tables[k];
|
||||
|
||||
if (symbol_table->symbols != 0){
|
||||
for (U32 i = 0; i < symbol_table->count; i += 1){
|
||||
ELF_Symbol64 *symbol = symbol_table->symbols + i;
|
||||
|
||||
String8 name =
|
||||
str8_cstring_capped(symbol_table->string_table_first + symbol->name,
|
||||
symbol_table->string_table_opl);
|
||||
|
||||
ELF_SymbolBinding bind = ELF_Symbol_BindFromInfo(symbol->info);
|
||||
ELF_SymbolType type = ELF_Symbol_TypeFromInfo(symbol->info);
|
||||
|
||||
ELF_SymbolVis vis = ELF_Symbol_VisFromOther(symbol->other);
|
||||
|
||||
String8 bind_string = elf_str8_from_symbol_binding(bind);
|
||||
String8 type_string = elf_str8_from_symbol_type(type);
|
||||
String8 vis_string = elf_str8_from_symbol_vis(vis);
|
||||
|
||||
m4_printf("%S[%u] = {\n"
|
||||
" name = \"%S\",\n"
|
||||
" info = bind: %S, type: %S,\n"
|
||||
" other = vis: %S,\n"
|
||||
" section_index = %u,\n"
|
||||
" value = %llu,\n"
|
||||
" size = %$llu,\n"
|
||||
"}\n",
|
||||
&symbol_table_name[k], i,
|
||||
&name,
|
||||
&bind_string, &type_string,
|
||||
&vis_string,
|
||||
symbol->section_index,
|
||||
symbol->value,
|
||||
symbol->size);
|
||||
}
|
||||
|
||||
m4_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// relocations
|
||||
for (ELFDUMP_Relocs *relocs = first_relocs;
|
||||
relocs != 0;
|
||||
relocs = relocs->next){
|
||||
m4_printf("relocations(%u) = {\n", relocs->section_idx);
|
||||
|
||||
U32 count = relocs->count;
|
||||
ELF_RelocationAdd64 *relocptr = relocs->relocs;
|
||||
for (U32 i = 0; i < count; i += 1, relocptr += 1){
|
||||
m4_printf(" { offset = %llu,\n"
|
||||
" info = %llu,\n"
|
||||
" addend = %lld,\n"
|
||||
" },\n", relocptr->offset, relocptr->info, relocptr->addend);
|
||||
}
|
||||
|
||||
m4_printf("}\n\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
#ifndef MR4TH_ELF_DUMP_H
|
||||
#define MR4TH_ELF_DUMP_H
|
||||
|
||||
////////////////////////////////
|
||||
// ELF DUMP Arguments Types
|
||||
|
||||
typedef struct ELFDUMP_Arguments{
|
||||
String8 input_file_name;
|
||||
} ELFDUMP_Arguments;
|
||||
|
||||
////////////////////////////////
|
||||
// ELF DUMP Types
|
||||
|
||||
typedef struct ELFDUMP_SymbolTable{
|
||||
ELF_Symbol64 *symbols;
|
||||
U32 count;
|
||||
U8 *string_table_first;
|
||||
U8 *string_table_opl;
|
||||
} ELFDUMP_SymbolTable;
|
||||
|
||||
typedef struct ELFDUMP_Relocs{
|
||||
struct ELFDUMP_Relocs *next;
|
||||
U32 section_idx;
|
||||
U32 symbol_table_section_idx;
|
||||
U32 target_section_idx;
|
||||
U32 count;
|
||||
ELF_RelocationAdd64 *relocs;
|
||||
} ELFDUMP_Relocs;
|
||||
|
||||
////////////////////////////////
|
||||
// ELF DUMP Arguments Functions
|
||||
|
||||
function ELFDUMP_Arguments* elfdump_args(Arena *arena, String8List *args);
|
||||
|
||||
////////////////////////////////
|
||||
// Entry Point
|
||||
|
||||
int main(int argc, char **argv);
|
||||
|
||||
#endif //MR4TH_ELF_DUMP_H
|
||||
|
|
@ -1,831 +0,0 @@
|
|||
#ifndef MR4TH_PE_H
|
||||
#define MR4TH_PE_H
|
||||
|
||||
/*
|
||||
** PE/COFF total layout summary:
|
||||
**
|
||||
** MS-DOS Stub [image only]
|
||||
** *****************
|
||||
** ptr> PE Signature [image only]
|
||||
** COFF Header
|
||||
** Optional Header [image only]
|
||||
** Section Table
|
||||
*/
|
||||
|
||||
////////////////////////////////
|
||||
// Types: COFF / PE
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
// MS-DOS Stub
|
||||
|
||||
// located at offset=0 in valid executables
|
||||
#define PE_MSDOS_MAGIC 0x5A4D
|
||||
|
||||
typedef struct PE_DosHeader{
|
||||
U16 magic;
|
||||
U16 last_page_size;
|
||||
U16 page_count;
|
||||
U16 reloc_count;
|
||||
U16 paragraph_header_size;
|
||||
U16 min_paragraph;
|
||||
U16 max_paragraph;
|
||||
U16 init_ss;
|
||||
U16 init_sp;
|
||||
U16 checksum;
|
||||
U16 init_ip;
|
||||
U16 init_cs;
|
||||
U16 reloc_table_file_off;
|
||||
U16 overlay_number;
|
||||
U16 reserved[4];
|
||||
U16 oem_id;
|
||||
U16 oem_info;
|
||||
U16 reserved2[10];
|
||||
U32 coff_file_offset;
|
||||
} PE_DosHeader;
|
||||
|
||||
// pe signature
|
||||
|
||||
#define PE_SIGNATURE 0x00004550
|
||||
|
||||
// coff header
|
||||
|
||||
#define PE_MachineType_XList(X)\
|
||||
X(UNKNOWN, 0x0)\
|
||||
X(ALPHA, 0x184)\
|
||||
X(ALPHA64, 0x284)\
|
||||
X(AM33, 0x1d3)\
|
||||
X(AMD64, 0x8664)\
|
||||
X(ARM, 0x1c0)\
|
||||
X(ARM64, 0xaa64)\
|
||||
X(ARMNT, 0x1c4)\
|
||||
X(EBC, 0xebc)\
|
||||
X(I386, 0x14c)\
|
||||
X(IA64, 0x200)\
|
||||
X(LOONGARCH32, 0x6232)\
|
||||
X(LOONGARCH64, 0x6264)\
|
||||
X(M32R, 0x9041)\
|
||||
X(MIPS16, 0x266)\
|
||||
X(MIPSFPU, 0x366)\
|
||||
X(MIPSFPU16, 0x466)\
|
||||
X(POWERPC, 0x1f0)\
|
||||
X(POWERPCFP, 0x1f1)\
|
||||
X(R4000, 0x166)\
|
||||
X(RISCV32, 0x5032)\
|
||||
X(RISCV64, 0x5064)\
|
||||
X(RISCV128, 0x5128)\
|
||||
X(SH3, 0x1a2)\
|
||||
X(SH3DSP, 0x1a3)\
|
||||
X(SH4, 0x1a6)\
|
||||
X(SH5, 0x1a8)\
|
||||
X(THUMB, 0x1c2)\
|
||||
X(WCEMIPSV2, 0x169)
|
||||
|
||||
typedef U16 PE_MachineType;
|
||||
enum{
|
||||
#define X(N,C) PE_MachineType_##N = C,
|
||||
PE_MachineType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_Flags_XList(X)\
|
||||
X(RELOCS_STRIPPED, 0x0001)\
|
||||
X(EXECUTABLE_IMAGE, 0x0002)\
|
||||
X(LINE_NUMS_STRIPPED, 0x0004)\
|
||||
X(LOCAL_SYMS_STRIPPED, 0x0008)\
|
||||
X(AGGRESSIVE_WS_TRIM, 0x0010)\
|
||||
X(LARGE_ADDRESS_AWARE, 0x0020)\
|
||||
X(RESERVED, 0x0040)\
|
||||
X(BYTES_REVERSED_LO, 0x0080)\
|
||||
X(32BIT_MACHINE, 0x0100)\
|
||||
X(DEBUG_STRIPPED, 0x0200)\
|
||||
X(REMOVABLE_RUN_FROM_SWAP, 0x0400)\
|
||||
X(NET_RUN_FROM_SWAP, 0x0800)\
|
||||
X(SYSTEM, 0x1000)\
|
||||
X(DLL, 0x2000)\
|
||||
X(UP_SYSTEM_ONLY, 0x4000)\
|
||||
X(BYTES_REVERSED_HI, 0x8000)\
|
||||
|
||||
typedef U16 PE_Flags;
|
||||
enum{
|
||||
#define X(N,C) PE_Flag_##N = C,
|
||||
PE_Flags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef struct PE_CoffHeader{
|
||||
PE_MachineType machine_type;
|
||||
U16 section_count;
|
||||
U32 time_stamp;
|
||||
U32 symbol_table_foff;
|
||||
U32 symbol_count;
|
||||
U16 optional_header_size;
|
||||
PE_Flags flags;
|
||||
} PE_CoffHeader;
|
||||
|
||||
// optional headers
|
||||
|
||||
#define PE_OptionalHeaderMagic_XList(X)\
|
||||
X(ROM, 0x107)\
|
||||
X(PE32, 0x10B)\
|
||||
X(PE32Plus, 0x20B)
|
||||
|
||||
typedef U16 PE_OptionalHeaderMagic;
|
||||
enum{
|
||||
#define X(N,C) PE_OptionalHeaderMagic_##N = C,
|
||||
PE_OptionalHeaderMagic_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_WindowsSubsystem_XList(X)\
|
||||
X(UNKNOWN, 0)\
|
||||
X(NATIVE, 1)\
|
||||
X(WINDOWS_GUI, 2)\
|
||||
X(WINDOWS_CUI, 3)\
|
||||
X(OS2_CUI, 5)\
|
||||
X(POSIX_CUI, 7)\
|
||||
X(NATIVE_WINDOWS, 8)\
|
||||
X(WINDOWS_CE_GUI, 9)\
|
||||
X(EFI_APPLICATION, 10)\
|
||||
X(EFI_BOOT_SERVICE_DRIVER, 11)\
|
||||
X(EFI_RUNTIME_DRIVER, 12)\
|
||||
X(EFI_ROM, 13)\
|
||||
X(XBOX, 14)\
|
||||
X(WINDOWS_BOOT_APPLICATION, 16)
|
||||
|
||||
typedef U16 PE_WindowsSubsystem;
|
||||
enum{
|
||||
#define X(N,C) PE_WindowsSubsystem_##N = C,
|
||||
PE_WindowsSubsystem_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_DLLFlags_XList(X)\
|
||||
X(RESERVED0, 0x0001)\
|
||||
X(RESERVED1, 0x0002)\
|
||||
X(RESERVED2, 0x0004)\
|
||||
X(RESERVED3, 0x0008)\
|
||||
X(HIGH_ENTROPY_VA, 0x0020)\
|
||||
X(DYNAMIC_BASE, 0x0040)\
|
||||
X(FORCE_INTEGRITY, 0x0080)\
|
||||
X(NX_COMPAT, 0x0100)\
|
||||
X(NO_ISOLATION, 0x0200)\
|
||||
X(NO_SEH, 0x0400)\
|
||||
X(NO_BIND, 0x0800)\
|
||||
X(APPCONTAINER, 0x1000)\
|
||||
X(WDM_DRIVER, 0x2000)\
|
||||
X(GUARD_CF, 0x4000)\
|
||||
X(TERMINAL_SERVER_AWARE, 0x8000)
|
||||
|
||||
typedef U16 PE_DLLFlags;
|
||||
enum{
|
||||
#define X(N,C) PE_DLLFlag_##N = C,
|
||||
PE_DLLFlags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef struct PE_OptionalHeader32{
|
||||
PE_OptionalHeaderMagic magic;
|
||||
U8 linker_version_major;
|
||||
U8 linker_version_minor;
|
||||
U32 total_size_text; // 'text' means executable code here
|
||||
U32 total_size_inited_data;
|
||||
U32 total_size_zeroed_data;
|
||||
U32 entry_point_voff;
|
||||
U32 text_voff;
|
||||
U32 data_voff;
|
||||
U32 image_base_vaddr;
|
||||
U32 section_alignment;
|
||||
U32 file_alignment;
|
||||
U16 os_version_major;
|
||||
U16 os_version_minor;
|
||||
U16 image_version_major;
|
||||
U16 image_version_minor;
|
||||
U16 subsystem_version_major;
|
||||
U16 subsystem_version_minor;
|
||||
U32 reserved0;
|
||||
U32 image_size;
|
||||
U32 headers_size;
|
||||
U32 checksum;
|
||||
PE_WindowsSubsystem subsystem;
|
||||
PE_DLLFlags dll_flags;
|
||||
U32 stack_size_reserve;
|
||||
U32 stack_size_commit;
|
||||
U32 heap_size_reserve;
|
||||
U32 heap_size_commit;
|
||||
U32 reserved1;
|
||||
U32 data_directory_count;
|
||||
} PE_OptionalHeader32;
|
||||
|
||||
typedef struct PE_OptionalHeader32Plus{
|
||||
U16 magic;
|
||||
U8 linker_version_major;
|
||||
U8 linker_version_minor;
|
||||
U32 total_size_text; // 'text' means executable code here
|
||||
U32 total_size_inited_data;
|
||||
U32 total_size_zeroed_data;
|
||||
U32 entry_point_voff;
|
||||
U32 text_voff;
|
||||
U64 image_base_vaddr;
|
||||
U32 section_alignment;
|
||||
U32 file_alignment;
|
||||
U16 os_version_major;
|
||||
U16 os_version_minor;
|
||||
U16 image_version_major;
|
||||
U16 image_version_minor;
|
||||
U16 subsystem_version_major;
|
||||
U16 subsystem_version_minor;
|
||||
U32 reserved0;
|
||||
U32 image_size;
|
||||
U32 headers_size;
|
||||
U32 checksum;
|
||||
PE_WindowsSubsystem subsystem;
|
||||
PE_DLLFlags dll_flags;
|
||||
U64 stack_size_reserve;
|
||||
U64 stack_size_commit;
|
||||
U64 heap_size_reserve;
|
||||
U64 heap_size_commit;
|
||||
U32 reserved1;
|
||||
U32 data_directory_count;
|
||||
} PE_OptionalHeader32Plus;
|
||||
|
||||
typedef struct PE_DataDirectory{
|
||||
U32 voff;
|
||||
U32 size;
|
||||
} PE_DataDirectory;
|
||||
|
||||
#define PE_DataDirectoryIdx_XList(X)\
|
||||
X(ExportTable, "Export Table", 0)\
|
||||
X(ImportTable, "Import Table", 1)\
|
||||
X(ResourceTable, "Resource Table", 2)\
|
||||
X(ExceptionTable, "Exception Table", 3)\
|
||||
X(CertificateTable, "Certificate Table", 4)\
|
||||
X(BaseRelocationTable, "Base Relocation Table", 5)\
|
||||
X(Debug, "Debug Directories", 6)\
|
||||
X(Architecture, "Architecture", 7)\
|
||||
X(GlobalPtr, "Global Ptr", 8)\
|
||||
X(TLSTable, "TLS Table", 9)\
|
||||
X(LoadConfigTable, "Load Config Table", 10)\
|
||||
X(BoundImport, "Bound Import", 11)\
|
||||
X(IAT, "IAT", 12)\
|
||||
X(DelayImportDescriptor, "Delay Import Descriptor", 13)\
|
||||
X(CLRRuntimeHeader, "CLR Runtime Header", 14)\
|
||||
X(Reserved, "Reserved", 15)
|
||||
|
||||
typedef U32 PE_DataDirectoryIdx;
|
||||
enum{
|
||||
#define X(N,D,C) PE_DataDirectoryIdx_##N = C,
|
||||
PE_DataDirectoryIdx_XList(X)
|
||||
#undef X
|
||||
PE_DataDirectoryIdx_COUNT
|
||||
};
|
||||
|
||||
// section table
|
||||
|
||||
#define PE_SectionFlags_XList(X)\
|
||||
X(TYPE_NO_PAD, 0x00000008)\
|
||||
X(CNT_CODE, 0x00000020)\
|
||||
X(CNT_INITIALIZED_DATA, 0x00000040)\
|
||||
X(CNT_UNINITIALIZED_DATA, 0x00000080)\
|
||||
X(LNK_OTHER, 0x00000100)\
|
||||
X(LNK_INFO, 0x00000200)\
|
||||
X(LNK_REMOVE, 0x00000800)\
|
||||
X(LNK_COMDAT, 0x00001000)\
|
||||
X(GPREL, 0x00008000)\
|
||||
X(MEM_16BIT, 0x00020000)\
|
||||
X(MEM_LOCKED, 0x00040000)\
|
||||
X(MEM_PRELOAD, 0x00080000)\
|
||||
X(LNK_NRELOC_OVFL, 0x01000000)\
|
||||
X(MEM_DISCARDABLE, 0x02000000)\
|
||||
X(MEM_NOT_CACHED, 0x04000000)\
|
||||
X(MEM_NOT_PAGED, 0x08000000)\
|
||||
X(MEM_SHARED, 0x10000000)\
|
||||
X(MEM_EXECUTE, 0x20000000)\
|
||||
X(MEM_READ, 0x40000000)\
|
||||
X(MEM_WRITE, 0x80000000)
|
||||
|
||||
#define PE_SectionAlignFromSectionFlags(f) ((f)&0x00F00000)
|
||||
|
||||
#define PE_SectionAlign_XList(X)\
|
||||
X(1, 0x00100000)\
|
||||
X(2, 0x00200000)\
|
||||
X(4, 0x00300000)\
|
||||
X(8, 0x00400000)\
|
||||
X(16, 0x00500000)\
|
||||
X(32, 0x00600000)\
|
||||
X(64, 0x00700000)\
|
||||
X(128, 0x00800000)\
|
||||
X(256, 0x00900000)\
|
||||
X(512, 0x00A00000)\
|
||||
X(1024, 0x00B00000)\
|
||||
X(2048, 0x00C00000)\
|
||||
X(4096, 0x00D00000)\
|
||||
X(8192, 0x00E00000)
|
||||
|
||||
typedef U32 PE_SectionFlags;
|
||||
enum{
|
||||
#define X(N,C) PE_SectionFlag_##N = C,
|
||||
PE_SectionFlags_XList(X)
|
||||
#undef X
|
||||
|
||||
#define X(N,C) PE_SectionAlign_##N = C,
|
||||
PE_SectionAlign_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef struct PE_SectionHeader{
|
||||
U8 name[8];
|
||||
U32 vsize;
|
||||
U32 voff;
|
||||
U32 fsize;
|
||||
U32 foff;
|
||||
U32 relocations_foff;
|
||||
U32 line_numbers_foff;
|
||||
U16 relocation_count;
|
||||
U16 line_number_count;
|
||||
PE_SectionFlags flags;
|
||||
} PE_SectionHeader;
|
||||
|
||||
// coff relocations
|
||||
|
||||
// TODO(allen): these are just the "x64" values
|
||||
// generalize PE_CoffRelocationType to all machines
|
||||
#define PE_CoffRelocationType_XList(X)\
|
||||
X(ABSOLUTE, 0x0000)\
|
||||
X(ADDR64, 0x0001)\
|
||||
X(ADDR32, 0x0002)\
|
||||
X(ADDR32NB, 0x0003)\
|
||||
X(REL32, 0x0004)\
|
||||
X(REL32_1, 0x0005)\
|
||||
X(REL32_2, 0x0006)\
|
||||
X(REL32_3, 0x0007)\
|
||||
X(REL32_4, 0x0008)\
|
||||
X(REL32_5, 0x0009)\
|
||||
X(SECTION, 0x000A)\
|
||||
X(SECREL, 0x000B)\
|
||||
X(SECREL7, 0x000C)\
|
||||
X(TOKEN, 0x000D)\
|
||||
X(SREL32, 0x000E)\
|
||||
X(PAIR, 0x000F)\
|
||||
X(SSPAN32, 0x0010)
|
||||
|
||||
typedef U16 PE_CoffRelocationType;
|
||||
enum{
|
||||
#define X(N,C) PE_CoffRelocationType_##N = C,
|
||||
PE_CoffRelocationType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef struct PE_CoffRelocation{
|
||||
U32 off;
|
||||
U32 symbol_idx;
|
||||
PE_CoffRelocationType type;
|
||||
} PE_CoffRelocation;
|
||||
|
||||
// coff symbol table
|
||||
|
||||
#define PE_CoffSymbolStorageClass_XList(X)\
|
||||
X(END_OF_FUNCTION, 0xFF)\
|
||||
X(NULL, 0)\
|
||||
X(AUTOMATIC, 1)\
|
||||
X(EXTERNAL, 2)\
|
||||
X(STATIC, 3)\
|
||||
X(REGISTER, 4)\
|
||||
X(EXTERNAL_DEF, 5)\
|
||||
X(LABEL, 6)\
|
||||
X(UNDEFINED_LABEL, 7)\
|
||||
X(MEMBER_OF_STRUCT, 8)\
|
||||
X(ARGUMENT, 9)\
|
||||
X(STRUCT_TAG, 10)\
|
||||
X(MEMBER_OF_UNION, 11)\
|
||||
X(UNION_TAG, 12)\
|
||||
X(TYPE_DEFINITION, 13)\
|
||||
X(UNDEFINED_STATIC, 14)\
|
||||
X(ENUM_TAG, 15)\
|
||||
X(MEMBER_OF_ENUM, 16)\
|
||||
X(REGISTER_PARAM, 17)\
|
||||
X(BIT_FIELD, 18)\
|
||||
X(BLOCK, 100)\
|
||||
X(FUNCTION, 101)\
|
||||
X(END_OF_STRUCT, 102)\
|
||||
X(FILE, 103)\
|
||||
X(SECTION, 104)\
|
||||
X(WEAK_EXTERNAL, 105)\
|
||||
X(CLR_TOKEN, 107)
|
||||
|
||||
typedef U8 PE_CoffSymbolStorageClass;
|
||||
enum{
|
||||
#define X(N,C) PE_CoffSymbolStorageClass_##N = C,
|
||||
PE_CoffSymbolStorageClass_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_CoffSymbolTypeLo_XList(X)\
|
||||
X(NULL, 0)\
|
||||
X(VOID, 1)\
|
||||
X(CHAR, 2)\
|
||||
X(SHORT, 3)\
|
||||
X(INT, 4)\
|
||||
X(LONG, 5)\
|
||||
X(FLOAT, 6)\
|
||||
X(DOUBLE, 7)\
|
||||
X(STRUCT, 8)\
|
||||
X(UNION, 9)\
|
||||
X(ENUM, 10)\
|
||||
X(MOE, 11)\
|
||||
X(BYTE, 12)\
|
||||
X(WORD, 13)\
|
||||
X(UINT, 14)\
|
||||
X(DWORD, 15)
|
||||
|
||||
enum{
|
||||
#define X(N,C) PE_CoffSymbolTypeLo_##N = C,
|
||||
PE_CoffSymbolTypeLo_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_CoffSymbolTypeHi_XList(X)\
|
||||
X(NULL, 0)\
|
||||
X(POINTER, 1)\
|
||||
X(FUNCTION, 2)\
|
||||
X(ARRAY, 3)
|
||||
|
||||
enum{
|
||||
#define X(N,C) PE_CoffSymbolTypeHi_##N = C,
|
||||
PE_CoffSymbolTypeHi_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef U16 PE_CoffSymbolType;
|
||||
|
||||
typedef struct PE_CoffSymbolRecord{
|
||||
union{
|
||||
U8 raw[8];
|
||||
struct{
|
||||
U32 zero;
|
||||
U32 string_table_off;
|
||||
};
|
||||
} name;
|
||||
U32 val;
|
||||
S16 sec_number;
|
||||
PE_CoffSymbolType type;
|
||||
PE_CoffSymbolStorageClass storage_class;
|
||||
U8 aux_symbol_count;
|
||||
} PE_CoffSymbolRecord;
|
||||
|
||||
// TODO(allen): COFF Line Numbers (Deprecated)
|
||||
|
||||
// TODO(allen): Attribute Certificate Table
|
||||
|
||||
// TODO(allen): Delay-Load Import Tables
|
||||
|
||||
// export data
|
||||
|
||||
typedef struct PE_ExportDirectoryTable{
|
||||
U32 reserved0;
|
||||
U32 time_stamp;
|
||||
U16 version_major;
|
||||
U16 version_minor;
|
||||
U32 binary_name_voff;
|
||||
U32 ordinal_base;
|
||||
U32 export_count;
|
||||
U32 ordinal_count;
|
||||
U32 export_voff;
|
||||
U32 name_voff;
|
||||
U32 ordinal_voff;
|
||||
|
||||
/*
|
||||
** NOTE(allen): Additional Structure Information
|
||||
** export : [ export_count] U32;
|
||||
** name : [ordinal_count] U32;
|
||||
** ordinal : [ordinal_count] U16;
|
||||
**
|
||||
** for i in [0,ordinal_count):
|
||||
** name[i] : voff to a cstring
|
||||
** export[ordinal[i]] : voff to a symbol OR voff to forwarding string
|
||||
** (voffs in export range are fowarding strings)
|
||||
** ordinal[i] : "unbiased ordinal"
|
||||
** ordinal[i] + ordinal_base : "ordinal"
|
||||
*/
|
||||
|
||||
} PE_ExportDirectoryTable;
|
||||
|
||||
// import data
|
||||
|
||||
typedef struct PE_ImportDirectoryTable{
|
||||
U32 import_lookup_table_voff;
|
||||
U32 time_stamp;
|
||||
U32 first_forwarder_idx;
|
||||
U32 name_voff;
|
||||
U32 import_address_table_voff;
|
||||
|
||||
/*
|
||||
** NOTE(allen): Additional Structure Information
|
||||
** IF PE32:
|
||||
** import_lookup_table : null-terminated [] U32;
|
||||
** IF PE32Plus:
|
||||
** import_lookup_table : null-terminated [] U64;
|
||||
**
|
||||
** WHEN lookup = import_lookup_table[i]
|
||||
** if (HighBits1(lookup)){
|
||||
** ordinal = LowBits16(lookup)
|
||||
** }
|
||||
** else{
|
||||
** hint_voff = LowBits31(lookup)
|
||||
** hint : { U16, null-terminated-cstring }
|
||||
** }
|
||||
*/
|
||||
|
||||
} PE_ImportDirectoryTable;
|
||||
|
||||
// exception handling
|
||||
|
||||
#if 0
|
||||
// NOTE(allen): untested - from documentation
|
||||
typedef struct PE_ExceptionHandler_MIPS{
|
||||
U32 begin_vaddr;
|
||||
U32 end_vaddr;
|
||||
U32 handler_vaddr;
|
||||
U32 handler_data;
|
||||
U32 prolog_end_vaddr;
|
||||
} PE_ExceptionHandler_MIPS;
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// NOTE(allen): untested - from documentation
|
||||
typedef struct PE_ExceptionHandler_ARM{
|
||||
U32 begin_vaddr;
|
||||
U32 info;
|
||||
} PE_ExceptionHandler_ARM;
|
||||
|
||||
#define PE_ExceptionHandler_ARMInfo_PrologLength(i) (((i) >> 0)&0xFF)
|
||||
#define PE_ExceptionHandler_ARMInfo_FuncLength(i) (((i) >> 8)&0x3FFFFF)
|
||||
#define PE_ExceptionHandler_ARMInfo_32Bit(i) (((i) >> 30)&0x1)
|
||||
#define PE_ExceptionHandler_ARMInfo_ExceptionFlag(i) (((i) >> 31)&0x1)
|
||||
#endif
|
||||
|
||||
typedef struct PE_ExceptionHandler_X86{
|
||||
U32 begin_voff;
|
||||
U32 end_voff;
|
||||
U32 unwind_voff;
|
||||
} PE_ExceptionHandler_X86;
|
||||
|
||||
typedef struct PE_UnwindInfo{
|
||||
U8 header;
|
||||
U8 prolog_size;
|
||||
U8 code_count;
|
||||
U8 frame;
|
||||
} PE_UnwindInfo;
|
||||
|
||||
#define PE_UnwindInfo_VersionFromHeader(x) ((x)&7)
|
||||
#define PE_UnwindInfo_FlagsFromHeader(x) (((x)>>3)&0x1F)
|
||||
|
||||
#define PE_UnwindInfoFlags_XList(X)\
|
||||
X(EHANDLER, (1 << 0))\
|
||||
X(UHANDLER, (1 << 1))\
|
||||
X(CHAINED, (1 << 2))
|
||||
|
||||
typedef U8 PE_UnwindInfoFlags;
|
||||
enum{
|
||||
#define X(N,C) PE_UnwindInfoFlag_##N = C,
|
||||
PE_UnwindInfoFlags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_UnwindInfo_RegFromFrame(x) ((x)&0xF)
|
||||
#define PE_UnwindInfo_OffFromFrame(x) (((x) >> 4)&0xF)
|
||||
|
||||
#define PE_UnwindOpCode_XList(X)\
|
||||
X(PUSH_NONVOL, 0)\
|
||||
X(ALLOC_LARGE, 1)\
|
||||
X(ALLOC_SMALL, 2)\
|
||||
X(SET_FPREG, 3)\
|
||||
X(SAVE_NONVOL, 4)\
|
||||
X(SAVE_NONVOL_FAR, 5)\
|
||||
X(EPILOG, 6)\
|
||||
X(SPARE, 7)\
|
||||
X(SAVE_XMM128, 8)\
|
||||
X(SAVE_XMM128_FAR, 9)\
|
||||
X(PUSH_MACHFRAME, 10)
|
||||
|
||||
typedef U8 PE_UnwindOpCode;
|
||||
enum{
|
||||
#define X(N,C) PE_UnwindOpCode_##N = C,
|
||||
PE_UnwindOpCode_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
#define PE_UnwindCode_GetOffset(x) (((x) >> 0)&0xFF)
|
||||
#define PE_UnwindCode_GetOpCode(x) (((x) >> 8)&0x0F)
|
||||
#define PE_UnwindCode_GetOpInfo(x) (((x) >> 12)&0x0F)
|
||||
|
||||
#define PE_UnwindCode_FromOffsetOpCodeInfo(off,opcode,opinfo) \
|
||||
(((off)&0xFF) | (((opcode)&0xF) << 8) | (((opinfo)&0xF) << 12))
|
||||
|
||||
#define PE_UnwindRegX64_XList(X)\
|
||||
X(RAX, 0)\
|
||||
X(RCX, 1)\
|
||||
X(RDX, 2)\
|
||||
X(RBX, 3)\
|
||||
X(RSP, 4)\
|
||||
X(RBP, 5)\
|
||||
X(RSI, 6)\
|
||||
X(RDI, 7)\
|
||||
X(R8, 8)\
|
||||
X(R9, 9)\
|
||||
X(R10, 10)\
|
||||
X(R11, 11)\
|
||||
X(R12, 12)\
|
||||
X(R13, 13)\
|
||||
X(R14, 14)\
|
||||
X(R15, 15)
|
||||
|
||||
typedef U8 PE_UnwindRegX64;
|
||||
enum{
|
||||
#define X(N,C) PE_UnwindRegX64_##N = C,
|
||||
PE_UnwindRegX64_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
// base relocations
|
||||
|
||||
typedef struct PE_BaseRelocationBlock{
|
||||
U32 page_voff;
|
||||
U32 block_size;
|
||||
} PE_BaseRelocationBlock;
|
||||
|
||||
typedef U16 PE_BaseRelocationTypeOffset;
|
||||
|
||||
#define PE_BaseRelocationType_XList(X)\
|
||||
X(ABSOLUTE, 0)\
|
||||
X(HIGH, 1)\
|
||||
X(LOW, 2)\
|
||||
X(HIGHLOW, 3)\
|
||||
X(HIGHADJ, 4)\
|
||||
X(SPLIT1, 5)\
|
||||
X(SPLIT2, 7)\
|
||||
X(SPLIT3, 8)\
|
||||
X(MIPS_JMPADDR16, 9)\
|
||||
X(DIR64, 10)
|
||||
|
||||
typedef U8 PE_BaseRelocationType;
|
||||
enum{
|
||||
#define X(N,C) PE_BaseRelocationType_##N = C,
|
||||
PE_BaseRelocationType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
// SPLIT1: MIPS -> JMPADDR, ARM -> MOV32, RISCV -> HIGH20
|
||||
// SPLIT2: THUMB -> MOV32, RISCV -> LOW12I
|
||||
// SPLIT3: RISCV -> LOW12S, LOONGARCH32 -> MARK_LA, LOONGARCH64 -> MARK_LA
|
||||
|
||||
#define PE_BaseRelocationTypeOffset_GetType(X) (((X) >> 12)&0xF)
|
||||
#define PE_BaseRelocationTypeOffset_GetOff(X) (((X) >> 0)&0xFFF)
|
||||
|
||||
// debug
|
||||
|
||||
#define PE_DebugType_XList(X)\
|
||||
X(UNKNOWN, 0)\
|
||||
X(COFF, 1)\
|
||||
X(CODEVIEW, 2)\
|
||||
X(FPO, 3)\
|
||||
X(MISC, 4)\
|
||||
X(EXCEPTION, 5)\
|
||||
X(OMAP_TO_SRC, 7)\
|
||||
X(OMAP_FROM_SRC, 8)\
|
||||
X(BORLAND, 9)\
|
||||
X(RESERVED10, 10)\
|
||||
X(CLSID, 11)\
|
||||
X(VC_FEATURE, 12)\
|
||||
X(POGO, 13)\
|
||||
X(ILTCG, 14)\
|
||||
X(MPX, 15)\
|
||||
X(REPRO, 16)\
|
||||
X(EMBEDDED, 17)\
|
||||
X(CRYPTOHASH, 19)\
|
||||
X(EX_DLLCHARACTERISTICS, 20)
|
||||
|
||||
typedef U32 PE_DebugType;
|
||||
enum{
|
||||
#define X(N,C) PE_DebugType_##N = C,
|
||||
PE_DebugType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
typedef struct PE_DebugDirectory{
|
||||
U32 reserved0;
|
||||
U32 time_stamp;
|
||||
U16 version_major;
|
||||
U16 version_minor;
|
||||
PE_DebugType type;
|
||||
U32 size;
|
||||
U32 voff;
|
||||
U32 foff;
|
||||
} PE_DebugDirectory;
|
||||
|
||||
/* TODO(allen):
|
||||
** [ ] Can we gather information about debug info types besides CODEVIEW ?
|
||||
** [ ] What are the first 24 bytes of the CODEVIEW data range?
|
||||
*/
|
||||
|
||||
// tls table
|
||||
|
||||
typedef U32 PE_TlsDirectoryFlags;
|
||||
#define PE_TLSDirectoryFlags_GetAlign(X) ((X)&0x00F00000)
|
||||
|
||||
typedef struct PE_TLSDirectory32{
|
||||
U32 raw_data_start_vaddr;
|
||||
U32 raw_data_end_vaddr;
|
||||
U32 tls_index_vaddr;
|
||||
U32 tls_callback_array_vaddr;
|
||||
U32 zero_fill_size;
|
||||
PE_TlsDirectoryFlags flags;
|
||||
} PE_TLSDirectory32;
|
||||
|
||||
typedef struct PE_TLSDirectory32Plus{
|
||||
U64 raw_data_start_vaddr;
|
||||
U64 raw_data_end_vaddr;
|
||||
U64 tls_index_vaddr;
|
||||
U64 tls_callback_array_vaddr;
|
||||
U32 zero_fill_size;
|
||||
PE_TlsDirectoryFlags flags;
|
||||
} PE_TLSDirectory32Plus;
|
||||
|
||||
// load config table
|
||||
|
||||
/* TODO(allen): pneumonics for load config that are missing
|
||||
** [ ] global flags
|
||||
** [ ] process affinity mask
|
||||
** [ ] process heap flags
|
||||
** [ ] control flow guard flags
|
||||
*/
|
||||
|
||||
typedef struct PE_LoadConfig32{
|
||||
U32 reserved0;
|
||||
U32 time_stamp;
|
||||
U16 version_major;
|
||||
U16 version_minor;
|
||||
U32 global_flags_clear;
|
||||
U32 global_flags_set;
|
||||
U32 default_critical_section_timeout;
|
||||
U32 decommit_free_block_threshold;
|
||||
U32 decommit_total_free_threshold;
|
||||
U32 lock_prefix_table_vaddr;
|
||||
U32 maximum_allocation_size;
|
||||
U32 virtual_memory_threshold;
|
||||
U32 process_affinity_mask;
|
||||
U32 process_heap_flags;
|
||||
U16 csd_version;
|
||||
U16 reserved1;
|
||||
U32 reserved2;
|
||||
U32 security_cookie_vaddr;
|
||||
U32 seh_table_vaddr;
|
||||
U32 seh_count;
|
||||
U32 control_flow_guard_check_function_vaddr;
|
||||
U32 control_flow_guard_dispatch_function_vaddr;
|
||||
U32 control_flow_guard_function_table_vaddr;
|
||||
U32 control_flow_guard_function_count;
|
||||
U32 control_flow_guard_flags;
|
||||
U8 code_integrity[12];
|
||||
U32 guard_address_taken_iat_table_vaddr;
|
||||
U32 guard_address_taken_iat_count;
|
||||
U32 guard_long_jump_target_table_vaddr;
|
||||
U32 guard_long_jump_target_count;
|
||||
} PE_LoadConfig32;
|
||||
|
||||
typedef struct PE_LoadConfig64{
|
||||
U32 reserved0;
|
||||
U32 time_stamp;
|
||||
U16 version_major;
|
||||
U16 version_minor;
|
||||
U32 global_flags_clear;
|
||||
U32 global_flags_set;
|
||||
U32 default_critical_section_timeout;
|
||||
U64 decommit_free_block_threshold;
|
||||
U64 decommit_total_free_threshold;
|
||||
U64 lock_prefix_table_vaddr;
|
||||
U64 maximum_allocation_size;
|
||||
U64 virtual_memory_threshold;
|
||||
U64 process_affinity_mask;
|
||||
U32 process_heap_flags;
|
||||
U16 csd_version;
|
||||
U16 reserved1;
|
||||
U64 reserved2;
|
||||
U64 security_cookie_vaddr;
|
||||
U64 seh_table_vaddr;
|
||||
U64 seh_count;
|
||||
U64 control_flow_guard_check_function_vaddr;
|
||||
U64 control_flow_guard_dispatch_function_vaddr;
|
||||
U64 control_flow_guard_function_table_vaddr;
|
||||
U64 control_flow_guard_function_count;
|
||||
U32 control_flow_guard_flags;
|
||||
U8 code_integrity[12];
|
||||
U64 guard_address_taken_iat_table_vaddr;
|
||||
U64 guard_address_taken_iat_count;
|
||||
U64 guard_long_jump_target_table_vaddr;
|
||||
U64 guard_long_jump_target_count;
|
||||
} PE_LoadConfig64;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //MR4TH_PE_H
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
////////////////////////////////
|
||||
// PE Get Section Function
|
||||
|
||||
static RangePtr
|
||||
pe_img_get_section(void *image_raw, String8 name){
|
||||
U8 *image = (U8*)image_raw;
|
||||
|
||||
// dos header
|
||||
PE_DosHeader *dos_header = (PE_DosHeader*)(image);
|
||||
if (dos_header->magic != PE_MSDOS_MAGIC){
|
||||
dos_header = 0;
|
||||
}
|
||||
|
||||
// coff header
|
||||
PE_CoffHeader *coff_header = 0;
|
||||
U64 after_coff_header_offset = 0;
|
||||
if (dos_header != 0){
|
||||
U64 pe_signature_offset = dos_header->coff_file_offset;
|
||||
U64 coff_header_offset = pe_signature_offset + sizeof(U32);
|
||||
U32 pe_signature = *(U32*)(image + pe_signature_offset);
|
||||
if (pe_signature == PE_SIGNATURE){
|
||||
coff_header = (PE_CoffHeader*)(image + coff_header_offset);
|
||||
after_coff_header_offset = coff_header_offset + sizeof(*coff_header);
|
||||
}
|
||||
}
|
||||
|
||||
// section table offset & count
|
||||
U32 section_table_offset = 0;
|
||||
U32 section_count = 0;
|
||||
if (coff_header != 0){
|
||||
section_table_offset = ( after_coff_header_offset
|
||||
+ coff_header->optional_header_size);
|
||||
section_count = coff_header->section_count;
|
||||
}
|
||||
|
||||
// scan section table
|
||||
PE_SectionHeader *match = 0;
|
||||
{
|
||||
PE_SectionHeader *sec = (PE_SectionHeader*)(image + section_table_offset);
|
||||
for (U32 i = 0; i < section_count; i += 1, sec += 1){
|
||||
U8 *secptr = sec->name;
|
||||
U8 *secopl = sec->name + sizeof(sec->name);
|
||||
U8 *keyptr = name.str;
|
||||
U8 *keyopl = name.str + name.size;
|
||||
B32 string_match = 1;
|
||||
for (;*secptr != 0 && secptr < secopl && keyptr < keyopl;
|
||||
secptr += 1, keyptr += 1){
|
||||
if (*secptr != *keyptr){
|
||||
string_match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (string_match){
|
||||
match = sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fill result
|
||||
RangePtr result = {0};
|
||||
if (match != 0){
|
||||
result.first = image + match->voff;
|
||||
result.opl = result.first + match->vsize;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef MR4TH_PE_IMG_GET_SECTION_H
|
||||
#define MR4TH_PE_IMG_GET_SECTION_H
|
||||
|
||||
////////////////////////////////
|
||||
// PE Get Section Function
|
||||
|
||||
static RangePtr pe_img_get_section(void *image, String8 name);
|
||||
|
||||
#endif //MR4TH_PE_IMG_GET_SECTION_H
|
||||
|
|
@ -2,66 +2,54 @@
|
|||
** C Scripting Example #1
|
||||
*/
|
||||
|
||||
#include "base.h"
|
||||
#include "symbol_set.h"
|
||||
|
||||
#include "example1.h"
|
||||
|
||||
#include "base.c"
|
||||
#include <stdio.h>
|
||||
|
||||
COMMAND_SCRIPT(foo, "Generates foo and increments the foo counter"){
|
||||
printf("foo, ");
|
||||
ctx->foo += 1;
|
||||
#include "symbol_set.c"
|
||||
|
||||
EX1_COMMAND_DEF(Hello, "Increments and prints the counter"){
|
||||
ctx->counter += 1;
|
||||
printf("Hello World! (%d)\n", ctx->counter);
|
||||
}
|
||||
|
||||
COMMAND_SCRIPT(bar, "Generates bar and decrements the foo counter"){
|
||||
printf("bar, ");
|
||||
ctx->foo -= 1;
|
||||
EX1_COMMAND_DEF(Goodbye, "Prints and decrements the counter"){
|
||||
printf("Goodbye! (%d)\n", ctx->counter);
|
||||
ctx->counter -= 1;
|
||||
}
|
||||
|
||||
COMMAND_SCRIPT(baz,
|
||||
"Generates 2 bars if the foo counter is positive, "
|
||||
"generates 2 foos if the foo counter is negative, "
|
||||
"otherwise generates baz"){
|
||||
if (ctx->foo > 0){
|
||||
printf("bar, bar, ");
|
||||
}
|
||||
else if (ctx->foo < 0){
|
||||
printf("foo, foo, ");
|
||||
}
|
||||
else{
|
||||
printf("baz, ");
|
||||
}
|
||||
EX1_COMMAND_DEF(UntilNextTime, "Resets the counter and prints"){
|
||||
ctx->counter = 0;
|
||||
printf("Until next time...\n");
|
||||
}
|
||||
|
||||
int main(void){
|
||||
// init sequence
|
||||
U32 command_ids[] = {
|
||||
COMMAND_ID(foo), COMMAND_ID(foo), COMMAND_ID(baz),
|
||||
COMMAND_ID(bar), COMMAND_ID(baz), COMMAND_ID(bar),
|
||||
COMMAND_ID(foo), COMMAND_ID(bar), COMMAND_ID(baz),
|
||||
};
|
||||
|
||||
// display the legend of rules
|
||||
printf("RULES:\n");
|
||||
{
|
||||
EX1_Command *commands = SymbolBasePtr(EX1_CommandSymbols);
|
||||
U64 count = SymbolCount(EX1_CommandSymbols);
|
||||
for (U64 i = 0; i < count; i += 1){
|
||||
EX1_Command *command = commands + i;
|
||||
printf("%.*s -> %.*s\n",
|
||||
str8_expand(command->name),
|
||||
str8_expand(command->description));
|
||||
}
|
||||
for (SyEach(EX1_COMMAND, command)){
|
||||
printf("%s -> %s\n", command->name, command->description);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// init the sequence
|
||||
Sy_U32 sequence[] = {
|
||||
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Hello),
|
||||
SyID(EX1_COMMAND, UntilNextTime),
|
||||
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Goodbye),
|
||||
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Goodbye),
|
||||
SyID(EX1_COMMAND, UntilNextTime),
|
||||
SyID(EX1_COMMAND, Goodbye), SyID(EX1_COMMAND, Goodbye),
|
||||
SyID(EX1_COMMAND, Goodbye), SyID(EX1_COMMAND, Hello),
|
||||
SyID(EX1_COMMAND, Hello), SyID(EX1_COMMAND, Hello),
|
||||
};
|
||||
|
||||
// display the sequence
|
||||
printf("SEQUENCE:\n");
|
||||
for (U32 i = 0; i < sizeof(command_ids)/sizeof(command_ids[0]); i += 1){
|
||||
U32 id = command_ids[i];
|
||||
EX1_Command *command = COMMAND_METADATA_FROM_ID(id);
|
||||
printf("%.*s, ", str8_expand(command->name));
|
||||
for (Sy_U32 i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i += 1){
|
||||
Sy_U32 id = sequence[i];
|
||||
EX1_Command *command = SyAddressFromID(EX1_COMMAND, id);
|
||||
printf("%s, ", command->name);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
|
|
@ -69,13 +57,12 @@ int main(void){
|
|||
printf("OUTPUT:\n");
|
||||
{
|
||||
EX1_Ctx ctx = {0};
|
||||
for (U32 i = 0; i < sizeof(command_ids)/sizeof(command_ids[0]); i += 1){
|
||||
U32 id = command_ids[i];
|
||||
EX1_Command *command = COMMAND_METADATA_FROM_ID(id);
|
||||
for (Sy_U32 i = 0; i < sizeof(sequence)/sizeof(sequence[0]); i += 1){
|
||||
Sy_U32 id = sequence[i];
|
||||
EX1_Command *command = SyAddressFromID(EX1_COMMAND, id);
|
||||
command->hook(&ctx);
|
||||
}
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -5,29 +5,26 @@
|
|||
// Setup a Symbol Set
|
||||
|
||||
typedef struct EX1_Ctx{
|
||||
S64 foo;
|
||||
int counter;
|
||||
} EX1_Ctx;
|
||||
|
||||
typedef void EX1_Hook(EX1_Ctx *ctx);
|
||||
|
||||
typedef struct EX1_Command{
|
||||
String8 name;
|
||||
String8 description;
|
||||
char *name;
|
||||
char *description;
|
||||
EX1_Hook *hook;
|
||||
} EX1_Command;
|
||||
|
||||
#define SYMBOL_SET_DEFINE EX1_CommandSymbols
|
||||
#define EX1_CommandSymbols_Type EX1_Command
|
||||
#define EX1_CommandSymbols_section ".ex1CMD"
|
||||
#define SYMBOL_SET_DEFINE EX1_COMMAND
|
||||
#define EX1_COMMAND_Type EX1_Command
|
||||
#define EX1_COMMAND_section ".sy.x1cm"
|
||||
#define EX1_COMMAND_marker x1cm
|
||||
#include "symbol_set.define.h"
|
||||
|
||||
#define COMMAND_ID(N) SymbolID(EX1_CommandSymbols, N)
|
||||
#define COMMAND_DECL(N) SymbolDeclare(EX1_CommandSymbols, N)
|
||||
#define COMMAND_METADATA_FROM_ID(id) SymbolMetadataFromID(EX1_CommandSymbols, id)
|
||||
#define EX1_COMMAND_DEF(N,desc) \
|
||||
void ex1cmd_##N(EX1_Ctx *ctx); \
|
||||
SyDefine(EX1_COMMAND, N) = { #N, desc, ex1cmd_##N };\
|
||||
void ex1cmd_##N(EX1_Ctx *ctx)
|
||||
|
||||
#define COMMAND_SCRIPT(N,desc) \
|
||||
void cmdhook_##N(EX1_Ctx *ctx); \
|
||||
SymbolDefine(EX1_CommandSymbols, N) = { str8_lit_const(#N), str8_lit_const(desc), cmdhook_##N };\
|
||||
void cmdhook_##N(EX1_Ctx *ctx)
|
||||
|
||||
#endif //EXAMPLE1_H
|
||||
#endif /* EXAMPLE1_H */
|
||||
|
|
|
|||
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);
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ X(PAD6, 15)
|
|||
|
||||
typedef enum ELF_IdentificationIdx{
|
||||
#define X(N,C) ELF_IdentificationIdx_##N = C,
|
||||
ELF_IdentificationIdx_XList(X)
|
||||
ELF_IdentificationIdx_XList(X)
|
||||
#undef X
|
||||
} ELF_IdentificationIdx;
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ X(64, 2)
|
|||
|
||||
typedef enum ELF_Class{
|
||||
#define X(N,C) ELF_Class_##N = C,
|
||||
ELF_Class_XList(X)
|
||||
ELF_Class_XList(X)
|
||||
#undef X
|
||||
} ELF_Class;
|
||||
|
||||
|
|
@ -65,7 +65,7 @@ X(2MSB, 2)
|
|||
|
||||
typedef enum ELF_Encoding{
|
||||
#define X(N,C) ELF_Encoding_##N = C,
|
||||
ELF_Encoding_XList(X)
|
||||
ELF_Encoding_XList(X)
|
||||
#undef X
|
||||
} ELF_Encoding;
|
||||
|
||||
|
|
@ -92,7 +92,7 @@ X(OPENVOS, 18)
|
|||
|
||||
typedef enum ELF_OsAbiExtension{
|
||||
#define X(N,C) ELF_OsAbiExtension_##N = C,
|
||||
ELF_OsAbiExtension_XList(X)
|
||||
ELF_OsAbiExtension_XList(X)
|
||||
#undef X
|
||||
} ELF_OsAbiExtension;
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ X(HIPROC, 0xffff)
|
|||
typedef U16 ELF_FileType;
|
||||
enum{
|
||||
#define X(N,C) ELF_FileType_##N = C,
|
||||
ELF_FileType_XList(X)
|
||||
ELF_FileType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
|
@ -306,37 +306,37 @@ typedef U16 ELF_MachineType;
|
|||
// elf header
|
||||
|
||||
typedef struct ELF_Header32{
|
||||
U8 ident[ELF_NUM_IDENT];
|
||||
ELF_FileType type;
|
||||
ELF_MachineType machine;
|
||||
U32 version;
|
||||
U32 entry;
|
||||
U32 segment_table_foff;
|
||||
U32 section_table_foff;
|
||||
U32 flags;
|
||||
U16 header_size;
|
||||
U16 segment_size;
|
||||
U16 segment_count;
|
||||
U16 section_size;
|
||||
U16 section_count;
|
||||
U16 string_section_index;
|
||||
U8 ident[ELF_NUM_IDENT];
|
||||
ELF_FileType type;
|
||||
ELF_MachineType machine;
|
||||
U32 version;
|
||||
U32 entry;
|
||||
U32 segment_table_foff;
|
||||
U32 section_table_foff;
|
||||
U32 flags;
|
||||
U16 header_size;
|
||||
U16 segment_size;
|
||||
U16 segment_count;
|
||||
U16 section_size;
|
||||
U16 section_count;
|
||||
U16 string_section_index;
|
||||
} ELF_Header32;
|
||||
|
||||
typedef struct ELF_Header64{
|
||||
U8 ident[ELF_NUM_IDENT];
|
||||
ELF_FileType type;
|
||||
ELF_MachineType machine;
|
||||
U32 version;
|
||||
U64 entry;
|
||||
U64 segment_table_foff;
|
||||
U64 section_table_foff;
|
||||
U32 flags;
|
||||
U16 header_size;
|
||||
U16 segment_size;
|
||||
U16 segment_count;
|
||||
U16 section_size;
|
||||
U16 section_count;
|
||||
U16 string_section_index;
|
||||
U8 ident[ELF_NUM_IDENT];
|
||||
ELF_FileType type;
|
||||
ELF_MachineType machine;
|
||||
U32 version;
|
||||
U64 entry;
|
||||
U64 segment_table_foff;
|
||||
U64 section_table_foff;
|
||||
U32 flags;
|
||||
U16 header_size;
|
||||
U16 segment_size;
|
||||
U16 segment_count;
|
||||
U16 section_size;
|
||||
U16 section_count;
|
||||
U16 string_section_index;
|
||||
} ELF_Header64;
|
||||
|
||||
// elf section type
|
||||
|
|
@ -369,7 +369,7 @@ X(HIUSER, 0xffffffff)
|
|||
typedef U32 ELF_SectionType;
|
||||
enum{
|
||||
#define X(N,C) ELF_SectionType_##N = C,
|
||||
ELF_SectionType_XList(X)
|
||||
ELF_SectionType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ X(MASKPROC, 0xf0000000)
|
|||
|
||||
enum{
|
||||
#define X(N,C) ELF_SectionFlag_##N = C,
|
||||
ELF_SectionFlags_XList(X)
|
||||
ELF_SectionFlags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
|
@ -412,7 +412,7 @@ X(HIRESERVE, 0xffff)
|
|||
|
||||
typedef enum ELF_SectionIndex{
|
||||
#define X(N,C) ELF_SectionIndex_##N = C,
|
||||
ELF_SectionIndex_XList(X)
|
||||
ELF_SectionIndex_XList(X)
|
||||
#undef X
|
||||
} ELF_SectionIndex;
|
||||
|
||||
|
|
@ -421,10 +421,10 @@ typedef enum ELF_SectionIndex{
|
|||
|
||||
typedef struct ELF_Section32{
|
||||
U32 name;
|
||||
ELF_SectionType type;
|
||||
ELF_SectionType type;
|
||||
U32 flags;
|
||||
U32 addr;
|
||||
U32 offset;
|
||||
U32 addr;
|
||||
U32 offset;
|
||||
U32 size;
|
||||
U32 link;
|
||||
U32 info;
|
||||
|
|
@ -434,10 +434,10 @@ typedef struct ELF_Section32{
|
|||
|
||||
typedef struct ELF_Section64{
|
||||
U32 name;
|
||||
ELF_SectionType type;
|
||||
ELF_SectionType type;
|
||||
U64 flags;
|
||||
U64 addr;
|
||||
U64 offset;
|
||||
U64 addr;
|
||||
U64 offset;
|
||||
U64 size;
|
||||
U32 link;
|
||||
U32 info;
|
||||
|
|
@ -456,23 +456,23 @@ X(HIPROC, 0x7fffffff)
|
|||
|
||||
typedef enum ELF_CompressionType{
|
||||
#define X(N,C) ELF_CompressionType_##N = C,
|
||||
ELF_CompressionType_XList(X)
|
||||
ELF_CompressionType_XList(X)
|
||||
#undef X
|
||||
} ELF_CompressionType;
|
||||
|
||||
// elf compression header
|
||||
|
||||
typedef struct ELF_CompressionHeader32{
|
||||
ELF_CompressionType type;
|
||||
ELF_CompressionType type;
|
||||
U32 size;
|
||||
U32 addralign;
|
||||
} ELF_CompressionHeader32;
|
||||
|
||||
typedef struct ELF_CompressionHeader64{
|
||||
ELF_CompressionType type;
|
||||
ELF_CompressionType type;
|
||||
U32 reserved;
|
||||
U64 size;
|
||||
U64 addralign;
|
||||
U64 size;
|
||||
U64 addralign;
|
||||
} ELF_CompressionHeader64;
|
||||
|
||||
// elf section group flags
|
||||
|
|
@ -485,28 +485,28 @@ X(MASKPROC, 0xf0000000)
|
|||
typedef U32 ELF_SectionGroupFlags;
|
||||
enum{
|
||||
#define X(N,C) ELF_SectionGroupFlag_##N = C,
|
||||
ELF_SectionGroupFlags_XList(X)
|
||||
ELF_SectionGroupFlags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
// elf symbol
|
||||
|
||||
typedef struct ELF_Symbol32{
|
||||
U32 name;
|
||||
U32 value;
|
||||
U32 size;
|
||||
U8 info;
|
||||
U8 other;
|
||||
U16 section_index;
|
||||
U32 name;
|
||||
U32 value;
|
||||
U32 size;
|
||||
U8 info;
|
||||
U8 other;
|
||||
U16 section_index;
|
||||
} ELF_Symbol32;
|
||||
|
||||
typedef struct ELF_Symbol64{
|
||||
U32 name;
|
||||
U8 info;
|
||||
U8 other;
|
||||
U16 section_index;
|
||||
U64 value;
|
||||
U64 size;
|
||||
U32 name;
|
||||
U8 info;
|
||||
U8 other;
|
||||
U16 section_index;
|
||||
U64 value;
|
||||
U64 size;
|
||||
} ELF_Symbol64;
|
||||
|
||||
#define ELF_Symbol_BindFromInfo(inf) ((inf)>>4)
|
||||
|
|
@ -529,7 +529,7 @@ X(HIPROC, 15)
|
|||
|
||||
typedef enum ELF_SymbolBinding{
|
||||
#define X(N,C) ELF_SymbolBinding_##N = C,
|
||||
ELF_SymbolBinding_XList(X)
|
||||
ELF_SymbolBinding_XList(X)
|
||||
#undef X
|
||||
} ELF_SymbolBinding;
|
||||
|
||||
|
|
@ -550,7 +550,7 @@ X(HIPROC, 15)
|
|||
|
||||
typedef enum ELF_SymbolType{
|
||||
#define X(N,C) ELF_SymbolType_##N = C,
|
||||
ELF_SymbolType_XList(X)
|
||||
ELF_SymbolType_XList(X)
|
||||
#undef X
|
||||
} ELF_SymbolType;
|
||||
|
||||
|
|
@ -564,31 +564,31 @@ X(PROTECTED, 3)
|
|||
|
||||
typedef enum ELF_SymbolVis{
|
||||
#define X(N,C) ELF_SymbolVis_##N = C,
|
||||
ELF_SymbolVis_XList(X)
|
||||
ELF_SymbolVis_XList(X)
|
||||
#undef X
|
||||
} ELF_SymbolVis;
|
||||
|
||||
// elf relocations
|
||||
|
||||
typedef struct ELF_Relocation32{
|
||||
U32 offset;
|
||||
U32 info;
|
||||
U32 offset;
|
||||
U32 info;
|
||||
} ELF_Relocation32;
|
||||
|
||||
typedef struct ELF_RelocationAdd32{
|
||||
U32 offset;
|
||||
U32 info;
|
||||
U32 offset;
|
||||
U32 info;
|
||||
S32 addend;
|
||||
} ELF_RelocationAdd32;
|
||||
|
||||
typedef struct ELF_Relocation64{
|
||||
U64 offset;
|
||||
U64 info;
|
||||
U64 offset;
|
||||
U64 info;
|
||||
} ELF_Relocation64;
|
||||
|
||||
typedef struct ELF_RelocationAdd64{
|
||||
U64 offset;
|
||||
U64 info;
|
||||
U64 offset;
|
||||
U64 info;
|
||||
S64 addend;
|
||||
} ELF_RelocationAdd64;
|
||||
|
||||
|
|
@ -611,7 +611,7 @@ X(HIPROC, 0x7fffffff)
|
|||
typedef U32 ELF_SegmentType;
|
||||
enum{
|
||||
#define X(N,C) ELF_SegmentType_##N = C,
|
||||
ELF_SegmentType_XList(X)
|
||||
ELF_SegmentType_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
|
|
@ -627,32 +627,32 @@ X(MASKPROC, 0xf0000000)\
|
|||
typedef U32 ELF_SegmentFlags;
|
||||
enum{
|
||||
#define X(N,C) ELF_SegmentFlag_##N = C,
|
||||
ELF_SegmentFlags_XList(X)
|
||||
ELF_SegmentFlags_XList(X)
|
||||
#undef X
|
||||
};
|
||||
|
||||
// elf segment
|
||||
|
||||
typedef struct ELF_Segment32{
|
||||
ELF_SegmentType type;
|
||||
U32 offset;
|
||||
U32 vaddr;
|
||||
U32 paddr;
|
||||
U32 file_size;
|
||||
U32 memory_size;
|
||||
ELF_SegmentFlags flags;
|
||||
U32 align;
|
||||
ELF_SegmentType type;
|
||||
U32 offset;
|
||||
U32 vaddr;
|
||||
U32 paddr;
|
||||
U32 file_size;
|
||||
U32 memory_size;
|
||||
ELF_SegmentFlags flags;
|
||||
U32 align;
|
||||
} ELF_Segment32;
|
||||
|
||||
typedef struct ELF_Segment64{
|
||||
ELF_SegmentType type;
|
||||
ELF_SegmentFlags flags;
|
||||
U64 offset;
|
||||
U64 vaddr;
|
||||
U64 paddr;
|
||||
U64 file_size;
|
||||
U64 memory_size;
|
||||
U64 align;
|
||||
ELF_SegmentType type;
|
||||
ELF_SegmentFlags flags;
|
||||
U64 offset;
|
||||
U64 vaddr;
|
||||
U64 paddr;
|
||||
U64 file_size;
|
||||
U64 memory_size;
|
||||
U64 align;
|
||||
} ELF_Segment64;
|
||||
|
||||
////////////////////////////////
|
||||
|
|
@ -660,46 +660,46 @@ typedef struct ELF_Segment64{
|
|||
|
||||
// normalizing
|
||||
|
||||
MR4TH_SYM_COMPTIME U16 elf_u16_decode(void *ptr, B32 flip);
|
||||
MR4TH_SYM_COMPTIME U32 elf_u32_decode(void *ptr, B32 flip);
|
||||
MR4TH_SYM_COMPTIME U64 elf_u64_decode(void *ptr, B32 flip);
|
||||
MR4TH_SYMBOL_STATIC U16 elf_u16_decode(void *ptr, B32 flip);
|
||||
MR4TH_SYMBOL_STATIC U32 elf_u32_decode(void *ptr, B32 flip);
|
||||
MR4TH_SYMBOL_STATIC U64 elf_u64_decode(void *ptr, B32 flip);
|
||||
|
||||
MR4TH_SYM_COMPTIME void elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME void elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_header64_from_header32(ELF_Header64 *dst, ELF_Header32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_header64_from_header64(ELF_Header64 *dst, ELF_Header64 *src, ELF_Encoding src_encoding);
|
||||
|
||||
MR4TH_SYM_COMPTIME void elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME void elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_section64_from_section32(ELF_Section64 *dst, ELF_Section32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_section64_from_section64(ELF_Section64 *dst, ELF_Section64 *src, ELF_Encoding src_encoding);
|
||||
|
||||
MR4TH_SYM_COMPTIME void elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME void elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_segment64_from_segment32(ELF_Segment64 *dst, ELF_Segment32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_segment64_from_segment64(ELF_Segment64 *dst, ELF_Segment64 *src, ELF_Encoding src_encoding);
|
||||
|
||||
MR4TH_SYM_COMPTIME void elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME void elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_symbol64_from_symbol32(ELF_Symbol64 *dst, ELF_Symbol32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_symbol64_from_symbol64(ELF_Symbol64 *dst, ELF_Symbol64 *src, ELF_Encoding src_encoding);
|
||||
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloc32(Arena *arena, ELF_Relocation32 *src, U64 count, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloc64(Arena *arena, ELF_Relocation64 *src, U64 count, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloca32(Arena *arena, ELF_RelocationAdd32 *src, U64 count, ELF_Encoding src_encoding);
|
||||
MR4TH_SYM_COMPTIME ELF_RelocationAdd64* elf_reloca64_from_reloca64(Arena *arena, ELF_RelocationAdd64 *src, U64 count, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloc32(ELF_RelocationAdd64 *dst, ELF_Relocation32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloc64(ELF_RelocationAdd64 *dst, ELF_Relocation64 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloca32(ELF_RelocationAdd64 *dst, ELF_RelocationAdd32 *src, ELF_Encoding src_encoding);
|
||||
MR4TH_SYMBOL_STATIC void elf_reloca64_from_reloca64(ELF_RelocationAdd64 *dst, ELF_RelocationAdd64 *src, ELF_Encoding src_encoding);
|
||||
|
||||
// strings
|
||||
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_identification_idx(ELF_IdentificationIdx idx);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_class(ELF_Class elf_class);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_encoding(ELF_Encoding elf_encoding);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_file_type(ELF_FileType file_type);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_machine_type(ELF_FileType machine_type);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_identification_idx(ELF_IdentificationIdx idx);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_class(ELF_Class elf_class);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_encoding(ELF_Encoding elf_encoding);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_osabi(ELF_OsAbiExtension elf_osabi);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_file_type(ELF_FileType file_type);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_machine_type(ELF_FileType machine_type);
|
||||
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_section_type(ELF_SectionType section_type);
|
||||
MR4TH_SYM_COMPTIME void elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_section_flags(Arena *arena, U32 flags);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_section_type(ELF_SectionType section_type);
|
||||
MR4TH_SYMBOL_STATIC void elf_str8list_from_section_flags(Arena *arena, String8List *out, U32 flags);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_section_flags(Arena *arena, U32 flags);
|
||||
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_segment_type(ELF_SegmentType segment_type);
|
||||
MR4TH_SYM_COMPTIME void elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_segment_type(ELF_SegmentType segment_type);
|
||||
MR4TH_SYMBOL_STATIC void elf_str8list_from_segment_flags(Arena *arena, String8List *out, ELF_SegmentFlags flags);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_segment_flags(Arena *arena, ELF_SegmentFlags flags);
|
||||
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_binding(ELF_SymbolBinding bind);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_type(ELF_SymbolType type);
|
||||
MR4TH_SYM_COMPTIME String8 elf_str8_from_symbol_vis(ELF_SymbolVis vis);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_binding(ELF_SymbolBinding bind);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_type(ELF_SymbolType type);
|
||||
MR4TH_SYMBOL_STATIC String8 elf_str8_from_symbol_vis(ELF_SymbolVis vis);
|
||||
|
||||
#endif //MR4TH_ELF_H
|
||||
|
|
@ -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 symbol_set.intro.h to get started.
|
||||
*/
|
||||
|
||||
#if SY__OS_WINDOWS
|
||||
|
||||
#pragma pack(push,1)
|
||||
#define SY__DOS_MAGIC 0x5A4D
|
||||
typedef struct Sy__DosHeader{
|
||||
Sy_U16 magic;
|
||||
Sy_U16 last_page_size;
|
||||
Sy_U16 page_count;
|
||||
Sy_U16 reloc_count;
|
||||
Sy_U16 paragraph_header_size;
|
||||
Sy_U16 min_paragraph;
|
||||
Sy_U16 max_paragraph;
|
||||
Sy_U16 init_ss;
|
||||
Sy_U16 init_sp;
|
||||
Sy_U16 checksum;
|
||||
Sy_U16 init_ip;
|
||||
Sy_U16 init_cs;
|
||||
Sy_U16 reloc_table_file_off;
|
||||
Sy_U16 overlay_number;
|
||||
Sy_U16 reserved[4];
|
||||
Sy_U16 oem_id;
|
||||
Sy_U16 oem_info;
|
||||
Sy_U16 reserved2[10];
|
||||
Sy_U32 coff_offset;
|
||||
} Sy__DosHeader;
|
||||
typedef struct Sy__CoffHeader{
|
||||
Sy_U16 machine_type;
|
||||
Sy_U16 section_count;
|
||||
Sy_U32 time_stamp;
|
||||
Sy_U32 symbol_table_foff;
|
||||
Sy_U32 symbol_count;
|
||||
Sy_U16 optional_header_size;
|
||||
Sy_U16 flags;
|
||||
} Sy__CoffHeader;
|
||||
typedef struct Sy_CoffSection{
|
||||
Sy_U8 name[8];
|
||||
Sy_U32 vsize;
|
||||
Sy_U32 voff;
|
||||
Sy_U32 fsize;
|
||||
Sy_U32 foff;
|
||||
Sy_U32 relocations_foff;
|
||||
Sy_U32 line_numbers_foff;
|
||||
Sy_U16 relocation_count;
|
||||
Sy_U16 line_number_count;
|
||||
Sy_U32 flags;
|
||||
} Sy_CoffSection;
|
||||
#pragma pack(pop)
|
||||
|
||||
void
|
||||
sy__section_init(char *name, Sy_U32 name_size, void **first_out, void **opl_out){
|
||||
if (name_size <= 8){
|
||||
extern Sy_U8 __ImageBase[];
|
||||
Sy_U8 *base = __ImageBase;
|
||||
Sy__DosHeader *dos = (Sy__DosHeader*)base;
|
||||
if (dos_header->magic == SY__DOS_MAGIC){
|
||||
Sy__CoffHeader *coff = (Sy__CoffHeader*)(base + dos->coff_offset);
|
||||
Sy_U32 sections_offset = (dos->coff_offset + sizeof(*coff) +
|
||||
coff->optional_header_size);
|
||||
Sy_U32 section_count = coff->section_count;
|
||||
Sy_CoffSection *section = (Sy_CoffSection*)(base + sections_offset);
|
||||
for (Sy_U32 i = 0; i < section_count; i += 1, section += 1){
|
||||
int match = 1;
|
||||
for (Sy_U32 j = 0; j < 8; j += 1){
|
||||
if (name[j] != section->name[j]){
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
if (name[j] == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match){
|
||||
*first_out = base + section->voff;
|
||||
*opl_out = base + section->voff + section->vsize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,13 +1,31 @@
|
|||
static U64 SymbolCount(SYMBOL_SET_DEFINE) = 0;
|
||||
static SYMBOL__TYPE(SYMBOL_SET_DEFINE) * SymbolBasePtr(SYMBOL_SET_DEFINE) = 0;
|
||||
static SYMBOL__TYPE(SYMBOL_SET_DEFINE) SYMBOL__SYM(SYMBOL_SET_DEFINE,0);
|
||||
#if SY__OS_LINUX
|
||||
|
||||
int spider;
|
||||
|
||||
extern SyType(SYMBOL_SET_DEFINE) SY__FIRST(SYMBOL_SET_DEFINE);
|
||||
extern SyType(SYMBOL_SET_DEFINE) SY__OPL(SYMBOL_SET_DEFINE);
|
||||
// (these symbols are resolved in the linker script)
|
||||
|
||||
#elif SY__OS_WINDOWS
|
||||
|
||||
#if COMPILER_CL
|
||||
# pragma SYMBOL__CL_PRAGMA
|
||||
# pragma section(SY__GLUE(SYMBOL_SET_DEFINE,_section),read,write)
|
||||
#endif
|
||||
BEFORE_MAIN(){
|
||||
void *image = os_this_image();
|
||||
RangePtr range = self_img_get_section(image, str8_lit(GLUE(SYMBOL_SET_DEFINE,_section)));
|
||||
SymbolCount(SYMBOL_SET_DEFINE) = (range.opl - range.first)/sizeof(SYMBOL__TYPE(SYMBOL_SET_DEFINE));
|
||||
SymbolBasePtr(SYMBOL_SET_DEFINE) = (SYMBOL__TYPE(SYMBOL_SET_DEFINE)*)(range.first);
|
||||
|
||||
SyType(SYMBOL_SET_DEFINE) *SY__FIRST(SYMBOL_SET_DEFINE) = 0;
|
||||
SyType(SYMBOL_SET_DEFINE) *SY__OPL(SYMBOL_SET_DEFINE) = 0;
|
||||
|
||||
SY__BEFORE_MAIN(SY__GLUE(SYMBOL_SET_DEFINE,__init)){
|
||||
int size = sizeof(SY__GLUE(SYMBOL_SET_DEFINE,_section)) - 1;
|
||||
void *first = 0;
|
||||
void *opl = 0;
|
||||
sy__section_init(SY__GLUE(SYMBOL_SET_DEFINE,_section), size,
|
||||
(void**)&SY__FIRST(SYMBOL_SET_DEFINE),
|
||||
(void**)&SY__OPL(SYMBOL_SET_DEFINE));
|
||||
}
|
||||
|
||||
#else
|
||||
# error symbol_set.define not implemented for this OS
|
||||
#endif
|
||||
|
||||
#undef SYMBOL_SET_DEFINE
|
||||
334
src/symbol_set.h
334
src/symbol_set.h
|
|
@ -1,78 +1,308 @@
|
|||
/*
|
||||
** Symbol Set
|
||||
/***********************************************************
|
||||
** symbol_set - A public domain C modifier library
|
||||
** by Allen Webster, "Mr. 4th", allenw@mr4th.com
|
||||
**
|
||||
** No warranty implied; use at your own risk
|
||||
**
|
||||
** Read symbol_set.intro.h to get started.
|
||||
*/
|
||||
|
||||
#ifndef SYMBOL_SET_H
|
||||
#define SYMBOL_SET_H
|
||||
|
||||
////////////////////////////////
|
||||
// Copy-Pastable
|
||||
#if 0
|
||||
/*********************
|
||||
** Context Cracking **
|
||||
*********************/
|
||||
|
||||
// To define a Symbol Set
|
||||
#define SYMBOL_SET_DEFINE example_name
|
||||
#define example_name_Type ExampleType
|
||||
#define example_name_section ".exmpl"
|
||||
#include "symbol_set.define.h"
|
||||
/* untangle compiler, os, & architecture */
|
||||
#if defined(__clang__)
|
||||
# define SY__COMPILER_CLANG 1
|
||||
|
||||
// Common wrappers to put around a Symbol Set (after defining it)
|
||||
#define EXAMPLE_ID(N) SymbolID(example_name, N)
|
||||
#define EXAMPLE_RAW(N) SymbolRaw(example_name, N)
|
||||
#define EXAMPLE_DECL(N) SymbolDeclare(example_name, N)
|
||||
# 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
|
||||
|
||||
////////////////////////////////
|
||||
// Symbol Set System
|
||||
#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
|
||||
|
||||
// Symbol Set key terms:
|
||||
// "count" - the total number of symbols in this set
|
||||
// "baseptr" - the pointer to the base of the array of symbol data
|
||||
// "oplptr" - the pointer to the spot one past the last element of the array
|
||||
// "id" - the 1-based index of the symbol
|
||||
// id=0 stands for the special 'nil' case
|
||||
// id values in the range [1,count] stand for a symbol in the set
|
||||
// "metadata" - a pointer to the slot in the array for this symbol
|
||||
// "raw" - address of the metadata as an integer
|
||||
/* language */
|
||||
#if defined(__cplusplus)
|
||||
# define SY__LANG_CXX 1
|
||||
#else
|
||||
# define SY__LANG_C 1
|
||||
#endif
|
||||
|
||||
// user interface
|
||||
#if !defined(SY__LANG_CXX)
|
||||
# define SY__LANG_CXX 0
|
||||
#endif
|
||||
#if !defined(SY__LANG_C)
|
||||
# define SY__LANG_C 0
|
||||
#endif
|
||||
|
||||
#define SymbolDeclare(E,N) \
|
||||
SECTION(E##_section) extern SYMBOL__TYPE(E) SYMBOL__SYM(E,N)
|
||||
/**********
|
||||
** Types **
|
||||
**********/
|
||||
|
||||
#define SymbolDefine(E,N) DO_NOT_ELIMINATE(SYMBOL__SYM(E,N)) SymbolDeclare(E,N)
|
||||
#define SymbolDefineNameless(E) SymbolDefine(E,GLUE(auto,__COUNTER__))
|
||||
#include <stdint.h>
|
||||
|
||||
#define SymbolCount(E) GLUE(E, _count)
|
||||
#define SymbolBasePtr(E) GLUE(E, _baseptr)
|
||||
#define SymbolOplPtr(E) (SymbolBasePtr(E) + SymbolCount(E))
|
||||
typedef uint8_t Sy_U8;
|
||||
typedef uint16_t Sy_U16;
|
||||
typedef uint32_t Sy_U32;
|
||||
typedef uint64_t Sy_U64;
|
||||
|
||||
#define SymbolMetadata(E,N) (&SYMBOL__SYM(E,N))
|
||||
#define SymbolID(E,N) SymbolIDFromMetadata(E, SymbolMetadata(E,N))
|
||||
#if SY__ARCH_X64 || SY__ARCH_ARM64
|
||||
typedef Sy_U64 Sy_UAddress;
|
||||
#else
|
||||
typedef Sy_U32 Sy_UAddress;
|
||||
#endif
|
||||
|
||||
#define SymbolIDFromMetadata(E,ptr) \
|
||||
((SymbolBasePtr(E) <= (ptr) && (ptr) < SymbolOplPtr(E))? \
|
||||
(U32)(1 + ((ptr) - SymbolBasePtr(E))):0)
|
||||
/******************
|
||||
** Macro Helpers **
|
||||
******************/
|
||||
|
||||
#define SymbolMetadataFromID(E,id) \
|
||||
((1 <= (id) && (id) <= SymbolCount(E))?\
|
||||
(SymbolBasePtr(E) + (id) - 1):(&SYMBOL__SYM(E,0)))
|
||||
#define SY__GLUE_(a,b) a##b
|
||||
#define SY__GLUE(a,b) SY__GLUE_(a,b)
|
||||
|
||||
#define SymbolRaw(E,N) IntFromPtr(SymbolMetadata(E,N))
|
||||
#define SymbolIDFromRaw(E,raw) SymbolIDFromMetadata(E,(SYMBOL__TYPE(E)*)(PtrFromInt(raw)))
|
||||
#define SymbolRawFromID(E,id) IntFromPtr(SymbolMetadataFromID(E,id))
|
||||
#define SY__STRIFY_(s) #s
|
||||
#define SY__STRIFY(s) SY__STRIFY_(s)
|
||||
|
||||
// internal
|
||||
/*****************
|
||||
** Align Helper **
|
||||
*****************/
|
||||
|
||||
#define SYMBOL__TYPE(E) GLUE(E,_Type)
|
||||
#define SYMBOL__SYM(E,N) GLUE(E, GLUE(__, N))
|
||||
#define SY__ALIGN_TO_POW2(x,a) (((x) + (a) - 1)&~((a) - 1))
|
||||
|
||||
#define SYMBOL__RAW_BASE(E) IntFromPtr(SymbolBasePtr(E))
|
||||
#define SYMBOL__RAW_OPL(E) (SYMBOL__RAW_BASE(E) + SymbolCount(E)*sizeof(SYMBOL__TYPE(E)))
|
||||
/*******************
|
||||
** Section Macros **
|
||||
*******************/
|
||||
|
||||
#define SYMBOL__BEFORE_MAIN_NAME GLUE(SYMBOL_SET_DEFINE,__init)
|
||||
#define SYMBOL__CL_PRAGMA section(GLUE(SYMBOL_SET_DEFINE,_section),read,write)
|
||||
/* IMPORTANT! On CL compiler add: #pragma section(<section>,read,write) */
|
||||
|
||||
#if SY__COMPILER_CLANG || SY__COMPILER_GCC
|
||||
# if SY__OS_MAC
|
||||
# define SY__SECTION_READONLY(N) __attribute__((__section__("__TEXT,"N))) const
|
||||
# define SY__SECTION_READWRITE(N) __attribute__((__section__("__READ,"N)))
|
||||
# else
|
||||
# define SY__SECTION_READONLY(N) __attribute__((__section__(N))) const
|
||||
# define SY__SECTION_READWRITE(N) __attribute__((__section__(N)))
|
||||
# endif
|
||||
#elif COMPILER_CL
|
||||
# define SY__SECTION_READONLY(N) __declspec(allocate(N)) const
|
||||
# define SY__SECTION_READWRITE(N) __declspec(allocate(N))
|
||||
#else
|
||||
# error SY__SECTION_* not defined for this compiler/OS
|
||||
#endif
|
||||
|
||||
/****************************
|
||||
** Do Not Mangle Qualifier **
|
||||
****************************/
|
||||
|
||||
#if SY__LANG_CXX
|
||||
# define SY__DO_NOT_MANGLE extern "C"
|
||||
#else
|
||||
# define SY__DO_NOT_MANGLE
|
||||
#endif
|
||||
|
||||
/*******************************
|
||||
** Do Not Eliminate Qualifier **
|
||||
*******************************/
|
||||
|
||||
#if SY__OS_WINDOWS
|
||||
# define SY__DO_NOT_ELIMINATE__S0(N) __pragma(comment(linker,"/include:" #N))
|
||||
# define SY__DO_NOT_ELIMINATE__S1(N) DO_NOT_ELIMINATE__S0(N)
|
||||
# define SY__DO_NOT_ELIMINATE(N) DO_NOT_ELIMINATE__S1(N)
|
||||
#else
|
||||
# define SY__DO_NOT_ELIMINATE(N)
|
||||
#endif
|
||||
|
||||
/********************
|
||||
** Align Qualifier **
|
||||
********************/
|
||||
|
||||
#if SY__COMPILER_CL
|
||||
# define SY__ALIGN_VAR(z) __declspec(align(z))
|
||||
#elif SY__COMPILER_CLANG || SY__COMPILER_GCC
|
||||
# define SY__ALIGN_VAR(z) __attribute__((__aligned__(z)))
|
||||
#else
|
||||
# error SY__ALIGN not defined for this compiler
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
** Before Mains **
|
||||
*****************/
|
||||
|
||||
#if SY__OS_WINDOWS
|
||||
# pragma section(".CRT$XCU", read)
|
||||
# define SY__BEFORE_MAIN__(n) \
|
||||
static void n(void); \
|
||||
SY__SECTIONREADWRITE(".CRT$XCU") \
|
||||
SY__DO_NOT_ELIMINATE(n##__) \
|
||||
SY__DO_NOT_MANGLE void (*n##__)(void); \
|
||||
void (*n##__)(void) = n; \
|
||||
static void n(void)
|
||||
#elif SY__OS_LINUX
|
||||
# define SY__BEFORE_MAIN__(n) __attribute__((constructor)) static void n(void)
|
||||
#else
|
||||
# error SY__BEFORE_MAIN__ missing for this OS
|
||||
#endif
|
||||
|
||||
#define SY__BEFORE_MAIN_(n) SY__BEFORE_MAIN__(n)
|
||||
#define SY__BEFORE_MAIN(n) SY__BEFORE_MAIN_(n)
|
||||
|
||||
/*************************************
|
||||
** Symbol Set Programming Interface **
|
||||
*************************************/
|
||||
|
||||
#define SyType(S) SY__GLUE(S,_Type)
|
||||
|
||||
#define SyDeclare(S,N) SY__ALIGN_VAR(8) SY__SECTION_READWRITE(S##_section) SyType(S) SY__SYMBOL(S,N)
|
||||
#define SyDefine(S,N) SY__DO_NOT_ELIMINATE(SY__SYMBOL(S,N)) SyDeclare(S,N)
|
||||
#define SyDefineUnnamed(S) SyDefine(S,SY__GLUE(unnamed,__COUNTER__))
|
||||
|
||||
#define SyAddress(S,N) (&SY__SYMBOL(S,N))
|
||||
#define SyID(S,N) SyIDFromAddress_Unchecked(S,SyAddress(S,N))
|
||||
#define SyFlag(S,N) (1llu << SyID(S,N))
|
||||
|
||||
#define SyStride(S) SY__ALIGN_TO_POW2(sizeof(SyType(S)), 8)
|
||||
|
||||
#if SY__OS_WINDOWS
|
||||
# define SyFirst(S) SY__FIRST(S)
|
||||
# define SyOpl(S) SY__OPL(S)
|
||||
#elif SY__OS_LINUX
|
||||
# define SyFirst(S) (&SY__FIRST(S))
|
||||
# define SyOpl(S) (&SY__OPL(S))
|
||||
#else
|
||||
# error missing implementation set locator for this OS
|
||||
#endif
|
||||
|
||||
#define SyCount(S) (((Sy_U8*)SyOpl(S) - (Sy_U8*)SyFirst(S))/SyStride(S))
|
||||
#define SyNext(S,addr) (SyType(S)*)((Sy_U8*)addr + SyStride(S))
|
||||
|
||||
#define SyEach(S,var) SyType(S)*var=SyFirst(S); var<SyOpl(S); var=SyNext(S,var)
|
||||
|
||||
#define SyIDFromAddress(S,addr) (SyAddressCheck(S,addr)?SyIDFromAddress_Unchecked(S,addr):0)
|
||||
#define SyAddressFromID(S,id) (SyIDCheck(S,id)?SyAddressFromID_Unchecked(S,id):0)
|
||||
|
||||
#define SyAddressCheck(S,addr) (SyFirst(S) <= (addr) && (addr) <= SyOpl(S))
|
||||
#define SyIDCheck(S,id) (1 <= (id) && (id) <= SyCount(S))
|
||||
|
||||
#define SyIDFromAddress_Unchecked(S,addr) ((Sy_U32)(1 + ((Sy_U8*)(addr) - (Sy_U8*)SyFirst(S))/SyStride(S)))
|
||||
#define SyAddressFromID_Unchecked(S,id) ((SyType(S)*)((Sy_U8*)SyFirst(S) + ((id) - 1)*SyStride(S)))
|
||||
|
||||
#define SyRaw(S,N) (Sy_UAddress)(SyAddress(S,N))
|
||||
#define SyIDFromRaw(S,raw) SyIDFromAddress(S,(SyType(S)*)(raw))
|
||||
#define SyIDFromRaw_Unchecked(S,raw) SyIDFromAddress_Unchecked(S,(SyType(S)*)(raw))
|
||||
|
||||
|
||||
#endif //SYMBOL_SET_H
|
||||
/*************
|
||||
** Internal **
|
||||
*************/
|
||||
|
||||
#define SY__SYMBOL(S,N) SY__GLUE(S,SY__GLUE(__,N))
|
||||
|
||||
#define SY__FIRST_(S) SY__GLUE(syfirst__, S##_marker)
|
||||
#define SY__OPL_(S) SY__GLUE(syopl__, S##_marker)
|
||||
|
||||
#define SY__FIRST(S) SY__FIRST_(S)
|
||||
#define SY__OPL(S) SY__OPL_(S)
|
||||
|
||||
#if SY__OS_WINDOWS
|
||||
void sy__section_init(char *name, Sy_U32 name_size, void **first_out, void **opl_out);
|
||||
#endif
|
||||
|
||||
#endif /* SYMBOL_SET_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
/****** Define One Symbol Set *******/
|
||||
#if 0
|
||||
/* To define a symbol set, copy-paste the block below and then:
|
||||
** Replace ZZZ with a name for the symbol set.
|
||||
** Replace Typezz with the type of the symbol set.
|
||||
** Replace secz with a unique name for the data section of the symbol set.
|
||||
** IMPORTANT NOTE: you only get 4 characters for the section name if you
|
||||
** want to port to Windows.
|
||||
*/
|
||||
|
||||
#define SYMBOL_SET_DEFINE ZZZ
|
||||
#define ZZZ_Type Typezz
|
||||
#define ZZZ_section ".sy.secz"
|
||||
#define ZZZ_marker secz
|
||||
#include "symbol_set.define.h"
|
||||
|
||||
#endif
|
||||
/****** Define One Symbol Set *******/
|
||||
|
||||
|
||||
|
||||
/****** Common Helpers For Defining Symbols *******/
|
||||
#if 0
|
||||
|
||||
/* Defining a basic struct with a NAME */
|
||||
#define ZZZ_DEF(N,...) SyDefine(ZZZ, NAME) = { ... }
|
||||
|
||||
/* Defining a basic struct without a name */
|
||||
#define ZZZ_DEF(...) SyDefineNameless(ZZZ, NAME) = { ... }
|
||||
|
||||
#endif
|
||||
/****** Common Helpers For Defining Symbols *******/
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
11
todo.txt
11
todo.txt
|
|
@ -62,17 +62,12 @@ Development:
|
|||
|
||||
Other Upgrade Research:
|
||||
|
||||
[ ] Could Symbol Sets syntax be organized in such a way that it's just a data
|
||||
section and type wrapped in a macro?
|
||||
|
||||
[ ] Could Symbol Sets syntax be organized in such a way that it's just a
|
||||
data section and type wrapped in a macro?
|
||||
|
||||
Support Tools:
|
||||
|
||||
[x] see data section size and layout info
|
||||
[ ] dump binary as hex from a data section
|
||||
[ ] see symbols inside data sections
|
||||
[ ] see symbols by name
|
||||
[ ] count of symbols in symbol set
|
||||
[ ] display of string and integer data in symbol from symbol set
|
||||
[ ] see symbols in symbol sets from object files
|
||||
[ ] size of types
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue