mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-15 14:01:25 -07:00
make export table with COFF obj writer,
partially converted import table to COFF obj writer
This commit is contained in:
committed by
Ryan Fleury
parent
3a2bb318c7
commit
19a7ada1dc
@@ -205,6 +205,27 @@ coff_make_ordinal64(U16 hint)
|
||||
return ordinal;
|
||||
}
|
||||
|
||||
internal String8
|
||||
coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint)
|
||||
{
|
||||
String8 ordinal_data = {0};
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
U64 *ordinal = push_array(arena, U64, 1);
|
||||
*ordinal = coff_make_ordinal64(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
case COFF_MachineType_X86: {
|
||||
U32 *ordinal = push_array(arena, U32, 1);
|
||||
*ordinal = coff_make_ordinal32(hint);
|
||||
ordinal_data = str8_struct(ordinal);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
return ordinal_data;
|
||||
}
|
||||
|
||||
internal String8
|
||||
coff_make_import_header_by_name(Arena *arena,
|
||||
String8 dll_name,
|
||||
|
||||
@@ -601,6 +601,7 @@ internal U64 coff_apply_size_from_reloc_x86(COFF_Reloc_X86 x);
|
||||
|
||||
internal U32 coff_make_ordinal32(U16 hint);
|
||||
internal U64 coff_make_ordinal64(U16 hint);
|
||||
internal String8 coff_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint);
|
||||
|
||||
internal String8 coff_make_import_lookup (Arena *arena, U16 hint, String8 name);
|
||||
internal String8 coff_make_import_header_by_name (Arena *arena, String8 dll_name, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 name, U16 hint, COFF_ImportType type);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
internal COFF_ObjWriter*
|
||||
coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine_type)
|
||||
coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||
{
|
||||
Arena *arena = arena_alloc();
|
||||
COFF_ObjWriter *obj_writer = push_array(arena, COFF_ObjWriter, 1);
|
||||
obj_writer->arena = arena;
|
||||
obj_writer->time_stamp = time_stamp;
|
||||
obj_writer->machine_type = machine_type;
|
||||
obj_writer->machine = machine;
|
||||
return obj_writer;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value,
|
||||
}
|
||||
|
||||
internal COFF_ObjSymbol *
|
||||
coff_obj_writer_push_symbol_external(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
|
||||
coff_obj_writer_push_symbol_extern(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_ObjSection *section)
|
||||
{
|
||||
COFF_SymbolLocation loc = {0};
|
||||
loc.type = COFF_SymbolLocation_Section;
|
||||
@@ -182,7 +182,7 @@ coff_obj_writer_serialize(Arena *arena, COFF_ObjWriter *obj_writer)
|
||||
// file header
|
||||
//
|
||||
COFF_FileHeader *file_header = push_array(scratch.arena, COFF_FileHeader, 1);
|
||||
file_header->machine = obj_writer->machine_type;
|
||||
file_header->machine = obj_writer->machine;
|
||||
file_header->section_count = obj_sections_count;
|
||||
file_header->time_stamp = obj_writer->time_stamp;
|
||||
file_header->symbol_table_foff = 0;
|
||||
|
||||
@@ -70,7 +70,7 @@ typedef struct COFF_ObjWriter
|
||||
{
|
||||
Arena *arena;
|
||||
COFF_TimeStamp time_stamp;
|
||||
COFF_MachineType machine_type;
|
||||
COFF_MachineType machine;
|
||||
|
||||
U64 symbol_count;
|
||||
COFF_ObjSymbolNode *symbol_first;
|
||||
@@ -83,7 +83,7 @@ typedef struct COFF_ObjWriter
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal COFF_ObjWriter* coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine_type);
|
||||
internal COFF_ObjWriter* coff_obj_writer_alloc(COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal void coff_obj_writer_release(COFF_ObjWriter **obj_writer);
|
||||
internal COFF_ObjSection* coff_obj_writer_push_section(COFF_ObjWriter *obj_writer, String8 name, COFF_SectionFlags flags, String8 data);
|
||||
internal COFF_ObjSymbol* coff_obj_writer_push_symbol(COFF_ObjWriter *obj_writer, String8 name, U32 value, COFF_SymbolLocation loc, COFF_SymbolType type, COFF_SymStorageClass storage_class);
|
||||
|
||||
+16
-8
@@ -286,19 +286,21 @@ hash_table_search_string_raw(HashTable *ht, String8 key, void **value_out)
|
||||
////////////////////////////////
|
||||
|
||||
internal int
|
||||
key_value_pair_is_before_u32(void *raw_a, void *raw_b)
|
||||
key_value_pair_is_before_u32(void *a, void *b)
|
||||
{
|
||||
KeyValuePair *a = raw_a;
|
||||
KeyValuePair *b = raw_b;
|
||||
return a->key_u32 < b->key_u32;
|
||||
return ((KeyValuePair *)a)->key_u32 < ((KeyValuePair *)b)->key_u32;
|
||||
}
|
||||
|
||||
internal int
|
||||
key_value_pair_is_before_u64(void *raw_a, void *raw_b)
|
||||
key_value_pair_is_before_u64(void *a, void *b)
|
||||
{
|
||||
KeyValuePair *a = raw_a;
|
||||
KeyValuePair *b = raw_b;
|
||||
return a->key_u64 < b->key_u64;
|
||||
return ((KeyValuePair *)a)->key_u64 < ((KeyValuePair *)b)->key_u64;
|
||||
}
|
||||
|
||||
internal int
|
||||
key_value_pair_is_before_string_sensitive(void *a, void *b)
|
||||
{
|
||||
return str8_compar_case_sensitive(((KeyValuePair*)a)->key_string, ((KeyValuePair*)b)->key_string) < 0;
|
||||
}
|
||||
|
||||
internal U32 *
|
||||
@@ -366,6 +368,12 @@ sort_key_value_pairs_as_u64(KeyValuePair *pairs, U64 count)
|
||||
radsort(pairs, count, key_value_pair_is_before_u64);
|
||||
}
|
||||
|
||||
internal void
|
||||
sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count)
|
||||
{
|
||||
radsort(pairs, count, key_value_pair_is_before_string_sensitive);
|
||||
}
|
||||
|
||||
internal U64Array
|
||||
remove_duplicates_u64_array(Arena *arena, U64Array arr)
|
||||
{
|
||||
|
||||
@@ -85,6 +85,7 @@ internal void * values_from_hash_table_raw(Arena *arena, HashTable *ht);
|
||||
|
||||
internal void sort_key_value_pairs_as_u32(KeyValuePair *pairs, U64 count);
|
||||
internal void sort_key_value_pairs_as_u64(KeyValuePair *pairs, U64 count);
|
||||
internal void sort_key_value_pairs_as_string_sensitive(KeyValuePair *pairs, U64 count);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
|
||||
+163
-166
@@ -698,10 +698,7 @@ lnk_make_res_obj(Arena *arena,
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_obj_from_res_file_list(TP_Context *tp,
|
||||
Arena *arena,
|
||||
LNK_SectionTable *sectab,
|
||||
LNK_SymbolTable *symtab,
|
||||
lnk_obj_from_res_file_list(Arena *arena,
|
||||
String8List res_data_list,
|
||||
String8List res_path_list,
|
||||
COFF_MachineType machine,
|
||||
@@ -790,7 +787,7 @@ lnk_make_linker_coff_obj(Arena *arena,
|
||||
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
||||
str8_list_push(scratch.arena, &env_list, str8_lit(""));
|
||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_ENVBLOCK, cv_make_envblock(scratch.arena, env_list));
|
||||
|
||||
|
||||
// TODO: emit S_SECTION and S_COFFGROUP
|
||||
// TODO: emit S_TRAMPOLINE
|
||||
|
||||
@@ -992,83 +989,67 @@ lnk_build_guard_data(Arena *arena, U64Array voff_arr, U64 stride)
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_push_pe_debug_data_directory(LNK_Section *sect,
|
||||
LNK_Chunk *dir_array_chunk,
|
||||
LNK_Symbol *data_symbol,
|
||||
lnk_push_pe_debug_data_directory(COFF_ObjWriter *obj_writer,
|
||||
COFF_ObjSymbol *data_symbol,
|
||||
PE_DebugDirectoryType type,
|
||||
COFF_TimeStamp time_stamp)
|
||||
{
|
||||
// init directory
|
||||
PE_DebugDirectory *dir = push_array(sect->arena, PE_DebugDirectory, 1);
|
||||
PE_DebugDirectory *dir = push_array(obj_writer->arena, PE_DebugDirectory, 1);
|
||||
dir->time_stamp = time_stamp;
|
||||
dir->type = type;
|
||||
//dir->voff = 0; // relocated through 'data_symbol'
|
||||
//dir->foff = 0; // relocated through 'data_symbol'
|
||||
//dir->size = 0; // relocated through 'data_symbol'
|
||||
|
||||
// push chunk
|
||||
LNK_Chunk *dir_entry_chunk = lnk_section_push_chunk_data(sect, dir_array_chunk, str8_struct(dir), str8_zero());
|
||||
lnk_chunk_set_debugf(sect->arena, dir_entry_chunk, "DebugDirectory[%u]", type);
|
||||
|
||||
// push debug directory relocs
|
||||
lnk_section_push_reloc(sect, dir_entry_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_DebugDirectory, voff), data_symbol);
|
||||
lnk_section_push_reloc(sect, dir_entry_chunk, LNK_Reloc_FILE_OFF_32, OffsetOf(PE_DebugDirectory, foff), data_symbol);
|
||||
lnk_section_push_reloc(sect, dir_entry_chunk, LNK_Reloc_CHUNK_SIZE_VIRT_32, OffsetOf(PE_DebugDirectory, size), data_symbol);
|
||||
COFF_ObjSection *debug_dir_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINKER_DEBUG_DIR$d"), LNK_DATA_SECTION_FLAGS, str8_struct(dir));
|
||||
coff_obj_writer_section_push_reloc(obj_writer, debug_dir_sect, OffsetOf(PE_DebugDirectory, voff), data_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, debug_dir_sect, OffsetOf(PE_DebugDirectory, foff), data_symbol, LNK_COFF_RELOC_FILE_OFFSET32);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, debug_dir_sect, OffsetOf(PE_DebugDirectory, size), data_symbol, LNK_COFF_RELOC_SECT_SIZE32);
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_build_debug_pdb(LNK_SectionTable *sectab,
|
||||
LNK_SymbolTable *symtab,
|
||||
LNK_Section *sect,
|
||||
LNK_Chunk *dir_array_chunk,
|
||||
COFF_TimeStamp time_stamp,
|
||||
Guid guid,
|
||||
U32 age,
|
||||
String8 pdb_path)
|
||||
internal LNK_InputObjList
|
||||
lnk_build_debug_directory_objs(Arena *arena, LNK_Config *config)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
// push chunks
|
||||
String8 debug_pdb_data = pe_make_debug_header_pdb70(sect->arena, guid, age, pdb_path);
|
||||
LNK_Chunk *debug_pdb_chunk = lnk_section_push_chunk_data(sect, sect->root, debug_pdb_data, str8(0, 0));
|
||||
lnk_chunk_set_debugf(sect->arena, debug_pdb_chunk, LNK_CV_HEADER_PDB70_SYMBOL_NAME);
|
||||
|
||||
// push symbols
|
||||
LNK_Symbol *debug_pdb_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_PDB70_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, 0, 0, 0);
|
||||
LNK_Symbol *guid_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_pdb_chunk, OffsetOf(PE_CvHeaderPDB70, guid), 0, 0);
|
||||
|
||||
// push debug directory
|
||||
lnk_push_pe_debug_data_directory(sect, dir_array_chunk, debug_pdb_symbol, PE_DebugDirectoryType_CODEVIEW, time_stamp);
|
||||
|
||||
ProfEnd();
|
||||
}
|
||||
LNK_InputObjList result = {0};
|
||||
|
||||
internal void
|
||||
lnk_build_debug_rdi(LNK_SectionTable *sectab,
|
||||
LNK_SymbolTable *symtab,
|
||||
LNK_Section *debug_sect,
|
||||
LNK_Chunk *debug_dir_array_chunk,
|
||||
COFF_TimeStamp time_stamp,
|
||||
Guid guid,
|
||||
String8 rdi_path)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
|
||||
LNK_Section *rdi_sect = lnk_section_table_push(sectab, str8_lit(".raddbg"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead);
|
||||
|
||||
// push chunks
|
||||
String8 debug_rdi = pe_make_debug_header_rdi(rdi_sect->arena, guid, rdi_path);
|
||||
LNK_Chunk *debug_rdi_chunk = lnk_section_push_chunk_data(rdi_sect, rdi_sect->root, debug_rdi, str8_zero());
|
||||
lnk_chunk_set_debugf(rdi_sect->arena, debug_rdi_chunk, LNK_CV_HEADER_RDI_SYMBOL_NAME);
|
||||
|
||||
// push symbols
|
||||
LNK_Symbol *debug_rdi_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_RDI_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, 0, 0, 0);
|
||||
LNK_Symbol *guid_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_CV_HEADER_GUID_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_rdi_chunk, OffsetOf(PE_CvHeaderRDI, guid), 0, 0);
|
||||
|
||||
// push debug directory
|
||||
lnk_push_pe_debug_data_directory(debug_sect, debug_dir_array_chunk, debug_rdi_symbol, PE_DebugDirectoryType_CODEVIEW, time_stamp);
|
||||
|
||||
ProfEnd();
|
||||
B32 build_pdb_header = config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null;
|
||||
B32 build_rdi_header = config->rad_debug == LNK_SwitchState_Yes;
|
||||
|
||||
if (build_pdb_header || build_rdi_header) {
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, config->machine);
|
||||
|
||||
COFF_ObjSection *sect_a = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINKER_DEBUG_DIR$a"), LNK_DATA_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *sect_z = coff_obj_writer_push_section(obj_writer, str8_lit(".RAD_LINKER_DEBUG_DIR$z"), LNK_DATA_SECTION_FLAGS, str8_zero());
|
||||
|
||||
// marker symbols for debug directory patcher
|
||||
coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINKER_DEBUG_SECTION_A"), 0, sect_a);
|
||||
coff_obj_writer_push_symbol_extern(obj_writer, str8_lit("RAD_LINKER_DEBUG_SECTION_Z"), 0, sect_z);
|
||||
|
||||
// debug entry for PDB
|
||||
if (build_pdb_header) {
|
||||
String8 debug_pdb_data = pe_make_debug_header_pdb70(obj_writer->arena, config->guid, config->age, config->pdb_alt_path);
|
||||
COFF_ObjSection *debug_pdb_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$z"), LNK_DATA_SECTION_FLAGS, debug_pdb_data);
|
||||
COFF_ObjSymbol *debug_pdb_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("PDB_DEBUG_HEADER_70"), 0, debug_pdb_sect);
|
||||
lnk_push_pe_debug_data_directory(obj_writer, debug_pdb_symbol, PE_DebugDirectoryType_CODEVIEW, config->time_stamp);
|
||||
}
|
||||
|
||||
// debug entry for RDI
|
||||
if (build_rdi_header) {
|
||||
String8 debug_rdi_data = pe_make_debug_header_rdi(obj_writer->arena, config->guid, config->rad_debug_alt_path);
|
||||
COFF_ObjSection *debug_rdi_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$z"), LNK_DATA_SECTION_FLAGS, debug_rdi_data);
|
||||
COFF_ObjSymbol *debug_rdi_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("RDI_DEBUG_HEADER"), 0, debug_rdi_sect);
|
||||
lnk_push_pe_debug_data_directory(obj_writer, debug_rdi_symbol, PE_DebugDirectoryType_CODEVIEW, config->time_stamp);
|
||||
}
|
||||
|
||||
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
|
||||
input->path = str8_lit("* Debug Directory *");
|
||||
input->dedup_id = input->path;
|
||||
input->data = coff_obj_writer_serialize(arena, obj_writer);
|
||||
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
@@ -2067,7 +2048,7 @@ THREAD_POOL_TASK_FUNC(lnk_undef_symbol_finder)
|
||||
|
||||
LNK_Symbol *has_defn = lnk_symbol_table_search(task->symtab, undef->scope_flags, symbol->name);
|
||||
if (has_defn) {
|
||||
Assert(LNK_Symbol_IsDefined(has_defn->type) || has_defn->type == LNK_Symbol_Weak);
|
||||
Assert(LNK_Symbol_IsDefined(has_defn->type) || has_defn->type == LNK_Symbol_Weak || has_defn->type == LNK_Symbol_Import);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2970,17 +2951,17 @@ lnk_run(int argc, char **argv)
|
||||
State_InputObjs,
|
||||
State_LookupUndef,
|
||||
State_LookupWeak,
|
||||
State_BuildImportObjs,
|
||||
State_BuildExportObjs,
|
||||
State_BuildDebugDirectoryObjs,
|
||||
State_BuildAndInputLinkerObj,
|
||||
State_BuildAndInputResObj,
|
||||
State_PushDllHelperUndefSymbol,
|
||||
State_PushLinkerSymbols,
|
||||
State_PushLoadConfigUndefSymbol,
|
||||
State_SearchEntryPoint,
|
||||
State_CheckUnusedDelayLoads,
|
||||
State_ReportUnresolvedSymbols,
|
||||
State_DiscardMetaDataSections,
|
||||
State_BuildDebugDirectory,
|
||||
State_BuildExportTable,
|
||||
State_MergeSections,
|
||||
State_BuildCFGuards,
|
||||
State_BuildBaseRelocs,
|
||||
@@ -3040,12 +3021,20 @@ lnk_run(int argc, char **argv)
|
||||
// input command line libs
|
||||
input_libs[LNK_InputSource_CmdLine] = config->input_list[LNK_Input_Lib];
|
||||
input_libs[LNK_InputSource_Default] = config->input_default_lib_list;
|
||||
|
||||
LNK_ImportTableFlags imptab_flags = 0;
|
||||
if (config->flags & LNK_ConfigFlag_DelayUnload) {
|
||||
imptab_flags |= LNK_ImportTableFlag_EmitUiat;
|
||||
}
|
||||
if (config->flags & LNK_ConfigFlag_DelayBind) {
|
||||
imptab_flags |= LNK_ImportTableFlag_EmitUiat;
|
||||
}
|
||||
|
||||
// state
|
||||
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
|
||||
LNK_SectionTable *sectab = lnk_init_section_table(symtab, config->section_virt_off, config->sect_align, config->file_align);
|
||||
LNK_ImportTable *imptab_static = 0;
|
||||
LNK_ImportTable *imptab_delayed = 0;
|
||||
LNK_ImportTable *imptab_static = lnk_import_table_alloc(0);
|
||||
LNK_ImportTable *imptab_delayed = lnk_import_table_alloc(imptab_flags);
|
||||
LNK_ExportTable *exptab = lnk_export_table_alloc();
|
||||
Arena *ht_arena = arena_alloc();
|
||||
HashTable *disallow_lib_ht = hash_table_init(scratch.arena, 0x100);
|
||||
@@ -3060,15 +3049,15 @@ lnk_run(int argc, char **argv)
|
||||
U64 entry_search_attempts = 0;
|
||||
B32 build_debug_info = lnk_do_debug_info(config);
|
||||
B32 build_linker_obj = build_debug_info;
|
||||
B32 build_debug_directory = build_debug_info;
|
||||
B32 build_debug_directory_objs = build_debug_info;
|
||||
B32 build_import_objs = 1;
|
||||
B32 build_export_objs = 1;
|
||||
B32 build_res_obj = 1;
|
||||
B32 discard_meta_data_sections = 1;
|
||||
B32 merge_sections = !!(config->flags & LNK_ConfigFlag_Merge);
|
||||
B32 build_cf_guards = 0; // (config->flags != LNK_Guard_NONE);
|
||||
B32 build_export_table = 1;
|
||||
B32 build_base_relocs = !(config->flags & LNK_ConfigFlag_Fixed);
|
||||
B32 report_unresolved_symbols = 1;
|
||||
B32 check_unused_delay_loads = !!(config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll);
|
||||
B32 build_imp_lib = config->build_imp_lib;
|
||||
B32 build_rad_chunk_map = (config->rad_chunk_map == LNK_SwitchState_Yes);
|
||||
LNK_ObjList obj_list = {0};
|
||||
@@ -3285,37 +3274,49 @@ lnk_run(int argc, char **argv)
|
||||
ProfBegin("Input Imports");
|
||||
for (LNK_InputImport *input = input_import_list.first; input != 0; input = input->next) {
|
||||
COFF_ParsedArchiveImportHeader *import_header = &input->import_header;
|
||||
KeyValuePair *is_delayed = hash_table_search_path(delay_load_dll_ht, import_header->dll_name);
|
||||
|
||||
if (import_header->machine != config->machine) {
|
||||
lnk_error(LNK_Error_IncompatibleMachine, "symbol pulls in an import with incompatible machine %S (expected %S)",
|
||||
coff_string_from_machine_type(input->import_header.machine),
|
||||
coff_string_from_machine_type(config->machine));
|
||||
}
|
||||
|
||||
KeyValuePair *is_delayed = hash_table_search_path(delay_load_dll_ht, import_header->dll_name);
|
||||
|
||||
LNK_ImportDLL *dll;
|
||||
LNK_ImportFunc *func;
|
||||
if (is_delayed) {
|
||||
if (!imptab_delayed) {
|
||||
Assert(config->machine != COFF_MachineType_Unknown);
|
||||
B32 is_unloadable = !!(config->flags & LNK_ConfigFlag_DelayUnload);
|
||||
B32 is_bindable = !!(config->flags & LNK_ConfigFlag_DelayBind);
|
||||
imptab_delayed = lnk_import_table_alloc_delayed(sectab, symtab, config->machine, is_unloadable, is_bindable);
|
||||
}
|
||||
LNK_ImportDLL *dll = lnk_import_table_search_dll(imptab_delayed, import_header->dll_name);
|
||||
dll = lnk_import_table_search_dll(imptab_delayed, import_header->dll_name);
|
||||
if (!dll) {
|
||||
dll = lnk_import_table_push_dll_delayed(imptab_delayed, symtab, import_header->dll_name, import_header->machine);
|
||||
dll = lnk_import_table_push_dll_delayed(imptab_delayed, import_header->dll_name, import_header->machine);
|
||||
}
|
||||
LNK_ImportFunc *func = lnk_import_table_search_func(dll, import_header->func_name);
|
||||
func = lnk_import_table_search_func(dll, import_header->func_name);
|
||||
if (!func) {
|
||||
func = lnk_import_table_push_func_delayed(imptab_delayed, symtab, dll, import_header);
|
||||
func = lnk_import_table_push_func_delayed(imptab_delayed, dll, import_header);
|
||||
}
|
||||
} else {
|
||||
if (!imptab_static) {
|
||||
Assert(config->machine != COFF_MachineType_Unknown);
|
||||
imptab_static = lnk_import_table_alloc_static(sectab, symtab, config->machine);
|
||||
}
|
||||
LNK_ImportDLL *dll = lnk_import_table_search_dll(imptab_static, import_header->dll_name);
|
||||
dll = lnk_import_table_search_dll(imptab_static, import_header->dll_name);
|
||||
if (!dll) {
|
||||
dll = lnk_import_table_push_dll_static(imptab_static, symtab, import_header->dll_name, import_header->machine);
|
||||
dll = lnk_import_table_push_dll_static(imptab_static, import_header->dll_name, import_header->machine);
|
||||
}
|
||||
LNK_ImportFunc *func = lnk_import_table_search_func(dll, import_header->func_name);
|
||||
func = lnk_import_table_search_func(dll, import_header->func_name);
|
||||
if (!func) {
|
||||
func = lnk_import_table_push_func_static(imptab_static, symtab, dll, import_header);
|
||||
func = lnk_import_table_push_func_static(imptab_static, dll, import_header);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LNK_Symbol *thunk_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
|
||||
thunk_symbol->name = func->thunk_symbol_name;
|
||||
thunk_symbol->type = LNK_Symbol_Import;
|
||||
|
||||
LNK_Symbol *iat_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
|
||||
iat_symbol->name = func->iat_symbol_name;
|
||||
iat_symbol->type = LNK_Symbol_Import;
|
||||
|
||||
lnk_symbol_table_push(symtab, thunk_symbol);
|
||||
lnk_symbol_table_push(symtab, iat_symbol);
|
||||
}
|
||||
}
|
||||
|
||||
// reset input
|
||||
@@ -3629,6 +3630,50 @@ lnk_run(int argc, char **argv)
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildImportObjs: {
|
||||
ProfBegin("Build Import Table");
|
||||
|
||||
if (config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll) {
|
||||
if (imptab_delayed) {
|
||||
for (String8Node *node = config->delay_load_dll_list.first; node != 0; node = node->next) {
|
||||
LNK_ImportDLL *dll = lnk_import_table_search_dll(imptab_delayed, node->string);
|
||||
if (dll == 0) {
|
||||
lnk_error(LNK_Warning_UnusedDelayLoadDll, "/DELAYLOAD: %S found no imports", node->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LNK_InputObjList static_imports = lnk_import_table_serialize(scratch.arena, imptab_static, str8_skip_last_slash(config->image_name), config->machine);
|
||||
LNK_InputObjList delayed_imports = lnk_import_table_serialize(scratch.arena, imptab_delayed, str8_skip_last_slash(config->image_name), config->machine);
|
||||
|
||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &static_imports);
|
||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &delayed_imports);
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildExportObjs: {
|
||||
ProfBegin("Build Export Table");
|
||||
|
||||
ProfBeginV("Push Exports [Count %u]", export_symbol_list.count);
|
||||
for (LNK_ExportParse *exp_parse = export_symbol_list.first; exp_parse != 0; exp_parse = exp_parse->next) {
|
||||
lnk_export_table_push_export(exptab, symtab, exp_parse);
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
LNK_InputObjList export_objs = lnk_export_table_serialize(scratch.arena, exptab, str8_skip_last_slash(config->image_name), config->machine);
|
||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &export_objs);
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildDebugDirectoryObjs: {
|
||||
ProfBegin("Build Debug Directory");
|
||||
|
||||
LNK_InputObjList debug_objs = lnk_build_debug_directory_objs(scratch.arena, config);
|
||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &debug_objs);
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildAndInputResObj: {
|
||||
String8List res_data_list = {0};
|
||||
String8List res_path_list = {0};
|
||||
@@ -3688,10 +3733,7 @@ lnk_run(int argc, char **argv)
|
||||
ProfBegin("Build * Resources *");
|
||||
|
||||
String8 obj_name = str8_lit("* Resources *");
|
||||
String8 obj_data = lnk_obj_from_res_file_list(tp,
|
||||
tp_arena->v[0],
|
||||
sectab,
|
||||
symtab,
|
||||
String8 obj_data = lnk_obj_from_res_file_list(scratch.arena,
|
||||
res_data_list,
|
||||
res_path_list,
|
||||
config->machine,
|
||||
@@ -3757,16 +3799,6 @@ lnk_run(int argc, char **argv)
|
||||
MemoryZeroStruct(&lookup_weak_list);
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_CheckUnusedDelayLoads: {
|
||||
if (imptab_delayed) {
|
||||
for (String8Node *node = config->delay_load_dll_list.first; node != 0; node = node->next) {
|
||||
LNK_ImportDLL *dll = lnk_import_table_search_dll(imptab_delayed, node->string);
|
||||
if (dll == 0) {
|
||||
lnk_error(LNK_Warning_UnusedDelayLoadDll, "/DELAYLOAD: %S found no imports", node->string);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case State_ReportUnresolvedSymbols: {
|
||||
// report unresolved symbols
|
||||
for (LNK_SymbolNode *node = unresolved_undef_list.first; node != 0; node = node->next) {
|
||||
@@ -3782,43 +3814,6 @@ lnk_run(int argc, char **argv)
|
||||
lnk_discard_meta_data_sections(sectab);
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildDebugDirectory: {
|
||||
ProfBegin("Build Debug Directory");
|
||||
|
||||
// push debug directory layout chunks
|
||||
LNK_Section *debug_sect = lnk_section_table_search(sectab, str8_lit(".rdata"));
|
||||
LNK_Chunk *debug_chunk = lnk_section_push_chunk_list(debug_sect, debug_sect->root, str8_zero());
|
||||
LNK_Chunk *debug_dir_array_chunk = lnk_section_push_chunk_list(debug_sect, debug_chunk, str8_zero());
|
||||
|
||||
// push symbols for PE directory patch
|
||||
lnk_symbol_table_push_defined_chunk(symtab, str8_lit(LNK_DEBUG_DIR_SYMBOL_NAME), LNK_DefinedSymbolVisibility_Internal, 0, debug_dir_array_chunk, 0, 0, 0);
|
||||
|
||||
// debug entry for PDB
|
||||
if (config->debug_mode != LNK_DebugMode_None && config->debug_mode != LNK_DebugMode_Null) {
|
||||
lnk_build_debug_pdb(sectab, symtab, debug_sect, debug_dir_array_chunk, config->time_stamp, config->guid, config->age, config->pdb_alt_path);
|
||||
}
|
||||
|
||||
// debug entry for RDI
|
||||
if (config->rad_debug == LNK_SwitchState_Yes) {
|
||||
lnk_build_debug_rdi(sectab, symtab, debug_sect, debug_dir_array_chunk, config->time_stamp, config->guid, config->rad_debug_alt_path);
|
||||
}
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_BuildExportTable: {
|
||||
ProfBegin("Build Export Table");
|
||||
|
||||
ProfBeginV("Push Exports [Count %u]", export_symbol_list.count);
|
||||
for (LNK_ExportParse *exp_parse = export_symbol_list.first; exp_parse != 0; exp_parse = exp_parse->next) {
|
||||
lnk_export_table_push_export(exptab, symtab, exp_parse);
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
// build export table section
|
||||
lnk_build_edata(exptab, sectab, symtab, config->image_name, config->machine);
|
||||
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_MergeSections: {
|
||||
ProfBegin("Merge Sections");
|
||||
lnk_section_table_merge(sectab, merge_list);
|
||||
@@ -4151,6 +4146,22 @@ lnk_run(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (build_import_objs) {
|
||||
build_import_objs = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildImportObjs);
|
||||
continue;
|
||||
}
|
||||
if (build_export_objs) {
|
||||
build_export_objs = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildExportObjs);
|
||||
continue;
|
||||
}
|
||||
if (build_debug_directory_objs) {
|
||||
build_debug_directory_objs = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildDebugDirectoryObjs);
|
||||
continue;
|
||||
}
|
||||
if (build_res_obj) {
|
||||
build_res_obj = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildAndInputResObj);
|
||||
@@ -4161,29 +4172,13 @@ lnk_run(int argc, char **argv)
|
||||
state_list_push(scratch.arena, state_list, State_BuildAndInputLinkerObj);
|
||||
continue;
|
||||
}
|
||||
if (check_unused_delay_loads) {
|
||||
check_unused_delay_loads = 0;
|
||||
state_list_push(scratch.arena, state_list, State_CheckUnusedDelayLoads);
|
||||
continue;
|
||||
}
|
||||
|
||||
/// --- inputs are ready ---
|
||||
|
||||
|
||||
|
||||
if (discard_meta_data_sections) {
|
||||
discard_meta_data_sections = 0;
|
||||
state_list_push(scratch.arena, state_list, State_DiscardMetaDataSections);
|
||||
continue;
|
||||
}
|
||||
if (build_debug_directory) {
|
||||
build_debug_directory = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildDebugDirectory);
|
||||
continue;
|
||||
}
|
||||
if (build_export_table) {
|
||||
build_export_table = 0;
|
||||
state_list_push(scratch.arena, state_list, State_BuildExportTable);
|
||||
continue;
|
||||
}
|
||||
if (merge_sections) {
|
||||
merge_sections = 0;
|
||||
state_list_push(scratch.arena, state_list, State_MergeSections);
|
||||
@@ -4199,6 +4194,8 @@ lnk_run(int argc, char **argv)
|
||||
state_list_push(scratch.arena, state_list, State_BuildBaseRelocs);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (image_data.size == 0) {
|
||||
state_list_push(scratch.arena, state_list, State_FinalizeImage);
|
||||
continue;
|
||||
|
||||
+6
-1
@@ -103,6 +103,11 @@
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
#define LNK_COFF_RELOC_FILE_OFFSET32 0x1000
|
||||
#define LNK_COFF_RELOC_SECT_SIZE32 0x1001
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LNK_InputSource_CmdLine, // specified on command line
|
||||
@@ -267,7 +272,7 @@ internal void lnk_merge_manifest_files(String8 mt_path, String8 out_name, Str
|
||||
internal void lnk_serialize_pe_resource_tree(COFF_ObjWriter *obj_writer, PE_ResourceDir *root_dir);
|
||||
internal void lnk_add_resource_debug_s(COFF_ObjWriter *obj_writer, String8 obj_path, String8 cwd_path, String8 exe_path, CV_Arch arch, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal String8 lnk_make_res_obj(Arena *arena, PE_ResourceDir *root_dir, COFF_TimeStamp time_stamp, COFF_MachineType machine, String8 path, String8 cwd_path, String8 exe_path, String8List res_file_list, MD5Hash *res_hash_array);
|
||||
internal String8 lnk_obj_from_res_file_list(TP_Context *tp, Arena *arena, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name);
|
||||
internal String8 lnk_obj_from_res_file_list(Arena *arena, String8List res_file_list, String8List res_path_list, COFF_MachineType machine, U32 time_stamp, String8 work_dir, PathStyle system_path_style, String8 obj_name);
|
||||
|
||||
////////////////////////////////
|
||||
// Debug
|
||||
|
||||
@@ -16,7 +16,7 @@ typedef enum
|
||||
LNK_Error_IllData,
|
||||
LNK_Error_IllExport,
|
||||
LNK_Error_IncomatibleCmdOptions,
|
||||
LNK_Error_IncompatibleObj,
|
||||
LNK_Error_IncompatibleMachine,
|
||||
LNK_Error_InvalidPrecompLeafCount,
|
||||
LNK_Error_InvalidStartIndex,
|
||||
LNK_Error_NoAccess,
|
||||
|
||||
+103
-88
@@ -170,17 +170,11 @@ lnk_export_array_from_list(Arena *arena, LNK_ExportList list)
|
||||
return arr;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8 image_name, COFF_MachineType machine)
|
||||
internal LNK_InputObjList
|
||||
lnk_export_table_serialize(Arena *arena, LNK_ExportTable *exptab, String8 image_name, COFF_MachineType machine)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
// is export table empty?
|
||||
if (exptab->name_export_ht->count == 0 && exptab->noname_export_ht->count == 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
// compute ordinal bounds
|
||||
U64 ordinal_low;
|
||||
for (ordinal_low = 0; ordinal_low < exptab->max_ordinal; ++ordinal_low) {
|
||||
@@ -195,96 +189,117 @@ lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *sectab, LNK_SymbolTab
|
||||
}
|
||||
}
|
||||
|
||||
LNK_Section *edata = lnk_section_table_search(sectab, str8_lit(".edata"));
|
||||
|
||||
// push header
|
||||
PE_ExportTableHeader *header = push_array(edata->arena, PE_ExportTableHeader, 1);
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine);
|
||||
|
||||
// fill out export table header
|
||||
PE_ExportTableHeader *header = push_array(obj_writer->arena, PE_ExportTableHeader, 1);
|
||||
header->ordinal_base = safe_cast_u16(ordinal_low + 1);
|
||||
header->export_address_table_count = safe_cast_u32(exptab->name_export_ht->count + exptab->noname_export_ht->count);
|
||||
header->name_pointer_table_count = safe_cast_u32(exptab->name_export_ht->count);
|
||||
|
||||
String8 header_data = str8((U8*)header, sizeof(*header));
|
||||
String8 image_name_cstr = push_cstr(edata->arena, str8_skip_last_slash(image_name));
|
||||
|
||||
// push edata chunks
|
||||
LNK_Chunk *header_chunk = lnk_section_push_chunk_data(edata, edata->root, header_data, str8_lit("a"));
|
||||
LNK_Chunk *voff_table_chunk = lnk_section_push_chunk_list(edata, edata->root, str8_lit("b"));
|
||||
LNK_Chunk *name_voff_table_chunk = lnk_section_push_chunk_list(edata, edata->root, str8_lit("c"));
|
||||
LNK_Chunk *ordinal_table_chunk = lnk_section_push_chunk_list(edata, edata->root, str8_lit("d"));
|
||||
LNK_Chunk *string_buffer_chunk = lnk_section_push_chunk_list(edata, edata->root, str8_lit("e"));
|
||||
LNK_Chunk *image_name_chunk = lnk_section_push_chunk_data(edata, string_buffer_chunk, image_name_cstr, str8(0,0));
|
||||
lnk_chunk_set_debugf(edata->arena, header_chunk, "EXPORT_HEADER");
|
||||
lnk_chunk_set_debugf(edata->arena, voff_table_chunk, "EXPORT_ADDRESS_TABLE");
|
||||
lnk_chunk_set_debugf(edata->arena, name_voff_table_chunk, "EXPORT_NAME_VOFF_TABLE");
|
||||
lnk_chunk_set_debugf(edata->arena, ordinal_table_chunk, "EXPORT_ORDINAL_TABLE");
|
||||
lnk_chunk_set_debugf(edata->arena, string_buffer_chunk, "EXPORT_STRING_BUFFER");
|
||||
lnk_chunk_set_debugf(edata->arena, image_name_chunk, "EXPORT_IMAGE_NAME");
|
||||
|
||||
LNK_Symbol *image_name_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.name_voff"), LNK_DefinedSymbolVisibility_Internal, 0, image_name_chunk, 0, 0, 0);
|
||||
LNK_Symbol *address_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.export_address_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, voff_table_chunk, 0, 0, 0);
|
||||
LNK_Symbol *name_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.name_pointer_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, name_voff_table_chunk, 0, 0, 0);
|
||||
LNK_Symbol *ordinal_table_symbol = lnk_symbol_table_push_defined_chunk(symtab, str8_lit("export_table.ordinal_table_voff"), LNK_DefinedSymbolVisibility_Internal, 0, ordinal_table_chunk, 0, 0, 0);
|
||||
|
||||
// patch header fields
|
||||
lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTableHeader, name_voff), image_name_symbol);
|
||||
lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTableHeader, export_address_table_voff), address_table_symbol);
|
||||
lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTableHeader, name_pointer_table_voff), name_table_symbol);
|
||||
lnk_section_push_reloc(edata, header_chunk, LNK_Reloc_VIRT_OFF_32, OffsetOf(PE_ExportTableHeader, ordinal_table_voff), ordinal_table_symbol);
|
||||
|
||||
// reserve virtual offset chunks
|
||||
LNK_Chunk **ordinal_voff_map = push_array(scratch.arena, LNK_Chunk *, exptab->max_ordinal);
|
||||
for (U32 i = ordinal_low; i <= ordinal_high; i += 1) {
|
||||
String8 sort_index = str8_from_bits_u32(edata->arena, i);
|
||||
LNK_Chunk *voff_chunk = lnk_section_push_chunk_bss(edata, voff_table_chunk, exptab->voff_size, sort_index);
|
||||
ordinal_voff_map[i] = voff_chunk;
|
||||
|
||||
|
||||
// make iamge name c-string
|
||||
String8 image_name_cstr = push_cstr(obj_writer->arena, image_name);
|
||||
|
||||
// push sections
|
||||
COFF_ObjSection *header_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$1"), LNK_EDATA_SECTION_FLAGS, str8_struct(header));
|
||||
COFF_ObjSection *voff_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$2"), LNK_EDATA_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *name_voff_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$3"), LNK_EDATA_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *ordinal_table_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$4"), LNK_EDATA_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *string_buffer_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$5"), LNK_EDATA_SECTION_FLAGS, str8_zero());
|
||||
COFF_ObjSection *image_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".edata$6"), LNK_EDATA_SECTION_FLAGS, image_name_cstr);
|
||||
|
||||
// push symbols
|
||||
COFF_ObjSymbol *image_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_TABLE_NAME_VOFF"), 0, image_name_sect);
|
||||
COFF_ObjSymbol *address_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_TABLE_ADDRESS_TABLE_VOFF"), 0, voff_table_sect);
|
||||
COFF_ObjSymbol *name_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_TABLE_NAME_POINTER_VOFF"), 0, name_voff_table_sect);
|
||||
COFF_ObjSymbol *ordinal_table_symbol = coff_obj_writer_push_symbol_static(obj_writer, str8_lit("EXPORT_TABLE_ORDINAL_TABLE_VOFF"), 0, ordinal_table_sect);
|
||||
|
||||
// patch export table header
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: {
|
||||
coff_obj_writer_section_push_reloc(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, name_voff), image_name_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, export_address_table_voff), address_table_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, name_pointer_table_voff), name_table_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, header_sect, OffsetOf(PE_ExportTableHeader, ordinal_table_voff), ordinal_table_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
} break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
B8 *is_ordinal_bound = push_array(scratch.arena, B8, exptab->max_ordinal);
|
||||
HashTable *exp_ht_arr[] = { exptab->name_export_ht, exptab->noname_export_ht };
|
||||
for (HashTable **ht_ptr = &exp_ht_arr[0], **ht_opl = ht_ptr + ArrayCount(exp_ht_arr);
|
||||
ht_ptr < ht_opl;
|
||||
ht_ptr += 1) {
|
||||
KeyValuePair *kv_arr = key_value_pairs_from_hash_table(scratch.arena, *ht_ptr);
|
||||
|
||||
for (U64 i = 0; i < (*ht_ptr)->count; ++i) {
|
||||
LNK_Export *exp = kv_arr[i].value_raw;
|
||||
String8 name_cstr = push_cstr(edata->arena, exp->name);
|
||||
|
||||
// push name string
|
||||
LNK_Chunk *name_chunk = lnk_section_push_chunk_data(edata, string_buffer_chunk, name_cstr, str8(0,0));
|
||||
lnk_chunk_set_debugf(edata->arena, name_chunk, "export: %S", name_cstr);
|
||||
|
||||
// push name symbol
|
||||
String8 name_export_name = push_str8f(symtab->arena->v[0], "export.%S", name_cstr);
|
||||
LNK_Symbol *name_symbol = lnk_symbol_table_push_defined_chunk(symtab, name_export_name, LNK_DefinedSymbolVisibility_Internal, 0, name_chunk, 0, 0, 0);
|
||||
|
||||
// name voff
|
||||
LNK_Chunk *voff_chunk = lnk_section_push_chunk_bss(edata, name_voff_table_chunk, exptab->voff_size, /* export table must be sorted lexically: */ name_cstr);
|
||||
lnk_chunk_set_debugf(edata->arena, voff_chunk, "voff for export name %S", name_cstr);
|
||||
|
||||
// link reloc with name symbol
|
||||
lnk_section_push_reloc(edata, voff_chunk, LNK_Reloc_VIRT_OFF_32, 0, name_symbol);
|
||||
for (U64 ht_idx = 0; ht_idx < ArrayCount(exp_ht_arr); ht_idx += 1) {
|
||||
HashTable *ht = exp_ht_arr[ht_idx];
|
||||
|
||||
// make ordinal relative
|
||||
U16 *ordinal_ptr = push_array(edata->arena, U16, 1);
|
||||
*ordinal_ptr = (exp->ordinal - ordinal_low);
|
||||
|
||||
// ordinal
|
||||
LNK_Chunk *ordinal_chunk = lnk_section_push_chunk_raw(edata, ordinal_table_chunk, ordinal_ptr, sizeof(*ordinal_ptr), /* ordinal table is parallel to the name table: */ name_cstr);
|
||||
lnk_chunk_set_debugf(edata->arena, ordinal_chunk, "ordinal %u for %S", exp->ordinal, exp->name);
|
||||
|
||||
// (ordinal - ordinal_low) -> export virtual offset
|
||||
if ( ! is_ordinal_bound[exp->ordinal]) {
|
||||
is_ordinal_bound[exp->ordinal] = 1;
|
||||
LNK_Chunk *export_func_voff_chunk = ordinal_voff_map[exp->ordinal];
|
||||
lnk_section_push_reloc(edata, export_func_voff_chunk, LNK_Reloc_VIRT_OFF_32, 0, exp->symbol);
|
||||
KeyValuePair *kv_arr = key_value_pairs_from_hash_table(scratch.arena, exptab->name_export_ht);
|
||||
|
||||
// named exports must be lexically sorted
|
||||
if (ht_idx == 0) {
|
||||
sort_key_value_pairs_as_string_sensitive(kv_arr, exptab->name_export_ht->count);
|
||||
}
|
||||
|
||||
for (U64 i = 0; i < ht->count; i += 1) {
|
||||
LNK_Export *exp = kv_arr[i].value_raw;
|
||||
|
||||
{
|
||||
U64 export_name_offset = string_buffer_sect->data.total_size;
|
||||
String8 export_name_cstr = push_cstr(obj_writer->arena, exp->name);
|
||||
str8_list_push(obj_writer->arena, &string_buffer_sect->data, export_name_cstr);
|
||||
|
||||
String8 export_name_symbol_name = push_str8f(obj_writer->arena, "EXPORT.%S", exp->name);
|
||||
COFF_ObjSymbol *export_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, export_name_symbol_name, export_name_offset, string_buffer_sect);
|
||||
|
||||
U64 export_name_voff_offset = name_voff_table_sect->data.total_size;
|
||||
U64 export_name_voff_size = sizeof(U32);
|
||||
U8 *export_name_voff = push_array(obj_writer->arena, U8, export_name_voff_size);
|
||||
str8_list_push(obj_writer->arena, &name_voff_table_sect->data, str8_array(export_name_voff, export_name_voff_size));
|
||||
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: { coff_obj_writer_section_push_reloc(obj_writer, name_voff_table_sect, export_name_voff_offset, export_name_symbol, COFF_Reloc_X64_Addr32Nb); } break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
U16 *ordinal = push_array(obj_writer->arena, U16, 1);
|
||||
*ordinal = exp->ordinal - ordinal_low;
|
||||
str8_list_push(obj_writer->arena, &ordinal_table_sect->data, str8_struct(ordinal));
|
||||
|
||||
if ( ! is_ordinal_bound[exp->ordinal]) {
|
||||
is_ordinal_bound[exp->ordinal] = 1;
|
||||
|
||||
U64 voff_offset = voff_table_sect->data.total_size;
|
||||
U32 *voff = push_array(obj_writer->arena, U32, 1);
|
||||
str8_list_push(obj_writer->arena, &voff_table_sect->data, str8_struct(voff));
|
||||
|
||||
COFF_ObjSymbol *symbol = coff_obj_writer_push_symbol_undef(obj_writer, exp->name);
|
||||
switch (machine) {
|
||||
case COFF_MachineType_Unknown: break;
|
||||
case COFF_MachineType_X64: { coff_obj_writer_section_push_reloc(obj_writer, voff_table_sect, voff_offset, symbol, COFF_Reloc_X64_Addr32Nb); } break;
|
||||
default: { NotImplemented; } break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
exit:;
|
||||
|
||||
|
||||
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
|
||||
LNK_InputObjList result = {0};
|
||||
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
|
||||
input->path = str8_lit("* Exports *");
|
||||
input->dedup_id = input->path;
|
||||
input->data = obj;
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -40,5 +40,5 @@ typedef struct LNK_ExportTable
|
||||
internal LNK_ExportTable * lnk_export_table_alloc(void);
|
||||
internal void lnk_export_table_release(LNK_ExportTable **exptab_ptr);
|
||||
internal LNK_Export * lnk_export_table_search(LNK_ExportTable *exptab, String8 name);
|
||||
internal void lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8 image_name, COFF_MachineType machine);
|
||||
internal LNK_InputObjList lnk_export_table_serialize(Arena *arena, LNK_ExportTable *exptab, String8 image_name, COFF_MachineType machine);
|
||||
|
||||
|
||||
+408
-451
File diff suppressed because it is too large
Load Diff
@@ -19,23 +19,24 @@ typedef struct LNK_ImportDLL
|
||||
struct LNK_ImportDLL *next;
|
||||
struct LNK_ImportFunc *first_func;
|
||||
struct LNK_ImportFunc *last_func;
|
||||
LNK_Chunk *dll_chunk;
|
||||
LNK_Chunk *int_table_chunk;
|
||||
LNK_Chunk *ilt_table_chunk;
|
||||
LNK_Chunk *iat_table_chunk;
|
||||
LNK_Chunk *biat_table_chunk;
|
||||
LNK_Chunk *uiat_table_chunk;
|
||||
LNK_Chunk *code_table_chunk;
|
||||
LNK_Symbol *tail_merge_symbol;
|
||||
COFF_ObjWriter *obj_writer;
|
||||
COFF_ObjSection *dll_sect;
|
||||
COFF_ObjSection *int_sect;
|
||||
COFF_ObjSection *ilt_sect;
|
||||
COFF_ObjSection *iat_sect;
|
||||
COFF_ObjSection *biat_sect;
|
||||
COFF_ObjSection *uiat_sect;
|
||||
COFF_ObjSection *code_sect;
|
||||
COFF_ObjSymbol *tail_merge_symbol;
|
||||
String8 name;
|
||||
COFF_MachineType machine;
|
||||
HashTable *func_ht;
|
||||
} LNK_ImportDLL;
|
||||
|
||||
enum
|
||||
{
|
||||
LNK_ImportTableFlag_EmitBiat = (1 << 0),
|
||||
LNK_ImportTableFlag_EmitUiat = (1 << 1),
|
||||
LNK_ImportTableFlag_Delayed = (1 << 0),
|
||||
LNK_ImportTableFlag_EmitBiat = (1 << 1),
|
||||
LNK_ImportTableFlag_EmitUiat = (1 << 2),
|
||||
};
|
||||
typedef U32 LNK_ImportTableFlags;
|
||||
|
||||
@@ -45,37 +46,28 @@ typedef struct LNK_ImportTable
|
||||
COFF_MachineType machine;
|
||||
LNK_ImportDLL *first_dll;
|
||||
LNK_ImportDLL *last_dll;
|
||||
LNK_Section *data_sect;
|
||||
LNK_Section *code_sect;
|
||||
LNK_Chunk *dll_table_chunk;
|
||||
LNK_Chunk *int_chunk;
|
||||
LNK_Chunk *handle_table_chunk;
|
||||
LNK_Chunk *iat_chunk;
|
||||
LNK_Chunk *ilt_chunk;
|
||||
LNK_Chunk *biat_chunk;
|
||||
LNK_Chunk *uiat_chunk;
|
||||
LNK_Chunk *code_chunk;
|
||||
LNK_ImportTableFlags flags;
|
||||
HashTable *dll_ht;
|
||||
} LNK_ImportTable;
|
||||
|
||||
internal LNK_ImportTable * lnk_import_table_alloc_static(LNK_SectionTable *sectab, LNK_SymbolTable *symtab, COFF_MachineType machine);
|
||||
internal LNK_ImportTable * lnk_import_table_alloc_delayed(LNK_SectionTable *sectab, LNK_SymbolTable *symtab, COFF_MachineType machine, B32 is_unloadable, B32 is_bindable);
|
||||
////////////////////////////////
|
||||
|
||||
internal LNK_ImportTable * lnk_import_table_alloc(LNK_ImportTableFlags flags);
|
||||
internal void lnk_import_table_release(LNK_ImportTable **imptab);
|
||||
internal LNK_ImportDLL * lnk_import_table_push_dll_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, String8 dll_name, COFF_MachineType machine);
|
||||
internal LNK_ImportDLL * lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, String8 dll_name, COFF_MachineType machine);
|
||||
internal LNK_ImportFunc * lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header);
|
||||
internal LNK_ImportFunc * lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_SymbolTable *symtab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header);
|
||||
internal LNK_ImportDLL * lnk_import_table_push_dll_static(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine);
|
||||
internal LNK_ImportDLL * lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine);
|
||||
internal LNK_ImportDLL * lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 name);
|
||||
|
||||
internal LNK_ImportFunc * lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header);
|
||||
internal LNK_ImportFunc * lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header);
|
||||
internal LNK_ImportFunc * lnk_import_table_search_func(LNK_ImportDLL *dll, String8 name);
|
||||
|
||||
internal String8 lnk_ordinal_data_from_hint(Arena *arena, COFF_MachineType machine, U16 hint);
|
||||
internal COFF_ObjSymbol * lnk_emit_indirect_jump_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *iat_symbol, String8 thunk_name);
|
||||
internal COFF_ObjSymbol * lnk_emit_load_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *imp_addr_ptr, COFF_ObjSymbol *tail_merge, String8 func_name);
|
||||
internal COFF_ObjSymbol * lnk_emit_tail_merge_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, String8 dll_name, COFF_ObjSymbol *dll_import_desc);
|
||||
|
||||
internal LNK_Chunk * lnk_emit_indirect_jump_thunk_x64(LNK_Section *sect, LNK_Chunk *parent, LNK_Symbol *addr_ptr);
|
||||
internal LNK_Chunk * lnk_emit_load_thunk_x64(LNK_Section *sect, LNK_Chunk *parent, LNK_Symbol *imp_addr_ptr, LNK_Symbol *tail_merge);
|
||||
internal LNK_Chunk * lnk_emit_tail_merge_thunk_x64(LNK_Section *sect, LNK_Chunk *parent, LNK_Symbol *dll_import_descriptor, LNK_Symbol *delay_load_helper);
|
||||
|
||||
internal LNK_Symbol * lnk_emit_load_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 func_name);
|
||||
internal LNK_Symbol * lnk_emit_jmp_thunk_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 func_name);
|
||||
internal LNK_Symbol * lnk_emit_tail_merge_symbol(LNK_SymbolTable *symtab, LNK_Chunk *chunk, String8 func_name);
|
||||
internal String8 lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal String8 lnk_build_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal String8 lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
|
||||
internal LNK_InputObjList lnk_import_table_serialize(Arena *arena, LNK_ImportTable *imptab, String8 image_name, COFF_MachineType machine);
|
||||
|
||||
@@ -536,145 +536,6 @@ lnk_build_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp,
|
||||
return lib;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
Assert(machine == COFF_MachineType_X64);
|
||||
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
||||
|
||||
String8 dll_name_no_ext = str8_chop_last_dot(dll_name);
|
||||
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||
|
||||
String8 debug_symbols;
|
||||
{
|
||||
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||
}
|
||||
|
||||
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name);
|
||||
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||
COFF_ObjSection *idata2 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_zero());
|
||||
COFF_ObjSection *idata6 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
|
||||
|
||||
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x1018175, COFF_SymStorageClass_Static);
|
||||
{
|
||||
String8 symbol_name = push_str8f(arena, "__IMPORT_DESCRIPTOR_%S", dll_name_no_ext);
|
||||
coff_obj_writer_push_symbol_external(obj_writer, symbol_name, 0, idata2);
|
||||
}
|
||||
COFF_ObjSymbol *idata2_symbol = coff_obj_writer_push_symbol_sect(obj_writer, idata2->name, idata2);
|
||||
COFF_ObjSymbol *idata6_symbol = coff_obj_writer_push_symbol_static(obj_writer, idata6->name, 0, idata6);
|
||||
COFF_ObjSymbol *idata4_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$4"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData);
|
||||
COFF_ObjSymbol *idata5_symbol = coff_obj_writer_push_symbol_undef_sect(obj_writer, str8_lit(".idata$5"), COFF_SectionFlag_MemWrite|COFF_SectionFlag_MemRead|COFF_SectionFlag_CntInitializedData);
|
||||
coff_obj_writer_push_symbol_undef(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR"));
|
||||
{
|
||||
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
||||
coff_obj_writer_push_symbol_undef(obj_writer, symbol_name);
|
||||
}
|
||||
|
||||
{
|
||||
PE_ImportEntry *import_entry = push_array(obj_writer->arena, PE_ImportEntry, 1);
|
||||
str8_list_push(obj_writer->arena, &idata2->data, str8_struct(import_entry));
|
||||
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, name_voff), idata6_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, lookup_table_voff), idata4_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
coff_obj_writer_section_push_reloc(obj_writer, idata2, OffsetOf(PE_ImportEntry, import_addr_table_voff), idata5_symbol, COFF_Reloc_X64_Addr32Nb);
|
||||
}
|
||||
|
||||
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_build_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||
|
||||
String8 debug_symbols;
|
||||
{
|
||||
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||
}
|
||||
|
||||
PE_ImportEntry *import_desc = push_array(obj_writer->arena, PE_ImportEntry, 1);
|
||||
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||
COFF_ObjSection *idata3 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$3"), LNK_DATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(import_desc));
|
||||
|
||||
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x01018175, COFF_SymStorageClass_Static);
|
||||
coff_obj_writer_push_symbol_external(obj_writer, str8_lit("__NULL_IMPORT_DESCRIPTOR"), 0, idata3);
|
||||
|
||||
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
Assert(str8_match_lit("dll", str8_skip_last_dot(dll_name), StringMatchFlag_CaseInsensitive|StringMatchFlag_RightSideSloppy));
|
||||
|
||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(time_stamp, machine);
|
||||
|
||||
String8 debug_symbols;
|
||||
{
|
||||
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
|
||||
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, machine);
|
||||
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||
debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||
}
|
||||
|
||||
COFF_ObjSection *debugs = coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, debug_symbols);
|
||||
COFF_ObjSection *idata4 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite, str8_zero());
|
||||
COFF_ObjSection *idata5 = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead|COFF_SectionFlag_MemWrite, str8_zero());
|
||||
|
||||
U64 import_size = coff_word_size_from_machine(machine);
|
||||
|
||||
U8 *null_thunk = push_array(obj_writer->arena, U8, import_size);
|
||||
U8 *null_lookup = push_array(obj_writer->arena, U8, import_size);
|
||||
|
||||
str8_list_push(obj_writer->arena, &idata5->data, str8_array(null_thunk, import_size));
|
||||
str8_list_push(obj_writer->arena, &idata4->data, str8_array(null_lookup, import_size));
|
||||
|
||||
idata4->flags |= coff_section_flag_from_align_size(import_size);
|
||||
idata5->flags |= coff_section_flag_from_align_size(import_size);
|
||||
|
||||
coff_obj_writer_push_symbol_abs(obj_writer, str8_lit("@comp.id"), 0x1018175, COFF_SymStorageClass_Static);
|
||||
{
|
||||
String8 dll_name_no_ext = str8_chop_last_dot(dll_name);
|
||||
String8 symbol_name = push_str8f(arena, "\x7f%S_NULL_THUNK_DATA", dll_name_no_ext);
|
||||
coff_obj_writer_push_symbol_external(obj_writer, symbol_name, 0, idata5);
|
||||
}
|
||||
|
||||
String8 obj = coff_obj_writer_serialize(arena, obj_writer);
|
||||
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
return obj;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_build_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size)
|
||||
{
|
||||
|
||||
@@ -128,9 +128,6 @@ internal String8List lnk_coff_archive_from_lib_build(Arena *arena, LNK_LibBu
|
||||
////////////////////////////////
|
||||
|
||||
internal LNK_LibBuild lnk_build_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ObjList obj_list, LNK_ExportTable *exptab);
|
||||
internal String8 lnk_build_import_entry_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal String8 lnk_build_null_import_descriptor_obj(Arena *arena, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal String8 lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp time_stamp, COFF_MachineType machine);
|
||||
internal String8 lnk_build_lib_member_header(Arena *arena, String8 name, COFF_TimeStamp time_stamp, U16 user_id, U16 group_id, U16 mode, U32 size);
|
||||
internal String8List lnk_build_import_lib(TP_Context *tp, TP_Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 lib_name, String8 dll_name, LNK_ExportTable *exptab);
|
||||
|
||||
|
||||
@@ -317,7 +317,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
||||
}
|
||||
|
||||
if (coff_info.machine != COFF_MachineType_Unknown && task->machine != coff_info.machine) {
|
||||
lnk_error_with_loc(LNK_Error_IncompatibleObj, input->path, input->lib_path,
|
||||
lnk_error_with_loc(LNK_Error_IncompatibleMachine, input->path, input->lib_path,
|
||||
"conflicting machine types expected %S but got %S",
|
||||
coff_string_from_machine_type(task->machine),
|
||||
coff_string_from_machine_type(coff_info.machine));
|
||||
|
||||
@@ -259,6 +259,9 @@ lnk_can_replace_symbol(LNK_Symbol *dst, LNK_Symbol *src)
|
||||
lnk_supplement_error("%S", src->obj->path);
|
||||
}
|
||||
}
|
||||
else if (dst->type == LNK_Symbol_Import) {
|
||||
can_replace = 1;
|
||||
}
|
||||
// defined VA vs defined chunk
|
||||
else if (LNK_Symbol_IsDefined(dst->type) && dst->u.defined.value_type == LNK_DefinedSymbolValue_VA &&
|
||||
LNK_Symbol_IsDefined(src->type)) {
|
||||
@@ -556,6 +559,7 @@ lnk_symbol_table_push_hash(LNK_SymbolTable *symtab, U64 hash, LNK_Symbol *symbol
|
||||
switch (symbol->type) {
|
||||
case LNK_Symbol_Null: break;
|
||||
|
||||
case LNK_Symbol_Import:
|
||||
case LNK_Symbol_DefinedExtern: {
|
||||
lnk_symbol_table_push_(symtab, symtab->arena->v[0], &symtab->chunk_lists[LNK_SymbolScopeIndex_Defined][0], LNK_SymbolScopeIndex_Defined, hash, symbol);
|
||||
} break;
|
||||
|
||||
@@ -88,6 +88,7 @@ typedef enum
|
||||
LNK_Symbol_Weak,
|
||||
LNK_Symbol_Lazy,
|
||||
LNK_Symbol_Undefined,
|
||||
LNK_Symbol_Import,
|
||||
} LNK_SymbolType;
|
||||
|
||||
typedef struct LNK_Symbol
|
||||
|
||||
Reference in New Issue
Block a user