mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
handle linker directives in a separate step after obj is initialized,
this way we don't need to store directives in obj struct
This commit is contained in:
committed by
Ryan Fleury
parent
307d3a7f4b
commit
55c76db902
@@ -15,9 +15,22 @@
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="LNK_ExportParseList">
|
||||
<DisplayString>{{count={count} first={first} last={last} }}</DisplayString>
|
||||
<Expand>
|
||||
<LinkedListItems>
|
||||
<Size>count</Size>
|
||||
<HeadPointer>first</HeadPointer>
|
||||
<NextPointer>next</NextPointer>
|
||||
<ValueNode>this</ValueNode>
|
||||
</LinkedListItems>
|
||||
</Expand>
|
||||
</Type>
|
||||
|
||||
<Type Name="LNK_SymbolList">
|
||||
<AlternativeType Name="LNK_SectionList"/>
|
||||
<AlternativeType Name="LNK_ChunkList"/>
|
||||
<AlternativeType Name="LNK_ExportParseList"/>
|
||||
<AlternativeType Name="CV_SymbolList"/>
|
||||
<DisplayString>{{count={count} first={first} last={last} }}</DisplayString>
|
||||
<Expand>
|
||||
|
||||
+158
-113
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+191
-165
@@ -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;
|
||||
}
|
||||
|
||||
+13
-4
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
+10
-169
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user