diff --git a/src/linker/lnk.c b/src/linker/lnk.c index b1583ccc..02938e2a 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -913,48 +913,6 @@ lnk_push_loaded_lib(Arena *arena, HashTable *loaded_lib_ht, String8 path) } } -internal void -lnk_push_export(Arena *arena, HashTable *export_ht, PE_ExportParseList *export_list, String8List *include_symbol_list, PE_ExportParse export_parse) -{ - PE_ExportParseNode *exp_n = 0; - String8 export_name = pe_name_from_export_parse(&export_parse); - hash_table_search_string_raw(export_ht, export_name, &exp_n); - - if (exp_n == 0) { - // make sure export is defined - if (!export_parse.is_forwarder) { - str8_list_push(arena, include_symbol_list, export_parse.name); - } - - // push new export - exp_n = pe_export_parse_list_push(arena, export_list, export_parse); - - hash_table_push_string_raw(arena, export_ht, export_name, exp_n); - } else { - B32 is_ambiguous = 1; - PE_ExportParse *extant_export = &exp_n->data; - - if (extant_export->alias.size && export_parse.alias.size && !str8_match(extant_export->alias, export_parse.alias, 0)) { - goto report; - } - - if (extant_export->ordinal != export_parse.ordinal) { - goto report; - } - - is_ambiguous = 0; - - if (extant_export->alias.size == 0 && export_parse.alias.size != 0) { - extant_export->alias = export_parse.alias; - } - - report:; - if (is_ambiguous) { - lnk_error_with_loc(LNK_Error_IllExport, export_parse.obj_path, export_parse.lib_path, "ambiguous symbol export %S", export_parse.name); - } - } -} - internal String8 lnk_make_linker_obj(Arena *arena, LNK_Config *config) { @@ -1063,6 +1021,10 @@ THREAD_POOL_TASK_FUNC(lnk_undef_symbol_finder) for (U64 symbol_idx = range.min; symbol_idx < range.max; symbol_idx += 1) { LNK_SymbolNode *symbol_n = task->lookup_node_arr.v[symbol_idx]; LNK_Symbol *symbol = symbol_n->data; + + if (str8_match(symbol->name, str8_lit("return_1"), 0)) { + int x = 0; + } LNK_Symbol *has_defn = lnk_symbol_table_search(task->symtab, LNK_SymbolScope_Defined, symbol->name); if (has_defn) { @@ -1217,6 +1179,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) State_InputSymbols, State_InputObjs, State_InputLibs, + State_InputAlternateNames, State_PushDllHelperUndefSymbol, State_InputLinkerObjs, State_PushLoadConfigUndefSymbol, @@ -1239,17 +1202,18 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) Temp scratch = scratch_begin(tp_arena->v, tp_arena->count); // inputs - String8List include_symbol_list = config->include_symbol_list; - String8List input_disallow_lib_list = config->disallow_lib_list; - String8List input_manifest_path_list = str8_list_copy(scratch.arena, &config->input_list[LNK_Input_Manifest]); - String8List manifest_dep_list = str8_list_copy(scratch.arena, &config->manifest_dependency_list); - PE_ExportParseList export_symbol_list = {0}; - HashTable *export_ht = hash_table_init(scratch.arena, max_U16/2); + String8Node **last_include_symbol = &config->include_symbol_list.first; + String8Node **last_disallow_lib = &config->disallow_lib_list.first; + LNK_AltNameNode **last_alt_name = &config->alt_name_list.first; LNK_InputObjList input_obj_list = {0}; LNK_InputImportList input_import_list = {0}; LNK_SymbolList input_weak_list = {0}; - LNK_InputLibList input_libs[LNK_InputSource_Count] = { config->input_list[LNK_Input_Lib], config->input_default_lib_list }; - + LNK_InputLib **input_libs[LNK_InputSource_Count] = { + &config->input_list[LNK_Input_Lib].first, + &config->input_default_lib_list.first, + &config->input_obj_lib_list.first + }; + // input :null_obj { LNK_InputObj *null_obj_input = lnk_input_obj_list_push(scratch.arena, &input_obj_list); @@ -1302,20 +1266,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) if (config->guard_flags != LNK_Guard_None) { state_list_push(scratch.arena, state_list, State_PushLoadConfigUndefSymbol); } - - // - // Push config exports - // - for (PE_ExportParseNode *exp_n = config->export_symbol_list.first; exp_n != 0; exp_n = exp_n->next) { - lnk_push_export(tp_arena->v[0], export_ht, &export_symbol_list, &include_symbol_list, exp_n->data); - } - - // - // Push config alternative names - // - for (LNK_AltNameNode *alt_n = config->alt_name_list.first; alt_n != 0; alt_n = alt_n->next) { - lnk_symbol_table_push_alt_name(symtab, 0, alt_n->data.from, alt_n->data.to); - } // // Run states @@ -1328,16 +1278,11 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) case State_InputDisallowLibs: { ProfBegin("Input /disallowlib"); - - for (String8Node *name_n = input_disallow_lib_list.first; name_n != 0; name_n = name_n->next) { - if ( ! lnk_is_lib_disallowed(disallow_lib_ht, name_n->string)) { - lnk_push_disallow_lib(scratch.arena, disallow_lib_ht, name_n->string); + for (; *last_disallow_lib; last_disallow_lib = &(*last_disallow_lib)->next) { + if ( ! lnk_is_lib_disallowed(disallow_lib_ht, (*last_disallow_lib)->string)) { + lnk_push_disallow_lib(scratch.arena, disallow_lib_ht, (*last_disallow_lib)->string); } } - - // reset input - MemoryZeroStruct(&input_disallow_lib_list); - ProfEnd(); } break; case State_InputImports: { @@ -1396,8 +1341,8 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfBegin("Input Symbols"); ProfBegin("Push /INCLUDE Symbols"); - for (String8Node *include_node = include_symbol_list.first; include_node != 0; include_node = include_node->next) { - String8 name = push_str8_copy(symtab->arena->v[0], include_node->string); + for (; *last_include_symbol; last_include_symbol = &(*last_include_symbol)->next) { + String8 name = push_str8_copy(symtab->arena->v[0], (*last_include_symbol)->string); LNK_Symbol *symbol = lnk_make_undefined_symbol(symtab->arena->v[0], name, 0); lnk_symbol_list_push(scratch.arena, &lookup_undef_list, symbol); } @@ -1409,7 +1354,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) lnk_symbol_list_concat_in_place(&lookup_weak_list, &unresolved_weak_list); // reset inputs - MemoryZeroStruct(&include_symbol_list); MemoryZeroStruct(&input_weak_list); ProfEnd(); @@ -1447,7 +1391,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) LNK_InputObj **thin_inputs = lnk_thin_array_from_input_obj_list(scratch.arena, unique_obj_input_list, &thin_inputs_count); String8Array thin_input_paths = lnk_path_array_from_input_obj_array(scratch.arena, thin_inputs, thin_inputs_count); String8Array thin_input_datas = lnk_read_data_from_file_path_parallel(tp, tp_arena->v[0], config->io_flags, thin_input_paths); - for (U64 thin_input_idx = 0; thin_input_idx < thin_inputs_count; thin_input_idx += 1) { + for EachIndex(thin_input_idx, thin_inputs_count) { thin_inputs[thin_input_idx]->has_disk_read_failed = thin_input_datas.v[thin_input_idx].size == 0; thin_inputs[thin_input_idx]->data = thin_input_datas.v[thin_input_idx]; } @@ -1455,7 +1399,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfBegin("Disk Read Check"); LNK_InputObj **input_obj_arr = lnk_array_from_input_obj_list(scratch.arena, unique_obj_input_list); - for (U64 input_idx = 0; input_idx < unique_obj_input_list.count; ++input_idx) { + for EachIndex(input_idx, unique_obj_input_list.count) { if (input_obj_arr[input_idx]->has_disk_read_failed) { lnk_error(LNK_Error_InvalidPath, "unable to find obj \"%S\"", input_obj_arr[input_idx]->path); } @@ -1464,7 +1408,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) if (lnk_get_log_status(LNK_Log_InputObj)) { U64 input_size = 0; - for (U64 i = 0; i < unique_obj_input_list.count; ++i) { input_size += input_obj_arr[i]->data.size; } + for EachIndex(i, unique_obj_input_list.count) { input_size += input_obj_arr[i]->data.size; } lnk_log(LNK_Log_InputObj, "[ Obj Input Size %M ]", input_size); } @@ -1486,80 +1430,20 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) config->infer_function_pad_min = 0; } - ProfBegin("Handle Directives"); + ProfBegin("Apply Directives"); for EachIndex(obj_idx, obj_node_arr.count) { LNK_Obj *obj = &obj_node_arr.v[obj_idx].data; String8List raw_directives = lnk_raw_directives_from_obj(scratch.arena, obj); LNK_DirectiveInfo directive_info = lnk_directive_info_from_raw_directives(scratch.arena, obj, raw_directives); - - // /EXPORT - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Export].first; dir != 0; dir = dir->next) { - PE_ExportParse export_parse = {0}; - lnk_parse_export_directive_ex(scratch.arena, dir->value_list, obj->path, lnk_obj_get_lib_path(obj), &export_parse); - lnk_push_export(tp_arena->v[0], export_ht, &export_symbol_list, &include_symbol_list, export_parse); - } - - // /INCLUDESYMBOL - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Include].first; dir != 0; dir = dir->next) { - str8_list_concat_in_place(&include_symbol_list, &dir->value_list); - } - - // /MERGE - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Merge].first; dir != 0; dir = dir->next) { - for (String8Node *value_n = dir->value_list.first; value_n != 0; value_n = value_n->next) { - LNK_MergeDirective merge_dir; - if (lnk_parse_merge_directive(value_n->string, obj->path, lnk_obj_get_lib_path(obj), &merge_dir)) { - merge_dir.src = push_str8_copy(tp_arena->v[0], merge_dir.src); - merge_dir.dst = push_str8_copy(tp_arena->v[0], merge_dir.dst); - lnk_merge_directive_list_push(tp_arena->v[0], &config->merge_list, merge_dir); - } + for EachIndex(i, ArrayCount(directive_info.v)) { + for (LNK_Directive *dir = directive_info.v[i].first; dir != 0; dir = dir->next) { + lnk_apply_cmd_option_to_config(tp_arena->v[0], config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); } } - - // /MANIFESTDEPENDENCY - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_ManifestDependency].first; dir != 0; dir = dir->next) { - str8_list_concat_in_place(&manifest_dep_list, &dir->value_list); - } - - // /DISALLOWLIB - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_DisallowLib].first; dir != 0; dir = dir->next) { - str8_list_concat_in_place(&input_disallow_lib_list, &dir->value_list); - } - - // /DEFAULTLIB - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_DefaultLib].first; dir != 0; dir = dir->next) { - str8_list_concat_in_place(&input_libs[LNK_InputSource_Obj], &dir->value_list); - } - - // /ALTERNATENAME - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_AlternateName].first; dir != 0; dir = dir->next) { - for (String8Node *string_n = dir->value_list.first; string_n != 0; string_n = string_n->next) { - LNK_AltName alt_name; - if (lnk_parse_alt_name_directive(string_n->string, obj->path, lnk_obj_get_lib_path(obj), &alt_name)) { - alt_name.from = push_str8_copy(tp_arena->v[0], alt_name.from); - alt_name.to = push_str8_copy(tp_arena->v[0], alt_name.to); - lnk_symbol_table_push_alt_name(symtab, obj, alt_name.from, alt_name.to); - } - } - } - - // /ENTRY - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Entry].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); - } - - // /SUBSYSTEM - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_SubSystem].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); - } - - // /STACK - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Stack].first; dir != 0; dir = dir->next) { - lnk_apply_cmd_option_to_config(scratch.arena, config, dir->id, dir->value_list, obj->path, lnk_obj_get_lib_path(obj)); - } } ProfEnd(); + // input extern symbols from each obj to the symbol table LNK_SymbolInputResult input_result = lnk_input_obj_symbols(tp, tp_arena, symtab, obj_node_arr); // schedule symbol input @@ -1584,12 +1468,11 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfBeginV("Input Source %S", lnk_string_from_input_source(input_source)); Temp temp = temp_begin(scratch.arena); - LNK_InputLibList input_lib_list = input_libs[input_source]; LNK_InputLibList unique_input_lib_list = {0}; ProfBegin("Collect unique input libs"); - for (LNK_InputLib *input = input_lib_list.first; input != 0; input = input->next) { - String8 path = input->string; + for (; *input_libs[input_source] != 0; input_libs[input_source] = &(*input_libs[input_source])->next) { + String8 path = (*input_libs[input_source])->string; if (input_source == LNK_InputSource_Default || input_source == LNK_InputSource_Obj) { if (!str8_ends_with(path, str8_lit(".lib"), StringMatchFlag_CaseInsensitive)) { @@ -1664,21 +1547,33 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfEnd(); } - // reset input libs - MemoryZeroArray(input_libs); - ProfEnd(); } break; + case State_InputAlternateNames: { + for (; *last_alt_name; last_alt_name = &(*last_alt_name)->next) { + lnk_symbol_table_push_alt_name(symtab, 0, (*last_alt_name)->data.from, (*last_alt_name)->data.to); + } + } break; case State_PushDllHelperUndefSymbol: { ProfBegin("Push Dll Helper Undef Symbol"); delay_load_helper_name = mscrt_delay_load_helper_name_from_machine(config->machine); - str8_list_push(scratch.arena, &include_symbol_list, delay_load_helper_name); + + // TODO: config_refactor + String8List value_strings = {0}; + str8_list_push(scratch.arena, &value_strings, delay_load_helper_name); + lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, str8_zero(), str8_zero()); + ProfEnd(); } break; case State_PushLoadConfigUndefSymbol: { ProfBegin("Push Load Config Undef Symbol"); String8 load_config_name = str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME); - str8_list_push(scratch.arena, &include_symbol_list, load_config_name); + + // TODO: config_refactor + String8List value_strings = {0}; + str8_list_push(scratch.arena, &value_strings, load_config_name); + lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, str8_zero(), str8_zero()); + ProfEnd(); } break; case State_LookupUndef: { @@ -1799,7 +1694,10 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) // generate undefined symbol so in case obj is in lib it will be linked if (config->entry_point_name.size) { - str8_list_push(scratch.arena, &include_symbol_list, config->entry_point_name); + // TODO: config_refactor + String8List value_strings = {0}; + str8_list_push(scratch.arena, &value_strings, config->entry_point_name); + lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, str8_zero(), str8_zero()); } // no entry point, error and exit else { @@ -1933,11 +1831,11 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfEnd(); } - if (export_symbol_list.count) { + if (config->export_symbol_list.count) { ProfBegin("Build Export Table"); PE_ExportParseList resolved_exports = {0}; - for (PE_ExportParseNode *exp_n = export_symbol_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) { + for (PE_ExportParseNode *exp_n = config->export_symbol_list.first, *exp_n_next; exp_n != 0; exp_n = exp_n_next) { exp_n_next = exp_n->next; PE_ExportParse *exp = &exp_n->data; @@ -1979,7 +1877,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) // do we have manifest deps passed through pragma alone? LNK_ManifestOpt manifest_opt = config->manifest_opt; - if (manifest_dep_list.node_count > 0 && manifest_opt == LNK_ManifestOpt_Null) { + if (config->manifest_dependency_list.node_count > 0 && manifest_opt == LNK_ManifestOpt_Null) { manifest_opt = LNK_ManifestOpt_Embed; } @@ -1988,7 +1886,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) ProfBegin("Embed Manifest"); // TODO: currently we convert manifest to res and parse res again, this unnecessary instead push manifest // resource to the tree directly - String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list); + String8 manifest_data = lnk_manifest_from_inputs(scratch.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, config->input_list[LNK_Input_Manifest], config->manifest_dependency_list); String8 manifest_res = pe_make_manifest_resource(scratch.arena, *config->manifest_resource_id, manifest_data); str8_list_push(scratch.arena, &res_data_list, manifest_res); str8_list_push(scratch.arena, &res_path_list, str8_lit("* Manifest *")); @@ -1997,14 +1895,14 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) case LNK_ManifestOpt_WriteToFile: { ProfBeginDynamic("Write Manifest To: %.*s", str8_varg(config->manifest_name)); Temp temp = temp_begin(scratch.arena); - String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, input_manifest_path_list, manifest_dep_list); + String8 manifest_data = lnk_manifest_from_inputs(temp.arena, config->io_flags, config->mt_path, config->manifest_name, config->manifest_uac, config->manifest_level, config->manifest_ui_access, config->input_list[LNK_Input_Manifest], config->manifest_dependency_list); lnk_write_data_to_file_path(config->manifest_name, str8_zero(), manifest_data); temp_end(temp); ProfEnd(); } break; case LNK_ManifestOpt_Null: { - Assert(input_manifest_path_list.node_count == 0); - Assert(manifest_dep_list.node_count == 0); + Assert(config->input_list[LNK_Input_Manifest].node_count == 0); + Assert(config->manifest_dependency_list.node_count == 0); } break; case LNK_ManifestOpt_No: { // omit manifest generation @@ -2087,7 +1985,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) } } - if (input_disallow_lib_list.node_count) { + if (*last_disallow_lib != 0) { state_list_push(scratch.arena, state_list, State_InputDisallowLibs); continue; } @@ -2095,7 +1993,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) state_list_push(scratch.arena, state_list, State_InputImports); continue; } - if (input_weak_list.count || include_symbol_list.node_count) { + if (input_weak_list.count || *last_include_symbol != 0) { state_list_push(scratch.arena, state_list, State_InputSymbols); continue; } @@ -2106,7 +2004,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) { B32 have_pending_lib_inputs = 0; for (U64 i = 0; i < ArrayCount(input_libs); ++i) { - if (input_libs[i].node_count) { + if (*input_libs[i] != 0) { have_pending_lib_inputs = 1; break; } @@ -2116,6 +2014,10 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) continue; } } + if (*last_alt_name != 0) { + state_list_push(scratch.arena, state_list, State_InputAlternateNames); + continue; + } if (lookup_undef_list.count) { state_list_push(scratch.arena, state_list, State_LookupUndef); continue; @@ -2177,8 +2079,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config) link_ctx.symtab = symtab; link_ctx.objs_count = obj_list.count; link_ctx.objs = lnk_array_from_obj_list(tp_arena->v[0], obj_list); - link_ctx.export_symbol_list = export_symbol_list; - link_ctx.delay_load_helper_name = delay_load_helper_name; MemoryCopyTyped(&link_ctx.lib_index[0], &lib_index[0], ArrayCount(lib_index)); ProfEnd(); @@ -2242,10 +2142,7 @@ lnk_gc_comdats(TP_Context *tp, U64 objs_count, LNK_Obj **objs, LNK_Symbol ***symlinks, - LNK_Config *config, - PE_ExportParseList export_symbol_list, - String8List include_symbol_list, - String8 delay_load_helper_name) + LNK_Config *config) { ProfBeginFunction(); Temp scratch = scratch_begin(0,0); @@ -2258,27 +2155,7 @@ lnk_gc_comdats(TP_Context *tp, // define roots // { - String8List roots = {0}; - - // entry point - str8_list_push(scratch.arena, &roots, config->entry_point_name); - - // exports - for (PE_ExportParseNode *exp_n = export_symbol_list.first; exp_n != 0; exp_n = exp_n->next) { - PE_ExportParse *exp = &exp_n->data; - str8_list_push(scratch.arena, &roots, exp->name); - } - - // load config - LNK_Symbol *load_config_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, MSCRT_LOAD_CONFIG_SYMBOL_NAME); - if (load_config_symbol) { - str8_list_push(scratch.arena, &roots, load_config_symbol->name); - } - - // delay load helper - if (delay_load_helper_name.size) { - str8_list_push(scratch.arena, &roots, delay_load_helper_name); - } + String8List roots = str8_list_copy(scratch.arena, &config->include_symbol_list); // tls LNK_Symbol *tls_symbol = lnk_symbol_table_searchf(symtab, LNK_SymbolScope_Defined, MSCRT_TLS_SYMBOL_NAME); @@ -2286,9 +2163,6 @@ lnk_gc_comdats(TP_Context *tp, str8_list_pushf(scratch.arena, &roots, MSCRT_TLS_SYMBOL_NAME); } - // include symbols - str8_list_concat_in_place(&roots, &include_symbol_list); - // push tasks for each root symbol for (String8Node *root_n = roots.first; root_n != 0; root_n = root_n->next) { LNK_Symbol *root = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, root_n->string); @@ -3947,9 +3821,6 @@ lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, - PE_ExportParseList export_symbol_list, - String8List include_symbol_list, - String8 delay_load_helper_name, U64 objs_count, LNK_Obj **objs) { @@ -3968,7 +3839,7 @@ lnk_build_image(TP_Arena *arena, // remove unreachable COMDAT sections // if (config->opt_ref == LNK_SwitchState_Yes) { - lnk_gc_comdats(tp, symtab, objs_count, objs, symlinks, config, export_symbol_list, include_symbol_list, delay_load_helper_name); + lnk_gc_comdats(tp, symtab, objs_count, objs, symlinks, config); } // @@ -4880,7 +4751,7 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) // // Image // - LNK_ImageContext image_ctx = lnk_build_image(arena, tp, config, link_ctx.symtab, link_ctx.export_symbol_list, link_ctx.include_symbol_list, link_ctx.delay_load_helper_name, link_ctx.objs_count, link_ctx.objs); + LNK_ImageContext image_ctx = lnk_build_image(arena, tp, config, link_ctx.symtab, link_ctx.objs_count, link_ctx.objs); // Write image in the background LNK_WriteThreadContext *image_write_ctx = push_array(scratch.arena, LNK_WriteThreadContext, 1); @@ -4904,7 +4775,7 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) ProfBegin("Build Import Library"); lnk_timer_begin(LNK_Timer_Lib); String8 linker_debug_symbols = lnk_make_linker_debug_symbols(scratch.arena, config->machine); - String8List lib_list = pe_make_import_lib(arena->v[0], config->machine, config->time_stamp, str8_skip_last_slash(config->image_name), linker_debug_symbols, link_ctx.export_symbol_list); + String8List lib_list = pe_make_import_lib(arena->v[0], config->machine, config->time_stamp, str8_skip_last_slash(config->image_name), linker_debug_symbols, config->export_symbol_list); lnk_write_data_list_to_file_path(config->imp_lib_name, str8_zero(), lib_list); lnk_timer_end(LNK_Timer_Lib); ProfEnd(); diff --git a/src/linker/lnk.h b/src/linker/lnk.h index 815b277e..2f579854 100644 --- a/src/linker/lnk.h +++ b/src/linker/lnk.h @@ -10,9 +10,6 @@ typedef struct LNK_LinkContext LNK_SymbolTable *symtab; U64 objs_count; LNK_Obj **objs; - PE_ExportParseList export_symbol_list; - String8List include_symbol_list; - String8 delay_load_helper_name; LNK_LibList lib_index[LNK_InputSource_Count]; } LNK_LinkContext; @@ -224,7 +221,7 @@ internal LNK_LinkContext lnk_build_link_context(TP_Context *tp, TP_Arena *tp_are internal String8List lnk_build_guard_tables(TP_Context *tp, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, U64 objs_count, LNK_Obj **objs, COFF_MachineType machine, String8 entry_point_name, LNK_GuardFlags guard_flags, B32 emit_suppress_flag); internal String8List lnk_build_base_relocs(TP_Context *tp, TP_Arena *tp_temp, LNK_Config *config, U64 objs_count, LNK_Obj **objs); 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 LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, PE_ExportParseList export_symbol_list, String8List include_symbol_list, String8 delay_load_helper_name, U64 obj_count, LNK_Obj **objs); +internal LNK_ImageContext lnk_build_image(TP_Arena *arena, TP_Context *tp, LNK_Config *config, LNK_SymbolTable *symtab, U64 obj_count, LNK_Obj **objs); // --- Logger ------------------------------------------------------------------ diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index 3eb42ddc..026b7f8d 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -609,6 +609,7 @@ lnk_parse_alt_name_directive(String8 string, String8 obj_path, String8 lib_path, if (pair.node_count == 2) { alt_out->from = pair.first->string; alt_out->to = pair.last->string; + is_parse_ok = 1; } else { lnk_error_cmd_switch(LNK_Error_Cmdl, obj_path, lib_path, LNK_CmdSwitch_AlternateName, "syntax error in \"%S\", expected format \"FROM=TO\"", string); } @@ -1163,7 +1164,11 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam case LNK_CmdSwitch_DefaultLib: { String8List default_lib_list = str8_list_copy(arena, &value_strings); - str8_list_concat_in_place(&config->input_default_lib_list, &default_lib_list); + if (obj_path.size) { + str8_list_concat_in_place(&config->input_obj_lib_list, &default_lib_list); + } else { + str8_list_concat_in_place(&config->input_default_lib_list, &default_lib_list); + } } break; case LNK_CmdSwitch_Delay: { @@ -1190,10 +1195,6 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam config->file_characteristics |= PE_ImageFileCharacteristic_FILE_DLL; } break; - case LNK_CmdSwitch_DisallowLib: { - lnk_not_implemented("TODO: how is this switch different from /nodefaultlib?"); - } break; - case LNK_CmdSwitch_DynamicBase: { lnk_cmd_switch_set_flag_16(obj_path, lib_path, cmd_switch, value_strings, &config->dll_characteristics, PE_DllCharacteristic_DYNAMIC_BASE); } break; @@ -1217,7 +1218,43 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam case LNK_CmdSwitch_Export: { PE_ExportParse export_parse = {0}; if (lnk_parse_export_directive_ex(arena, value_strings, obj_path, lib_path, &export_parse)) { - pe_export_parse_list_push(arena, &config->export_symbol_list, export_parse); + PE_ExportParseNode *exp_n = 0; + String8 export_name = pe_name_from_export_parse(&export_parse); + hash_table_search_string_raw(config->export_ht, export_name, &exp_n); + + if (exp_n == 0) { + // make sure export is defined + if (!export_parse.is_forwarder) { + str8_list_push(arena, &config->include_symbol_list, export_parse.name); + } + + // push new export + exp_n = pe_export_parse_list_push(arena, &config->export_symbol_list, export_parse); + + hash_table_push_string_raw(arena, config->export_ht, export_name, exp_n); + } else { + B32 is_ambiguous = 1; + PE_ExportParse *extant_export = &exp_n->data; + + if (extant_export->alias.size && export_parse.alias.size && !str8_match(extant_export->alias, export_parse.alias, 0)) { + goto report; + } + + if (extant_export->ordinal != export_parse.ordinal) { + goto report; + } + + is_ambiguous = 0; + + if (extant_export->alias.size == 0 && export_parse.alias.size != 0) { + extant_export->alias = export_parse.alias; + } + + report:; + if (is_ambiguous) { + lnk_error_with_loc(LNK_Error_IllExport, export_parse.obj_path, export_parse.lib_path, "ambiguous symbol export %S", export_parse.name); + } + } } } break; @@ -1485,6 +1522,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam str8_list_concat_in_place(&config->natvis_list, &natvis_list); } break; + case LNK_CmdSwitch_DisallowLib: case LNK_CmdSwitch_NoDefaultLib: { if (value_strings.node_count == 0) { config->no_default_libs = 1; @@ -1939,6 +1977,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd config->pdb_hash_type_names = LNK_TypeNameHashMode_None; config->pdb_hash_type_name_length = 8; config->data_dir_count = PE_DataDirectoryIndex_COUNT; + config->export_ht = hash_table_init(scratch.arena, max_U16/2); // process command line switches for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) { diff --git a/src/linker/lnk_config.h b/src/linker/lnk_config.h index a3d806f1..812acd4e 100644 --- a/src/linker/lnk_config.h +++ b/src/linker/lnk_config.h @@ -359,6 +359,7 @@ typedef struct LNK_Config U64 pdb_hash_type_name_length; PE_ExportParseList export_symbol_list; String8List input_list[LNK_Input_Count]; + String8List input_obj_lib_list; String8List input_default_lib_list; String8List disallow_lib_list; String8List delay_load_dll_list; @@ -390,6 +391,7 @@ typedef struct LNK_Config String8 temp_rad_chunk_map_name; String8List remove_sections; LNK_IO_Flags io_flags; + HashTable *export_ht; } LNK_Config; // --- MSVC Error Codes --------------------------------------------------------