From 55c76db902db6649357e86033db2f6fef59ae4ad Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Thu, 10 Apr 2025 17:06:23 -0700 Subject: [PATCH] handle linker directives in a separate step after obj is initialized, this way we don't need to store directives in obj struct --- src/linker/linker.natvis | 13 ++ src/linker/lnk.c | 271 +++++++++++++++----------- src/linker/lnk_config.c | 356 ++++++++++++++++++---------------- src/linker/lnk_config.h | 17 +- src/linker/lnk_export_table.c | 12 -- src/linker/lnk_export_table.h | 2 - src/linker/lnk_obj.c | 179 +---------------- src/linker/lnk_obj.h | 4 - 8 files changed, 385 insertions(+), 469 deletions(-) diff --git a/src/linker/linker.natvis b/src/linker/linker.natvis index 4b6e5c55..82533c44 100644 --- a/src/linker/linker.natvis +++ b/src/linker/linker.natvis @@ -15,9 +15,22 @@ + + {{count={count} first={first} last={last} }} + + + count + first + next + this + + + + + {{count={count} first={first} last={last} }} diff --git a/src/linker/lnk.c b/src/linker/lnk.c index 2e3f6eb0..235881fd 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -2891,34 +2891,6 @@ lnk_init_section_table(LNK_SymbolTable *symtab, U64 section_virt_off, U64 sect_a return sectab; } -internal LNK_MergeDirectiveList -lnk_init_merge_directive_list(Arena *arena, LNK_ObjList obj_list) -{ - ProfBeginFunction(); - - LNK_MergeDirectiveList result = {0}; - - lnk_merge_directive_list_push(arena, &result, (LNK_MergeDirective){ str8_lit_comp(".xdata") , str8_lit_comp(".rdata") }); - //lnk_merge_directive_list_push(arena, &result, (LNK_MergeDirective){ str8_lit_comp(".tls"), str8_lit_comp(".data") }); - - // collect merge directives from objs - for (LNK_ObjNode *obj_node = obj_list.first; obj_node != 0; obj_node = obj_node->next) { - LNK_Obj *obj = &obj_node->data; - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_Merge].first; dir != 0; dir = dir->next) { - for (String8Node *value_node = dir->value_list.first; value_node != 0; value_node = value_node->next) { - LNK_MergeDirective merge_dir; - if (lnk_parse_merge_directive(value_node->string, &merge_dir)) { lnk_merge_directive_list_push(arena, &result, merge_dir); - } else { - lnk_error_obj(LNK_Warning_IllData, obj, "can't parse merge directive \"%S\"", value_node->string); - } - } - } - } - - ProfEnd(); - return result; -} - internal void lnk_discard_meta_data_sections(LNK_SectionTable *sectab) { @@ -3391,29 +3363,25 @@ lnk_run(int argc, char **argv) ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); + + lnk_init_error_handler(); - LNK_Config *config = lnk_build_config(scratch.arena, argc, argv); - + LNK_Config *config = lnk_build_config(scratch.arena, argc, argv); TP_Context *tp = tp_alloc(scratch.arena, config->worker_count, config->max_worker_count, config->shared_thread_pool_name); TP_Arena *tp_arena = tp_arena_alloc(tp); -#if PROFILE_TELEMETRY - { - String8 cmdl = str8_list_join(scratch.arena, &config->raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") }); - tmMessage(0, TMMF_ICON_NOTE, "Command Line: %.*s", str8_varg(cmdl)); - } -#endif - // 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(tp_arena->v[0], &config->input_list[LNK_Input_Manifest]); - String8List manifest_dep_list = str8_list_copy(scratch.arena, &config->manifest_dependency_list); - LNK_AltNameList alt_name_list = config->alt_name_list; - LNK_InputLibList input_libs[LNK_InputSource_Count] = {0}; - LNK_InputObjList input_obj_list = {0}; - LNK_InputImportList input_import_list = {0}; - LNK_SymbolList input_weak_list = {0}; + 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(tp_arena->v[0], &config->input_list[LNK_Input_Manifest]); + String8List manifest_dep_list = str8_list_copy(scratch.arena, &config->manifest_dependency_list); + LNK_ExportParseList export_symbol_list = config->export_symbol_list; + LNK_MergeDirectiveList merge_list = config->merge_list; + LNK_AltNameList alt_name_list = config->alt_name_list; + LNK_InputLibList input_libs[LNK_InputSource_Count] = {0}; + LNK_InputObjList input_obj_list = {0}; + LNK_InputImportList input_import_list = {0}; + LNK_SymbolList input_weak_list = {0}; // :null_obj lnk_input_obj_list_push(scratch.arena, &input_obj_list); @@ -3427,39 +3395,39 @@ lnk_run(int argc, char **argv) input_libs[LNK_InputSource_Default] = config->input_default_lib_list; // state - LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena); - LNK_SectionTable *sectab = lnk_init_section_table(symtab, config->section_virt_off, config->sect_align, config->file_align); - LNK_ImportTable *imptab_static = 0; - LNK_ImportTable *imptab_delayed = 0; - LNK_ExportTable *exptab = lnk_export_table_alloc(); - Arena *ht_arena = arena_alloc(); - HashTable *disallow_lib_ht = hash_table_init(scratch.arena, 0x100); - HashTable *delay_load_dll_ht = hash_table_init(scratch.arena, 0x100); - HashTable *loaded_lib_ht = hash_table_init(scratch.arena, 0x100); - HashTable *missing_lib_ht = hash_table_init(scratch.arena, 0x100); - HashTable *loaded_obj_ht = hash_table_init(scratch.arena, 0x4000); - LNK_SymbolList lookup_undef_list = {0}; - LNK_SymbolList lookup_weak_list = {0}; - LNK_SymbolList unresolved_undef_list = {0}; - LNK_SymbolList unresolved_weak_list = {0}; - U64 entry_search_attempts = 0; - B32 build_debug_info = lnk_do_debug_info(config); - B32 build_linker_obj = build_debug_info; - B32 build_debug_directory = build_debug_info; - B32 build_res_obj = 1; - B32 discard_meta_data_sections = 1; - B32 merge_sections = !!(config->flags & LNK_ConfigFlag_Merge); - B32 build_cf_guards = 0; // (config->flags != LNK_Guard_NONE); - B32 build_export_table = 1; - B32 build_base_relocs = !(config->flags & LNK_ConfigFlag_Fixed); - B32 report_unresolved_symbols = 1; - B32 check_unused_delay_loads = !!(config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll); - B32 build_imp_lib = config->build_imp_lib; - B32 build_rad_chunk_map = (config->rad_chunk_map == LNK_SwitchState_Yes); - LNK_ObjList obj_list = {0}; - LNK_LibList lib_index[LNK_InputSource_Count] = {0}; - String8 image_data = str8_zero(); - OS_Handle image_write_thread = {0}; + LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena); + LNK_SectionTable *sectab = lnk_init_section_table(symtab, config->section_virt_off, config->sect_align, config->file_align); + LNK_ImportTable *imptab_static = 0; + LNK_ImportTable *imptab_delayed = 0; + LNK_ExportTable *exptab = lnk_export_table_alloc(); + Arena *ht_arena = arena_alloc(); + HashTable *disallow_lib_ht = hash_table_init(scratch.arena, 0x100); + HashTable *delay_load_dll_ht = hash_table_init(scratch.arena, 0x100); + HashTable *loaded_lib_ht = hash_table_init(scratch.arena, 0x100); + HashTable *missing_lib_ht = hash_table_init(scratch.arena, 0x100); + HashTable *loaded_obj_ht = hash_table_init(scratch.arena, 0x4000); + LNK_SymbolList lookup_undef_list = {0}; + LNK_SymbolList lookup_weak_list = {0}; + LNK_SymbolList unresolved_undef_list = {0}; + LNK_SymbolList unresolved_weak_list = {0}; + U64 entry_search_attempts = 0; + B32 build_debug_info = lnk_do_debug_info(config); + B32 build_linker_obj = build_debug_info; + B32 build_debug_directory = build_debug_info; + B32 build_res_obj = 1; + B32 discard_meta_data_sections = 1; + B32 merge_sections = !!(config->flags & LNK_ConfigFlag_Merge); + B32 build_cf_guards = 0; // (config->flags != LNK_Guard_NONE); + B32 build_export_table = 1; + B32 build_base_relocs = !(config->flags & LNK_ConfigFlag_Fixed); + B32 report_unresolved_symbols = 1; + B32 check_unused_delay_loads = !!(config->flags & LNK_ConfigFlag_CheckUnusedDelayLoadDll); + B32 build_imp_lib = config->build_imp_lib; + B32 build_rad_chunk_map = (config->rad_chunk_map == LNK_SwitchState_Yes); + LNK_ObjList obj_list = {0}; + LNK_LibList lib_index[LNK_InputSource_Count] = {0}; + String8 image_data = str8_zero(); + OS_Handle image_write_thread = {0}; // init state machine struct StateList state_list = {0}; @@ -3478,6 +3446,9 @@ lnk_run(int argc, char **argv) if (config->guard_flags != LNK_Guard_None) { state_list_push(scratch.arena, state_list, State_PushLoadConfigUndefSymbol); } + + // default section merges + lnk_merge_directive_list_push(scratch.arena, &merge_list, (LNK_MergeDirective){ str8_lit_comp(".xdata") , str8_lit_comp(".rdata") }); ProfBegin("Image"); // :EndImage ProfBegin("Build"); // :EndBuild @@ -3761,7 +3732,20 @@ lnk_run(int argc, char **argv) } ProfEnd(); - LNK_ObjNodeArray obj_node_arr = lnk_obj_list_push_parallel(tp, tp_arena, &obj_list, sectab, config->function_pad_min, config->machine, unique_obj_input_list.count, input_obj_arr); + 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; } + lnk_log(LNK_Log_InputObj, "[ Obj Input Size %M ]", input_size); + } + + LNK_ObjNodeArray obj_node_arr = lnk_obj_list_push_parallel(tp, + tp_arena, + &obj_list, + sectab, + config->function_pad_min, + config->machine, + unique_obj_input_list.count, + input_obj_arr); // // if the machine was omitted on the command line, derive machine from obj @@ -3774,41 +3758,114 @@ lnk_run(int argc, char **argv) } } } - - ProfBegin("Collect Directives"); - for (U64 i = 0; i < obj_node_arr.count; ++i) { - LNK_Obj *obj = &obj_node_arr.v[i].data; - str8_list_concat_in_place(&include_symbol_list, &obj->include_symbol_list); + ProfBegin("Handle Directives"); + for (U64 obj_idx = 0; obj_idx < obj_node_arr.count; obj_idx += 1) { + LNK_Obj *obj = &obj_node_arr.v[obj_idx].data; - lnk_alt_name_list_concat_in_place(&alt_name_list, &obj->alt_name_list); + LNK_DirectiveInfo directive_info = {0}; + { + COFF_FileHeaderInfo coff_info = coff_file_header_info_from_data(obj->data); + COFF_SectionHeader *coff_section_table = (COFF_SectionHeader *)str8_substr(obj->data, coff_info.section_table_range).str; - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_DisallowLib].first; dir != 0; dir = dir->next) { + String8List drectve_data = {0}; + for (U64 sect_idx = 0; sect_idx < coff_info.section_count_no_null; sect_idx += 1) { + COFF_SectionHeader *sect_header = &coff_section_table[sect_idx]; + if (sect_header->flags & COFF_SectionFlag_LnkInfo) { + String8 sect_name = str8_cstring_capped(sect_header->name, sect_header->name + sizeof(sect_header->name)); + if (str8_match(sect_name, str8_lit(".drectve"), 0)) { + if (sect_header->flags & COFF_SectionFlag_CntUninitializedData) { + lnk_error_obj(LNK_Error_IllData, obj, ".drectve section header has flag COFF_SectionFlag_CntUninitializedData"); + break; + } + if (sect_header->fsize < 3) { + lnk_error_obj(LNK_Error_IllData, obj, "not enough bytes to parse .drectve"); + break; + } + if (sect_header->reloc_count > 0) { + lnk_error_obj(LNK_Error_IllData, obj, ".drectve must not have relocations"); + break; + } + Rng1U64 sect_range = rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize); + str8_list_push(scratch.arena, &drectve_data, str8_substr(obj->data, sect_range)); + } + } + } + + for (String8Node *drectve_n = drectve_data.first; drectve_n != 0; drectve_n = drectve_n->next) { + lnk_parse_msvc_linker_directive(scratch.arena, obj, &directive_info, drectve_n->string); + } + } + + // /EXPORT + { + LNK_ExportParseList obj_exports = {0}; + for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Export].first; dir != 0; dir = dir->next) { + lnk_parse_export_directive(scratch.arena, &obj_exports, dir->value_list, obj->path, obj->lib_path); + } + for (LNK_ExportParse *exp = obj_exports.first; exp != 0; exp = exp->next) { + str8_list_push(scratch.arena, &include_symbol_list, exp->name); + } + lnk_export_parse_list_concat_in_place(&export_symbol_list, &obj_exports); + } + + // /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, &merge_dir)) { + lnk_merge_directive_list_push(scratch.arena, &merge_list, merge_dir); + } else { + lnk_error_obj(LNK_Warning_IllData, obj, "can't parse merge directive \"%S\"", value_n->string); + } + } + } + + // /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); } - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_Entry].first; dir != 0; dir = dir->next) { + // /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) { + String8 *invalid_string = lnk_parse_alt_name_directive_list(scratch.arena, dir->value_list, &alt_name_list); + if (invalid_string) { + lnk_error_obj(LNK_Error_Cmdl, obj, "invalid syntax \"%S\", expected format \"FROM=TO\"", *invalid_string); + } + } + + // /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, obj->lib_path); } - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_SubSystem].first; dir != 0; dir = dir->next) { + // /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, obj->lib_path); } - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_Stack].first; dir != 0; dir = dir->next) { + // /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, obj->lib_path); } } ProfEnd(); - // collect manifest dependencies - String8List obj_dep_list = lnk_collect_manifest_dependency_list(tp, tp_arena, obj_node_arr); - str8_list_concat_in_place(&manifest_dep_list, &obj_dep_list); - - // collect libs for input - LNK_InputLibList lib_list = lnk_collect_default_lib_obj_arr(tp, tp_arena, obj_node_arr); // TODO: put these on temp arena - str8_list_concat_in_place(&input_libs[LNK_InputSource_Obj], &lib_list); - // update symbol table lnk_push_defined_symbols(tp, symtab, obj_node_arr); @@ -3823,14 +3880,6 @@ lnk_run(int argc, char **argv) // reset input objs MemoryZeroStruct(&input_obj_list); - if (lnk_get_log_status(LNK_Log_InputObj)) { - U64 input_size = 0; - for (U64 i = 0; i < obj_node_arr.count; ++i) { - input_size += obj_node_arr.v[i].data.data.size; - } - lnk_log(LNK_Log_InputObj, "[ Obj Input Size %M ]", input_size); - } - ProfEnd(); } break; case State_InputLibs: { @@ -4112,13 +4161,11 @@ lnk_run(int argc, char **argv) case State_BuildExportTable: { ProfBegin("Build Export Table"); - // push exports from command line - for (LNK_ExportParse *exp_parse = config->export_symbol_list.first; exp_parse != 0; exp_parse = exp_parse->next) { + ProfBeginV("Push Exports [Count %u]", export_symbol_list.count); + for (LNK_ExportParse *exp_parse = export_symbol_list.first; exp_parse != 0; exp_parse = exp_parse->next) { lnk_export_table_push_export(exptab, symtab, exp_parse); } - - // push exports from obj directives - lnk_collect_exports_from_obj_directives(exptab, obj_list, symtab); + ProfEnd(); // build export table section lnk_build_edata(exptab, sectab, symtab, config->image_name, config->machine); @@ -4127,7 +4174,6 @@ lnk_run(int argc, char **argv) } break; case State_MergeSections: { ProfBegin("Merge Sections"); - LNK_MergeDirectiveList merge_list = lnk_init_merge_directive_list(scratch.arena, obj_list); lnk_section_table_merge(sectab, merge_list); ProfEnd(); } break; @@ -4564,7 +4610,6 @@ lnk_run(int argc, char **argv) internal void entry_point(CmdLine *cmdline) { - lnk_init_error_handler(); lnk_run(cmdline->argc, cmdline->argv); } diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index 53ad9cda..86862571 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -4,168 +4,163 @@ //////////////////////////////// // Enum <-> String -global read_only struct -{ - LNK_CmdSwitchType type; - char *name; - char *args; - char *desc; -} g_cmd_switch_map[] = { - { LNK_CmdSwitch_Null, "", "", "" }, - { LNK_CmdSwitch_NotImplemented, "NOT_IMPLEMENTED", "", "" }, - { LNK_CmdSwitch_Align, "ALIGN", ":#", "" }, - { LNK_CmdSwitch_AllowBind, "ALLOWBIND", "[:NO]", "" }, - { LNK_CmdSwitch_AllowIsolation, "ALLOWISOLATION", "[:NO]", "" }, - { LNK_CmdSwitch_AlternateName, "ALTERNATENAME", "Creates an a symbol alias \"FROM=TO\"." }, - { LNK_CmdSwitch_AppContainer, "APPCONTAINER", "[:NO]", "" }, - { LNK_CmdSwitch_NotImplemented, "ASSEMBLYDEBUG", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "ASSEMBLYLINKRESOURCE", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "ASSEMBLYMODULE", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "ASSEMBLYRESOURCE", "", "" }, // .NET - { LNK_CmdSwitch_Base, "BASE", "{ADDRESS[,SIZE]|@FILENAME,KEY}", "" }, - { LNK_CmdSwitch_NotImplemented, "CLRIMAGETYPE", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "CLRLOADEROPTIMIZATION","", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "CLRSUPPORTLASTERROR", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "CLRTHREADATTRIBUTE", "", "" }, // .NET - { LNK_CmdSwitch_NotImplemented, "CLRUNMANAGEDCODECHECK","", "" }, // .NET - { LNK_CmdSwitch_Debug, "DEBUG", "[:{FULL|NONE}]", "" }, - { LNK_CmdSwitch_Dump, "DUMP", "", "" }, - { LNK_CmdSwitch_NotImplemented, "DEF", ":FILENAME", "" }, - { LNK_CmdSwitch_DefaultLib, "DEFAULTLIB", ":LIBNAME", "" }, - { LNK_CmdSwitch_Delay, "DELAY", ":{NOBIND|UNLOAD}", "" }, - { LNK_CmdSwitch_DelayLoad, "DELAYLOAD", ":DLL", "" }, - { LNK_CmdSwitch_NotImplemented, "DELAYSIGN", "", "" }, - { LNK_CmdSwitch_NotImplemented, "DEPENDENTLOADFLAG", "", "" }, - { LNK_CmdSwitch_Dll, "DLL", "", "" }, - { LNK_CmdSwitch_NotImplemented, "DRIVER", "", "" }, - { LNK_CmdSwitch_DisallowLib, "DISALLOWLIB", ":LIBRARY", "", }, - { LNK_CmdSwitch_EditAndContinue, "EDITANDCONTINUE", "[:NO]", "" }, - { LNK_CmdSwitch_DynamicBase, "DYNAMICBASE", "[:NO]", "" }, - { LNK_CmdSwitch_NotImplemented, "EMITVOLATILEMETADATA", "", "" }, - { LNK_CmdSwitch_Entry, "ENTRY", ":FUNCTION", "" }, - { LNK_CmdSwitch_Null, "ERRORREPORT", "", "Deprecated starting Windows Vista." }, - { LNK_CmdSwitch_Export, "EXPORT", ":SYMBOL", "" }, - { LNK_CmdSwitch_NotImplemented, "EXPORTADMIN", "", "" }, - { LNK_CmdSwitch_FastFail, "FASTFAIL", "", "Not used." }, - { LNK_CmdSwitch_NotImplemented, "FASTGENPROFILE", "", "" }, - { LNK_CmdSwitch_FailIfMismatch, "FAILIFMISMATCH", "", "" }, - { LNK_CmdSwitch_FileAlign, "FILEALIGN", ":#", "" }, - { LNK_CmdSwitch_Fixed, "FIXED", "[:NO]", "" }, - { LNK_CmdSwitch_NotImplemented, "FORCE", "", "" }, - { LNK_CmdSwitch_FunctionPadMin, "FUNCTIONPADMIN", ":#", "Not Implemented" }, - { LNK_CmdSwitch_NotImplemented, "GUARD", "", "" }, - { LNK_CmdSwitch_GuardSym, "GUARDSYM", "", "", }, - { LNK_CmdSwitch_NotImplemented, "GENPROFILE", "", "" }, - { LNK_CmdSwitch_Heap, "HEAP", "RESERVE[,COMMIT]", "" }, - { LNK_CmdSwitch_HighEntropyVa, "HIGHENTROPYVA", "[:NO]", "" }, - { LNK_CmdSwitch_NotImplemented, "IDLOUT", "", "" }, - { LNK_CmdSwitch_Ignore, "IGNORE", ":#", "" }, - { LNK_CmdSwitch_NotImplemented, "IGNOREIDL", "", "" }, - { LNK_CmdSwitch_NotImplemented, "ILK", "", "" }, - { LNK_CmdSwitch_ImpLib, "IMPLIB", ":FILENAME", "" }, - { LNK_CmdSwitch_Include, "INCLUDE", "", "" }, - { LNK_CmdSwitch_Incremental, "INCREMENTAL", "[:NO]", "Incremental linking is not supported." }, - { LNK_CmdSwitch_NotImplemented, "INTEGRITYCHECK", "", "" }, - { LNK_CmdSwitch_InferAsanLibs, "INFERASANLIBS", "[:NO]", "" }, - { LNK_CmdSwitch_InferAsanLibsNo, "INFERASANLIBSNO", "", "", }, - { LNK_CmdSwitch_NotImplemented, "KERNEL", "", "" }, - { LNK_CmdSwitch_NotImplemented, "KEYCONTAINER", "", "" }, - { LNK_CmdSwitch_NotImplemented, "KEYFILE", "", "" }, - { LNK_CmdSwitch_LargeAddressAware, "LARGEADDRESSAWARE", "[:NO]", "" }, - { LNK_CmdSwitch_Lib, "LIB", "" }, - { LNK_CmdSwitch_LibPath, "LIBPATH", ":DIR", "" }, - { LNK_CmdSwitch_NotImplemented, "LINKERREPO", "", "" }, - { LNK_CmdSwitch_NotImplemented, "LINKERREPOTARGET", "", "" }, - { LNK_CmdSwitch_NotImplemented, "LTCG", "", "" }, - { LNK_CmdSwitch_NotImplemented, "LTCGOUT", "", "" }, - { LNK_CmdSwitch_Machine, "MACHINE", ":{X64|X86}", "" }, - { LNK_CmdSwitch_Manifest, "MANIFEST", "[:{EMBED[,ID=#]|NO]", "" }, - { LNK_CmdSwitch_ManifestDependency, "MANIFESTDEPENDENCY", ":\"manifest dependency XML string\"", "" }, - { LNK_CmdSwitch_ManifestFile, "MANIFESTFILE", ":FILENAME", "" }, - { LNK_CmdSwitch_ManifestInput, "MANIFESTINPUT", ":FILENAME", "" }, - { LNK_CmdSwitch_ManifestUac, "MANIFESTUAC", ":{NO|{'level'={'asInvoker'|'highestAvailable'|'requireAdministrator'} ['uiAccess'={'true'|'false'}]}}", "" }, - { LNK_CmdSwitch_NotImplemented, "MAP", "", "" }, - { LNK_CmdSwitch_NotImplemented, "MAPINFO", "", "" }, - { LNK_CmdSwitch_Merge, "MERGE", ":from=to", "" }, - { LNK_CmdSwitch_NotImplemented, "MIDL", "", "" }, - { LNK_CmdSwitch_Natvis, "NATVIS", ":FILENAME", "" }, - { LNK_CmdSwitch_NotImplemented, "NOASSEMBLY", "", "" }, - { LNK_CmdSwitch_NoDefaultLib, "NODEFAULTLIB", ":LIBNAME", "" }, - { LNK_CmdSwitch_NoDefaultLib, "NOD", ":LIBNAME", "" }, - { LNK_CmdSwitch_NotImplemented, "NOENTRY", "", "" }, - { LNK_CmdSwitch_NoExp, "NOEXP", "", ".exp is not supported." }, - { LNK_CmdSwitch_NoImpLib, "NOIMPLIB", "", "" }, - { LNK_CmdSwitch_NoLogo, "NOLOGO", "", "" }, - { LNK_CmdSwitch_NxCompat, "NXCOMPAT", "[:NO]", "" }, - { LNK_CmdSwitch_Opt, "OPT", "", "" }, - { LNK_CmdSwitch_NotImplemented, "ORDER", "", "" }, - { LNK_CmdSwitch_Out, "OUT", ":FILENAME", "" }, - { LNK_CmdSwitch_Pdb, "PDB", ":FILENAME", "" }, - { LNK_CmdSwitch_PdbAltPath, "PDBALTPATH", "", "" }, - { LNK_CmdSwitch_NotImplemented, "PDBSTRIPPED", "", "" }, - { LNK_CmdSwitch_PdbPageSize, "PDBPAGESIZE", ":#", "Page size must be power of two" }, - { LNK_CmdSwitch_NotImplemented, "PROFILE", "", "" }, - { LNK_CmdSwitch_Release, "RELEASE", "", "" }, - { LNK_CmdSwitch_NotImplemented, "SAFESEH", "", "" }, - { LNK_CmdSwitch_NotImplemented, "SECTION", "", "" }, - { LNK_CmdSwitch_NotImplemented, "SOURCELINK", "", "" }, - { LNK_CmdSwitch_Stack, "STACK", ":RESERVE[,COMMIT]", "" }, - { LNK_CmdSwitch_NotImplemented, "STUB", "", "" }, - { LNK_CmdSwitch_SubSystem, "SUBSYSTEM", ":{CONSOLE|NATIVE|WINDOWS}[,#[.##]]", "" }, - { LNK_CmdSwitch_NotImplemented, "SWAPRUN", "", "" }, - { LNK_CmdSwitch_NotImplemented, "TLBID", "", "" }, - { LNK_CmdSwitch_NotImplemented, "TLBOUT", "", "" }, - { LNK_CmdSwitch_NotImplemented, "TIME", "", "" }, - { LNK_CmdSwitch_TsAware, "TSAWARE", "[:NO]", "" }, - { LNK_CmdSwitch_ThrowingNew, "THROWINGNEW", "", "" }, - { LNK_CmdSwitch_NotImplemented, "USERPROFILE", "", "" }, - { LNK_CmdSwitch_NotImplemented, "VERBOSE", "", "" }, - { LNK_CmdSwitch_Version, "VERSION", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WINMD", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WINMDDELAYSIGN", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WINMDKEYCONTAINER", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WINMDKEYFILE", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WHOLEARCHIVE", "", "" }, - { LNK_CmdSwitch_NotImplemented, "WX", "", "" }, +global read_only LNK_CmdSwitch g_cmd_switch_map[] = { + { LNK_CmdSwitch_Null, 0, "", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "NOT_IMPLEMENTED", "", "" }, + { LNK_CmdSwitch_Align, 0, "ALIGN", ":#", "" }, + { LNK_CmdSwitch_AllowBind, 0, "ALLOWBIND", "[:NO]", "" }, + { LNK_CmdSwitch_AllowIsolation, 0, "ALLOWISOLATION", "[:NO]", "" }, + { LNK_CmdSwitch_AlternateName, 1, "ALTERNATENAME", "Creates an a symbol alias \"FROM=TO\"." }, + { LNK_CmdSwitch_AppContainer, 0, "APPCONTAINER", "[:NO]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYDEBUG", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYLINKRESOURCE", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYMODULE", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "ASSEMBLYRESOURCE", "", "" }, // .NET + { LNK_CmdSwitch_Base, 0, "BASE", "{ADDRESS[,SIZE]|@FILENAME,KEY}", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "CLRIMAGETYPE", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "CLRLOADEROPTIMIZATION","", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "CLRSUPPORTLASTERROR", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "CLRTHREADATTRIBUTE", "", "" }, // .NET + { LNK_CmdSwitch_NotImplemented, 0, "CLRUNMANAGEDCODECHECK","", "" }, // .NET + { LNK_CmdSwitch_Debug, 0, "DEBUG", "[:{FULL|NONE}]", "" }, + { LNK_CmdSwitch_Dump, 0, "DUMP", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "DEF", ":FILENAME", "" }, + { LNK_CmdSwitch_DefaultLib, 1, "DEFAULTLIB", ":LIBNAME", "" }, + { LNK_CmdSwitch_Delay, 0, "DELAY", ":{NOBIND|UNLOAD}", "" }, + { LNK_CmdSwitch_DelayLoad, 0, "DELAYLOAD", ":DLL", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "DELAYSIGN", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "DEPENDENTLOADFLAG", "", "" }, + { LNK_CmdSwitch_Dll, 0, "DLL", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "DRIVER", "", "" }, + { LNK_CmdSwitch_DisallowLib, 1, "DISALLOWLIB", ":LIBRARY", "", }, + { LNK_CmdSwitch_EditAndContinue, 1, "EDITANDCONTINUE", "[:NO]", "" }, + { LNK_CmdSwitch_DynamicBase, 0, "DYNAMICBASE", "[:NO]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "EMITVOLATILEMETADATA", "", "" }, + { LNK_CmdSwitch_Entry, 1, "ENTRY", ":FUNCTION", "" }, + { LNK_CmdSwitch_Null, 0, "ERRORREPORT", "", "Deprecated starting Windows Vista." }, + { LNK_CmdSwitch_Export, 1, "EXPORT", ":SYMBOL", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "EXPORTADMIN", "", "" }, + { LNK_CmdSwitch_FastFail, 0, "FASTFAIL", "", "Not used." }, + { LNK_CmdSwitch_NotImplemented, 0, "FASTGENPROFILE", "", "" }, + { LNK_CmdSwitch_FailIfMismatch, 1, "FAILIFMISMATCH", "", "" }, + { LNK_CmdSwitch_FileAlign, 0, "FILEALIGN", ":#", "" }, + { LNK_CmdSwitch_Fixed, 0, "FIXED", "[:NO]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "FORCE", "", "" }, + { LNK_CmdSwitch_FunctionPadMin, 0, "FUNCTIONPADMIN", ":#", "Not Implemented" }, + { LNK_CmdSwitch_NotImplemented, 0, "GUARD", "", "" }, + { LNK_CmdSwitch_GuardSym, 1, "GUARDSYM", "", "", }, + { LNK_CmdSwitch_NotImplemented, 0, "GENPROFILE", "", "" }, + { LNK_CmdSwitch_Heap, 0, "HEAP", "RESERVE[,COMMIT]", "" }, + { LNK_CmdSwitch_HighEntropyVa, 0, "HIGHENTROPYVA", "[:NO]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "IDLOUT", "", "" }, + { LNK_CmdSwitch_Ignore, 0, "IGNORE", ":#", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "IGNOREIDL", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "ILK", "", "" }, + { LNK_CmdSwitch_ImpLib, 0, "IMPLIB", ":FILENAME", "" }, + { LNK_CmdSwitch_Include, 1, "INCLUDE", "", "" }, + { LNK_CmdSwitch_Incremental, 0, "INCREMENTAL", "[:NO]", "Incremental linking is not supported." }, + { LNK_CmdSwitch_NotImplemented, 0, "INTEGRITYCHECK", "", "" }, + { LNK_CmdSwitch_InferAsanLibs, 1, "INFERASANLIBS", "[:NO]", "" }, + { LNK_CmdSwitch_InferAsanLibsNo, 1, "INFERASANLIBSNO", "", "", }, + { LNK_CmdSwitch_NotImplemented, 0, "KERNEL", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "KEYCONTAINER", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "KEYFILE", "", "" }, + { LNK_CmdSwitch_LargeAddressAware, 0, "LARGEADDRESSAWARE", "[:NO]", "" }, + { LNK_CmdSwitch_Lib, 0, "LIB", "" }, + { LNK_CmdSwitch_LibPath, 0, "LIBPATH", ":DIR", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "LINKERREPO", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "LINKERREPOTARGET", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "LTCG", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "LTCGOUT", "", "" }, + { LNK_CmdSwitch_Machine, 0, "MACHINE", ":{X64|X86}", "" }, + { LNK_CmdSwitch_Manifest, 0, "MANIFEST", "[:{EMBED[,ID=#]|NO]", "" }, + { LNK_CmdSwitch_ManifestDependency, 1, "MANIFESTDEPENDENCY", ":\"manifest dependency XML string\"", "" }, + { LNK_CmdSwitch_ManifestFile, 0, "MANIFESTFILE", ":FILENAME", "" }, + { LNK_CmdSwitch_ManifestInput, 0, "MANIFESTINPUT", ":FILENAME", "" }, + { LNK_CmdSwitch_ManifestUac, 0, "MANIFESTUAC", ":{NO|{'level'={'asInvoker'|'highestAvailable'|'requireAdministrator'} ['uiAccess'={'true'|'false'}]}}", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "MAP", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "MAPINFO", "", "" }, + { LNK_CmdSwitch_Merge, 1, "MERGE", ":from=to", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "MIDL", "", "" }, + { LNK_CmdSwitch_Natvis, 0, "NATVIS", ":FILENAME", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "NOASSEMBLY", "", "" }, + { LNK_CmdSwitch_NoDefaultLib, 1, "NODEFAULTLIB", ":LIBNAME", "" }, + { LNK_CmdSwitch_NoDefaultLib, 0, "NOD", ":LIBNAME", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "NOENTRY", "", "" }, + { LNK_CmdSwitch_NoExp, 0, "NOEXP", "", ".exp is not supported." }, + { LNK_CmdSwitch_NoImpLib, 0, "NOIMPLIB", "", "" }, + { LNK_CmdSwitch_NoLogo, 0, "NOLOGO", "", "" }, + { LNK_CmdSwitch_NxCompat, 0, "NXCOMPAT", "[:NO]", "" }, + { LNK_CmdSwitch_Opt, 0, "OPT", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "ORDER", "", "" }, + { LNK_CmdSwitch_Out, 0, "OUT", ":FILENAME", "" }, + { LNK_CmdSwitch_Pdb, 0, "PDB", ":FILENAME", "" }, + { LNK_CmdSwitch_PdbAltPath, 0, "PDBALTPATH", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "PDBSTRIPPED", "", "" }, + { LNK_CmdSwitch_PdbPageSize, 0, "PDBPAGESIZE", ":#", "Page size must be power of two" }, + { LNK_CmdSwitch_NotImplemented, 0, "PROFILE", "", "" }, + { LNK_CmdSwitch_Release, 1, "RELEASE", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "SAFESEH", "", "" }, + { LNK_CmdSwitch_Section, 1, "SECTION", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "SOURCELINK", "", "" }, + { LNK_CmdSwitch_Stack, 1, "STACK", ":RESERVE[,COMMIT]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "STUB", "", "" }, + { LNK_CmdSwitch_SubSystem, 1, "SUBSYSTEM", ":{CONSOLE|NATIVE|WINDOWS}[,#[.##]]", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "SWAPRUN", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "TLBID", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "TLBOUT", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "TIME", "", "" }, + { LNK_CmdSwitch_TsAware, 0, "TSAWARE", "[:NO]", "" }, + { LNK_CmdSwitch_ThrowingNew, 1, "THROWINGNEW", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "USERPROFILE", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "VERBOSE", "", "" }, + { LNK_CmdSwitch_Version, 0, "VERSION", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WINMD", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WINMDDELAYSIGN", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WINMDKEYCONTAINER", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WINMDKEYFILE", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WHOLEARCHIVE", "", "" }, + { LNK_CmdSwitch_NotImplemented, 0, "WX", "", "" }, //- internal switches - { LNK_CmdSwitch_Rad_Age, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." }, - { LNK_CmdSwitch_Rad_BuildInfo, "RAD_BUILD_INFO", "", "Print build info and exit." }, - { LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" }, - { LNK_CmdSwitch_Rad_ChunkMap, "RAD_CHUNK_MAP", ":FILENAME", "Emit file with the output image's layout description." }, - { LNK_CmdSwitch_Rad_Debug, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." }, - { LNK_CmdSwitch_Rad_DebugAltPath, "RAD_DEBUGALTPATH", "", "" }, - { LNK_CmdSwitch_Rad_DebugName, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." }, - { LNK_CmdSwitch_Rad_DelayBind, "RAD_DELAY_BIND", "[:NO]", "" }, - { LNK_CmdSwitch_Rad_DoMerge, "RAD_DO_MERGE", "[:NO]", "" }, - { LNK_CmdSwitch_Rad_EnvLib, "RAD_ENV_LIB", "[:NO]", "" }, - { LNK_CmdSwitch_Rad_Exe, "RAD_EXE", "[:NO]", "" }, - { LNK_CmdSwitch_Rad_Guid, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" }, - { LNK_CmdSwitch_Rad_LargePages, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." }, - { LNK_CmdSwitch_Rad_LinkVer, "RAD_LINK_VER", ":##,##", "" }, - { LNK_CmdSwitch_Rad_Log, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" }, - { LNK_CmdSwitch_Rad_MtPath, "RAD_MT_PATH", ":EXEPATH", "Exe path to manifest tool, default: " LNK_MANIFEST_MERGE_TOOL_NAME }, - { LNK_CmdSwitch_Rad_OsVer, "RAD_OS_VER", ":##,##", "" }, - { LNK_CmdSwitch_Rad_PageSize, "RAD_PAGE_SIZE", ":#", "Must be power of two." }, - { LNK_CmdSwitch_Rad_PathStyle, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" }, - { LNK_CmdSwitch_Rad_PdbHashTypeNameLength, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." }, - { LNK_CmdSwitch_Rad_PdbHashTypeNameMap, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." }, - { LNK_CmdSwitch_Rad_PdbHashTypeNames, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." }, - { LNK_CmdSwitch_Rad_SectVirtOff, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." }, - { LNK_CmdSwitch_Rad_SharedThreadPool, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" }, - { LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." }, - { LNK_CmdSwitch_Rad_SuppressError, "RAD_SUPPRESS_ERROR", ":#", "" }, - { LNK_CmdSwitch_Rad_SymbolTableCapDefined, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." }, - { LNK_CmdSwitch_Rad_SymbolTableCapInternal, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." }, - { LNK_CmdSwitch_Rad_SymbolTableCapLib, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." }, - { LNK_CmdSwitch_Rad_SymbolTableCapWeak, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." }, - { LNK_CmdSwitch_Rad_TargetOs, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" }, - { LNK_CmdSwitch_Rad_WriteTempFiles, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." }, - { LNK_CmdSwitch_Rad_TimeStamp, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." }, - { LNK_CmdSwitch_Rad_Version, "RAD_VERSION", "", "Print version and exit." }, - { LNK_CmdSwitch_Rad_Workers, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." }, - { LNK_CmdSwitch_Help, "HELP", "", "" }, - { LNK_CmdSwitch_Help, "?", "", "" }, + { LNK_CmdSwitch_Rad_Age, 0, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." }, + { LNK_CmdSwitch_Rad_BuildInfo, 0, "RAD_BUILD_INFO", "", "Print build info and exit." }, + { LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, 0, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" }, + { LNK_CmdSwitch_Rad_ChunkMap, 0, "RAD_CHUNK_MAP", ":FILENAME", "Emit file with the output image's layout description." }, + { LNK_CmdSwitch_Rad_Debug, 0, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." }, + { LNK_CmdSwitch_Rad_DebugAltPath, 0, "RAD_DEBUGALTPATH", "", "" }, + { LNK_CmdSwitch_Rad_DebugName, 0, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." }, + { LNK_CmdSwitch_Rad_DelayBind, 0, "RAD_DELAY_BIND", "[:NO]", "" }, + { LNK_CmdSwitch_Rad_DoMerge, 0, "RAD_DO_MERGE", "[:NO]", "" }, + { LNK_CmdSwitch_Rad_EnvLib, 0, "RAD_ENV_LIB", "[:NO]", "" }, + { LNK_CmdSwitch_Rad_Exe, 0, "RAD_EXE", "[:NO]", "" }, + { LNK_CmdSwitch_Rad_Guid, 0, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" }, + { LNK_CmdSwitch_Rad_LargePages, 0, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." }, + { LNK_CmdSwitch_Rad_LinkVer, 0, "RAD_LINK_VER", ":##,##", "" }, + { LNK_CmdSwitch_Rad_Log, 0, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" }, + { LNK_CmdSwitch_Rad_MtPath, 0, "RAD_MT_PATH", ":EXEPATH", "Exe path to manifest tool, default: " LNK_MANIFEST_MERGE_TOOL_NAME }, + { LNK_CmdSwitch_Rad_OsVer, 0, "RAD_OS_VER", ":##,##", "" }, + { LNK_CmdSwitch_Rad_PageSize, 0, "RAD_PAGE_SIZE", ":#", "Must be power of two." }, + { LNK_CmdSwitch_Rad_PathStyle, 0, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" }, + { LNK_CmdSwitch_Rad_PdbHashTypeNameLength, 0, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." }, + { LNK_CmdSwitch_Rad_PdbHashTypeNameMap, 0, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." }, + { LNK_CmdSwitch_Rad_PdbHashTypeNames, 0, "RAD_PDB_HASH_TYPE_NAMES", ":{NONE|LENIENT|FULL}", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." }, + { LNK_CmdSwitch_Rad_SectVirtOff, 0, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." }, + { LNK_CmdSwitch_Rad_SharedThreadPool, 0, "RAD_SHARED_THREAD_POOL", "[:STRING]", "Default value \"" LNK_DEFAULT_THREAD_POOL_NAME "\"" }, + { LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers, 0, "RAD_SHARED_THREAD_POOL_MAX_WORKERS", ":#", "Sets maximum number of workers in a thread pool." }, + { LNK_CmdSwitch_Rad_SuppressError, 0, "RAD_SUPPRESS_ERROR", ":#", "" }, + { LNK_CmdSwitch_Rad_SymbolTableCapDefined, 0, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." }, + { LNK_CmdSwitch_Rad_SymbolTableCapInternal, 0, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." }, + { LNK_CmdSwitch_Rad_SymbolTableCapLib, 0, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." }, + { LNK_CmdSwitch_Rad_SymbolTableCapWeak, 0, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." }, + { LNK_CmdSwitch_Rad_TargetOs, 0, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" }, + { LNK_CmdSwitch_Rad_WriteTempFiles, 0, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." }, + { LNK_CmdSwitch_Rad_TimeStamp, 0, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." }, + { LNK_CmdSwitch_Rad_Version, 0, "RAD_VERSION", "", "Print version and exit." }, + { LNK_CmdSwitch_Rad_Workers, 0, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024. When /RAD_SHARED_THREAD_POOL is specified this number cant exceed /RAD_SHARED_THREAD_POOL_MAX_WORKERS." }, + + { LNK_CmdSwitch_Help, 0, "HELP", "", "" }, + { LNK_CmdSwitch_Help, 0, "?", "", "" }, }; global read_only struct @@ -213,15 +208,33 @@ lnk_cmd_switch_type_from_string(String8 name) return LNK_CmdSwitch_Null; } -internal String8 -lnk_string_from_cmd_switch_type(LNK_CmdSwitchType type) +internal LNK_CmdSwitch * +lnk_cmd_switch_from_string(String8 name) +{ + for (U64 i = 0; i < ArrayCount(g_cmd_switch_map); i += 1) { + if (str8_match_cstr(g_cmd_switch_map[i].name, name, StringMatchFlag_CaseInsensitive)) { + return &g_cmd_switch_map[i]; + } + } + return 0; +} + +internal LNK_CmdSwitch * +lnk_cmd_switch_from_type(LNK_CmdSwitchType type) { for (U64 cmd_idx = 0; cmd_idx < ArrayCount(g_cmd_switch_map); cmd_idx += 1) { if (g_cmd_switch_map[cmd_idx].type == type) { - return str8_cstring(g_cmd_switch_map[cmd_idx].name); + return &g_cmd_switch_map[cmd_idx]; } } - return str8_zero(); + return 0; +} + +internal String8 +lnk_string_from_cmd_switch_type(LNK_CmdSwitchType type) +{ + LNK_CmdSwitch *cmd_switch = lnk_cmd_switch_from_type(type); + return cmd_switch ? str8_cstring(cmd_switch->name) : str8_zero(); } internal LNK_InputType @@ -784,6 +797,12 @@ lnk_parse_alt_name_directive_list(Arena *arena, String8List list, LNK_AltNameLis return 0; } +internal void +lnk_export_parse_list_concat_in_place(LNK_ExportParseList *list, LNK_ExportParseList *to_concat) +{ + SLLConcatInPlace(list, to_concat); +} + internal LNK_ExportParse * lnk_parse_export_directive(Arena *arena, LNK_ExportParseList *list, String8List value_list, String8 obj_path, String8 lib_path) { @@ -964,7 +983,7 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam lnk_error_with_loc(LNK_Warning_UnknownSwitch, obj_path, lib_path, "unknown switch: \"/%S%s%S\"", cmd_name, value.size ? ":" : "", value); } break; - default: { InvalidPath; } break; + default: break; case LNK_CmdSwitch_NotImplemented: { String8 value = str8_list_join(scratch.arena, &value_strings, &(StringJoin){.sep=str8_lit_comp(",")}); @@ -2096,6 +2115,13 @@ lnk_build_config(Arena *arena, int argc, char **argv) // init config LNK_Config *config = lnk_config_from_cmd_line(arena, raw_cmd_line); +#if PROFILE_TELEMETRY + { + String8 cmdl = str8_list_join(scratch.arena, &config->raw_cmd_line, &(StringJoin){ .sep = str8_lit_comp(" ") }); + tmMessage(0, TMMF_ICON_NOTE, "Command Line: %.*s", str8_varg(cmdl)); + } +#endif + scratch_end(scratch); return config; } diff --git a/src/linker/lnk_config.h b/src/linker/lnk_config.h index 81f64066..60fb1701 100644 --- a/src/linker/lnk_config.h +++ b/src/linker/lnk_config.h @@ -167,6 +167,15 @@ typedef enum LNK_CmdSwitch_Count } LNK_CmdSwitchType; +typedef struct LNK_CmdSwitch +{ + LNK_CmdSwitchType type; + B32 is_legal_directive; + char *name; + char *args; + char *desc; +} LNK_CmdSwitch; + typedef enum { LNK_SwitchState_Null, @@ -233,10 +242,10 @@ typedef struct LNK_AltNameList typedef struct LNK_ExportParse { - struct LNK_ExportParse *next; String8 name; String8 alias; String8 type; + struct LNK_ExportParse *next; } LNK_ExportParse; typedef struct LNK_ExportParseList @@ -265,8 +274,6 @@ typedef struct LNK_MergeDirectiveList LNK_MergeDirectiveNode *last; } LNK_MergeDirectiveList; - - typedef enum { LNK_DebugInfoGuid_Null, @@ -362,6 +369,7 @@ typedef struct LNK_Config String8 rad_debug_alt_path; String8List include_symbol_list; LNK_AltNameList alt_name_list; + LNK_MergeDirectiveList merge_list; U64 symbol_table_cap_defined; U64 symbol_table_cap_internal; U64 symbol_table_cap_weak; @@ -512,7 +520,8 @@ typedef enum // Enum <-> String internal String8 lnk_string_cmd_switch_type(LNK_CmdSwitchType type); -internal LNK_CmdSwitchType lnk_cmd_switch_from_string(String8 string); +internal LNK_CmdSwitchType lnk_cmd_switch_type_from_string(String8 string); +internal LNK_CmdSwitch * lnk_cmd_switch_from_string(String8 string); internal LNK_InputType lnk_input_type_from_string(String8 string); internal LNK_DebugMode lnk_debug_mode_from_string(String8 string); internal LNK_TypeNameHashMode lnk_type_name_hash_mode_from_string(String8 string); diff --git a/src/linker/lnk_export_table.c b/src/linker/lnk_export_table.c index d2beb95e..c8112392 100644 --- a/src/linker/lnk_export_table.c +++ b/src/linker/lnk_export_table.c @@ -287,16 +287,4 @@ exit:; ProfEnd(); } -internal void -lnk_collect_exports_from_obj_directives(LNK_ExportTable *exptab, LNK_ObjList obj_list, LNK_SymbolTable *symtab) -{ - ProfBeginFunction(); - for (LNK_ObjNode *obj_node = obj_list.first; obj_node != 0; obj_node = obj_node->next) { - for (LNK_ExportParse *exp_parse = obj_node->data.export_parse.first; exp_parse != 0; exp_parse = exp_parse->next) { - lnk_export_table_push_export(exptab, symtab, exp_parse); - } - } - ProfEnd(); -} - diff --git a/src/linker/lnk_export_table.h b/src/linker/lnk_export_table.h index 08be801f..e0ccb8ed 100644 --- a/src/linker/lnk_export_table.h +++ b/src/linker/lnk_export_table.h @@ -40,7 +40,5 @@ typedef struct LNK_ExportTable internal LNK_ExportTable * lnk_export_table_alloc(void); internal void lnk_export_table_release(LNK_ExportTable **exptab_ptr); internal LNK_Export * lnk_export_table_search(LNK_ExportTable *exptab, String8 name); -internal void lnk_collect_exports_from_def_files(LNK_ExportTable *exptab, String8List path_list); internal void lnk_build_edata(LNK_ExportTable *exptab, LNK_SectionTable *sectab, LNK_SymbolTable *symtab, String8 image_name, COFF_MachineType machine); -internal void lnk_collect_exports_from_obj_directives(LNK_ExportTable *exptab, LNK_ObjList obj_list, LNK_SymbolTable *symtab); diff --git a/src/linker/lnk_obj.c b/src/linker/lnk_obj.c index 2c305ee7..225f2491 100644 --- a/src/linker/lnk_obj.c +++ b/src/linker/lnk_obj.c @@ -92,42 +92,17 @@ lnk_input_obj_list_from_string_list(Arena *arena, String8List list) //////////////////////////////// internal void -lnk_parse_msvc_linker_directive(Arena *arena, String8 obj_path, String8 lib_path, LNK_DirectiveInfo *directive_info, String8 buffer) +lnk_parse_msvc_linker_directive(Arena *arena, LNK_Obj *obj, LNK_DirectiveInfo *directive_info, String8 buffer) { Temp scratch = scratch_begin(&arena, 1); - local_persist B32 init_table = 1; - local_persist B8 is_legal[LNK_CmdSwitch_Count]; - if (init_table) { - init_table = 0; - is_legal[LNK_CmdSwitch_AlternateName] = 1; - is_legal[LNK_CmdSwitch_DefaultLib] = 1; - is_legal[LNK_CmdSwitch_DisallowLib] = 1; - is_legal[LNK_CmdSwitch_EditAndContinue] = 1; - is_legal[LNK_CmdSwitch_Entry] = 1; - is_legal[LNK_CmdSwitch_Export] = 1; - is_legal[LNK_CmdSwitch_FailIfMismatch] = 1; - is_legal[LNK_CmdSwitch_GuardSym] = 1; - is_legal[LNK_CmdSwitch_Include] = 1; - is_legal[LNK_CmdSwitch_InferAsanLibs] = 1; - is_legal[LNK_CmdSwitch_InferAsanLibsNo] = 1; - is_legal[LNK_CmdSwitch_ManifestDependency] = 1; - is_legal[LNK_CmdSwitch_Merge] = 1; - is_legal[LNK_CmdSwitch_NoDefaultLib] = 1; - is_legal[LNK_CmdSwitch_Release] = 1; - is_legal[LNK_CmdSwitch_Section] = 1; - is_legal[LNK_CmdSwitch_Stack] = 1; - is_legal[LNK_CmdSwitch_SubSystem] = 1; - is_legal[LNK_CmdSwitch_ThrowingNew] = 1; - } - String8 to_parse; { local_persist const U8 bom_sig[] = { 0xEF, 0xBB, 0xBF }; local_persist const U8 ascii_sig[] = { 0x20, 0x20, 0x20 }; if (MemoryMatch(buffer.str, &bom_sig[0], sizeof(bom_sig))) { to_parse = str8_zero(); - lnk_error_with_loc(LNK_Error_IllData, obj_path, lib_path, "TODO: support for BOM encoding"); + lnk_error_obj(LNK_Error_IllData, obj, "TODO: support for BOM encoding"); } else if (MemoryMatch(buffer.str, &ascii_sig[0], sizeof(ascii_sig))) { to_parse = str8_skip(buffer, sizeof(ascii_sig)); } else { @@ -139,23 +114,23 @@ lnk_parse_msvc_linker_directive(Arena *arena, String8 obj_path, String8 lib_path LNK_CmdLine cmd_line = lnk_cmd_line_parse_windows_rules(scratch.arena, arg_list); for (LNK_CmdOption *opt = cmd_line.first_option; opt != 0; opt = opt->next) { - LNK_CmdSwitchType type = lnk_cmd_switch_type_from_string(opt->string); + LNK_CmdSwitch *cmd_switch = lnk_cmd_switch_from_string(opt->string); - if (type == LNK_CmdSwitch_Null) { - lnk_error_with_loc(LNK_Warning_UnknownDirective, obj_path, lib_path, "unknown directive \"%S\"", opt->string); + if (cmd_switch == 0) { + lnk_error_obj(LNK_Warning_UnknownDirective, obj, "unknown directive \"%S\"", opt->string); continue; } - if (!is_legal[type]) { - lnk_error_with_loc(LNK_Warning_IllegalDirective, obj_path, lib_path, "illegal directive \"%S\"", opt->string); + if (!cmd_switch->is_legal_directive) { + lnk_error_obj(LNK_Warning_IllegalDirective, obj, "illegal directive \"%S\"", opt->string); continue; } LNK_Directive *directive = push_array_no_zero(arena, LNK_Directive, 1); directive->next = 0; - directive->id = push_str8_copy(arena, opt->string); + directive->id = str8_cstring(cmd_switch->name); directive->value_list = str8_list_copy(arena, &opt->value_strings); - LNK_DirectiveList *directive_list = &directive_info->v[type]; + LNK_DirectiveList *directive_list = &directive_info->v[cmd_switch->type]; SLLQueuePush(directive_list->first, directive_list->last, directive); ++directive_list->count; } @@ -286,74 +261,6 @@ lnk_run_symbol_collector(TP_Context *tp, TP_Arena *arena, LNK_ObjNodeArray arr, return list; } -internal -THREAD_POOL_TASK_FUNC(lnk_default_lib_collector) -{ - LNK_DefaultLibCollector *task = raw_task; - Rng1U64 range = task->range_arr[task_id]; - String8List *result = &task->out_arr[task_id]; - for (U64 obj_idx = range.min; obj_idx < range.max; obj_idx += 1) { - LNK_Obj *obj = &task->in_arr.v[obj_idx].data; - for (LNK_Directive *dir = obj->directive_info.v[LNK_CmdSwitch_DefaultLib].first; dir != 0; dir = dir->next) { - str8_list_concat_in_place(result, &dir->value_list); - } - } -} - -internal LNK_InputLibList -lnk_collect_default_lib_obj_arr(TP_Context *tp, TP_Arena *arena, LNK_ObjNodeArray arr) -{ - Temp scratch = scratch_begin(0,0); - - LNK_DefaultLibCollector task_data; - task_data.range_arr = tp_divide_work(scratch.arena, arr.count, tp->worker_count); - task_data.in_arr = arr; - task_data.out_arr = push_array(scratch.arena, LNK_InputLibList, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, lnk_default_lib_collector, &task_data); - - String8List result = str8_list_arr_concat(task_data.out_arr, tp->worker_count); - - scratch_end(scratch); - return result; -} - -internal -THREAD_POOL_TASK_FUNC(lnk_manifest_dependency_collector) -{ - LNK_ManifestDependencyCollector *task = raw_task; - Rng1U64 range = task->range_arr[task_id]; - String8List *list = &task->out_arr[task_id]; - - LNK_ObjNode *obj_ptr = &task->in_arr[range.min]; - LNK_ObjNode *obj_opl = &task->in_arr[range.max]; - - for (; obj_ptr < obj_opl; obj_ptr += 1) { - LNK_Obj *obj = &obj_ptr->data; - LNK_DirectiveList *dirs = &obj->directive_info.v[LNK_CmdSwitch_ManifestDependency]; - for (LNK_Directive *dir = dirs->first; dir != 0; dir = dir->next) { - String8List dep = str8_list_copy(arena, &dir->value_list); - str8_list_concat_in_place(list, &dep); - } - } -} - -internal String8List -lnk_collect_manifest_dependency_list(TP_Context *tp, TP_Arena *arena, LNK_ObjNodeArray obj_node_arr) -{ - Temp scratch = scratch_begin(arena->v, arena->count); - - LNK_ManifestDependencyCollector task_data = {0}; - task_data.in_arr = obj_node_arr.v; - task_data.out_arr = push_array(scratch.arena, String8List, tp->worker_count); - task_data.range_arr = tp_divide_work(scratch.arena, obj_node_arr.count, tp->worker_count); - tp_for_parallel(tp, arena, tp->worker_count, lnk_manifest_dependency_collector, &task_data); - - String8List result = str8_list_arr_concat(task_data.out_arr, tp->worker_count); - - scratch_end(scratch); - return result; -} - internal void lnk_sect_defn_list_push_node(LNK_SectDefnList *list, LNK_SectDefn *node) { @@ -437,7 +344,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "corrupted file, unable to read string table"); } - U64 chunk_count = coff_info.section_count_no_null + /* :common_block */ 1; + U64 chunk_count = coff_info.section_count_no_null + /* :common_block */ 1; String8 *sect_name_arr = push_array_no_zero(arena, String8, chunk_count); String8 *sect_sort_arr = push_array_no_zero(arena, String8, chunk_count); LNK_Chunk *chunk_arr = push_array(arena, LNK_Chunk, chunk_count); @@ -543,68 +450,6 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) LNK_SymbolList symbol_list = lnk_symbol_list_from_array(arena, symbol_arr); LNK_RelocList *reloc_list_arr = lnk_reloc_list_array_from_coff(arena, coff_info.machine, input->data, coff_info.section_count_no_null, coff_section_table, chunk_ptr_arr, symbol_arr); - // - // parse directives - // - - String8List drectve_data = {0}; - for (U64 sect_idx = 0; sect_idx < coff_info.section_count_no_null; sect_idx += 1) { - COFF_SectionHeader *sect_header = &coff_section_table[sect_idx]; - - if (sect_header->flags & COFF_SectionFlag_LnkInfo) { - if (str8_match(sect_name_arr[sect_idx], str8_lit(".drectve"), 0)) { - if (sect_header->flags & COFF_SectionFlag_CntUninitializedData) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, ".drectve section header has flag COFF_SectionFlag_CntUninitializedData"); - break; - } - if (sect_header->fsize < 3) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, "not enough bytes to parse .drectve"); - break; - } - if (sect_header->reloc_count > 0) { - lnk_error_with_loc(LNK_Error_IllData, input->path, input->lib_path, ".drectve must not have relocations"); - break; - } - - Rng1U64 sect_range = rng_1u64(sect_header->foff, sect_header->foff + sect_header->fsize); - str8_list_push(scratch.arena, &drectve_data, str8_substr(input->data, sect_range)); - } - } - } - - LNK_DirectiveInfo directive_info = {0}; - for (String8Node *drectve_n = drectve_data.first; drectve_n != 0; drectve_n = drectve_n->next) { - lnk_parse_msvc_linker_directive(arena, input->path, input->lib_path, &directive_info, drectve_n->string); - } - - // parse exports - LNK_ExportParseList export_parse = {0}; - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_Export].first; dir != 0; dir = dir->next) { - lnk_parse_export_directive(arena, &export_parse, dir->value_list, input->path, input->lib_path); - } - - // push /export symbols - for (LNK_ExportParse *exp = export_parse.first; exp != 0; exp = exp->next) { - LNK_Symbol *symbol = lnk_make_undefined_symbol(arena, exp->name, LNK_SymbolScopeFlag_Main); - lnk_symbol_list_push(arena, &symbol_list, symbol); - } - - // push /include symbols - String8List include_symbol_list = {0}; - 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); - } - - // parse /alternatename - LNK_AltNameList alt_name_list = {0}; - for (LNK_Directive *dir = directive_info.v[LNK_CmdSwitch_AlternateName].first; dir != 0; dir = dir->next) { - String8 *invalid_string = lnk_parse_alt_name_directive_list(arena, dir->value_list, &alt_name_list); - if (invalid_string != 0) { - lnk_error_with_loc(LNK_Error_Cmdl, input->path, input->lib_path, "invalid syntax \"%S\", expected format \"FROM=TO\"", *invalid_string); - } - } - - // fill out obj obj->data = input->data; obj->path = push_str8_copy(arena, input->path); @@ -618,10 +463,6 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer) obj->chunk_arr = chunk_ptr_arr; obj->symbol_list = symbol_list; obj->sect_reloc_list_arr = reloc_list_arr; - obj->directive_info = directive_info; - obj->export_parse = export_parse; - obj->include_symbol_list = include_symbol_list; - obj->alt_name_list = alt_name_list; scratch_end(scratch); } diff --git a/src/linker/lnk_obj.h b/src/linker/lnk_obj.h index f7790b54..ca5c48e0 100644 --- a/src/linker/lnk_obj.h +++ b/src/linker/lnk_obj.h @@ -62,10 +62,6 @@ typedef struct LNK_Obj LNK_RelocList *sect_reloc_list_arr; LNK_ChunkPtr *chunk_arr; LNK_SymbolList symbol_list; - LNK_DirectiveInfo directive_info; - LNK_ExportParseList export_parse; - String8List include_symbol_list; - LNK_AltNameList alt_name_list; } LNK_Obj; typedef struct LNK_ObjNode