WIP switching to creating import table objs

This commit is contained in:
Nikita Smith
2025-05-13 11:09:39 -07:00
committed by Ryan Fleury
parent 1b21d0709f
commit 69d5010245
13 changed files with 476 additions and 604 deletions
+2 -2
View File
@@ -195,8 +195,8 @@ typedef struct COFF_ParsedArchiveImportHeader
typedef struct COFF_ArchiveMember
{
COFF_ParsedArchiveMemberHeader header;
U64 offset;
String8 data;
U64 offset;
String8 data;
} COFF_ArchiveMember;
typedef struct COFF_ArchiveFirstMember
+52 -93
View File
@@ -960,21 +960,29 @@ lnk_push_linker_symbols(Arena *arena, LNK_Config *config)
}
internal void
lnk_queue_lib_member_input(Arena *arena, PathStyle path_style, LNK_SymbolLib *symbol, LNK_InputImportList *input_import_list, LNK_InputObjList *input_obj_list)
lnk_queue_lib_member_input(Arena *arena,
PathStyle path_style,
LNK_SymbolLib *symbol,
LNK_InputImportList *input_import_list,
LNK_InputObjList *input_obj_list)
{
LNK_Lib *lib = symbol->lib;
U64 input_idx = Compose64Bit(lib->input_idx, symbol->member_offset);
// parse member
COFF_ArchiveMember member_info = coff_archive_member_from_offset(symbol->lib->data, symbol->member_offset);
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, symbol->member_offset);
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
switch (member_type) {
case COFF_DataType_Null: break;
case COFF_DataType_Import: {
LNK_InputImport *input = lnk_input_import_list_push(arena, input_import_list);
input->import_header = coff_archive_import_from_data(member_info.data);
input->coff_import = member_info.data;
input->input_idx = input_idx;
} break;
case COFF_DataType_BigObj:
case COFF_DataType_Obj: {
String8 obj_path = coff_parse_long_name(symbol->lib->long_names, member_info.header.name);
String8 obj_path = coff_parse_long_name(lib->long_names, member_info.header.name);
// obj path in thin archive has slash appended which screws up
// file lookup on disk; it couble be there to enable paths to symbols
@@ -985,11 +993,11 @@ lnk_queue_lib_member_input(Arena *arena, PathStyle path_style, LNK_SymbolLib *sy
}
// obj path in thin archive is relative to directory with archive
B32 is_thin = symbol->lib->type == COFF_Archive_Thin;
B32 is_thin = lib->type == COFF_Archive_Thin;
if (is_thin) {
Temp scratch = scratch_begin(&arena, 1);
String8List obj_path_list = {0};
str8_list_push(scratch.arena, &obj_path_list, str8_chop_last_slash(symbol->lib->path));
str8_list_push(scratch.arena, &obj_path_list, str8_chop_last_slash(lib->path));
str8_list_push(scratch.arena, &obj_path_list, obj_path);
obj_path = str8_path_list_join_by_style(arena, &obj_path_list, path_style);
scratch_end(scratch);
@@ -997,10 +1005,11 @@ lnk_queue_lib_member_input(Arena *arena, PathStyle path_style, LNK_SymbolLib *sy
LNK_InputObj *input = lnk_input_obj_list_push(arena, input_obj_list);
input->is_thin = is_thin;
input->dedup_id = push_str8f(arena, "%S/%S", symbol->lib->path, obj_path);
input->dedup_id = push_str8f(arena, "%S/%S", lib->path, obj_path);
input->path = obj_path;
input->data = member_info.data;
input->lib_path = symbol->lib->path;
input->lib_path = lib->path;
input->input_idx = input_idx;
} break;
}
}
@@ -2225,7 +2234,7 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
COFF_SectionFlags flags = sect_header->flags & ~COFF_SectionFlags_LnkFlags;
LNK_Section *sect = lnk_section_table_search(sectab, sect_name, flags);
String8Node *data_n = push_array(sect->arena, String8Node, 1);
String8Node *data_n = push_array(sectab->arena, String8Node, 1);
data_n->string = sect_data;
// fill out contrib
@@ -3147,47 +3156,6 @@ lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_S
return image_data;
}
internal String8List
lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportParseList export_list)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
dll_name = str8_skip_last_slash(dll_name);
// These objects appear in first three members of any lib that linker produces with /dll.
// Objects are used by MSVC linker to build import table.
String8 import_entry_obj = lnk_build_import_entry_obj(scratch.arena, dll_name, time_stamp, machine);
String8 null_import_descriptor_obj = lnk_build_null_import_descriptor_obj(scratch.arena, time_stamp, machine);
String8 null_thunk_data_obj = lnk_build_null_thunk_data_obj(scratch.arena, dll_name, time_stamp, machine);
COFF_LibWriter *lib_writer = coff_lib_writer_alloc();
// push import table nulls
coff_lib_writer_push_obj(lib_writer, dll_name, import_entry_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_import_descriptor_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_thunk_data_obj);
// push exports
for (LNK_ExportParseNode *exp_n = export_list.first; exp_n != 0; exp_n = exp_n->next) {
LNK_ExportParse *exp = &exp_n->data;
if (exp->is_noname_present) {
coff_lib_writer_push_export_by_ordinal(lib_writer, machine, time_stamp, dll_name, exp->type, exp->ordinal);
} else {
String8 name = lnk_name_from_export_parse(exp);
coff_lib_writer_push_export_by_name(lib_writer, machine, time_stamp, dll_name, exp->type, name, exp->hint);
}
}
// serialize lib
String8List lib = coff_lib_writer_serialize(arena, lib_writer, COFF_TimeStamp_Max, 0, /* emit second member: */ 1);
coff_lib_writer_release(&lib_writer);
scratch_end(scratch);
ProfEnd();
return lib;
}
////////////////////////////////
internal
@@ -3591,8 +3559,8 @@ lnk_run(int argc, char **argv)
// state
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
LNK_SectionTable *sectab = 0;
LNK_ImportTable *imptab_static = lnk_import_table_alloc(0);
LNK_ImportTable *imptab_delayed = lnk_import_table_alloc(config->import_table_flags);
LNK_ImportTable *imptab_static = lnk_import_table_alloc();
LNK_ImportTable *imptab_delayed = lnk_import_table_alloc();
LNK_ObjList obj_list = {0};
LNK_LibList lib_index[LNK_InputSource_Count] = {0};
Arena *ht_arena = arena_alloc();
@@ -3681,50 +3649,26 @@ lnk_run(int argc, char **argv)
case State_InputImports: {
ProfBegin("Input Imports");
for (LNK_InputImport *input = input_import_list.first; input != 0; input = input->next) {
COFF_ParsedArchiveImportHeader *import_header = &input->import_header;
COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(input->coff_import);
if (import_header->machine != config->machine) {
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(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_Symbol *thunk_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
thunk_symbol->type = LNK_Symbol_Import;
thunk_symbol->name = import_header.func_name;
thunk_symbol->u.coff_import = input->coff_import;
LNK_ImportDLL *dll;
LNK_ImportFunc *func;
if (is_delayed) {
dll = lnk_import_table_search_dll(imptab_delayed, import_header->dll_name);
if (!dll) {
dll = lnk_import_table_push_dll_delayed(imptab_delayed, import_header->dll_name, import_header->machine);
}
func = lnk_import_table_search_func(dll, import_header->func_name);
if (!func) {
func = lnk_import_table_push_func_delayed(imptab_delayed, dll, import_header);
}
} else {
dll = lnk_import_table_search_dll(imptab_static, import_header->dll_name);
if (!dll) {
dll = lnk_import_table_push_dll_static(imptab_static, import_header->dll_name, import_header->machine);
}
func = lnk_import_table_search_func(dll, import_header->func_name);
if (!func) {
func = lnk_import_table_push_func_static(imptab_static, dll, import_header);
}
}
LNK_Symbol *iat_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
iat_symbol->type = LNK_Symbol_Import;
iat_symbol->name = push_str8f(symtab->arena->v[0], "__imp_%S", import_header.func_name);
iat_symbol->u.coff_import = input->coff_import;
{
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);
}
lnk_symbol_table_push(symtab, thunk_symbol);
lnk_symbol_table_push(symtab, iat_symbol);
}
// reset input
@@ -4235,6 +4179,7 @@ lnk_run(int argc, char **argv)
if (input_import_list.count) {
ProfBegin("Build Import Table");
// warn about unused delayloads
if (config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll) {
if (imptab_delayed) {
for (String8Node *node = config->delay_load_dll_list.first; node != 0; node = node->next) {
@@ -4246,11 +4191,25 @@ lnk_run(int argc, char **argv)
}
}
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);
// make and input static imports
String8Array import_objs_static = lnk_make_import_dlls_static(scratch.arena, imptab_static, config->machine, str8_skip_last_slash(config->image_name));
for (U64 i = 0; i < import_objs_static.count; i += 1) {
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
input->path = str8_lit("* Import Obj *");
input->input_idx = i;
input->data = import_objs_static.v[i];
}
lnk_input_obj_list_concat_in_place(&input_obj_list, &static_imports);
lnk_input_obj_list_concat_in_place(&input_obj_list, &delayed_imports);
// make and input delayed imports
B32 emit_biat = config->import_table_emit_biat == LNK_SwitchState_Yes;
B32 emit_uiat = config->import_table_emit_uiat == LNK_SwitchState_Yes;
String8Array import_objs_delayed = lnk_make_import_dlls_delayed(scratch.arena, imptab_delayed, config->machine, str8_skip_last_slash(config->image_name), emit_biat, emit_uiat);
for (U64 i = 0; i < import_objs_delayed.count; i += 1) {
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
input->path = str8_lit("* Import Obj *");
input->input_idx = import_objs_static.count + i;
input->data = import_objs_delayed.v[i];
}
ProfEnd();
}
-4
View File
@@ -192,10 +192,6 @@ internal String8List lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_temp, LN
internal String8List lnk_build_win32_image_header(Arena *arena, LNK_SymbolTable *symtab, LNK_Config *config, LNK_SectionArray sect_arr, U64 expected_image_header_size);
internal String8 lnk_build_win32_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, LNK_ObjList obj_list);
// --- Import Lib --------------------------------------------------------------
internal String8List lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportParseList export_list);
// --- Logger ------------------------------------------------------------------
internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab);
+4 -4
View File
@@ -1019,9 +1019,9 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
} else {
String8 value = value_strings.first->string;
if (str8_match_lit("unload", value, StringMatchFlag_CaseInsensitive)) {
config->flags |= LNK_ImportTableFlag_EmitUiat;
config->import_table_emit_uiat = 1;
} else if (str8_match_lit("nobind", value, StringMatchFlag_CaseInsensitive)) {
config->flags &= ~LNK_ImportTableFlag_EmitBiat;
config->import_table_emit_biat = 0;
} else {
lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, cmd_switch, "unknown parameter \"%S\"", value);
}
@@ -1519,7 +1519,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
} break;
case LNK_CmdSwitch_Rad_DelayBind: {
lnk_cmd_switch_set_flag_64(obj_path, lib_path, cmd_switch, value_strings, &config->flags, LNK_ImportTableFlag_EmitBiat);
lnk_cmd_switch_parse_flag(obj_path, lib_path, cmd_switch, value_strings, &config->import_table_emit_biat);
} break;
case LNK_CmdSwitch_Rad_DoMerge: {
@@ -1935,7 +1935,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
// don't emit bind table with /ALLOWBIND:NO
if (config->dll_characteristics & PE_DllCharacteristic_NO_BIND) {
config->flags &= ~LNK_ImportTableFlag_EmitBiat;
config->import_table_emit_biat = LNK_SwitchState_No;
}
// set flags for /OPT
+2 -1
View File
@@ -289,7 +289,8 @@ typedef struct LNK_Config
LNK_SwitchState opt_icf;
LNK_SwitchState opt_lbr;
U64 opt_iter_count;
LNK_ImportTableFlags import_table_flags;
LNK_SwitchState import_table_emit_biat;
LNK_SwitchState import_table_emit_uiat;
LNK_GuardFlags guard_flags;
LNK_DebugInfoGuidType guid_type;
Guid guid;
+45
View File
@@ -403,4 +403,49 @@ lnk_make_edata_obj(Arena *arena,
return obj;
}
internal String8List
lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportParseList export_list)
{
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
dll_name = str8_skip_last_slash(dll_name);
// These objects appear in first three members of any lib that linker produces with /dll.
// Objects are used by MSVC linker to build import table.
String8 import_entry_obj = lnk_build_import_entry_obj(scratch.arena, dll_name, time_stamp, machine);
String8 null_import_descriptor_obj = lnk_build_null_import_descriptor_obj(scratch.arena, time_stamp, machine);
String8 null_thunk_data_obj = lnk_build_null_thunk_data_obj(scratch.arena, dll_name, time_stamp, machine);
COFF_LibWriter *lib_writer = coff_lib_writer_alloc();
// push import table nulls
coff_lib_writer_push_obj(lib_writer, dll_name, import_entry_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_import_descriptor_obj);
coff_lib_writer_push_obj(lib_writer, dll_name, null_thunk_data_obj);
// push exports
for (LNK_ExportParseNode *exp_n = export_list.first; exp_n != 0; exp_n = exp_n->next) {
LNK_ExportParse *exp = &exp_n->data;
if (exp->is_noname_present) {
coff_lib_writer_push_export_by_ordinal(lib_writer, machine, time_stamp, dll_name, exp->type, exp->ordinal);
} else {
String8 name = lnk_name_from_export_parse(exp);
COFF_LibWriterSymbolNode *member_symbol = coff_lib_writer_push_export_by_name(lib_writer, machine, time_stamp, dll_name, exp->type, name, exp->hint);
COFF_LibWriterSymbol imp_symbol = {0};
imp_symbol.name = push_str8f(lib_writer->arena, "__imp_%S", name);
imp_symbol.member_idx = member_symbol->data.member_idx;
coff_lib_writer_symbol_list_push(lib_writer->arena, &lib_writer->symbol_list, imp_symbol);
}
}
// serialize lib
String8List lib = coff_lib_writer_serialize(arena, lib_writer, COFF_TimeStamp_Max, 0, /* emit second member: */ 1);
coff_lib_writer_release(&lib_writer);
scratch_end(scratch);
ProfEnd();
return lib;
}
+1 -1
View File
@@ -43,4 +43,4 @@ internal B32 lnk_parse_export_directive_ex(Arena *arena, String8List directive,
internal B32 lnk_parse_export_directive(Arena *arena, String8 directive, String8 obj_path, String8 lib_path, LNK_ExportParse *parse_out);
internal LNK_ExportParsePtrArray lnk_array_from_export_list(Arena *arena, LNK_ExportParseList list);
internal LNK_ExportParseNode * lnk_export_parse_list_push(Arena *arena, LNK_ExportParseList *list, LNK_ExportParse data);
internal String8List lnk_build_import_lib(Arena *arena, COFF_MachineType machine, COFF_TimeStamp time_stamp, String8 dll_name, LNK_ExportParseList export_list);
+342 -444
View File
@@ -2,17 +2,12 @@
// Licensed under the MIT license (https://opensource.org/license/mit/)
internal LNK_ImportTable *
lnk_import_table_alloc(LNK_ImportTableFlags flags)
lnk_import_table_alloc(void)
{
ProfBeginFunction();
Arena *arena = arena_alloc();
LNK_ImportTable *imptab = push_array(arena, LNK_ImportTable, 1);
imptab->arena = arena;
imptab->flags = flags;
imptab->dll_ht = hash_table_init(arena, LNK_IMPORT_DLL_HASH_TABLE_BUCKET_COUNT);
ProfEnd();
imptab->arena = arena;
imptab->dll_ht = hash_table_init(arena, 512);
return imptab;
}
@@ -25,381 +20,37 @@ lnk_import_table_release(LNK_ImportTable **imptab_ptr)
ProfEnd();
}
internal BucketNode *
lnk_import_table_push_dll_node(LNK_ImportTable *imptab, LNK_ImportDLL *dll)
internal LNK_ImportDLL *
lnk_import_table_push_dll(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine)
{
LNK_ImportDLL *dll = push_array(imptab->arena, LNK_ImportDLL, 1);
// update list
SLLQueuePush(imptab->first_dll, imptab->last_dll, dll);
// update name -> dll hash table
return hash_table_push_path_raw(imptab->arena, imptab->dll_ht, dll->name, dll);
}
hash_table_push_path_raw(imptab->arena, imptab->dll_ht, dll->name, dll);
internal BucketNode *
lnk_import_table_push_func_node(LNK_ImportTable *imptab, LNK_ImportDLL *dll, LNK_ImportFunc *func)
{
// update list
SLLQueuePush(dll->first_func, dll->last_func, func);
// update name -> func hash table
return hash_table_push_string_raw(imptab->arena, dll->func_ht, func->name, func);
}
internal LNK_ImportDLL *
lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 name)
{
return hash_table_search_path_raw(imptab->dll_ht, name);
}
internal LNK_ImportFunc *
lnk_import_table_search_func(LNK_ImportDLL *dll, String8 name)
{
LNK_ImportFunc *func = 0;
hash_table_search_string_raw(dll->func_ht, name, (void **)&func);
return func;
}
internal LNK_ImportDLL *
lnk_import_table_push_dll_static(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine)
{
ProfBeginFunction();
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine);
U64 import_size = coff_word_size_from_machine(machine);
COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size);
PE_ImportEntry *impdesc = push_array(obj_writer->arena, PE_ImportEntry, 1);
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name);
COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc));
COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero());
COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$7"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), LNK_TEXT_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero());
COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect);
COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect);
COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect);
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: {
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, lookup_table_voff), ilt_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, name_voff), dll_name_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, import_addr_table_voff), iat_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
default: { NotImplemented; } break;
}
// push to list
LNK_ImportDLL *dll = push_array(imptab->arena, LNK_ImportDLL, 1);
dll->obj_writer = obj_writer;
dll->name = push_str8_copy(imptab->arena, dll_name);
dll->dll_sect = dll_sect;
dll->int_sect = int_sect;
dll->ilt_sect = ilt_sect;
dll->iat_sect = iat_sect;
dll->code_sect = code_sect;
dll->func_ht = hash_table_init(imptab->arena, LNK_IMPORT_FUNC_HASH_TABLE_BUCKET_COUNT);
lnk_import_table_push_dll_node(imptab, dll);
ProfEnd();
return dll;
}
internal LNK_ImportDLL *
lnk_import_table_push_dll_delayed(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine)
lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 dll_name)
{
ProfBeginFunction();
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine);
// import descriptor
PE_DelayedImportEntry *impdesc = push_array(obj_writer->arena, PE_DelayedImportEntry, 1);
impdesc->attributes = 1;
// DLL name cstring
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll_name);
// DLL handle
U64 handle_size = coff_word_size_from_machine(machine);
U8 *handle = push_array(obj_writer->arena, U8, handle_size);
// import align
U64 import_size = coff_word_size_from_machine(machine);
COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size);
COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc));
COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero());
COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$7"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
COFF_ObjSection *biat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$8"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *uiat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$9"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), LNK_TEXT_SECTION_FLAGS, str8_zero());
COFF_ObjSection *handle_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$h"), LNK_DATA_SECTION_FLAGS, str8_array(handle, handle_size));
COFF_ObjSymbol *dll_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_sect->name, 0, dll_sect);
COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect);
COFF_ObjSymbol *handle_symbol = coff_obj_writer_push_symbol_static(obj_writer, handle_sect->name, 0, handle_sect);
COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect);
COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect);
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: {
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_voff), dll_name_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, module_handle_voff), handle_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, iat_voff), iat_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_table_voff), ilt_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
default: { NotImplemented; } break;
}
if (imptab->flags & LNK_ImportTableFlag_EmitBiat) {
COFF_ObjSymbol *biat_symbol = coff_obj_writer_push_symbol_static(obj_writer, biat_sect->name, 0, biat_sect);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, bound_table_voff), biat_symbol, COFF_Reloc_X64_Addr32Nb);
}
if (imptab->flags & LNK_ImportTableFlag_EmitUiat) {
COFF_ObjSymbol *uiat_symbol = coff_obj_writer_push_symbol_static(obj_writer, uiat_sect->name, 0, uiat_sect);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, unload_table_voff), uiat_symbol, COFF_Reloc_X64_Addr32Nb);
}
// emit tail merge
COFF_ObjSymbol *tail_merge_symbol = 0;
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: { tail_merge_symbol = lnk_emit_tail_merge_thunk_x64(obj_writer, code_sect, dll_name, dll_symbol); } break;
default: { NotImplemented; } break;
}
// fill out result
LNK_ImportDLL *dll = push_array(imptab->arena, LNK_ImportDLL, 1);
dll->dll_sect = dll_sect;
dll->int_sect = int_sect;
dll->iat_sect = iat_sect;
dll->ilt_sect = ilt_sect;
dll->biat_sect = biat_sect;
dll->uiat_sect = uiat_sect;
dll->code_sect = code_sect;
dll->tail_merge_symbol = tail_merge_symbol;
dll->name = push_str8_copy(imptab->arena, dll_name);
dll->func_ht = hash_table_init(imptab->arena, LNK_IMPORT_FUNC_HASH_TABLE_BUCKET_COUNT);
lnk_import_table_push_dll_node(imptab, dll);
ProfEnd();
LNK_ImportDLL *dll = 0;
hash_table_search_string_raw(imptab->dll_ht, dll_name, &dll);
return dll;
}
internal LNK_ImportFunc *
lnk_import_table_push_func_static(LNK_ImportTable *imptab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header)
lnk_import_table_push_func(LNK_ImportTable *imptab, LNK_ImportDLL *dll, struct LNK_Symbol *symbol)
{
ProfBeginFunction();
COFF_ObjWriter *obj_writer = dll->obj_writer;
String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", header->func_name);
U64 iat_offset = dll->iat_sect->data.total_size;
U64 ilt_offset = dll->ilt_sect->data.total_size;
U64 int_offset = dll->int_sect->data.total_size;
COFF_ObjSymbol *iat_symbol = 0;
switch (header->import_by) {
case COFF_ImportBy_Ordinal: {
String8 ordinal_data = coff_ordinal_data_from_hint(obj_writer->arena, header->machine, header->hint_or_ordinal);
str8_list_push(obj_writer->arena, &dll->ilt_sect->data, ordinal_data);
str8_list_push(obj_writer->arena, &dll->iat_sect->data, ordinal_data);
iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_offset, dll->iat_sect);
} break;
case COFF_ImportBy_Name: {
// put together name look up entry
String8 int_data = coff_make_import_lookup(obj_writer->arena, header->hint_or_ordinal, header->func_name);
str8_list_push(obj_writer->arena, &dll->int_sect->data, int_data);
// create symbol for lookup entry
COFF_ObjSymbol *int_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll->int_sect->name, int_offset, dll->int_sect);
// in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses
U64 import_size = coff_word_size_from_machine(header->machine);
U8 *import_entry = push_array(obj_writer->arena, U8, import_size);
str8_list_push(obj_writer->arena, &dll->ilt_sect->data, str8_array(import_entry, import_size));
str8_list_push(obj_writer->arena, &dll->iat_sect->data, str8_array(import_entry, import_size));
iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_offset, dll->iat_sect);
// patch IAT and ILT
coff_obj_writer_section_push_reloc(obj_writer, dll->ilt_sect, ilt_offset, int_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll->iat_sect, iat_offset, int_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
case COFF_ImportBy_Undecorate: {
NotImplemented;
} break;
case COFF_ImportBy_NameNoPrefix: {
NotImplemented;
} break;
}
// generate thunks
COFF_ObjSymbol *jmp_thunk_symbol = 0;
if (header->type == COFF_ImportHeader_Code) {
switch (header->machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: { jmp_thunk_symbol = lnk_emit_indirect_jump_thunk_x64(obj_writer, dll->code_sect, iat_symbol, header->func_name); } break;
default: { NotImplemented; } break;
}
}
// fill out import
LNK_ImportFunc *func = push_array(imptab->arena, LNK_ImportFunc, 1);
func->name = push_str8_copy(imptab->arena, header->func_name);
func->thunk_symbol_name = push_str8_copy(imptab->arena, jmp_thunk_symbol->name);
func->iat_symbol_name = iat_symbol_name;
LNK_ImportFunc *func = push_array(imptab->arena, LNK_ImportFunc, 1);
func->symbol = symbol;
lnk_import_table_push_func_node(imptab, dll, func);
ProfEnd();
return func;
}
internal LNK_ImportFunc *
lnk_import_table_push_func_delayed(LNK_ImportTable *imptab, LNK_ImportDLL *dll, COFF_ParsedArchiveImportHeader *header)
{
#if 0
ProfBeginFunction();
COFF_ObjWriter *obj_writer = dll->obj_writer;
Assert(dll->machine == header->machine); // TODO: error handle
U64 import_size = coff_word_size_from_machine(dll->machine);
LNK_Symbol *int_symbol = 0;
// generate thunks
LNK_Symbol *jmp_thunk_symbol = g_null_symbol_ptr;
LNK_Symbol *load_thunk_symbol = g_null_symbol_ptr;
LNK_Chunk *jmp_thunk_chunk = 0;
LNK_Chunk *load_thunk_chunk = 0;
if (header->type == COFF_ImportHeader_Code) {
switch (dll->machine) {
case COFF_MachineType_X64: {
String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name);
LNK_Symbol *iat_symbol = lnk_make_undefined_symbol(symtab->arena->v[0], iat_symbol_name, LNK_SymbolScope_Main);
// emit jmp thunk chunk
jmp_thunk_chunk = lnk_emit_indirect_jump_thunk_x64(code_sect, code_table_chunk, iat_symbol);
jmp_thunk_symbol = lnk_emit_jmp_thunk_symbol(symtab, jmp_thunk_chunk, header->func_name);
// emit load thunk
load_thunk_chunk = lnk_emit_load_thunk_x64(code_sect, code_table_chunk, iat_symbol, dll->tail_merge_symbol);
load_thunk_symbol = lnk_emit_load_thunk_symbol(symtab, load_thunk_chunk, header->func_name);
} break;
default: lnk_not_implemented("TODO: support for machine 0x%X", dll->machine); break;
}
}
switch (header->import_by) {
case COFF_ImportBy_Ordinal: {
String8 ordinal_data = lnk_ordinal_data_from_hint(data_sect->arena, dll->machine, header->hint_or_ordinal);
Assert(ordinal_data.size == import_size);
ilt_chunk = lnk_section_push_chunk_data(data_sect, ilt_table_chunk, ordinal_data, sort_index);
iat_chunk = lnk_section_push_chunk_bss(data_sect, iat_table_chunk, import_size, sort_index);
lnk_section_push_reloc(data_sect, iat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
lnk_section_associate_chunks(data_sect, iat_chunk, ilt_chunk);
if (imptab->flags & LNK_ImportTableFlag_EmitBiat) {
biat_chunk = lnk_section_push_chunk_bss(data_sect, biat_table_chunk, import_size, sort_index);
lnk_section_push_reloc(data_sect, biat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
lnk_section_associate_chunks(data_sect, iat_chunk, biat_chunk);
}
if (imptab->flags & LNK_ImportTableFlag_EmitUiat) {
uiat_chunk = lnk_section_push_chunk_bss(data_sect, uiat_table_chunk, import_size, sort_index);
lnk_section_push_reloc(data_sect, uiat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
lnk_section_associate_chunks(data_sect, iat_chunk, uiat_chunk);
}
} break;
case COFF_ImportBy_Name: {
// put together name look up entry
String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint_or_ordinal, header->func_name);
LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero());
// create symbol for lookup chunk
String8 int_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.name.delayed", dll->name, header->func_name);
int_symbol = lnk_symbol_table_push_defined_chunk(symtab, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0);
// dynamic linker patches this voff on DLL load event
ilt_chunk = lnk_section_push_chunk_bss(data_sect, ilt_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, ilt_chunk, "ILT entry (delayed) %S.%S", dll->name, header->func_name);
// patch-in ILT with import voff
lnk_section_push_reloc(data_sect, ilt_chunk, LNK_Reloc_VIRT_OFF_32, 0, int_symbol);
// in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses.
iat_chunk = lnk_section_push_chunk_bss(data_sect, iat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, iat_chunk, "IAT entre (delayed) %S.%S", dll->name, header->func_name);
// associate chunks
lnk_section_associate_chunks(data_sect, iat_chunk, ilt_chunk);
lnk_section_associate_chunks(data_sect, iat_chunk, int_chunk);
// patch-in thunk address
lnk_section_push_reloc(data_sect, iat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
if (imptab->flags & LNK_ImportTableFlag_EmitBiat) {
biat_chunk = lnk_section_push_chunk_bss(data_sect, biat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, biat_chunk, "%S.biat.%S (delayed)", dll->name, header->func_name);
// patch-in thunk address
lnk_section_push_reloc(data_sect, biat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
}
if (imptab->flags & LNK_ImportTableFlag_EmitUiat) {
uiat_chunk = lnk_section_push_chunk_bss(data_sect, uiat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, uiat_chunk, "%S.uiat.%S (delayed)", dll->name, header->func_name);
// patch-in thunk address
lnk_section_push_reloc(data_sect, uiat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
}
} break;
case COFF_ImportBy_Undecorate: {
lnk_not_implemented("TODO: COFF_ImportBy_Undecorate");
} break;
case COFF_ImportBy_NameNoPrefix: {
lnk_not_implemented("TODO: COFF_ImportBy_NameNoPrefix");
} break;
}
if (jmp_thunk_chunk) {
lnk_section_associate_chunks(data_sect, iat_chunk, jmp_thunk_chunk);
}
if (load_thunk_chunk) {
lnk_section_associate_chunks(data_sect, iat_chunk, load_thunk_chunk);
}
String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name);
LNK_Symbol *iat_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0);
String8 ilt_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.ilt.delayed", dll->name, header->func_name);
LNK_Symbol *ilt_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0);
// fill out import
LNK_ImportFunc *func = push_array(imptab->arena, LNK_ImportFunc, 1);
func->name = push_str8_copy(imptab->arena, header->func_name);
func->thunk_symbol_name = push_str8_copy(imptab->arena, jmp_thunk_symbol->name);
func->iat_symbol_name = push_str8_copy(imptab->arena, iat_symbol->name);
lnk_import_table_push_func_node(imptab, dll, func);
ProfEnd();
return func;
#endif
return 0;
}
internal COFF_ObjSymbol *
lnk_emit_indirect_jump_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *iat_symbol, String8 thunk_name)
{
@@ -645,96 +296,343 @@ lnk_build_null_thunk_data_obj(Arena *arena, String8 dll_name, COFF_TimeStamp tim
return obj;
}
internal LNK_InputObjList
lnk_import_table_serialize(Arena *arena, LNK_ImportTable *imptab, String8 image_name, COFF_MachineType machine)
internal void
lnk_emit_dll_import_debug_symbols(COFF_ObjWriter *obj_writer, String8 dll_name)
{
Temp scratch = scratch_begin(&arena, 1);
Temp scratch = scratch_begin(0,0);
// append .debug$S
for (LNK_ImportDLL *dll = imptab->first_dll; dll != 0; dll = dll->next) {
String8 debug_symbols = {0};
{
Temp temp = temp_begin(scratch.arena);
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
CV_SymbolList symbol_list = { .signature = CV_Signature_C13 };
// S_OBJ
String8 obj_data = cv_make_obj_name(scratch.arena, dll_name, 0);
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
// S_OBJ
String8 obj_data = cv_make_obj_name(temp.arena, dll->name, 0);
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
// S_COMPILE3
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, obj_writer->machine);
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
// S_COMPILE3
String8 comp3_data = lnk_make_linker_compile3(temp.arena, dll->obj_writer->machine);
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
// S_END
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_END, str8_zero());
// S_END
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_END, str8_zero());
// TODO: add thunks
// TODO: add thunks
// serialize symbols
String8 debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
// serialize symbols
debug_symbols = lnk_make_debug_s(dll->obj_writer->arena, symbol_list);
temp_end(temp);
}
coff_obj_writer_push_section(dll->obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS, debug_symbols);
}
LNK_InputObjList result = {0};
// serialize obj writers
for (LNK_ImportDLL *dll = imptab->first_dll; dll != 0; dll = dll->next) {
String8 obj = coff_obj_writer_serialize(arena, dll->obj_writer);
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
input->data = obj;
input->path = push_str8f(arena, "Import:%S", dll->name);
input->dedup_id = input->path;
}
// generate null terminator objs
String8 null_import_entry_obj = lnk_build_import_entry_obj(arena, image_name, COFF_TimeStamp_Max, machine);
String8 null_import_descriptor_obj = lnk_build_null_import_descriptor_obj(arena, COFF_TimeStamp_Max, machine);
String8 null_thunk_data_obj = lnk_build_null_thunk_data_obj(arena, image_name, COFF_TimeStamp_Max, machine);
// pick null terminator obj paths
String8 null_import_path;
String8 null_import_descriptor_path;
String8 null_thunk_path;
if (imptab->flags & LNK_ImportTableFlag_Delayed) {
null_import_path = str8_lit("DELAYED_NULL_IMPORT_ENTRY_OBJ");
null_import_descriptor_path = str8_lit("DELAYED_NULL_IMPORT_DESCRIPTOR_OBJ");
null_thunk_path = str8_lit("DELAYED_NULL_THUNK_OBJ");
} else {
null_import_path = str8_lit("NULL_IMPORT_ENTRY_OBJ");
null_import_descriptor_path = str8_lit("NULL_IMPORT_DESCRIPTOR_OBJ");
null_thunk_path = str8_lit("NULL_THUNK_OBJ");
}
os_write_data_to_file_path(str8_lit("null_import_entry.obj"), null_import_entry_obj);
os_write_data_to_file_path(str8_lit("null_import_descriptor.obj"), null_import_descriptor_obj);
os_write_data_to_file_path(str8_lit("null_thunk.obj"), null_thunk_data_obj);
// append null terminators
{
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
input->data = null_import_entry_obj;
input->path = null_import_path;
input->dedup_id = input->path;
}
{
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
input->data = null_import_descriptor_obj;
input->path = null_import_descriptor_path;
input->dedup_id = input->path;
}
{
LNK_InputObj *input = lnk_input_obj_list_push(arena, &result);
input->data = null_thunk_data_obj;
input->path = null_thunk_path;
input->dedup_id = input->path;
}
coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS, debug_symbols);
scratch_end(scratch);
return result;
}
internal String8
lnk_obj_from_import_dll_static(Arena *arena, COFF_MachineType machine, LNK_ImportDLL *dll)
{
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, machine);
U64 import_size = coff_word_size_from_machine(machine);
COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size);
PE_ImportEntry *impdesc = push_array(obj_writer->arena, PE_ImportEntry, 1);
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll->name);
COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$2"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc));
COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$4"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$5"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$6"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero());
COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".idata$7"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), LNK_TEXT_SECTION_FLAGS|COFF_SectionFlag_Align1Bytes, str8_zero());
COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect);
COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect);
COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect);
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: {
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, lookup_table_voff), ilt_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, name_voff), dll_name_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_ImportEntry, import_addr_table_voff), iat_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
default: { NotImplemented; } break;
}
for (LNK_ImportFunc *func = dll->first_func; func != 0; func = func->next) {
LNK_Symbol *import_symbol = func->symbol;
COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(import_symbol->u.coff_import);
String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", import_header.func_name);
U64 iat_offset = iat_sect->data.total_size;
U64 ilt_offset = ilt_sect->data.total_size;
U64 int_offset = int_sect->data.total_size;
COFF_ObjSymbol *iat_symbol = 0;
switch (import_header.import_by) {
case COFF_ImportBy_Ordinal: {
String8 ordinal_data = coff_ordinal_data_from_hint(obj_writer->arena, import_header.machine, import_header.hint_or_ordinal);
str8_list_push(obj_writer->arena, &ilt_sect->data, ordinal_data);
str8_list_push(obj_writer->arena, &iat_sect->data, ordinal_data);
iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_offset, iat_sect);
} break;
case COFF_ImportBy_Name: {
// put together name look up entry
String8 int_data = coff_make_import_lookup(obj_writer->arena, import_header.hint_or_ordinal, import_header.func_name);
str8_list_push(obj_writer->arena, &int_sect->data, int_data);
// create symbol for lookup entry
COFF_ObjSymbol *int_symbol = coff_obj_writer_push_symbol_static(obj_writer, int_sect->name, int_offset, int_sect);
// in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses
U64 import_size = coff_word_size_from_machine(import_header.machine);
U8 *import_entry = push_array(obj_writer->arena, U8, import_size);
str8_list_push(obj_writer->arena, &ilt_sect->data, str8_array(import_entry, import_size));
str8_list_push(obj_writer->arena, &iat_sect->data, str8_array(import_entry, import_size));
iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_offset, iat_sect);
// patch IAT and ILT
coff_obj_writer_section_push_reloc(obj_writer, ilt_sect, ilt_offset, int_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, iat_sect, iat_offset, int_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
case COFF_ImportBy_Undecorate: {
NotImplemented;
} break;
case COFF_ImportBy_NameNoPrefix: {
NotImplemented;
} break;
}
// emit thunks
COFF_ObjSymbol *jmp_thunk_symbol = 0;
if (import_header.type == COFF_ImportHeader_Code) {
switch (import_header.machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: { jmp_thunk_symbol = lnk_emit_indirect_jump_thunk_x64(obj_writer, code_sect, iat_symbol, import_header.func_name); } break;
default: { NotImplemented; } break;
}
}
}
String8 dll_obj = coff_obj_writer_serialize(arena, obj_writer);
coff_obj_writer_release(&obj_writer);
return dll_obj;
}
internal String8
lnk_obj_from_import_dll_delayed(Arena *arena, COFF_MachineType machine, LNK_ImportDLL *dll, B32 emit_biat, B32 emit_uiat)
{
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(COFF_TimeStamp_Max, machine);
// import descriptor
PE_DelayedImportEntry *impdesc = push_array(obj_writer->arena, PE_DelayedImportEntry, 1);
impdesc->attributes = 1;
// DLL name cstring
String8 dll_name_cstr = push_cstr(obj_writer->arena, dll->name);
// DLL handle
U64 handle_size = coff_word_size_from_machine(machine);
U8 *handle = push_array(obj_writer->arena, U8, handle_size);
// import align
U64 import_size = coff_word_size_from_machine(machine);
COFF_SectionFlags import_align = coff_section_flag_from_align_size(import_size);
COFF_ObjSection *dll_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$2"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align4Bytes, str8_struct(impdesc));
COFF_ObjSection *ilt_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$4"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *iat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$5"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *int_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$6"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, str8_zero());
COFF_ObjSection *dll_name_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$7"), LNK_IDATA_SECTION_FLAGS|COFF_SectionFlag_Align2Bytes, dll_name_cstr);
COFF_ObjSection *biat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$8"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *uiat_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".didat$9"), LNK_IDATA_SECTION_FLAGS|import_align, str8_zero());
COFF_ObjSection *code_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".text$i"), LNK_TEXT_SECTION_FLAGS, str8_zero());
COFF_ObjSection *handle_sect = coff_obj_writer_push_section(obj_writer, str8_lit(".data$h"), LNK_DATA_SECTION_FLAGS, str8_array(handle, handle_size));
COFF_ObjSymbol *dll_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_sect->name, 0, dll_sect);
COFF_ObjSymbol *dll_name_symbol = coff_obj_writer_push_symbol_static(obj_writer, dll_name_sect->name, 0, dll_name_sect);
COFF_ObjSymbol *handle_symbol = coff_obj_writer_push_symbol_static(obj_writer, handle_sect->name, 0, handle_sect);
COFF_ObjSymbol *iat_symbol = coff_obj_writer_push_symbol_static(obj_writer, iat_sect->name, 0, iat_sect);
COFF_ObjSymbol *ilt_symbol = coff_obj_writer_push_symbol_static(obj_writer, ilt_sect->name, 0, ilt_sect);
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: {
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_voff), dll_name_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, module_handle_voff), handle_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, iat_voff), iat_symbol, COFF_Reloc_X64_Addr32Nb);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, name_table_voff), ilt_symbol, COFF_Reloc_X64_Addr32Nb);
} break;
default: { NotImplemented; } break;
}
if (emit_biat) {
COFF_ObjSymbol *biat_symbol = coff_obj_writer_push_symbol_static(obj_writer, biat_sect->name, 0, biat_sect);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, bound_table_voff), biat_symbol, COFF_Reloc_X64_Addr32Nb);
}
if (emit_uiat) {
COFF_ObjSymbol *uiat_symbol = coff_obj_writer_push_symbol_static(obj_writer, uiat_sect->name, 0, uiat_sect);
coff_obj_writer_section_push_reloc(obj_writer, dll_sect, OffsetOf(PE_DelayedImportEntry, unload_table_voff), uiat_symbol, COFF_Reloc_X64_Addr32Nb);
}
// emit tail merge
COFF_ObjSymbol *tail_merge_symbol = 0;
switch (machine) {
case COFF_MachineType_Unknown: {} break;
case COFF_MachineType_X64: { tail_merge_symbol = lnk_emit_tail_merge_thunk_x64(obj_writer, code_sect, dll->name, dll_symbol); } break;
default: { NotImplemented; } break;
}
for (LNK_ImportFunc *func = dll->first_func; func != 0; func = func->next) {
#if 0
LNK_Symbol *import_symbol = func->symbol;
COFF_ParsedArchiveImportHeader import_header = coff_archive_import_from_data(import_symbol->u.coff_import);
// emit thunks
COFF_ObjSymbol *jmp_thunk_symbol = 0;
COFF_ObjSymbol *load_thunk_symbol = 0;
if (import_header.type == COFF_ImportHeader_Code) {
switch (machine) {
case COFF_MachineType_X64: {
String8 iat_symbol_name = push_str8f(obj_writer->arena, "__imp_%S", header->func_name);
coff_obj_writer_push_symbol_undef(obj_writer, iat_symbol_name);
// emit jmp thunk
jmp_thunk_symbol = lnk_emit_indirect_jump_thunk_x64(obj_writer, code_sect, iat_symbol, import_header.func_name);
// emit load thunk
load_thunk_chunk = lnk_emit_load_thunk_x64(code_sect, code_table_chunk, iat_symbol, dll->tail_merge_symbol);
} break;
default: lnk_not_implemented("TODO: support for machine 0x%X", dll->machine); break;
}
}
U64 import_size = coff_word_size_from_machine(machine);
switch (header->import_by) {
case COFF_ImportBy_Ordinal: {
String8 ordinal_data = coff_ordinal_data_from_hint(obj_writer->arena, import_header.machine, import_header.hint_or_ordinal);
str8_list_push(obj_writer->arena, &ilt_sect->data, ordinal_data);
str8_list_push(obj_writer->arena, &iat_sect->data, ordinal_data);
iat_symbol = coff_obj_writer_push_symbol_extern(obj_writer, iat_symbol_name, iat_offset, iat_sect);
if (emit_biat) {
biat_chunk = lnk_section_push_chunk_bss(data_sect, biat_table_chunk, import_size, sort_index);
lnk_section_push_reloc(data_sect, biat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
lnk_section_associate_chunks(data_sect, iat_chunk, biat_chunk);
}
if (emit_uiat) {
uiat_chunk = lnk_section_push_chunk_bss(data_sect, uiat_table_chunk, import_size, sort_index);
lnk_section_push_reloc(data_sect, uiat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
lnk_section_associate_chunks(data_sect, iat_chunk, uiat_chunk);
}
} break;
case COFF_ImportBy_Name: {
// put together name look up entry
String8 int_data = coff_make_import_lookup(data_sect->arena, header->hint_or_ordinal, header->func_name);
LNK_Chunk *int_chunk = lnk_section_push_chunk_data(data_sect, int_table_chunk, int_data, str8_zero());
// create symbol for lookup chunk
String8 int_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.name.delayed", dll->name, header->func_name);
int_symbol = lnk_symbol_table_push_defined_chunk(symtab, int_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, int_chunk, 0, 0, 0);
// dynamic linker patches this voff on DLL load event
ilt_chunk = lnk_section_push_chunk_bss(data_sect, ilt_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, ilt_chunk, "ILT entry (delayed) %S.%S", dll->name, header->func_name);
// patch-in ILT with import voff
lnk_section_push_reloc(data_sect, ilt_chunk, LNK_Reloc_VIRT_OFF_32, 0, int_symbol);
// in the file IAT mirrors ILT, dynamic linker later overwrites it with imported function addresses.
iat_chunk = lnk_section_push_chunk_bss(data_sect, iat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, iat_chunk, "IAT entre (delayed) %S.%S", dll->name, header->func_name);
// associate chunks
lnk_section_associate_chunks(data_sect, iat_chunk, ilt_chunk);
lnk_section_associate_chunks(data_sect, iat_chunk, int_chunk);
// patch-in thunk address
lnk_section_push_reloc(data_sect, iat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
if (imptab->flags & LNK_ImportTableFlag_EmitBiat) {
biat_chunk = lnk_section_push_chunk_bss(data_sect, biat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, biat_chunk, "%S.biat.%S (delayed)", dll->name, header->func_name);
// patch-in thunk address
lnk_section_push_reloc(data_sect, biat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
}
if (imptab->flags & LNK_ImportTableFlag_EmitUiat) {
uiat_chunk = lnk_section_push_chunk_bss(data_sect, uiat_table_chunk, import_size, sort_index);
lnk_chunk_set_debugf(data_sect->arena, uiat_chunk, "%S.uiat.%S (delayed)", dll->name, header->func_name);
// patch-in thunk address
lnk_section_push_reloc(data_sect, uiat_chunk, LNK_Reloc_ADDR_64, 0, load_thunk_symbol);
}
} break;
case COFF_ImportBy_Undecorate: {
lnk_not_implemented("TODO: COFF_ImportBy_Undecorate");
} break;
case COFF_ImportBy_NameNoPrefix: {
lnk_not_implemented("TODO: COFF_ImportBy_NameNoPrefix");
} break;
}
if (jmp_thunk_chunk) {
lnk_section_associate_chunks(data_sect, iat_chunk, jmp_thunk_chunk);
}
if (load_thunk_chunk) {
lnk_section_associate_chunks(data_sect, iat_chunk, load_thunk_chunk);
}
String8 iat_symbol_name = push_str8f(symtab->arena->v[0], "__imp_%S", header->func_name);
LNK_Symbol *iat_symbol = lnk_symbol_table_push_defined_chunk(symtab, iat_symbol_name, LNK_DefinedSymbolVisibility_Extern, 0, iat_chunk, 0, 0, 0);
String8 ilt_symbol_name = push_str8f(symtab->arena->v[0], "%S.%S.ilt.delayed", dll->name, header->func_name);
LNK_Symbol *ilt_symbol = lnk_symbol_table_push_defined_chunk(symtab, ilt_symbol_name, LNK_DefinedSymbolVisibility_Internal, 0, ilt_chunk, 0, 0, 0);
#endif
}
return str8_zero();
}
internal String8Array
lnk_make_import_dlls_static(Arena *arena, LNK_ImportTable *imptab, COFF_MachineType machine, String8 image_name)
{
String8Array objs = {0};
if (imptab->dll_count) {
objs.v = push_array(arena, String8, imptab->dll_count + 3);
// make objs for each DLL
for (LNK_ImportDLL *dll = imptab->first_dll; dll != 0; dll = dll->next) {
objs.v[objs.count++] = lnk_obj_from_import_dll_static(arena, machine, dll);
}
// make null terminator objs
objs.v[objs.count++] = lnk_build_import_entry_obj(arena, image_name, COFF_TimeStamp_Max, machine);
objs.v[objs.count++] = lnk_build_null_import_descriptor_obj(arena, COFF_TimeStamp_Max, machine);
objs.v[objs.count++] = lnk_build_null_thunk_data_obj(arena, image_name, COFF_TimeStamp_Max, machine);
}
return objs;
}
internal String8Array
lnk_make_import_dlls_delayed(Arena *arena, LNK_ImportTable *imptab, COFF_MachineType machine, String8 image_name, B32 emit_biat, B32 emit_uiat)
{
String8Array objs = {0};
if (imptab->dll_count) {
objs.v = push_array(arena, String8, imptab->dll_count + 3);
// make objs for each DLL
for (LNK_ImportDLL *dll = imptab->first_dll; dll != 0; dll = dll->next) {
objs.v[objs.count++] = lnk_obj_from_import_dll_delayed(arena, machine, dll, emit_biat, emit_uiat);
}
// make null terminator objs
objs.v[objs.count++] = lnk_build_import_entry_obj(arena, image_name, COFF_TimeStamp_Max, machine);
objs.v[objs.count++] = lnk_build_null_import_descriptor_obj(arena, COFF_TimeStamp_Max, machine);
objs.v[objs.count++] = lnk_build_null_thunk_data_obj(arena, image_name, COFF_TimeStamp_Max, machine);
}
return objs;
}
+19 -41
View File
@@ -3,15 +3,10 @@
#pragma once
#define LNK_IMPORT_DLL_HASH_TABLE_BUCKET_COUNT 512
#define LNK_IMPORT_FUNC_HASH_TABLE_BUCKET_COUNT 2048
typedef struct LNK_ImportFunc
{
struct LNK_ImportFunc *next;
String8 name;
String8 thunk_symbol_name;
String8 iat_symbol_name;
struct LNK_Symbol *symbol;
} LNK_ImportFunc;
typedef struct LNK_ImportDLL
@@ -19,55 +14,38 @@ typedef struct LNK_ImportDLL
struct LNK_ImportDLL *next;
struct LNK_ImportFunc *first_func;
struct LNK_ImportFunc *last_func;
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;
HashTable *func_ht;
} LNK_ImportDLL;
enum
{
LNK_ImportTableFlag_Delayed = (1 << 0),
LNK_ImportTableFlag_EmitBiat = (1 << 1),
LNK_ImportTableFlag_EmitUiat = (1 << 2),
};
typedef U32 LNK_ImportTableFlags;
typedef struct LNK_ImportTable
{
Arena *arena;
COFF_MachineType machine;
LNK_ImportDLL *first_dll;
LNK_ImportDLL *last_dll;
LNK_ImportTableFlags flags;
HashTable *dll_ht;
Arena *arena;
LNK_ImportDLL *first_dll;
LNK_ImportDLL *last_dll;
U64 dll_count;
HashTable *dll_ht;
} LNK_ImportTable;
////////////////////////////////
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, 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 LNK_ImportTable * lnk_import_table_alloc(void);
internal void lnk_import_table_release(LNK_ImportTable **imptab_ptr);
internal LNK_ImportDLL * lnk_import_table_push_dll(LNK_ImportTable *imptab, String8 dll_name, COFF_MachineType machine);
internal LNK_ImportDLL * lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 dll_name);
internal LNK_ImportFunc * lnk_import_table_push_func(LNK_ImportTable *imptab, LNK_ImportDLL *dll, struct LNK_Symbol *symbol);
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 COFF_ObjSymbol * lnk_emit_tail_merge_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, String8 dll_name, COFF_ObjSymbol *dll_import_descriptor);
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);
internal void lnk_emit_dll_import_debug_symbols(COFF_ObjWriter *obj_writer, String8 dll_name);
internal String8 lnk_obj_from_import_dll_static(Arena *arena, COFF_MachineType machine, LNK_ImportDLL *dll);
internal String8 lnk_obj_from_import_dll_delayed(Arena *arena, COFF_MachineType machine, LNK_ImportDLL *dll, B32 emit_biat, B32 emit_uiat);
internal String8Array lnk_make_import_dlls_static(Arena *arena, LNK_ImportTable *imptab, COFF_MachineType machine, String8 image_name);
internal String8Array lnk_make_import_dlls_delayed(Arena *arena, LNK_ImportTable *imptab, COFF_MachineType machine, String8 image_name, B32 emit_biat, B32 emit_uiat);
+4 -12
View File
@@ -131,13 +131,9 @@ lnk_list_from_input_import_arr(LNK_InputImport **arr, U64 count)
int
lnk_input_import_is_before(void *raw_a, void *raw_b)
{
LNK_InputImport **a = raw_a;
LNK_InputImport **b = raw_b;
int cmp = str8_compar_ignore_case(&(*a)->import_header.dll_name, &(*b)->import_header.dll_name);
if (cmp == 0) {
cmp = str8_compar_case_sensitive(&(*a)->import_header.func_name, &(*b)->import_header.func_name);
}
return cmp < 0;
LNK_InputImport *a = *(LNK_InputImport **)raw_a;
LNK_InputImport *b = *(LNK_InputImport **)raw_b;
return a->input_idx < b->input_idx;
}
int
@@ -145,10 +141,6 @@ lnk_input_import_compar(const void *raw_a, const void *raw_b)
{
LNK_InputImport * const *a = raw_a;
LNK_InputImport * const *b = raw_b;
int cmp = str8_compar_ignore_case(&(*a)->import_header.dll_name, &(*b)->import_header.dll_name);
if (cmp == 0) {
cmp = str8_compar_case_sensitive(&(*a)->import_header.func_name, &(*b)->import_header.func_name);
}
return cmp;
return u64_compar(&(*a)->input_idx, &(*b)->input_idx);
}
+3 -1
View File
@@ -16,8 +16,9 @@ typedef String8List LNK_InputLibList;
typedef struct LNK_InputImport
{
COFF_ParsedArchiveImportHeader import_header;
struct LNK_InputImport *next;
String8 coff_import;
U64 input_idx;
} LNK_InputImport;
typedef struct LNK_InputImportList
@@ -36,6 +37,7 @@ typedef struct LNK_InputObj
String8 path;
String8 data;
String8 lib_path;
U64 input_idx;
} LNK_InputObj;
typedef struct LNK_InputObjList
+1 -1
View File
@@ -85,7 +85,7 @@ lnk_get_first_section_contrib(LNK_Section *sect)
{
if (sect->contribs.chunk_count > 0) {
if (sect->contribs.first->count > 0) {
return &sect->contribs.first->v[0];
return sect->contribs.first->v[0];
}
}
return 0;
+1
View File
@@ -38,6 +38,7 @@ typedef struct LNK_Symbol
union {
LNK_SymbolDefined defined;
LNK_SymbolLib lib;
String8 coff_import;
LNK_SymbolUndefined undef;
} u;
} LNK_Symbol;