trim down the PE parsing code; switch to lighter weight image pointer retrieval via '__ImageBase'
parent
6c7c13f93b
commit
14fb4e3944
|
|
@ -8,6 +8,7 @@ patterns = {
|
|||
"*.bat",
|
||||
"*.sh",
|
||||
"*.4coder",
|
||||
"*.txt",
|
||||
};
|
||||
blacklist_patterns = {
|
||||
".*",
|
||||
|
|
|
|||
31
src/base.c
31
src/base.c
|
|
@ -34,21 +34,11 @@ str8_match(String8 a, String8 b, U32 flags){
|
|||
|
||||
#if OS_WINDOWS
|
||||
|
||||
static RangePtr
|
||||
// see: https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483
|
||||
static void*
|
||||
os_this_image(void){
|
||||
RangePtr result = {0};
|
||||
HMODULE module = 0;
|
||||
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||
(LPWSTR)os_this_image, &module);
|
||||
if (module != 0){
|
||||
HANDLE process = GetCurrentProcess();
|
||||
MODULEINFO module_info = {0};
|
||||
if (GetModuleInformation(process, module,
|
||||
&module_info, sizeof(module_info))){
|
||||
result.first = (U8*)module_info.lpBaseOfDll;
|
||||
result.opl = result.first + module_info.SizeOfImage;
|
||||
}
|
||||
}
|
||||
extern U8 __ImageBase[];
|
||||
void *result = __ImageBase;
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
@ -59,18 +49,11 @@ os_this_image(void){
|
|||
#if OS_WINDOWS
|
||||
|
||||
# include "binary/pe/mr4th_pe.h"
|
||||
# include "binary/pe/mr4th_pe.parse.h"
|
||||
# include "binary/pe/mr4th_pe.parse.c"
|
||||
# include "binary/pe/mr4th_pe.img_get_section.c"
|
||||
|
||||
static RangePtr
|
||||
selfimg_get_section(RangePtr image, String8 name){
|
||||
RangePtr result = {0};
|
||||
String8 image_str = str8(image.first, image.opl - image.first);
|
||||
PE_SectionHeader *section = pe_section_header_from_name(image_str, name);
|
||||
if (section != 0){
|
||||
result.first = image.first + section->voff;
|
||||
result.opl = result.first + section->vsize;
|
||||
}
|
||||
self_img_get_section(void *image, String8 name){
|
||||
RangePtr result = pe_img_get_section(image, name);
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,5 +247,6 @@ typedef struct String8{
|
|||
static String8 str8(U8 *str, U64 size);
|
||||
static B32 str8_match(String8 a, String8 b, U32 flags);
|
||||
|
||||
static RangePtr os_this_image(void);
|
||||
static RangePtr selfimg_get_section(RangePtr image, String8 name);
|
||||
static void* os_this_image(void);
|
||||
|
||||
static RangePtr self_img_get_section(void *image, String8 name);
|
||||
|
|
|
|||
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef MR4TH_BINARY_H
|
||||
#define MR4TH_BINARY_H
|
||||
|
||||
/* TODO:
|
||||
** BINARY FILE PROJECT
|
||||
**
|
||||
** Research Questions:
|
||||
** [ ] What the heck is that blob of data between the
|
||||
** DOS header and the PE signature/COFF header?
|
||||
** And why does it change so much from binary to binary?
|
||||
** [ ] Unwind Info: The docs say there is a ULONG after the unwind codes???
|
||||
**
|
||||
** TASKS:
|
||||
**
|
||||
** [x] Useful PE/COFF Table Tool
|
||||
** [ ] PE/COFF Linker
|
||||
** [ ] PE/COFF ObjFromRaw
|
||||
** [ ] PE/COFF editing to hard wire magic IDs without a data section
|
||||
** [ ] PE/COFF editing to merge separate data sections to
|
||||
** consolidate magic gathered arrays into plain old .data
|
||||
**
|
||||
** [ ] Renaming pass over mr4th_elf.dump (similar to pe.dump -> pe.parsex)
|
||||
** [ ] ELF Generator
|
||||
** [ ] Useful ELF ASCII Visualizer
|
||||
** [ ] ELF Linker
|
||||
** [ ] Debug Information (CODEVIEW,DWARF)
|
||||
**
|
||||
*/
|
||||
|
||||
#endif //MR4TH_BINARY_H
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
////////////////////////////////
|
||||
// Functions: COFF / PE
|
||||
|
||||
// properties
|
||||
|
||||
MR4TH_SYM_COMPTIME U32
|
||||
pe_unwind_num_code_slot_from_opcode_opinfo(PE_UnwindOpCode opcode, U8 opinfo){
|
||||
U32 num = 1;
|
||||
|
||||
switch (opcode){
|
||||
case PE_UnwindOpCode_PUSH_NONVOL:
|
||||
case PE_UnwindOpCode_ALLOC_SMALL:
|
||||
case PE_UnwindOpCode_SET_FPREG:
|
||||
case PE_UnwindOpCode_PUSH_MACHFRAME:
|
||||
case PE_UnwindOpCode_EPILOG:
|
||||
case PE_UnwindOpCode_SPARE:
|
||||
{
|
||||
num = 1;
|
||||
}break;
|
||||
|
||||
case PE_UnwindOpCode_ALLOC_LARGE:
|
||||
{
|
||||
if (opinfo == 0){
|
||||
num = 2;
|
||||
}
|
||||
else{
|
||||
num = 3;
|
||||
}
|
||||
}break;
|
||||
|
||||
case PE_UnwindOpCode_SAVE_NONVOL:
|
||||
case PE_UnwindOpCode_SAVE_XMM128:
|
||||
{
|
||||
num = 2;
|
||||
}break;
|
||||
|
||||
case PE_UnwindOpCode_SAVE_NONVOL_FAR:
|
||||
case PE_UnwindOpCode_SAVE_XMM128_FAR:
|
||||
{
|
||||
num = 3;
|
||||
}break;
|
||||
}
|
||||
|
||||
return(num);
|
||||
}
|
||||
|
||||
// checks
|
||||
|
||||
MR4TH_SYM_COMPTIME B32
|
||||
pe_machine_type_is_valid(PE_MachineType machine_type){
|
||||
B32 result = 0;
|
||||
switch (machine_type){
|
||||
#define X(N,C) case C:
|
||||
PE_MachineType_XList(X)
|
||||
#undef X
|
||||
result = 1; break;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
// strings
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_machine_type(PE_MachineType machine_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (machine_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_MachineType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
pe_str8list_from_flags(Arena *arena, String8List *out, PE_Flags flags){
|
||||
U32 f = 1;
|
||||
for (U32 i = 0; i < 8*sizeof(flags); i += 1){
|
||||
if ((flags & f) != 0){
|
||||
switch (f){
|
||||
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
|
||||
PE_Flags_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
f <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_flags(Arena *arena, PE_Flags flags){
|
||||
ArenaTemp scratch = arena_get_scratch(&arena, 1);
|
||||
String8List list = {0};
|
||||
pe_str8list_from_flags(scratch.arena, &list, flags);
|
||||
String8 result = str8_join_flags(arena, &list);
|
||||
arena_release_scratch(&scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_optional_header_magic(PE_OptionalHeaderMagic magic){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (magic){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_OptionalHeaderMagic_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_windows_subsystem(PE_WindowsSubsystem subsystem){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (subsystem){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_WindowsSubsystem_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
pe_str8list_from_dll_flags(Arena *arena, String8List *out, PE_DLLFlags dll_flags){
|
||||
U32 f = 1;
|
||||
for (U32 i = 0; i < 8*sizeof(dll_flags); i += 1){
|
||||
if ((dll_flags & f) != 0){
|
||||
switch (f){
|
||||
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
|
||||
PE_DLLFlags_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
f <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_dll_flags(Arena *arena, PE_DLLFlags dll_flags){
|
||||
ArenaTemp scratch = arena_get_scratch(&arena, 1);
|
||||
String8List list = {0};
|
||||
pe_str8list_from_dll_flags(scratch.arena, &list, dll_flags);
|
||||
String8 result = str8_join_flags(arena, &list);
|
||||
arena_release_scratch(&scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_data_directory_idx(PE_DataDirectoryIdx idx){
|
||||
String8 result = {0};
|
||||
switch (idx){
|
||||
#define X(N,D,C) case C: result = str8_lit(#N); break;
|
||||
PE_DataDirectoryIdx_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_display_string_from_data_directory_idx(PE_DataDirectoryIdx idx){
|
||||
String8 result = {0};
|
||||
switch (idx){
|
||||
#define X(N,D,C) case C: result = str8_lit(D); break;
|
||||
PE_DataDirectoryIdx_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_sec_alignment(U32 alignment){
|
||||
String8 result = {0};
|
||||
switch (alignment){
|
||||
#define X(Z,C) case C: result = str8_lit("ALIGN_" #Z "BYTES"); break;
|
||||
PE_SectionAlign_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME void
|
||||
pe_str8list_from_sec_flags(Arena *arena, String8List *out, PE_SectionFlags sec_flags){
|
||||
// align
|
||||
U32 section_align = PE_SectionAlignFromSectionFlags(sec_flags);
|
||||
String8 align_str = pe_str8_from_sec_alignment(section_align);
|
||||
if (align_str.size > 0){
|
||||
str8_list_push(arena, out, align_str);
|
||||
}
|
||||
|
||||
// other flags
|
||||
U32 f = 1;
|
||||
for (U32 i = 0; i < 8*sizeof(sec_flags); i += 1){
|
||||
if ((sec_flags & f) != 0){
|
||||
switch (f){
|
||||
#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break;
|
||||
PE_SectionFlags_XList(X)
|
||||
#undef X
|
||||
}
|
||||
}
|
||||
f <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_sec_flags(Arena *arena, PE_SectionFlags sec_flags){
|
||||
ArenaTemp scratch = arena_get_scratch(&arena, 1);
|
||||
String8List list = {0};
|
||||
pe_str8list_from_sec_flags(scratch.arena, &list, sec_flags);
|
||||
String8 result = str8_join_flags(arena, &list);
|
||||
arena_release_scratch(&scratch);
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_coff_relocation_type(PE_CoffRelocationType type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_CoffRelocationType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_coff_symbol_type(Arena *arena, PE_CoffSymbolType type){
|
||||
String8 lo = str8_lit("ERROR");
|
||||
switch (type & 0xF){
|
||||
#define X(N,C) case C: lo = str8_lit(#N); break;
|
||||
PE_CoffSymbolTypeLo_XList(X)
|
||||
#undef X
|
||||
}
|
||||
|
||||
String8 result = lo;
|
||||
switch ((type >> 4) & 0xF){
|
||||
case PE_CoffSymbolTypeHi_NULL: break;
|
||||
case PE_CoffSymbolTypeHi_POINTER:
|
||||
result = str8_pushf(arena, "POINTER %S", lo); break;
|
||||
case PE_CoffSymbolTypeHi_FUNCTION:
|
||||
result = str8_pushf(arena, "FUNCTION %S", lo); break;
|
||||
case PE_CoffSymbolTypeHi_ARRAY:
|
||||
result = str8_pushf(arena, "ARRAY %S", lo); break;
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_coff_symbol_storage_class(PE_CoffSymbolStorageClass storage_class){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (storage_class){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_CoffSymbolStorageClass_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_base_relocation_type(PE_BaseRelocationType type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_BaseRelocationType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
MR4TH_SYM_COMPTIME String8
|
||||
pe_str8_from_debug_type(PE_DebugType debug_type){
|
||||
String8 result = str8_lit("ERROR");
|
||||
switch (debug_type){
|
||||
#define X(N,C) case C: result = str8_lit(#N); break;
|
||||
PE_DebugType_XList(X)
|
||||
#undef X
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,463 +0,0 @@
|
|||
#ifndef MR4TH_PE_GEN_H
|
||||
#define MR4TH_PE_GEN_H
|
||||
|
||||
////////////////////////////////
|
||||
// PE Generator Types
|
||||
|
||||
// data block system
|
||||
|
||||
typedef struct PEGEN_Block{
|
||||
struct PEGEN_Block *next_bucket;
|
||||
struct PEGEN_Block *next_sibling;
|
||||
struct PEGEN_Block *first_child;
|
||||
struct PEGEN_Block *last_child;
|
||||
struct PEGEN_Block *parent;
|
||||
U32 child_count;
|
||||
B8 attached;
|
||||
U8 padding_fillbyte;
|
||||
U32 base_alignment;
|
||||
U8 *data;
|
||||
U32 total_size;
|
||||
U32 off_within_parent;
|
||||
} PEGEN_Block;
|
||||
|
||||
typedef struct PEGEN_Ctx{
|
||||
Arena *arena;
|
||||
|
||||
PEGEN_Block *first_block;
|
||||
PEGEN_Block *last_block;
|
||||
U64 block_count;
|
||||
} PEGEN_Ctx;
|
||||
|
||||
typedef struct PEGEN_Label{
|
||||
PEGEN_Block *block;
|
||||
U32 off;
|
||||
} PEGEN_Label;
|
||||
|
||||
// sections
|
||||
|
||||
typedef struct PEGEN_Section{
|
||||
struct PEGEN_Section *next;
|
||||
PEGEN_Block *block;
|
||||
U8 *name;
|
||||
U32 name_size;
|
||||
U16 secnum;
|
||||
PE_SectionFlags flags;
|
||||
U32 vsize;
|
||||
struct PEGEN_CoffRelocList *coff_relocs;
|
||||
} PEGEN_Section;
|
||||
|
||||
typedef struct PEGEN_SectionList{
|
||||
PEGEN_Section *first;
|
||||
PEGEN_Section *last;
|
||||
U64 count;
|
||||
} PEGEN_SectionList;
|
||||
|
||||
// patches for pe/coff files
|
||||
|
||||
typedef enum PEGEN_PatchKind{
|
||||
PEGEN_PatchKind_FileAbsolute,
|
||||
PEGEN_PatchKind_FileRelative,
|
||||
PEGEN_PatchKind_VirtAbsolute,
|
||||
PEGEN_PatchKind_VirtRelative,
|
||||
PEGEN_PatchKind_VirtAddress,
|
||||
PEGEN_PatchKind_SectionNumber,
|
||||
PEGEN_PatchKind_SectionOffset,
|
||||
} PEGEN_PatchKind;
|
||||
|
||||
typedef struct PEGEN_Patch{
|
||||
struct PEGEN_Patch *next;
|
||||
|
||||
// positions
|
||||
PEGEN_Label patchpos;
|
||||
PEGEN_Label targetpos;
|
||||
|
||||
// patch bits
|
||||
U8 patch_bitoff;
|
||||
U8 patch_numbits;
|
||||
|
||||
// value calculation
|
||||
PEGEN_PatchKind kind;
|
||||
S8 bias;
|
||||
U8 shift;
|
||||
|
||||
// val = ( (flags.SecIdx?IdxOf(SecOf(target)):VoffOf(target))
|
||||
// + (flags.Vaddr?ImageBaseVaddr:0)
|
||||
// - (flags.RelocRel?AddrOf(reloc):0)
|
||||
// - (flags.SecRel?AddrOf(SecOf(target)):0)
|
||||
// + bias) >> shift
|
||||
|
||||
} PEGEN_Patch;
|
||||
|
||||
typedef struct PEGEN_PatchList{
|
||||
PEGEN_Patch *first;
|
||||
PEGEN_Patch *last;
|
||||
U64 count;
|
||||
} PEGEN_PatchList;
|
||||
|
||||
// image config
|
||||
|
||||
typedef struct PEGEN_ImgConfig{
|
||||
U64 base_vaddr;
|
||||
U32 file_align;
|
||||
U32 virt_align;
|
||||
PEGEN_Label entry_point;
|
||||
PEGEN_Block *data_directories[PE_DataDirectoryIdx_COUNT];
|
||||
} PEGEN_ImgConfig;
|
||||
|
||||
// object config
|
||||
|
||||
typedef struct PEGEN_ObjConfig{
|
||||
struct PEGEN_SymbolTableBaked *symbol_table;
|
||||
} PEGEN_ObjConfig;
|
||||
|
||||
// headers & layouts
|
||||
|
||||
typedef struct PEGEN_LayoutSection{
|
||||
PEGEN_Block *block;
|
||||
U8 *name;
|
||||
U32 name_size;
|
||||
U32 voff;
|
||||
U32 foff;
|
||||
U32 vsize;
|
||||
U32 fsize;
|
||||
U16 fsize_padding;
|
||||
PE_SectionFlags flags;
|
||||
U16 reloc_count;
|
||||
PEGEN_Block *reloc_block;
|
||||
} PEGEN_LayoutSection;
|
||||
|
||||
typedef struct PEGEN_Layout{
|
||||
PEGEN_LayoutSection *sections;
|
||||
U32 section_count;
|
||||
U64 image_base_vaddr;
|
||||
} PEGEN_Layout;
|
||||
|
||||
typedef struct PEGEN_HeaderAndLayout{
|
||||
PEGEN_Block *header;
|
||||
PEGEN_Layout *layout;
|
||||
} PEGEN_HeaderAndLayout;
|
||||
|
||||
// symbol table
|
||||
|
||||
typedef struct PEGEN_Symbol{
|
||||
struct PEGEN_Symbol *next;
|
||||
String8 name;
|
||||
PE_CoffSymbolStorageClass storage_class;
|
||||
PE_CoffSymbolType type;
|
||||
PEGEN_Label pos;
|
||||
} PEGEN_Symbol;
|
||||
|
||||
typedef struct PEGEN_SymbolTable{
|
||||
PEGEN_Symbol *first;
|
||||
PEGEN_Symbol *last;
|
||||
U64 count;
|
||||
} PEGEN_SymbolTable;
|
||||
|
||||
typedef struct PEGEN_SymbolTableBaked{
|
||||
PEGEN_Block *block;
|
||||
U64 symbol_count;
|
||||
// TODO(allen): accelerate Ptr -> Idx
|
||||
PEGEN_Symbol **symbols;
|
||||
U32 *symbol_idxs;
|
||||
} PEGEN_SymbolTableBaked;
|
||||
|
||||
// coff relocs
|
||||
|
||||
typedef struct PEGEN_CoffReloc{
|
||||
struct PEGEN_CoffReloc *next;
|
||||
U32 off;
|
||||
PEGEN_Symbol *symbol;
|
||||
PE_CoffRelocationType type;
|
||||
} PEGEN_CoffReloc;
|
||||
|
||||
typedef struct PEGEN_CoffRelocList{
|
||||
PEGEN_CoffReloc *first;
|
||||
PEGEN_CoffReloc *last;
|
||||
U64 count;
|
||||
} PEGEN_CoffRelocList;
|
||||
|
||||
// exports
|
||||
|
||||
typedef struct PEGEN_Export{
|
||||
struct PEGEN_Export *next;
|
||||
|
||||
PEGEN_Label symbol_label;
|
||||
String8 symbol_fwdname;
|
||||
String8List names;
|
||||
} PEGEN_Export;
|
||||
|
||||
typedef struct PEGEN_ExportTable{
|
||||
PEGEN_Export *first;
|
||||
PEGEN_Export *last;
|
||||
U32 count;
|
||||
U32 name_count;
|
||||
|
||||
U32 time_stamp;
|
||||
U16 version_major;
|
||||
U16 version_minor;
|
||||
String8 binary_name;
|
||||
} PEGEN_ExportTable;
|
||||
|
||||
// imports
|
||||
|
||||
typedef struct PEGEN_Import{
|
||||
struct PEGEN_Import *next;
|
||||
String8 name;
|
||||
U16 ordinal;
|
||||
} PEGEN_Import;
|
||||
|
||||
// TODO(allen): renaming - these aren't "tables"
|
||||
typedef struct PEGEN_ImportTable{
|
||||
struct PEGEN_ImportTable *next;
|
||||
|
||||
PEGEN_Import *first;
|
||||
PEGEN_Import *last;
|
||||
U32 count;
|
||||
|
||||
U32 time_stamp;
|
||||
String8 binary_name;
|
||||
} PEGEN_ImportTable;
|
||||
|
||||
typedef struct PEGEN_ImportList{
|
||||
PEGEN_ImportTable *first_table;
|
||||
PEGEN_ImportTable *last_table;
|
||||
U64 table_count;
|
||||
} PEGEN_ImportList;
|
||||
|
||||
typedef struct PEGEN_ImportBlocks{
|
||||
PEGEN_Block *directory_table;
|
||||
PEGEN_Block *iat;
|
||||
PEGEN_Block *import_data;
|
||||
} PEGEN_ImportBlocks;
|
||||
|
||||
// base relocations
|
||||
|
||||
typedef struct PEGEN_BaseRelocationLoose{
|
||||
struct PEGEN_BaseRelocationLoose *next;
|
||||
PE_BaseRelocationType type;
|
||||
PEGEN_Label label;
|
||||
} PEGEN_BaseRelocationLoose;
|
||||
|
||||
typedef struct PEGEN_BaseRelocationList{
|
||||
PEGEN_BaseRelocationLoose *first;
|
||||
PEGEN_BaseRelocationLoose *last;
|
||||
U64 count;
|
||||
} PEGEN_BaseRelocationList;
|
||||
|
||||
typedef struct PEGEN_BaseRelocation{
|
||||
PE_BaseRelocationType type;
|
||||
U32 voff;
|
||||
} PEGEN_BaseRelocation;
|
||||
|
||||
// unwind info
|
||||
|
||||
typedef struct PEGEN_UnwindCode{
|
||||
struct PEGEN_UnwindCode *next;
|
||||
U8 offset;
|
||||
U8 opcode;
|
||||
U8 opinfo;
|
||||
U32 x;
|
||||
} PEGEN_UnwindCode;
|
||||
|
||||
typedef struct PEGEN_UnwindInfo{
|
||||
struct PEGEN_UnwindInfo *next;
|
||||
|
||||
PEGEN_Label start_pos;
|
||||
PEGEN_Label opl_pos;
|
||||
|
||||
PE_UnwindInfoFlags flags;
|
||||
U8 prolog_size;
|
||||
U8 frame_reg;
|
||||
U8 frame_off;
|
||||
|
||||
PEGEN_UnwindCode *first_code;
|
||||
PEGEN_UnwindCode *last_code;
|
||||
U8 code_count;
|
||||
U8 code_slot_count;
|
||||
} PEGEN_UnwindInfo;
|
||||
|
||||
typedef struct PEGEN_UnwindInfoList{
|
||||
PEGEN_UnwindInfo *first;
|
||||
PEGEN_UnwindInfo *last;
|
||||
U64 count;
|
||||
} PEGEN_UnwindInfoList;
|
||||
|
||||
typedef struct PEGEN_UnwindBlocks{
|
||||
PEGEN_Block *exception_handlers;
|
||||
PEGEN_Block *unwind_info;
|
||||
} PEGEN_UnwindBlocks;
|
||||
|
||||
////////////////////////////////
|
||||
// PE Generator Functions
|
||||
|
||||
/// gen api ///
|
||||
|
||||
// ctx
|
||||
function PEGEN_Ctx* pegen_begin(void);
|
||||
function void pegen_release(PEGEN_Ctx *gen);
|
||||
|
||||
// data blocks
|
||||
function PEGEN_Block* pegen_block_new(PEGEN_Ctx *gen);
|
||||
function PEGEN_Block* pegen_block_new_write(PEGEN_Ctx *gen, String8 data);
|
||||
function PEGEN_Block* pegen_block_new_aligned(PEGEN_Ctx *gen, U32 align);
|
||||
|
||||
function void*pegen_block_push(PEGEN_Ctx *gen, PEGEN_Block* block, U32 size);
|
||||
function void*pegen_block_push_write(PEGEN_Ctx *gen, PEGEN_Block* block, String8 data);
|
||||
function U8* pegen_block_push_cstring(PEGEN_Ctx *gen, PEGEN_Block* block, String8 string);
|
||||
|
||||
#define pegen_block_push_array(gen,block,T,c) (T*)pegen_block_push((gen),(block),sizeof(T)*(c))
|
||||
|
||||
function void pegen_block_align(PEGEN_Ctx *gen, PEGEN_Block* block, U8 fillbyte, U32 align);
|
||||
function void pegen_block_fill_to_size(PEGEN_Ctx *gen, PEGEN_Block *block, U8 fillbyte, U32 target_size);
|
||||
|
||||
function void pegen_block_push_block(PEGEN_Ctx *gen, PEGEN_Block *list, PEGEN_Block *block);
|
||||
|
||||
function U32 pegen_block_get_size(PEGEN_Block* block);
|
||||
function String8 pegen_block_flatten(Arena *arena, PEGEN_Block *block);
|
||||
function void pegen_block_flatten__recursive(PEGEN_Block *block, U8 *dst);
|
||||
|
||||
function U32 pegen_block_off_relative_to_ancestor(PEGEN_Block *block, PEGEN_Block *ancestor);
|
||||
|
||||
// labels
|
||||
function PEGEN_Label pegen_label(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off);
|
||||
function PEGEN_Label pegen_label_from_pointer(PEGEN_Ctx *gen, void *ptr);
|
||||
function void* pegen_pointer_from_block_off(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off);
|
||||
function void* pegen_pointer_from_label(PEGEN_Ctx *gen, PEGEN_Label label);
|
||||
|
||||
// patches
|
||||
function PEGEN_PatchList* pegen_patch_list_new(PEGEN_Ctx *gen);
|
||||
|
||||
function PEGEN_Patch* pegen_patch_push(PEGEN_Ctx *gen, PEGEN_PatchList *list);
|
||||
|
||||
function void pegen_patch_foff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos);
|
||||
|
||||
function void pegen_patch_voff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos);
|
||||
function void pegen_patch_voff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, void *targetpos_ptr);
|
||||
|
||||
function void pegen_patch_vrel32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, PEGEN_Label patchpos, PEGEN_Label targetpos, S8 bias);
|
||||
|
||||
function void pegen_patch_vaddr64_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, PEGEN_Label patchpos, PEGEN_Label targetpos);
|
||||
|
||||
function void pegen_patch_secnum16(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos);
|
||||
function void pegen_patch_secoff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos);
|
||||
|
||||
function void pegen_data_apply_patches(PEGEN_Ctx *gen, U8 *data, U64 size, PEGEN_Block *block, PEGEN_Layout *layout, PEGEN_PatchList *patch_list);
|
||||
|
||||
// sections
|
||||
function PEGEN_SectionList* pegen_section_list_new(PEGEN_Ctx *gen);
|
||||
|
||||
function PEGEN_Section*
|
||||
pegen_section_push(PEGEN_Ctx *gen, PEGEN_SectionList *list,
|
||||
String8 name, PE_SectionFlags flags, U32 vsize,
|
||||
PEGEN_Block *block);
|
||||
|
||||
function void
|
||||
pegen_section_equip_coff_relocs(PEGEN_Section *section,
|
||||
PEGEN_CoffRelocList *list);
|
||||
|
||||
#define PEGEN_DefaultVSize (~((U32)0))
|
||||
|
||||
// image config
|
||||
function PEGEN_ImgConfig* pegen_img_config_new(PEGEN_Ctx *gen);
|
||||
|
||||
function void pegen_img_config_base_vaddr(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U64 base_vaddr);
|
||||
function void pegen_img_config_file_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U32 file_align);
|
||||
function void pegen_img_config_virt_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U32 virt_align);
|
||||
function void pegen_img_config_entry_point(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, PEGEN_Label label);
|
||||
function void pegen_img_config_data_directory(PEGEN_Ctx *gen, PEGEN_ImgConfig *config,
|
||||
PE_DataDirectoryIdx idx, PEGEN_Block *block);
|
||||
|
||||
// object config
|
||||
function PEGEN_ObjConfig* pegen_obj_config_new(PEGEN_Ctx *gen);
|
||||
|
||||
function void pegen_obj_config_symbol_table(PEGEN_Ctx *gen, PEGEN_ObjConfig *config,
|
||||
PEGEN_SymbolTableBaked *table);
|
||||
|
||||
// headers & layouts
|
||||
function PEGEN_HeaderAndLayout
|
||||
pegen_img_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list,
|
||||
PEGEN_SectionList *section_list,
|
||||
PEGEN_ImgConfig *img_config);
|
||||
|
||||
function PEGEN_HeaderAndLayout
|
||||
pegen_obj_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list,
|
||||
PEGEN_SectionList *section_list,
|
||||
PEGEN_ObjConfig *obj_config);
|
||||
|
||||
function U32 pegen_layout_voff_from_foff(PEGEN_Layout *layout, U32 foff);
|
||||
function U32 pegen_layout_secnum_from_foff(PEGEN_Layout *layout, U32 foff);
|
||||
function U32 pegen_layout_secoff_from_foff(PEGEN_Layout *layout, U32 foff);
|
||||
|
||||
function U32 pegen_layout_voff_from_block(PEGEN_Layout *layout, PEGEN_Block *block);
|
||||
function U32 pegen_layout_voff_from_label(PEGEN_Layout *layout, PEGEN_Label label);
|
||||
|
||||
// symbol table
|
||||
function PEGEN_SymbolTable* pegen_symbol_table_new(PEGEN_Ctx *gen);
|
||||
|
||||
function PEGEN_Symbol* pegen_symbol_push(PEGEN_Ctx *gen, PEGEN_SymbolTable *symbols,
|
||||
String8 name, PE_CoffSymbolStorageClass storage_class,
|
||||
PE_CoffSymbolType type,
|
||||
PEGEN_Label pos);
|
||||
|
||||
function PEGEN_SymbolTableBaked*
|
||||
pegen_block_from_symbol_table(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list,
|
||||
PEGEN_SymbolTable *symbol_table);
|
||||
|
||||
function U32 pegen_symbol_idx_from_ptr(PEGEN_SymbolTableBaked *table,
|
||||
PEGEN_Symbol *symbol);
|
||||
|
||||
// coff relocs
|
||||
function PEGEN_CoffRelocList* pegen_coff_reloc_list_new(PEGEN_Ctx *gen);
|
||||
|
||||
function void pegen_coff_reloc_push(PEGEN_Ctx *gen, PEGEN_CoffRelocList *list,
|
||||
U32 off, PEGEN_Symbol *symbol,
|
||||
PE_CoffRelocationType reloc_type);
|
||||
|
||||
function PEGEN_Block*
|
||||
pegen_block_from_coff_reloc_list(PEGEN_Ctx *gen,
|
||||
PEGEN_SymbolTableBaked *symbol_table,
|
||||
PEGEN_CoffRelocList *list);
|
||||
|
||||
// export table
|
||||
function PEGEN_ExportTable* pegen_export_table_new(PEGEN_Ctx *gen);
|
||||
|
||||
function void pegen_export_table_set_binary_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 name);
|
||||
function void pegen_export_table_set_time_stamp(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U32 timestamp);
|
||||
function void pegen_export_table_set_version(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U16 major, U16 minor);
|
||||
|
||||
function PEGEN_Export* pegen_export_new(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Label label);
|
||||
function PEGEN_Export* pegen_export_new_fwd(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 fwdname);
|
||||
function void pegen_export_add_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Export *exp, String8 name);
|
||||
|
||||
function PEGEN_Block* pegen_block_from_exports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list_out, PEGEN_ExportTable *table);
|
||||
|
||||
// import table
|
||||
function PEGEN_ImportList* pegen_import_list_new(PEGEN_Ctx *gen);
|
||||
|
||||
function PEGEN_ImportTable* pegen_import_table_new(PEGEN_Ctx *gen, PEGEN_ImportList *list,
|
||||
String8 binary_name, U32 time_stamp);
|
||||
|
||||
function void pegen_import_new(PEGEN_Ctx *gen, PEGEN_ImportTable *table,
|
||||
String8 name, U16 ordinal);
|
||||
|
||||
function PEGEN_ImportBlocks pegen_blocks_from_imports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, PEGEN_ImportList *imports);
|
||||
|
||||
// base relocations
|
||||
function PEGEN_BaseRelocationList* pegen_base_relocation_list_new(PEGEN_Ctx *gen);
|
||||
function void pegen_base_relocation_new(PEGEN_Ctx *gen, PEGEN_BaseRelocationList *list,
|
||||
PE_BaseRelocationType type, PEGEN_Label label);
|
||||
|
||||
function PEGEN_Block* pegen_block_from_base_relocations(PEGEN_Ctx *gen, PEGEN_Layout *layout, PEGEN_BaseRelocationList *list);
|
||||
|
||||
function S32 pegen_base_relocation_compare(void *a, void *b, void *udata);
|
||||
|
||||
// unwind info
|
||||
function PEGEN_UnwindInfoList* pegen_unwind_info_list_new(PEGEN_Ctx *gen);
|
||||
function PEGEN_UnwindInfo* pegen_unwind_info_push(PEGEN_Ctx *gen, PEGEN_UnwindInfoList *list);
|
||||
function void pegen_unwind_info_code(PEGEN_Ctx *gen, PEGEN_UnwindInfo *handler,
|
||||
U8 offset, U8 opcode, U8 opinfo, U32 x);
|
||||
|
||||
function PEGEN_UnwindBlocks pegen_blocks_from_unwind_info(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, PEGEN_UnwindInfoList *list);
|
||||
|
||||
#endif //MR4TH_PE_GEN_H
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
/*
|
||||
** PE File Generator Development
|
||||
*/
|
||||
|
||||
#include "mr4th_base.h"
|
||||
#include "mr4th_base.stdio.h"
|
||||
#include "mr4th_keywords.h"
|
||||
|
||||
#include "block/mr4th_block.h"
|
||||
|
||||
#include "mr4th_pe.h"
|
||||
#include "mr4th_pe.gen.h"
|
||||
|
||||
#include "mr4th_base.c"
|
||||
#include "mr4th_pe.c"
|
||||
#include "mr4th_pe.gen.c"
|
||||
|
||||
#include "block/mr4th_block.c"
|
||||
|
||||
////////////////////////////////
|
||||
// Entry Point
|
||||
|
||||
int main(int argc, char **argv){
|
||||
os_main_init(argc, argv);
|
||||
|
||||
PEGEN_Ctx *gen = pegen_begin();
|
||||
|
||||
String8 output_filename = str8_lit("generated.obj");
|
||||
B32 gen_img = 0;
|
||||
|
||||
// time stamp
|
||||
DateTime date = os_now_universal_time();
|
||||
DateTime local_date = os_local_time_from_universal(&date);
|
||||
U32 time_stamp = os_time_stamp_32_from_date_time(&local_date);
|
||||
|
||||
/// loose construction helper ///
|
||||
PEGEN_SectionList *section_list = pegen_section_list_new(gen);
|
||||
PEGEN_PatchList *patch_list = pegen_patch_list_new(gen);
|
||||
PEGEN_UnwindInfoList *unwind_info_list = pegen_unwind_info_list_new(gen);
|
||||
|
||||
|
||||
/// loose construction helper (image) ///
|
||||
PEGEN_ImgConfig *img_config = 0;
|
||||
PEGEN_ExportTable *exports = 0;
|
||||
PEGEN_ImportList *imports = 0;
|
||||
PEGEN_BaseRelocationList *base_relocs = 0;
|
||||
|
||||
if (gen_img){
|
||||
// init img config
|
||||
img_config = pegen_img_config_new(gen);
|
||||
|
||||
// init exports
|
||||
exports = pegen_export_table_new(gen);
|
||||
pegen_export_table_set_binary_name(gen, exports, output_filename);
|
||||
pegen_export_table_set_time_stamp(gen, exports, time_stamp);
|
||||
pegen_export_table_set_version(gen, exports, 0, 0);
|
||||
|
||||
// init imports
|
||||
imports = pegen_import_list_new(gen);
|
||||
#if 0
|
||||
PEGEN_ImportTable *table =
|
||||
pegen_import_table_new(gen, imports, str8_lit("api-ms-win-crt-heap-l1-1-0.dll"), time_stamp);
|
||||
pegen_import_new(gen, table, str8_lit("malloc"), 25);
|
||||
#endif
|
||||
|
||||
// init base relocations
|
||||
base_relocs = pegen_base_relocation_list_new(gen);
|
||||
}
|
||||
|
||||
|
||||
/// loose construction helper (object) ///
|
||||
PEGEN_ObjConfig *obj_config = 0;
|
||||
PEGEN_SymbolTable *symbol_table = 0;
|
||||
|
||||
if (!gen_img){
|
||||
// init obj config
|
||||
obj_config = pegen_obj_config_new(gen);
|
||||
|
||||
// init symbol table
|
||||
symbol_table = pegen_symbol_table_new(gen);
|
||||
}
|
||||
|
||||
// arrange section data
|
||||
{
|
||||
// bake imports
|
||||
PEGEN_ImportBlocks import_blocks = {0};
|
||||
if (gen_img){
|
||||
import_blocks = pegen_blocks_from_imports(gen, patch_list, imports);
|
||||
pegen_img_config_data_directory(gen, img_config,
|
||||
PE_DataDirectoryIdx_ImportTable,
|
||||
import_blocks.directory_table);
|
||||
pegen_img_config_data_directory(gen, img_config,
|
||||
PE_DataDirectoryIdx_IAT,
|
||||
import_blocks.iat);
|
||||
}
|
||||
|
||||
// text & data
|
||||
PEGEN_Block *text_block = pegen_block_new_write(gen, str8(text, sizeof(text)));
|
||||
PEGEN_Section *text_section =
|
||||
pegen_section_push(gen, section_list, str8_lit(".text$mn"),
|
||||
PE_SectionFlag_CNT_CODE |
|
||||
PE_SectionFlag_MEM_EXECUTE |
|
||||
PE_SectionFlag_MEM_READ,
|
||||
PEGEN_DefaultVSize,
|
||||
text_block);
|
||||
|
||||
PEGEN_CoffRelocList *text_relocs = 0;
|
||||
if (!gen_img){
|
||||
text_relocs = pegen_coff_reloc_list_new(gen);
|
||||
pegen_section_equip_coff_relocs(text_section, text_relocs);
|
||||
}
|
||||
|
||||
PEGEN_Block *data_block = pegen_block_new_write(gen, str8(data, sizeof(data)));
|
||||
pegen_section_push(gen, section_list, str8_lit(".data"),
|
||||
PE_SectionFlag_CNT_INITIALIZED_DATA |
|
||||
PE_SectionFlag_MEM_READ |
|
||||
PE_SectionFlag_MEM_WRITE,
|
||||
PEGEN_DefaultVSize,
|
||||
data_block);
|
||||
|
||||
// entry point
|
||||
if (gen_img){
|
||||
PEGEN_Label entry_point = pegen_label(gen, text_block, 0);
|
||||
pegen_img_config_entry_point(gen, img_config, entry_point);
|
||||
}
|
||||
|
||||
// symbol table
|
||||
PEGEN_Symbol *sym_sum_longname = 0;
|
||||
PEGEN_Symbol *sym_variable = 0;
|
||||
|
||||
if (!gen_img){
|
||||
|
||||
{
|
||||
PEGEN_Label pos = pegen_label(gen, text_block, 0);
|
||||
sym_sum_longname =
|
||||
pegen_symbol_push(gen, symbol_table, str8_lit("sum_longname"),
|
||||
PE_CoffSymbolStorageClass_EXTERNAL,
|
||||
(PE_CoffSymbolTypeHi_FUNCTION << 4), pos);
|
||||
}
|
||||
|
||||
{
|
||||
PEGEN_Label pos = pegen_label(gen, data_block, 0);
|
||||
sym_variable =
|
||||
pegen_symbol_push(gen, symbol_table, str8_lit("variable"),
|
||||
PE_CoffSymbolStorageClass_EXTERNAL, 0, pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// text coff relocation
|
||||
if (!gen_img){
|
||||
pegen_coff_reloc_push(gen, text_relocs, 9, sym_variable,
|
||||
PE_CoffRelocationType_REL32);
|
||||
}
|
||||
|
||||
// bake exports
|
||||
PEGEN_Block *export_block = 0;
|
||||
if (gen_img){
|
||||
export_block = pegen_block_from_exports(gen, patch_list, exports);
|
||||
pegen_img_config_data_directory(gen, img_config,
|
||||
PE_DataDirectoryIdx_ExportTable,
|
||||
export_block);
|
||||
}
|
||||
|
||||
// bake unwind info
|
||||
PEGEN_UnwindBlocks unwind_blocks = {0};
|
||||
if (gen_img){
|
||||
unwind_blocks = pegen_blocks_from_unwind_info(gen, patch_list, unwind_info_list);
|
||||
pegen_img_config_data_directory(gen, img_config,
|
||||
PE_DataDirectoryIdx_ExceptionTable,
|
||||
unwind_blocks.exception_handlers);
|
||||
}
|
||||
|
||||
// bake symbol table
|
||||
PEGEN_SymbolTableBaked *symbol_table_baked = 0;
|
||||
if (!gen_img){
|
||||
symbol_table_baked =
|
||||
pegen_block_from_symbol_table(gen, patch_list, symbol_table);
|
||||
pegen_obj_config_symbol_table(gen, obj_config, symbol_table_baked);
|
||||
}
|
||||
|
||||
// put exports & imports into rdata
|
||||
if (gen_img){
|
||||
PEGEN_Block *rdata_block = pegen_block_new(gen);
|
||||
pegen_block_push_block(gen, rdata_block, import_blocks.iat);
|
||||
pegen_block_push_block(gen, rdata_block, export_block);
|
||||
pegen_block_push_block(gen, rdata_block, unwind_blocks.unwind_info);
|
||||
pegen_block_push_block(gen, rdata_block, import_blocks.directory_table);
|
||||
pegen_block_push_block(gen, rdata_block, import_blocks.import_data);
|
||||
|
||||
if (pegen_block_get_size(rdata_block) > 0){
|
||||
pegen_section_push(gen, section_list, str8_lit(".rdata"),
|
||||
PE_SectionFlag_CNT_INITIALIZED_DATA |
|
||||
PE_SectionFlag_MEM_READ,
|
||||
PEGEN_DefaultVSize,
|
||||
rdata_block);
|
||||
}
|
||||
}
|
||||
|
||||
// put exception handlers into pdata
|
||||
if (gen_img){
|
||||
if (pegen_block_get_size(unwind_blocks.exception_handlers) > 0){
|
||||
pegen_section_push(gen, section_list, str8_lit(".pdata"),
|
||||
PE_SectionFlag_CNT_INITIALIZED_DATA |
|
||||
PE_SectionFlag_MEM_READ,
|
||||
PEGEN_DefaultVSize,
|
||||
unwind_blocks.exception_handlers);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// header block
|
||||
PEGEN_HeaderAndLayout hdr_layout = {0};
|
||||
if (gen_img){
|
||||
hdr_layout = pegen_img_header_bake(gen, patch_list, section_list, img_config);
|
||||
}
|
||||
else{
|
||||
hdr_layout = pegen_obj_header_bake(gen, patch_list, section_list, obj_config);
|
||||
}
|
||||
|
||||
// assemble file
|
||||
PEGEN_Block *file = pegen_block_new(gen);
|
||||
{
|
||||
pegen_block_push_block(gen, file, hdr_layout.header);
|
||||
|
||||
for (U32 i = 0; i < hdr_layout.layout->section_count; i += 1){
|
||||
PEGEN_LayoutSection *sec = hdr_layout.layout->sections + i;
|
||||
pegen_block_fill_to_size(gen, file, 0, sec->foff);
|
||||
pegen_block_push_block(gen, file, sec->block);
|
||||
|
||||
U32 aligned_up_foff = sec->foff + sec->fsize + sec->fsize_padding;
|
||||
pegen_block_fill_to_size(gen, file, 0, aligned_up_foff);
|
||||
|
||||
if (sec->reloc_block != 0){
|
||||
pegen_block_push_block(gen, file, sec->reloc_block);
|
||||
}
|
||||
}
|
||||
|
||||
if (!gen_img){
|
||||
if (obj_config->symbol_table != 0){
|
||||
pegen_block_push_block(gen, file, obj_config->symbol_table->block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render file
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
String8 data = pegen_block_flatten(arena, file);
|
||||
pegen_data_apply_patches(gen, data.str, data.size, file,
|
||||
hdr_layout.layout, patch_list);
|
||||
os_file_write(output_filename, data);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#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
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
////////////////////////////////
|
||||
// PE Parse Functions
|
||||
|
||||
static PE_SectionHeader*
|
||||
pe_section_header_from_name(String8 img, String8 name){
|
||||
// extract dos header
|
||||
PE_DosHeader *dos_header = 0;
|
||||
if (sizeof(*dos_header) <= img.size){
|
||||
dos_header = (PE_DosHeader*)(img.str);
|
||||
if (dos_header->magic != PE_MSDOS_MAGIC){
|
||||
dos_header = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// extract coff file offset
|
||||
U32 coff_file_offset = 0;
|
||||
if (dos_header != 0){
|
||||
coff_file_offset = dos_header->coff_file_offset;
|
||||
}
|
||||
|
||||
// extract pe signature
|
||||
U32 pe_signature = 0;
|
||||
U32 coff_header_offset = 0;
|
||||
if (0 < coff_file_offset &&
|
||||
coff_file_offset + sizeof(pe_signature) <= img.size){
|
||||
pe_signature = *(U32*)(img.str + coff_file_offset);
|
||||
if (pe_signature == PE_SIGNATURE){
|
||||
coff_header_offset = coff_file_offset + sizeof(pe_signature);
|
||||
}
|
||||
}
|
||||
|
||||
// extract coff header
|
||||
PE_CoffHeader *coff_header = 0;
|
||||
if (0 < coff_header_offset &&
|
||||
coff_header_offset + sizeof(*coff_header) <= img.size){
|
||||
coff_header = (PE_CoffHeader*)(img.str + coff_header_offset);
|
||||
}
|
||||
|
||||
// extract section table offset & count
|
||||
U32 section_table_offset = 0;
|
||||
U32 section_count = 0;
|
||||
if (coff_header != 0){
|
||||
section_table_offset = ( coff_header_offset
|
||||
+ sizeof(*coff_header)
|
||||
+ coff_header->optional_header_size);
|
||||
section_count = coff_header->section_count;
|
||||
}
|
||||
|
||||
// scan section table
|
||||
PE_SectionHeader *match = 0;
|
||||
if (0 < section_table_offset &&
|
||||
section_table_offset + sizeof(PE_SectionHeader)*section_count <= img.size){
|
||||
PE_SectionHeader *sec = (PE_SectionHeader*)(img.str + section_table_offset);
|
||||
for (U32 i = 0; i < section_count; i += 1, sec += 1){
|
||||
U8 *ptr = sec->name;
|
||||
for (;*ptr != 0 && ptr < sec->name + sizeof(sec->name); ptr += 1);
|
||||
String8 secname = str8(sec->name, ptr - sec->name);
|
||||
if (str8_match(name, secname, 0)){
|
||||
match = sec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(match);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef MR4TH_PE_PARSE_H
|
||||
#define MR4TH_PE_PARSE_H
|
||||
|
||||
////////////////////////////////
|
||||
// PE Parse Functions
|
||||
|
||||
static PE_SectionHeader* pe_section_header_from_name(String8 img, String8 name);
|
||||
|
||||
#endif //MR4TH_PE_PARSE_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,82 +0,0 @@
|
|||
#ifndef MR4TH_PE_PARSE_EXAMPLE_H
|
||||
#define MR4TH_PE_PARSE_EXAMPLE_H
|
||||
|
||||
////////////////////////////////
|
||||
// PE Parse Example Arguments Types
|
||||
|
||||
typedef struct PEDUMP_Arguments{
|
||||
String8 input_file_name;
|
||||
} PEDUMP_Arguments;
|
||||
|
||||
////////////////////////////////
|
||||
// PE Parse Example Helper Types
|
||||
|
||||
typedef struct PEDUMP_CoffSymbol{
|
||||
String8 name;
|
||||
U32 val;
|
||||
S16 sec_number;
|
||||
PE_CoffSymbolType type;
|
||||
PE_CoffSymbolStorageClass storage_class;
|
||||
U8 aux_symbol_count;
|
||||
} PEDUMP_CoffSymbol;
|
||||
|
||||
typedef struct PEDUMP_ExportSymbol{
|
||||
U32 voff;
|
||||
String8 fwd;
|
||||
String8 name;
|
||||
} PEDUMP_ExportSymbol;
|
||||
|
||||
typedef struct PEDUMP_ImportSymbol{
|
||||
U16 ordinal;
|
||||
String8 name;
|
||||
} PEDUMP_ImportSymbol;
|
||||
|
||||
typedef struct PEDUMP_ImportTable{
|
||||
struct PEDUMP_ImportTable *next;
|
||||
|
||||
U32 time_stamp;
|
||||
U32 first_forwarder_idx;
|
||||
|
||||
String8 name;
|
||||
|
||||
PEDUMP_ImportSymbol *syms;
|
||||
U64 lookup_count;
|
||||
} PEDUMP_ImportTable;
|
||||
|
||||
typedef struct PEDUMP_BaseRelocation{
|
||||
U32 type;
|
||||
U32 voff;
|
||||
} PEDUMP_BaseRelocation;
|
||||
|
||||
typedef struct PEDUMP_UnwindCode{
|
||||
struct PEDUMP_UnwindCode *next;
|
||||
U8 offset;
|
||||
U8 opcode;
|
||||
U8 opinfo;
|
||||
U8 extra_slot_count;
|
||||
U32 x;
|
||||
} PEDUMP_UnwindCode;
|
||||
|
||||
typedef struct PEDUMP_UnwindInfo{
|
||||
U8 version;
|
||||
U8 flags;
|
||||
U8 prolog_size;
|
||||
U8 code_slot_count;
|
||||
U8 code_count;
|
||||
U8 frame_reg;
|
||||
U8 frame_off;
|
||||
PEDUMP_UnwindCode *first_code;
|
||||
PEDUMP_UnwindCode *last_code;
|
||||
} PEDUMP_UnwindInfo;
|
||||
|
||||
////////////////////////////////
|
||||
// PE Parse Example Arguments Functions
|
||||
|
||||
function PEDUMP_Arguments* pedump_args(Arena *arena, String8List *args);
|
||||
|
||||
////////////////////////////////
|
||||
// Entry Point
|
||||
|
||||
int main(int argc, char **argv);
|
||||
|
||||
#endif //MR4TH_PE_PARSE_EXAMPLE_H
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
/*
|
||||
** PE Tabulator
|
||||
*/
|
||||
|
||||
#include "mr4th_base.h"
|
||||
#include "mr4th_base.stdio.h"
|
||||
#include "mr4th_keywords.h"
|
||||
|
||||
#include "mr4th_pe.h"
|
||||
#include "mr4th_stream.h"
|
||||
#include "mr4th_ascii.h"
|
||||
|
||||
#include "mr4th_pe.table.h"
|
||||
|
||||
#include "mr4th_base.c"
|
||||
#include "mr4th_pe.c"
|
||||
#include "mr4th_stream.c"
|
||||
#include "mr4th_ascii.c"
|
||||
|
||||
////////////////////////////////
|
||||
// PE Tabulator Argument Functions
|
||||
|
||||
function PETAB_Args*
|
||||
petab_args(Arena *arena, String8List *command_line_args){
|
||||
// parse
|
||||
CMDLN *cmdln = cmdln_from_args(arena, command_line_args);
|
||||
|
||||
// setup args
|
||||
PETAB_Args *args = push_array(arena, PETAB_Args, 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();
|
||||
PETAB_Args *args = petab_args(arena, &command_line_args);
|
||||
|
||||
// load input file
|
||||
String8 data = os_file_read(arena, args->input_file_name);
|
||||
|
||||
|
||||
/////////////////
|
||||
///// PARSE /////
|
||||
/////////////////
|
||||
|
||||
// extract dos header
|
||||
PE_DosHeader *dos_header = 0;
|
||||
if (sizeof(*dos_header) <= data.size){
|
||||
dos_header = (PE_DosHeader*)(data.str);
|
||||
if (dos_header->magic != PE_MSDOS_MAGIC){
|
||||
dos_header = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// extract coff file offset
|
||||
U32 coff_file_offset = 0;
|
||||
if (dos_header != 0){
|
||||
coff_file_offset = dos_header->coff_file_offset;
|
||||
}
|
||||
|
||||
// extract pe signature
|
||||
U32 pe_signature = 0;
|
||||
U32 coff_header_offset = 0;
|
||||
if (0 < coff_file_offset &&
|
||||
coff_file_offset + sizeof(pe_signature) <= data.size){
|
||||
pe_signature = *(U32*)(data.str + coff_file_offset);
|
||||
if (pe_signature == PE_SIGNATURE){
|
||||
coff_header_offset = coff_file_offset + sizeof(pe_signature);
|
||||
}
|
||||
}
|
||||
|
||||
// extract coff header
|
||||
PE_CoffHeader *coff_header = 0;
|
||||
U64 coff_header_opl = 0;
|
||||
if (When(dos_header != 0, 0 < coff_header_offset) &&
|
||||
coff_header_offset + sizeof(*coff_header) <= data.size){
|
||||
coff_header = (PE_CoffHeader*)(data.str + coff_header_offset);
|
||||
coff_header_opl = coff_header_offset + sizeof(*coff_header);
|
||||
}
|
||||
|
||||
// optional header
|
||||
U64 optional_header_opl = coff_header_opl;
|
||||
if (coff_header != 0 &&
|
||||
coff_header->optional_header_size > 0){
|
||||
optional_header_opl = coff_header_opl + coff_header->optional_header_size;
|
||||
}
|
||||
|
||||
// determine if this is an image file
|
||||
B32 is_image = (coff_header_offset != 0);
|
||||
|
||||
// parse section table
|
||||
PE_SectionHeader *section_table = 0;
|
||||
U64 section_count = 0;
|
||||
if (coff_header != 0){
|
||||
U64 section_table_offset = optional_header_opl;
|
||||
U64 section_table_opl = section_table_offset + coff_header->section_count*sizeof(PE_SectionHeader);
|
||||
if (section_table_opl <= data.size){
|
||||
section_table = (PE_SectionHeader*)(data.str + section_table_offset);
|
||||
section_count = coff_header->section_count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/////////////////
|
||||
///// PRINT /////
|
||||
/////////////////
|
||||
|
||||
STREAM *stream = stream_new();
|
||||
STREAM *tempstr = stream_new();
|
||||
|
||||
{
|
||||
TABLE *table = table_begin(arena);
|
||||
|
||||
{
|
||||
table_default_align(table, TABLE_CellFlag_CenterAlign);
|
||||
|
||||
// TODO(allen): conditionals on columns
|
||||
table_row(arena, table);
|
||||
table_cellf(arena, table, "#");
|
||||
table_cellf(arena, table, "Name");
|
||||
table_cellf(arena, table, "V.Size");
|
||||
table_cellf(arena, table, "V.Off");
|
||||
table_cellf(arena, table, "F.Size");
|
||||
table_cellf(arena, table, "F.Off");
|
||||
table_cellf(arena, table, "Mem");
|
||||
table_cellf(arena, table, "#Relocs");
|
||||
table_cellf(arena, table, "#Lines");
|
||||
table_hz_separator(arena, table);
|
||||
|
||||
table_default_align(table, TABLE_CellFlag_LeftAlign);
|
||||
}
|
||||
|
||||
{
|
||||
PE_SectionHeader *sec = section_table;
|
||||
for (U64 i = 0; i < section_count; i += 1, sec += 1){
|
||||
table_row(arena, table);
|
||||
|
||||
table_cellf(arena, table, "%u", i + 1);
|
||||
table_cell_align(table, TABLE_CellFlag_RightAlign);
|
||||
|
||||
table_cellf(arena, table, "%.*s", ArrayCount(sec->name), sec->name);
|
||||
|
||||
table_default_align(table, TABLE_CellFlag_RightAlign);
|
||||
table_cellf(arena, table, "%$u", sec->vsize);
|
||||
table_cellf(arena, table, "0x%x", sec->voff);
|
||||
table_cellf(arena, table, "%$u", sec->fsize);
|
||||
table_cellf(arena, table, "0x%x", sec->foff);
|
||||
table_default_align(table, TABLE_CellFlag_LeftAlign);
|
||||
|
||||
// memory flags
|
||||
// TODO(allen): here we want to be able to write this cell
|
||||
// by writing into a stream
|
||||
{
|
||||
stream_clear(tempstr);
|
||||
stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_READ )?"r":"-");
|
||||
stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_WRITE )?"w":"-");
|
||||
stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_EXECUTE)?"x":"-");
|
||||
table_cell(arena, table, stream_read(arena, tempstr));
|
||||
}
|
||||
|
||||
table_default_align(table, TABLE_CellFlag_RightAlign);
|
||||
table_cellf(arena, table, "%u", sec->relocation_count);
|
||||
table_cellf(arena, table, "%u", sec->line_number_count);
|
||||
table_default_align(table, TABLE_CellFlag_LeftAlign);
|
||||
}
|
||||
}
|
||||
|
||||
stream_printf(stream, "SECTIONS: (Total %u)\n", section_count);
|
||||
table_print(stream, table, &table_wire_style);
|
||||
stream_printf(stream, "\n");
|
||||
}
|
||||
|
||||
stream_fprint(stdout, stream);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#ifndef MR4TH_PE_TABLE_H
|
||||
#define MR4TH_PE_TABLE_H
|
||||
|
||||
////////////////////////////////
|
||||
// PE Tabulator Argument Types
|
||||
|
||||
typedef struct PETAB_Args{
|
||||
String8 input_file_name;
|
||||
} PETAB_Args;
|
||||
|
||||
////////////////////////////////
|
||||
// PE Tabulator Argument Functions
|
||||
|
||||
function PETAB_Args* petab_args(Arena *arena, String8List *args);
|
||||
|
||||
////////////////////////////////
|
||||
// Entry Point
|
||||
|
||||
int main(int argc, char **argv);
|
||||
|
||||
#endif //MR4TH_PE_TABLE_H
|
||||
|
|
@ -5,8 +5,8 @@ static SYMBOL__TYPE(SYMBOL_SET_DEFINE) SYMBOL__SYM(SYMBOL_SET_DEFINE,0);
|
|||
# pragma SYMBOL__CL_PRAGMA
|
||||
#endif
|
||||
BEFORE_MAIN(){
|
||||
RangePtr image = os_this_image();
|
||||
RangePtr range = selfimg_get_section(image, str8_lit(GLUE(SYMBOL_SET_DEFINE,_section)));
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue