mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-07 06:18:42 +00:00
WIP switching to creating import table objs
This commit is contained in:
committed by
Ryan Fleury
parent
1b21d0709f
commit
69d5010245
+46
-87
@@ -960,21 +960,29 @@ lnk_push_linker_symbols(Arena *arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
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
|
// 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);
|
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
|
||||||
|
|
||||||
switch (member_type) {
|
switch (member_type) {
|
||||||
case COFF_DataType_Null: break;
|
case COFF_DataType_Null: break;
|
||||||
case COFF_DataType_Import: {
|
case COFF_DataType_Import: {
|
||||||
LNK_InputImport *input = lnk_input_import_list_push(arena, input_import_list);
|
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;
|
} break;
|
||||||
case COFF_DataType_BigObj:
|
case COFF_DataType_BigObj:
|
||||||
case COFF_DataType_Obj: {
|
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
|
// obj path in thin archive has slash appended which screws up
|
||||||
// file lookup on disk; it couble be there to enable paths to symbols
|
// 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
|
// 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) {
|
if (is_thin) {
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
String8List obj_path_list = {0};
|
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);
|
str8_list_push(scratch.arena, &obj_path_list, obj_path);
|
||||||
obj_path = str8_path_list_join_by_style(arena, &obj_path_list, path_style);
|
obj_path = str8_path_list_join_by_style(arena, &obj_path_list, path_style);
|
||||||
scratch_end(scratch);
|
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);
|
LNK_InputObj *input = lnk_input_obj_list_push(arena, input_obj_list);
|
||||||
input->is_thin = is_thin;
|
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->path = obj_path;
|
||||||
input->data = member_info.data;
|
input->data = member_info.data;
|
||||||
input->lib_path = symbol->lib->path;
|
input->lib_path = lib->path;
|
||||||
|
input->input_idx = input_idx;
|
||||||
} break;
|
} 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;
|
COFF_SectionFlags flags = sect_header->flags & ~COFF_SectionFlags_LnkFlags;
|
||||||
LNK_Section *sect = lnk_section_table_search(sectab, sect_name, flags);
|
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;
|
data_n->string = sect_data;
|
||||||
|
|
||||||
// fill out contrib
|
// 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;
|
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
|
internal
|
||||||
@@ -3591,8 +3559,8 @@ lnk_run(int argc, char **argv)
|
|||||||
// state
|
// state
|
||||||
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
|
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
|
||||||
LNK_SectionTable *sectab = 0;
|
LNK_SectionTable *sectab = 0;
|
||||||
LNK_ImportTable *imptab_static = lnk_import_table_alloc(0);
|
LNK_ImportTable *imptab_static = lnk_import_table_alloc();
|
||||||
LNK_ImportTable *imptab_delayed = lnk_import_table_alloc(config->import_table_flags);
|
LNK_ImportTable *imptab_delayed = lnk_import_table_alloc();
|
||||||
LNK_ObjList obj_list = {0};
|
LNK_ObjList obj_list = {0};
|
||||||
LNK_LibList lib_index[LNK_InputSource_Count] = {0};
|
LNK_LibList lib_index[LNK_InputSource_Count] = {0};
|
||||||
Arena *ht_arena = arena_alloc();
|
Arena *ht_arena = arena_alloc();
|
||||||
@@ -3681,51 +3649,27 @@ lnk_run(int argc, char **argv)
|
|||||||
case State_InputImports: {
|
case State_InputImports: {
|
||||||
ProfBegin("Input Imports");
|
ProfBegin("Input Imports");
|
||||||
for (LNK_InputImport *input = input_import_list.first; input != 0; input = input->next) {
|
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)",
|
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));
|
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) {
|
|
||||||
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 *thunk_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
|
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;
|
thunk_symbol->type = LNK_Symbol_Import;
|
||||||
|
thunk_symbol->name = import_header.func_name;
|
||||||
|
thunk_symbol->u.coff_import = input->coff_import;
|
||||||
|
|
||||||
LNK_Symbol *iat_symbol = push_array(symtab->arena->v[0], LNK_Symbol, 1);
|
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;
|
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_table_push(symtab, thunk_symbol);
|
lnk_symbol_table_push(symtab, thunk_symbol);
|
||||||
lnk_symbol_table_push(symtab, iat_symbol);
|
lnk_symbol_table_push(symtab, iat_symbol);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// reset input
|
// reset input
|
||||||
MemoryZeroStruct(&input_import_list);
|
MemoryZeroStruct(&input_import_list);
|
||||||
@@ -4235,6 +4179,7 @@ lnk_run(int argc, char **argv)
|
|||||||
if (input_import_list.count) {
|
if (input_import_list.count) {
|
||||||
ProfBegin("Build Import Table");
|
ProfBegin("Build Import Table");
|
||||||
|
|
||||||
|
// warn about unused delayloads
|
||||||
if (config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll) {
|
if (config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll) {
|
||||||
if (imptab_delayed) {
|
if (imptab_delayed) {
|
||||||
for (String8Node *node = config->delay_load_dll_list.first; node != 0; node = node->next) {
|
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);
|
// make and input static imports
|
||||||
LNK_InputObjList delayed_imports = lnk_import_table_serialize(scratch.arena, imptab_delayed, str8_skip_last_slash(config->image_name), config->machine);
|
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);
|
// make and input delayed imports
|
||||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &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();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 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);
|
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 ------------------------------------------------------------------
|
// --- Logger ------------------------------------------------------------------
|
||||||
|
|
||||||
internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab);
|
internal void lnk_log_link_stats(LNK_ObjList obj_list, LNK_LibList *lib_index, LNK_SectionTable *sectab);
|
||||||
|
|||||||
@@ -1019,9 +1019,9 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
|||||||
} else {
|
} else {
|
||||||
String8 value = value_strings.first->string;
|
String8 value = value_strings.first->string;
|
||||||
if (str8_match_lit("unload", value, StringMatchFlag_CaseInsensitive)) {
|
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)) {
|
} else if (str8_match_lit("nobind", value, StringMatchFlag_CaseInsensitive)) {
|
||||||
config->flags &= ~LNK_ImportTableFlag_EmitBiat;
|
config->import_table_emit_biat = 0;
|
||||||
} else {
|
} else {
|
||||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, cmd_switch, "unknown parameter \"%S\"", value);
|
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;
|
} break;
|
||||||
|
|
||||||
case LNK_CmdSwitch_Rad_DelayBind: {
|
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;
|
} break;
|
||||||
|
|
||||||
case LNK_CmdSwitch_Rad_DoMerge: {
|
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
|
// don't emit bind table with /ALLOWBIND:NO
|
||||||
if (config->dll_characteristics & PE_DllCharacteristic_NO_BIND) {
|
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
|
// set flags for /OPT
|
||||||
|
|||||||
@@ -289,7 +289,8 @@ typedef struct LNK_Config
|
|||||||
LNK_SwitchState opt_icf;
|
LNK_SwitchState opt_icf;
|
||||||
LNK_SwitchState opt_lbr;
|
LNK_SwitchState opt_lbr;
|
||||||
U64 opt_iter_count;
|
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_GuardFlags guard_flags;
|
||||||
LNK_DebugInfoGuidType guid_type;
|
LNK_DebugInfoGuidType guid_type;
|
||||||
Guid guid;
|
Guid guid;
|
||||||
|
|||||||
@@ -403,4 +403,49 @@ lnk_make_edata_obj(Arena *arena,
|
|||||||
return obj;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 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_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 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);
|
||||||
|
|||||||
+334
-436
@@ -2,17 +2,12 @@
|
|||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
internal LNK_ImportTable *
|
internal LNK_ImportTable *
|
||||||
lnk_import_table_alloc(LNK_ImportTableFlags flags)
|
lnk_import_table_alloc(void)
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
|
||||||
|
|
||||||
Arena *arena = arena_alloc();
|
Arena *arena = arena_alloc();
|
||||||
LNK_ImportTable *imptab = push_array(arena, LNK_ImportTable, 1);
|
LNK_ImportTable *imptab = push_array(arena, LNK_ImportTable, 1);
|
||||||
imptab->arena = arena;
|
imptab->arena = arena;
|
||||||
imptab->flags = flags;
|
imptab->dll_ht = hash_table_init(arena, 512);
|
||||||
imptab->dll_ht = hash_table_init(arena, LNK_IMPORT_DLL_HASH_TABLE_BUCKET_COUNT);
|
|
||||||
|
|
||||||
ProfEnd();
|
|
||||||
return imptab;
|
return imptab;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,381 +20,37 @@ lnk_import_table_release(LNK_ImportTable **imptab_ptr)
|
|||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal BucketNode *
|
internal LNK_ImportDLL *
|
||||||
lnk_import_table_push_dll_node(LNK_ImportTable *imptab, LNK_ImportDLL *dll)
|
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
|
// update list
|
||||||
SLLQueuePush(imptab->first_dll, imptab->last_dll, dll);
|
SLLQueuePush(imptab->first_dll, imptab->last_dll, dll);
|
||||||
|
|
||||||
// update name -> dll hash table
|
// 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;
|
return dll;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LNK_ImportDLL *
|
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();
|
LNK_ImportDLL *dll = 0;
|
||||||
|
hash_table_search_string_raw(imptab->dll_ht, dll_name, &dll);
|
||||||
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();
|
|
||||||
return dll;
|
return dll;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LNK_ImportFunc *
|
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);
|
LNK_ImportFunc *func = push_array(imptab->arena, LNK_ImportFunc, 1);
|
||||||
func->name = push_str8_copy(imptab->arena, header->func_name);
|
func->symbol = symbol;
|
||||||
func->thunk_symbol_name = push_str8_copy(imptab->arena, jmp_thunk_symbol->name);
|
|
||||||
func->iat_symbol_name = iat_symbol_name;
|
|
||||||
|
|
||||||
lnk_import_table_push_func_node(imptab, dll, func);
|
lnk_import_table_push_func_node(imptab, dll, func);
|
||||||
|
|
||||||
ProfEnd();
|
|
||||||
return func;
|
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 *
|
internal COFF_ObjSymbol *
|
||||||
lnk_emit_indirect_jump_thunk_x64(COFF_ObjWriter *obj_writer, COFF_ObjSection *code_sect, COFF_ObjSymbol *iat_symbol, String8 thunk_name)
|
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;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal LNK_InputObjList
|
internal void
|
||||||
lnk_import_table_serialize(Arena *arena, LNK_ImportTable *imptab, String8 image_name, COFF_MachineType machine)
|
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
|
// S_OBJ
|
||||||
String8 obj_data = cv_make_obj_name(temp.arena, dll->name, 0);
|
String8 obj_data = cv_make_obj_name(scratch.arena, dll_name, 0);
|
||||||
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_OBJNAME, obj_data);
|
||||||
|
|
||||||
// S_COMPILE3
|
// S_COMPILE3
|
||||||
String8 comp3_data = lnk_make_linker_compile3(temp.arena, dll->obj_writer->machine);
|
String8 comp3_data = lnk_make_linker_compile3(scratch.arena, obj_writer->machine);
|
||||||
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_COMPILE3, comp3_data);
|
||||||
|
|
||||||
// S_END
|
// S_END
|
||||||
cv_symbol_list_push_data(temp.arena, &symbol_list, CV_SymKind_END, str8_zero());
|
cv_symbol_list_push_data(scratch.arena, &symbol_list, CV_SymKind_END, str8_zero());
|
||||||
|
|
||||||
// TODO: add thunks
|
// TODO: add thunks
|
||||||
|
|
||||||
// serialize symbols
|
// serialize symbols
|
||||||
debug_symbols = lnk_make_debug_s(dll->obj_writer->arena, symbol_list);
|
String8 debug_symbols = lnk_make_debug_s(obj_writer->arena, symbol_list);
|
||||||
|
|
||||||
temp_end(temp);
|
coff_obj_writer_push_section(obj_writer, str8_lit(".debug$S"), LNK_DEBUG_SECTION_FLAGS, debug_symbols);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_end(scratch);
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,15 +3,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define LNK_IMPORT_DLL_HASH_TABLE_BUCKET_COUNT 512
|
|
||||||
#define LNK_IMPORT_FUNC_HASH_TABLE_BUCKET_COUNT 2048
|
|
||||||
|
|
||||||
typedef struct LNK_ImportFunc
|
typedef struct LNK_ImportFunc
|
||||||
{
|
{
|
||||||
struct LNK_ImportFunc *next;
|
struct LNK_ImportFunc *next;
|
||||||
String8 name;
|
struct LNK_Symbol *symbol;
|
||||||
String8 thunk_symbol_name;
|
|
||||||
String8 iat_symbol_name;
|
|
||||||
} LNK_ImportFunc;
|
} LNK_ImportFunc;
|
||||||
|
|
||||||
typedef struct LNK_ImportDLL
|
typedef struct LNK_ImportDLL
|
||||||
@@ -19,55 +14,38 @@ typedef struct LNK_ImportDLL
|
|||||||
struct LNK_ImportDLL *next;
|
struct LNK_ImportDLL *next;
|
||||||
struct LNK_ImportFunc *first_func;
|
struct LNK_ImportFunc *first_func;
|
||||||
struct LNK_ImportFunc *last_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;
|
String8 name;
|
||||||
HashTable *func_ht;
|
|
||||||
} LNK_ImportDLL;
|
} 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
|
typedef struct LNK_ImportTable
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
COFF_MachineType machine;
|
|
||||||
LNK_ImportDLL *first_dll;
|
LNK_ImportDLL *first_dll;
|
||||||
LNK_ImportDLL *last_dll;
|
LNK_ImportDLL *last_dll;
|
||||||
LNK_ImportTableFlags flags;
|
U64 dll_count;
|
||||||
HashTable *dll_ht;
|
HashTable *dll_ht;
|
||||||
} LNK_ImportTable;
|
} LNK_ImportTable;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
internal LNK_ImportTable * lnk_import_table_alloc(LNK_ImportTableFlags flags);
|
internal LNK_ImportTable * lnk_import_table_alloc(void);
|
||||||
internal void lnk_import_table_release(LNK_ImportTable **imptab);
|
internal void lnk_import_table_release(LNK_ImportTable **imptab_ptr);
|
||||||
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(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 dll_name);
|
||||||
internal LNK_ImportDLL * lnk_import_table_search_dll(LNK_ImportTable *imptab, String8 name);
|
internal LNK_ImportFunc * lnk_import_table_push_func(LNK_ImportTable *imptab, LNK_ImportDLL *dll, struct LNK_Symbol *symbol);
|
||||||
|
|
||||||
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 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_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_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_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_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_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
@@ -131,13 +131,9 @@ lnk_list_from_input_import_arr(LNK_InputImport **arr, U64 count)
|
|||||||
int
|
int
|
||||||
lnk_input_import_is_before(void *raw_a, void *raw_b)
|
lnk_input_import_is_before(void *raw_a, void *raw_b)
|
||||||
{
|
{
|
||||||
LNK_InputImport **a = raw_a;
|
LNK_InputImport *a = *(LNK_InputImport **)raw_a;
|
||||||
LNK_InputImport **b = raw_b;
|
LNK_InputImport *b = *(LNK_InputImport **)raw_b;
|
||||||
int cmp = str8_compar_ignore_case(&(*a)->import_header.dll_name, &(*b)->import_header.dll_name);
|
return a->input_idx < b->input_idx;
|
||||||
if (cmp == 0) {
|
|
||||||
cmp = str8_compar_case_sensitive(&(*a)->import_header.func_name, &(*b)->import_header.func_name);
|
|
||||||
}
|
|
||||||
return cmp < 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
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 *a = raw_a;
|
||||||
LNK_InputImport * const *b = raw_b;
|
LNK_InputImport * const *b = raw_b;
|
||||||
int cmp = str8_compar_ignore_case(&(*a)->import_header.dll_name, &(*b)->import_header.dll_name);
|
return u64_compar(&(*a)->input_idx, &(*b)->input_idx);
|
||||||
if (cmp == 0) {
|
|
||||||
cmp = str8_compar_case_sensitive(&(*a)->import_header.func_name, &(*b)->import_header.func_name);
|
|
||||||
}
|
|
||||||
return cmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ typedef String8List LNK_InputLibList;
|
|||||||
|
|
||||||
typedef struct LNK_InputImport
|
typedef struct LNK_InputImport
|
||||||
{
|
{
|
||||||
COFF_ParsedArchiveImportHeader import_header;
|
|
||||||
struct LNK_InputImport *next;
|
struct LNK_InputImport *next;
|
||||||
|
String8 coff_import;
|
||||||
|
U64 input_idx;
|
||||||
} LNK_InputImport;
|
} LNK_InputImport;
|
||||||
|
|
||||||
typedef struct LNK_InputImportList
|
typedef struct LNK_InputImportList
|
||||||
@@ -36,6 +37,7 @@ typedef struct LNK_InputObj
|
|||||||
String8 path;
|
String8 path;
|
||||||
String8 data;
|
String8 data;
|
||||||
String8 lib_path;
|
String8 lib_path;
|
||||||
|
U64 input_idx;
|
||||||
} LNK_InputObj;
|
} LNK_InputObj;
|
||||||
|
|
||||||
typedef struct LNK_InputObjList
|
typedef struct LNK_InputObjList
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ lnk_get_first_section_contrib(LNK_Section *sect)
|
|||||||
{
|
{
|
||||||
if (sect->contribs.chunk_count > 0) {
|
if (sect->contribs.chunk_count > 0) {
|
||||||
if (sect->contribs.first->count > 0) {
|
if (sect->contribs.first->count > 0) {
|
||||||
return §->contribs.first->v[0];
|
return sect->contribs.first->v[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ typedef struct LNK_Symbol
|
|||||||
union {
|
union {
|
||||||
LNK_SymbolDefined defined;
|
LNK_SymbolDefined defined;
|
||||||
LNK_SymbolLib lib;
|
LNK_SymbolLib lib;
|
||||||
|
String8 coff_import;
|
||||||
LNK_SymbolUndefined undef;
|
LNK_SymbolUndefined undef;
|
||||||
} u;
|
} u;
|
||||||
} LNK_Symbol;
|
} LNK_Symbol;
|
||||||
|
|||||||
Reference in New Issue
Block a user