make export table with COFF obj writer,

partially converted import table to COFF obj writer
This commit is contained in:
Nikita Smith
2025-04-18 15:35:16 -07:00
committed by Ryan Fleury
parent 3a2bb318c7
commit 19a7ada1dc
18 changed files with 760 additions and 900 deletions
+21
View File
@@ -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,
+1
View File
@@ -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);
+4 -4
View File
@@ -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;
+2 -2
View File
@@ -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
View File
@@ -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)
{
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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;
}
+1 -1
View File
@@ -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);
File diff suppressed because it is too large Load Diff
+27 -35
View File
@@ -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);
-139
View File
@@ -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)
{
-3
View File
@@ -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);
+1 -1
View File
@@ -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));
+4
View File
@@ -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;
+1
View File
@@ -88,6 +88,7 @@ typedef enum
LNK_Symbol_Weak,
LNK_Symbol_Lazy,
LNK_Symbol_Undefined,
LNK_Symbol_Import,
} LNK_SymbolType;
typedef struct LNK_Symbol