mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-06 22:08:41 +00:00
changed symbol search logic to run in three steps: undefined, weak,
and anti-dependency weak, allowing linking to proceed only after symbols from previous step are added to the symbol table this solves the problem of anti-dependency symbols because they are searched in libraries if the dependency is unresolved weak symbol
This commit is contained in:
committed by
Nikita Smith
parent
e1786d0a11
commit
1bca83610f
+333
-312
@@ -966,7 +966,7 @@ lnk_make_linker_obj(Arena *arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnk_queue_lib_member_input(Arena *arena,
|
lnk_queue_lib_member_for_input(Arena *arena,
|
||||||
LNK_Config *config,
|
LNK_Config *config,
|
||||||
LNK_Symbol *pull_in_ref,
|
LNK_Symbol *pull_in_ref,
|
||||||
LNK_Symbol *member_symbol,
|
LNK_Symbol *member_symbol,
|
||||||
@@ -1039,16 +1039,10 @@ lnk_queue_lib_member_input(Arena *arena,
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnk_find_refs(Arena *arena,
|
lnk_opt_ref(TP_Context *tp, LNK_SymbolTable *symtab, LNK_Config *config, LNK_ObjList objs)
|
||||||
TP_Context *tp,
|
|
||||||
LNK_SymbolTable *symtab,
|
|
||||||
LNK_Config *config,
|
|
||||||
LNK_ObjList objs,
|
|
||||||
LNK_InputImportList *imports_out,
|
|
||||||
LNK_InputObjList *objs_out)
|
|
||||||
{
|
{
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
Temp scratch = scratch_begin(&arena,1);
|
Temp scratch = scratch_begin(0,0);
|
||||||
|
|
||||||
struct Task { struct Task *next; LNK_Obj *obj; COFF_RelocArray relocs; U32 section_number; };
|
struct Task { struct Task *next; LNK_Obj *obj; COFF_RelocArray relocs; U32 section_number; };
|
||||||
struct Task *task_stack = 0;
|
struct Task *task_stack = 0;
|
||||||
@@ -1099,7 +1093,7 @@ lnk_find_refs(Arena *arena,
|
|||||||
// is section eligible for walking?
|
// is section eligible for walking?
|
||||||
if (lnk_is_coff_section_debug(obj, sect_idx)) { continue; }
|
if (lnk_is_coff_section_debug(obj, sect_idx)) { continue; }
|
||||||
if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; }
|
if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; }
|
||||||
if (config->opt_ref == LNK_SwitchState_Yes && section_header->flags & COFF_SectionFlag_LnkCOMDAT) { continue; }
|
if (section_header->flags & COFF_SectionFlag_LnkCOMDAT) { continue; }
|
||||||
|
|
||||||
// divide relocs and push task for each reloc block
|
// divide relocs and push task for each reloc block
|
||||||
COFF_RelocArray relocs = lnk_coff_reloc_info_from_section_number(obj, section_number);
|
COFF_RelocArray relocs = lnk_coff_reloc_info_from_section_number(obj, section_number);
|
||||||
@@ -1132,87 +1126,31 @@ lnk_find_refs(Arena *arena,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
COFF_ParsedSymbol ref_parsed = lnk_parsed_symbol_from_coff_symbol_idx(ref_symbol.obj, ref_symbol.symbol_idx);
|
COFF_ParsedSymbol ref_parsed = lnk_parsed_symbol_from_coff_symbol_idx(ref_symbol.obj, ref_symbol.symbol_idx);
|
||||||
COFF_SymbolValueInterpType ref_interp = coff_interp_from_parsed_symbol(ref_parsed);
|
COFF_SymbolValueInterpType ref_interp = coff_interp_from_parsed_symbol(ref_parsed);
|
||||||
if (ref_interp == COFF_SymbolValueInterp_Weak) {
|
|
||||||
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
|
|
||||||
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_defined(defn);
|
|
||||||
COFF_SymbolValueInterpType defn_interp = coff_interp_from_parsed_symbol(defn_parsed);
|
|
||||||
if (defn_interp == COFF_SymbolValueInterp_Weak) {
|
|
||||||
LNK_Symbol *member_symbol = 0;
|
|
||||||
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(ref_parsed, ref_symbol.obj->header.is_big_obj);
|
|
||||||
switch (weak_ext->characteristics) {
|
|
||||||
case COFF_WeakExt_NoLibrary: {
|
|
||||||
// NOLIBRARY means weak symbol should be resolved in case where strong definition pulls in lib member.
|
|
||||||
} break;
|
|
||||||
case COFF_WeakExt_AntiDependency:
|
|
||||||
case COFF_WeakExt_SearchLibrary: {
|
|
||||||
member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, ref_parsed.name);
|
|
||||||
} break;
|
|
||||||
case COFF_WeakExt_SearchAlias: {
|
|
||||||
member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, ref_parsed.name);
|
|
||||||
if (member_symbol == 0) {
|
|
||||||
if (str8_match_lit(".weak.", ref_parsed.name, StringMatchFlag_RightSideSloppy)) {
|
|
||||||
// TODO: Clang and MingGW encode extra info in alias
|
|
||||||
//
|
|
||||||
// __attribute__((weak,alias("foo"))) void bar(void);
|
|
||||||
// static void foo() {}
|
|
||||||
//
|
|
||||||
// Clang write these COFF symbols in obj for code above:
|
|
||||||
//
|
|
||||||
// 30 00000000 0000000001 0 FUNC NULL EXTERNAL foo
|
|
||||||
// ...
|
|
||||||
// 33 00000000 UNDEF 1 NULL NULL WEAK_EXTERNAL bar
|
|
||||||
// Tag Index 35, Characteristics SEARCH_ALIAS
|
|
||||||
// 35 00000000 0000000001 0 NULL NULL EXTERNAL .weak.bar.default.foo
|
|
||||||
//
|
|
||||||
// In this case linker needs to parse .weak.bar.default.foo and search for bar and foo as well.
|
|
||||||
Assert("TODO: MinGW weak symbol");
|
|
||||||
} else {
|
|
||||||
COFF_ParsedSymbol tag = lnk_parsed_symbol_from_coff_symbol_idx(ref_symbol.obj, weak_ext->tag_index);
|
|
||||||
member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, tag.name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
default: { NotImplemented; } break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (member_symbol) {
|
LNK_SymbolDefined next_ref = {0};
|
||||||
lnk_queue_lib_member_input(arena, config, defn, member_symbol, imports_out, objs_out);
|
if (ref_interp == COFF_SymbolValueInterp_Regular) {
|
||||||
MemoryZeroStruct(&ref_symbol);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ref_symbol = lnk_resolve_weak_symbol(symtab, ref_symbol);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ref_symbol = defn->u.defined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (ref_interp == COFF_SymbolValueInterp_Undefined) {
|
|
||||||
if (ref_parsed.storage_class == COFF_SymStorageClass_External) {
|
|
||||||
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
|
|
||||||
COFF_ParsedSymbol defn_parsed = lnk_parsed_symbol_from_defined(defn);
|
|
||||||
COFF_SymbolValueInterpType defn_interp = coff_interp_from_parsed_symbol(defn_parsed);
|
|
||||||
|
|
||||||
if (defn_interp == COFF_SymbolValueInterp_Undefined) {
|
|
||||||
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, ref_parsed.name);
|
|
||||||
if (member_symbol) {
|
|
||||||
lnk_queue_lib_member_input(arena, config, defn, member_symbol, imports_out, objs_out);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ref_symbol = defn->u.defined;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (ref_interp == COFF_SymbolValueInterp_Regular) {
|
|
||||||
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(ref_symbol.obj, ref_parsed.section_number);
|
LNK_Symbol *symlink = lnk_obj_get_comdat_symlink(ref_symbol.obj, ref_parsed.section_number);
|
||||||
if (symlink) {
|
if (symlink) {
|
||||||
ref_symbol = symlink->u.defined;
|
ref_symbol = symlink->u.defined;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
} else if (ref_interp == COFF_SymbolValueInterp_Undefined) {
|
||||||
|
if (reloc_parsed.storage_class == COFF_SymStorageClass_External) {
|
||||||
|
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
|
||||||
|
next_ref = defn->u.defined;
|
||||||
|
}
|
||||||
|
} else if (ref_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
|
LNK_Symbol *defn = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, ref_parsed.name);
|
||||||
|
next_ref = defn->u.defined;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (MemoryMatchStruct(&next_ref, &ref_symbol)) {
|
||||||
|
MemoryZeroStruct(&ref_symbol);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ref_symbol = next_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip unresolved symbol
|
// skip unresolved symbol
|
||||||
@@ -1241,8 +1179,8 @@ lnk_find_refs(Arena *arena,
|
|||||||
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(ref_obj, section_number);
|
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(ref_obj, section_number);
|
||||||
|
|
||||||
// is section eligible for walking?
|
// is section eligible for walking?
|
||||||
if (section_header->flags & LNK_SECTION_FLAG_IS_LIVE) { continue; }
|
|
||||||
if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; }
|
if (section_header->flags & COFF_SectionFlag_LnkRemove) { continue; }
|
||||||
|
if (section_header->flags & LNK_SECTION_FLAG_IS_LIVE) { continue; }
|
||||||
if (lnk_is_coff_section_debug(ref_obj, section_number-1)) { continue; }
|
if (lnk_is_coff_section_debug(ref_obj, section_number-1)) { continue; }
|
||||||
|
|
||||||
// mark section
|
// mark section
|
||||||
@@ -1265,12 +1203,42 @@ lnk_find_refs(Arena *arena,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProfBegin("Remove Unreachable Sections");
|
||||||
|
for (LNK_ObjNode *obj_n = objs.first; obj_n != 0; obj_n = obj_n->next) {
|
||||||
|
LNK_Obj *obj = &obj_n->data;
|
||||||
|
for EachIndex(sect_idx, obj->header.section_count_no_null) {
|
||||||
|
U32 section_number = sect_idx+1;
|
||||||
|
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
|
||||||
|
|
||||||
|
if (lnk_is_coff_section_debug(obj, sect_idx)) { continue; }
|
||||||
|
|
||||||
|
// remove unreferenced sections
|
||||||
|
if (~section_header->flags & LNK_SECTION_FLAG_IS_LIVE && section_header->flags & COFF_SectionFlag_LnkCOMDAT) {
|
||||||
|
section_header->flags |= COFF_SectionFlag_LnkRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Reset reserved flag so it does not get propagated to the image sections.
|
||||||
|
// We need to mask out reserved flags when gathering section definitions to actually
|
||||||
|
// prevent propagation.
|
||||||
|
section_header->flags &= ~LNK_SECTION_FLAG_IS_LIVE;
|
||||||
|
|
||||||
|
if (section_header->flags & COFF_SectionFlag_LnkRemove) {
|
||||||
|
for (U32Node *section_number_n = obj->associated_sections[section_number]; section_number_n != 0; section_number_n = section_number_n->next) {
|
||||||
|
U32 section_number = section_number_n->data;
|
||||||
|
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
|
||||||
|
section_header->flags |= COFF_SectionFlag_LnkRemove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProfEnd();
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
THREAD_POOL_TASK_FUNC(lnk_replace_weak_symbols_with_default_symbol_task)
|
THREAD_POOL_TASK_FUNC(lnk_replace_weak_with_default_symbol_task)
|
||||||
{
|
{
|
||||||
LNK_ReplaceWeakSymbolsWithDefaultSymbolTask *task = raw_task;
|
LNK_ReplaceWeakSymbolsWithDefaultSymbolTask *task = raw_task;
|
||||||
LNK_SymbolTable *symtab = task->symtab;
|
LNK_SymbolTable *symtab = task->symtab;
|
||||||
@@ -1280,7 +1248,26 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_symbols_with_default_symbol_task)
|
|||||||
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
||||||
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
|
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
|
||||||
if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
symbol->u.defined = lnk_resolve_weak_symbol(symtab, symbol->u.defined);
|
LNK_SymbolDefined resolve = lnk_resolve_weak_symbol(symtab, symbol->u.defined);
|
||||||
|
COFF_ParsedSymbol resolve_parsed = lnk_parsed_symbol_from_coff_symbol_idx(resolve.obj, resolve.symbol_idx);
|
||||||
|
COFF_SymbolValueInterpType resolve_interp = coff_interp_from_parsed_symbol(resolve_parsed);
|
||||||
|
if (resolve_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
|
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(resolve_parsed, symbol->u.defined.obj->header.is_big_obj);
|
||||||
|
COFF_SymStorageClass storage_class = weak_ext->characteristics == COFF_WeakExt_AntiDependency ? COFF_SymStorageClass_Null : COFF_SymStorageClass_External;
|
||||||
|
if (symbol->u.defined.obj->header.is_big_obj) {
|
||||||
|
COFF_Symbol32 *symbol32 = symbol_parsed.raw_symbol;
|
||||||
|
symbol32->section_number = COFF_Symbol_UndefinedSection;
|
||||||
|
symbol32->value = 0;
|
||||||
|
symbol32->storage_class = storage_class;
|
||||||
|
} else {
|
||||||
|
COFF_Symbol16 *symbol16 = symbol_parsed.raw_symbol;
|
||||||
|
symbol16->section_number = COFF_Symbol_UndefinedSection;
|
||||||
|
symbol16->value = 0;
|
||||||
|
symbol16->storage_class = storage_class;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
symbol->u.defined = resolve;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1288,20 +1275,20 @@ THREAD_POOL_TASK_FUNC(lnk_replace_weak_symbols_with_default_symbol_task)
|
|||||||
internal LNK_LinkContext
|
internal LNK_LinkContext
|
||||||
lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||||
{
|
{
|
||||||
enum State {
|
enum {
|
||||||
State_Null,
|
State_Null,
|
||||||
State_InputDisallowLibs,
|
State_InputDisallowLibs,
|
||||||
State_InputImports,
|
State_InputImports,
|
||||||
State_InputSymbols,
|
State_InputInclude,
|
||||||
State_InputObjs,
|
State_InputObjs,
|
||||||
State_InputLibs,
|
State_InputLibs,
|
||||||
State_InputAlternateNames,
|
State_InputAlternateNames,
|
||||||
State_PushDllHelperUndefSymbol,
|
State_InputDelayLoadDlls,
|
||||||
State_InputLinkerObjs,
|
State_InputLinkerObjs,
|
||||||
State_PushLoadConfigUndefSymbol,
|
State_SearchUndefined,
|
||||||
State_FindRefs,
|
State_SearchWeak,
|
||||||
State_LookupEntryPoint,
|
State_SearchWeakAntiDep,
|
||||||
State_ReportUnresolvedSymbols,
|
State_SearchEntryPoint,
|
||||||
};
|
};
|
||||||
struct StateNode { struct StateNode *next; enum State state; };
|
struct StateNode { struct StateNode *next; enum State state; };
|
||||||
struct StateList { U64 count; struct StateNode *first; struct StateNode *last; };
|
struct StateList { U64 count; struct StateNode *first; struct StateNode *last; };
|
||||||
@@ -1312,75 +1299,68 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
l.count += 1; \
|
l.count += 1; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define state_list_pop(l) (l).first->state; SLLQueuePop((l).first, (l).last); (l).count -= 1
|
#define state_list_pop(l) (l).first->state; SLLQueuePop((l).first, (l).last); (l).count -= 1
|
||||||
|
typedef enum {
|
||||||
|
SearchFlag_Undefined = (1 << 0),
|
||||||
|
SearchFlag_Weak = (1 << 1),
|
||||||
|
SearchFlag_WeakAntiDep = (1 << 2),
|
||||||
|
SearchFlag_All = (SearchFlag_Undefined|SearchFlag_Weak|SearchFlag_WeakAntiDep)
|
||||||
|
} SearchFlags;
|
||||||
|
|
||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
Temp scratch = scratch_begin(tp_arena->v, tp_arena->count);
|
Temp scratch = scratch_begin(tp_arena->v, tp_arena->count);
|
||||||
|
|
||||||
// inputs
|
//
|
||||||
|
// state
|
||||||
|
//
|
||||||
|
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
|
||||||
String8Node **last_include_symbol = &config->include_symbol_list.first;
|
String8Node **last_include_symbol = &config->include_symbol_list.first;
|
||||||
String8Node **last_disallow_lib = &config->disallow_lib_list.first;
|
String8Node **last_disallow_lib = &config->disallow_lib_list.first;
|
||||||
|
String8Node **last_delay_load_dll = &config->delay_load_dll_list.first;
|
||||||
LNK_AltNameNode **last_alt_name = &config->alt_name_list.first;
|
LNK_AltNameNode **last_alt_name = &config->alt_name_list.first;
|
||||||
LNK_InputObjList input_obj_list = {0};
|
LNK_InputObjList input_obj_list = {0};
|
||||||
LNK_InputImportList input_import_list = {0};
|
LNK_InputImportList input_import_list = {0};
|
||||||
LNK_InputLib **input_libs[LNK_InputSource_Count] = {
|
LNK_InputLib **input_libs[LNK_InputSource_Count] = { &config->input_list[LNK_Input_Lib].first, &config->input_default_lib_list.first, &config->input_obj_lib_list.first };
|
||||||
&config->input_list[LNK_Input_Lib].first,
|
LNK_ObjList obj_list = {0};
|
||||||
&config->input_default_lib_list.first,
|
LNK_LibList lib_index[LNK_InputSource_Count] = {0};
|
||||||
&config->input_obj_lib_list.first
|
U64 entry_point_search_attempts = 0;
|
||||||
};
|
SearchFlags search_flags = SearchFlag_All;
|
||||||
|
B32 input_linker_objs = 1;
|
||||||
|
HashTable *static_imports = hash_table_init(scratch.arena, 512);
|
||||||
|
HashTable *delayed_imports = hash_table_init(scratch.arena, 512);
|
||||||
|
HashTable *import_stub_ht = hash_table_init(scratch.arena, 0x1000);
|
||||||
|
// TODO: move disallow_lib, loaded_lib, missing_lib, and loaded_obj to config
|
||||||
|
Arena *ht_arena = arena_alloc();
|
||||||
|
HashTable *disallow_lib_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);
|
||||||
|
|
||||||
// input :null_obj
|
// TODO: this should happen in the config before state machine setup
|
||||||
{
|
{
|
||||||
|
// input :null_obj
|
||||||
LNK_InputObj *null_obj_input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
LNK_InputObj *null_obj_input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
||||||
null_obj_input->exclude_from_debug_info = 1;
|
null_obj_input->exclude_from_debug_info = 1;
|
||||||
null_obj_input->path = str8_lit("* Null Obj *");
|
null_obj_input->path = str8_lit("* Null Obj *");
|
||||||
null_obj_input->dedup_id = null_obj_input->path;
|
null_obj_input->dedup_id = null_obj_input->path;
|
||||||
null_obj_input->data = lnk_make_null_obj(tp_arena->v[0]);
|
null_obj_input->data = lnk_make_null_obj(tp_arena->v[0]);
|
||||||
}
|
|
||||||
|
|
||||||
// input command line objs
|
// input command line objs
|
||||||
LNK_InputObjList cmd_line_obj_inputs = lnk_input_obj_list_from_string_list(scratch.arena, config->input_list[LNK_Input_Obj]);
|
LNK_InputObjList cmd_line_obj_inputs = lnk_input_obj_list_from_string_list(scratch.arena, config->input_list[LNK_Input_Obj]);
|
||||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &cmd_line_obj_inputs);
|
lnk_input_obj_list_concat_in_place(&input_obj_list, &cmd_line_obj_inputs);
|
||||||
|
}
|
||||||
|
|
||||||
// state
|
// TODO: MSVC does not need this flag to include load config
|
||||||
LNK_SymbolTable *symtab = lnk_symbol_table_init(tp_arena);
|
if (config->guard_flags != LNK_Guard_None) {
|
||||||
LNK_SectionTable *sectab = 0;
|
// TODO: config_refactor
|
||||||
HashTable *static_imports = hash_table_init(scratch.arena, 512);
|
String8List value_strings = {0};
|
||||||
HashTable *delayed_imports = hash_table_init(scratch.arena, 512);
|
str8_list_push(scratch.arena, &value_strings, str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME));
|
||||||
LNK_ObjList obj_list = {0};
|
lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, 0);
|
||||||
LNK_LibList lib_index[LNK_InputSource_Count] = {0};
|
}
|
||||||
Arena *ht_arena = arena_alloc();
|
|
||||||
String8 delay_load_helper_name = {0};
|
|
||||||
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);
|
|
||||||
U64 entry_point_lookup_attempts = 0;
|
|
||||||
B32 input_linker_objs = 1;
|
|
||||||
B32 pending_refs = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Init state machine
|
// run states
|
||||||
//
|
//
|
||||||
struct StateList state_list = {0};
|
struct StateList state_list = {0};
|
||||||
state_list_push(scratch.arena, state_list, State_InputDisallowLibs);
|
|
||||||
state_list_push(scratch.arena, state_list, State_InputObjs);
|
|
||||||
state_list_push(scratch.arena, state_list, State_InputLibs);
|
|
||||||
if (config->delay_load_dll_list.node_count) {
|
|
||||||
for (String8Node *delay_load_dll_node = config->delay_load_dll_list.first;
|
|
||||||
delay_load_dll_node != 0;
|
|
||||||
delay_load_dll_node = delay_load_dll_node->next) {
|
|
||||||
hash_table_push_path_u64(scratch.arena, delay_load_dll_ht, delay_load_dll_node->string, 0);
|
|
||||||
}
|
|
||||||
state_list_push(scratch.arena, state_list, State_PushDllHelperUndefSymbol);
|
|
||||||
}
|
|
||||||
if (config->guard_flags != LNK_Guard_None) {
|
|
||||||
state_list_push(scratch.arena, state_list, State_PushLoadConfigUndefSymbol);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Run states
|
|
||||||
//
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for (; state_list.count > 0; ) {
|
for (; state_list.count > 0; ) {
|
||||||
enum State state = state_list_pop(state_list);
|
enum State state = state_list_pop(state_list);
|
||||||
@@ -1410,6 +1390,10 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// skip duplicate import inputs
|
||||||
|
if (hash_table_search_string_raw(import_stub_ht, import_header.func_name, 0)) { continue; }
|
||||||
|
hash_table_push_string_raw(ht_arena, import_stub_ht, import_header.func_name, 0);
|
||||||
|
|
||||||
// create import stubs (later replaced with acutal imports generated by linker)
|
// create import stubs (later replaced with acutal imports generated by linker)
|
||||||
LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit(LNK_IMPORT_STUB));
|
LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, str8_lit(LNK_IMPORT_STUB));
|
||||||
LNK_Symbol *thunk_symbol = lnk_make_defined_symbol(symtab->arena->v[0], import_header.func_name, import_stub->u.defined.obj, import_stub->u.defined.symbol_idx);
|
LNK_Symbol *thunk_symbol = lnk_make_defined_symbol(symtab->arena->v[0], import_header.func_name, import_stub->u.defined.obj, import_stub->u.defined.symbol_idx);
|
||||||
@@ -1418,15 +1402,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
lnk_symbol_table_push(symtab, LNK_SymbolScope_Defined, imp_symbol);
|
lnk_symbol_table_push(symtab, LNK_SymbolScope_Defined, imp_symbol);
|
||||||
|
|
||||||
// pick imports hash table
|
// pick imports hash table
|
||||||
HashTable *imports_ht;
|
HashTable *imports_ht = lnk_is_dll_delay_load(config, import_header.dll_name) ? delayed_imports : static_imports;
|
||||||
{
|
|
||||||
B32 is_delay_load_dll = hash_table_search_path_u64(delay_load_dll_ht, import_header.dll_name, 0);
|
|
||||||
if (is_delay_load_dll) {
|
|
||||||
imports_ht = delayed_imports;
|
|
||||||
} else {
|
|
||||||
imports_ht = static_imports;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// search DLL symbol list
|
// search DLL symbol list
|
||||||
String8List *import_symbols = hash_table_search_path_raw(imports_ht, import_header.dll_name);
|
String8List *import_symbols = hash_table_search_path_raw(imports_ht, import_header.dll_name);
|
||||||
@@ -1444,8 +1420,8 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_InputSymbols: {
|
case State_InputInclude: {
|
||||||
ProfBegin("Input Symbols");
|
ProfBegin("Input Include");
|
||||||
|
|
||||||
// push a relocation which references an undefined include symbol
|
// push a relocation which references an undefined include symbol
|
||||||
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown);
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown);
|
||||||
@@ -1524,7 +1500,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
|
|
||||||
// if the machine was omitted on the command line, derive machine from obj
|
// if the machine was omitted on the command line, derive machine from obj
|
||||||
if (config->machine == COFF_MachineType_Unknown) {
|
if (config->machine == COFF_MachineType_Unknown) {
|
||||||
for (U64 obj_idx = 0; obj_idx < obj_node_arr.count; obj_idx += 1) {
|
for EachIndex(obj_idx, obj_node_arr.count) {
|
||||||
if (obj_node_arr.v[obj_idx].data.header.machine != COFF_MachineType_Unknown) {
|
if (obj_node_arr.v[obj_idx].data.header.machine != COFF_MachineType_Unknown) {
|
||||||
config->machine = obj_node_arr.v[obj_idx].data.header.machine;
|
config->machine = obj_node_arr.v[obj_idx].data.header.machine;
|
||||||
break;
|
break;
|
||||||
@@ -1532,12 +1508,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// infer minimal padding size for functions from the target machine
|
|
||||||
if (config->machine != COFF_MachineType_Unknown && config->infer_function_pad_min) {
|
|
||||||
config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
|
|
||||||
config->infer_function_pad_min = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProfBegin("Apply Directives");
|
ProfBegin("Apply Directives");
|
||||||
for EachIndex(obj_idx, obj_node_arr.count) {
|
for EachIndex(obj_idx, obj_node_arr.count) {
|
||||||
LNK_Obj *obj = &obj_node_arr.v[obj_idx].data;
|
LNK_Obj *obj = &obj_node_arr.v[obj_idx].data;
|
||||||
@@ -1555,7 +1525,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
lnk_input_obj_symbols(tp, tp_arena, symtab, obj_node_arr);
|
lnk_input_obj_symbols(tp, tp_arena, symtab, obj_node_arr);
|
||||||
|
|
||||||
// schedule symbol input
|
// schedule symbol input
|
||||||
pending_refs = 1;
|
search_flags = SearchFlag_All;
|
||||||
|
|
||||||
// reset input objs
|
// reset input objs
|
||||||
MemoryZeroStruct(&input_obj_list);
|
MemoryZeroStruct(&input_obj_list);
|
||||||
@@ -1641,7 +1611,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
if (lnk_get_log_status(LNK_Log_InputLib)) {
|
if (lnk_get_log_status(LNK_Log_InputLib)) {
|
||||||
if (libs.count > 0) {
|
if (libs.count > 0) {
|
||||||
U64 input_size = 0;
|
U64 input_size = 0;
|
||||||
for (U64 i = 0; i < libs.count; ++i) { input_size += libs.v[i].data.data.size; }
|
for EachIndex(i, libs.count) { input_size += libs.v[i].data.data.size; }
|
||||||
lnk_log(LNK_Log_InputObj, "[ Lib Input Size %M ]", input_size);
|
lnk_log(LNK_Log_InputObj, "[ Lib Input Size %M ]", input_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1651,76 +1621,129 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// schedule symbol input
|
// schedule symbol input
|
||||||
pending_refs = 1;
|
search_flags = SearchFlag_All;
|
||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_InputAlternateNames: {
|
case State_InputAlternateNames: {
|
||||||
ProfBegin("Input Alternate Names");
|
ProfBegin("Input Alternate Names");
|
||||||
COFF_ObjWriter *obj_writer = 0;
|
|
||||||
for (; *last_alt_name; last_alt_name = &(*last_alt_name)->next) {
|
// linker is not allowed to create a new alternate name if the "from" symbol already exists
|
||||||
// make object writer if it was reset
|
// (MSVC silently ignores the directive)
|
||||||
if (obj_writer == 0) {
|
{
|
||||||
obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown);
|
LNK_Symbol *extant_from = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, (*last_alt_name)->data.from);
|
||||||
|
if (extant_from) {
|
||||||
|
COFF_SymbolValueInterpType extant_interp = lnk_interp_from_symbol(extant_from);
|
||||||
|
if (extant_interp != COFF_SymbolValueInterp_Undefined) { break; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// append weak symbol
|
// make & input alternate name obj
|
||||||
COFF_ObjSymbol *tag = coff_obj_writer_push_symbol_undef(obj_writer, (*last_alt_name)->data.to);
|
{
|
||||||
coff_obj_writer_push_symbol_weak(obj_writer, (*last_alt_name)->data.from, COFF_WeakExt_AntiDependency, tag);
|
COFF_ObjWriter *obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown);
|
||||||
|
|
||||||
|
COFF_ObjSymbol *null_symbol = coff_obj_writer_push_symbol_undef(obj_writer, str8_lit(LNK_NULL_SYMBOL));
|
||||||
|
COFF_ObjSymbol *from_symbol = coff_obj_writer_push_symbol_weak(obj_writer, (*last_alt_name)->data.from, COFF_WeakExt_Rad_WeakSearchLibrary, null_symbol);
|
||||||
|
COFF_ObjSymbol *to_symbol = coff_obj_writer_push_symbol_weak(obj_writer, (*last_alt_name)->data.to, COFF_WeakExt_Rad_WeakSearchLibrary, from_symbol);
|
||||||
|
|
||||||
|
String8 alt_name_obj = coff_obj_writer_serialize(tp_arena->v[0], obj_writer);
|
||||||
|
coff_obj_writer_release(&obj_writer);
|
||||||
|
|
||||||
// flush on last directive or next directive is issued from a different obj
|
|
||||||
if ((*last_alt_name)->next == 0 || (*last_alt_name)->data.obj != (*last_alt_name)->next->data.obj) {
|
|
||||||
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
||||||
input->path = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->path : str8_lit("RADLINK");
|
input->path = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->path : str8_lit("RADLINK");
|
||||||
input->exclude_from_debug_info = 1;
|
input->exclude_from_debug_info = 1;
|
||||||
input->dedup_id = push_str8f(scratch.arena, "* ALTERNATE NAMES FOR %S *", input->path);
|
input->dedup_id = push_str8f(scratch.arena, "* ALTERNATE NAMES FOR %S * %u", input->path, obj_list.count);
|
||||||
input->data = coff_obj_writer_serialize(tp_arena->v[0], obj_writer);
|
input->data = alt_name_obj;
|
||||||
input->lib = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->lib : 0;
|
input->lib = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->lib : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// advance to next alt name
|
||||||
|
last_alt_name = &(*last_alt_name)->next;
|
||||||
|
|
||||||
// reset obj writer
|
|
||||||
coff_obj_writer_release(&obj_writer);
|
|
||||||
obj_writer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_PushDllHelperUndefSymbol: {
|
case State_InputDelayLoadDlls: {
|
||||||
ProfBegin("Push Dll Helper Undef Symbol");
|
ProfBegin("Input Delay Load Dlls");
|
||||||
delay_load_helper_name = mscrt_delay_load_helper_name_from_machine(config->machine);
|
|
||||||
|
for (; *last_delay_load_dll; last_delay_load_dll = &(*last_delay_load_dll)->next);
|
||||||
|
|
||||||
// TODO: config_refactor
|
// TODO: config_refactor
|
||||||
String8List value_strings = {0};
|
String8List value_strings = {0};
|
||||||
str8_list_push(scratch.arena, &value_strings, delay_load_helper_name);
|
str8_list_push(scratch.arena, &value_strings, config->delay_load_helper_name);
|
||||||
lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, 0);
|
lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, 0);
|
||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_PushLoadConfigUndefSymbol: {
|
case State_SearchUndefined: {
|
||||||
ProfBegin("Push Load Config Undef Symbol");
|
ProfBegin("Search Undefined");
|
||||||
String8 load_config_name = str8_lit(MSCRT_LOAD_CONFIG_SYMBOL_NAME);
|
for EachIndex(worker_id, symtab->arena->count) {
|
||||||
|
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
|
||||||
// TODO: config_refactor
|
for EachIndex(i, c->count) {
|
||||||
String8List value_strings = {0};
|
LNK_Symbol *symbol = c->v[i].symbol;
|
||||||
str8_list_push(scratch.arena, &value_strings, load_config_name);
|
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
||||||
lnk_apply_cmd_option_to_config(tp_arena->v[0], config, str8_lit("include"), value_strings, 0);
|
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
|
||||||
|
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
||||||
|
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol->name);
|
||||||
|
if (member_symbol) {
|
||||||
|
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_FindRefs: {
|
case State_SearchWeak: {
|
||||||
ProfBegin("Find Refs");
|
ProfBegin("Search Weak");
|
||||||
|
for EachIndex(worker_id, symtab->arena->count) {
|
||||||
LNK_InputImportList new_imports = {0};
|
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
|
||||||
LNK_InputObjList new_objs = {0};
|
for EachIndex(i, c->count) {
|
||||||
lnk_find_refs(scratch.arena, tp, symtab, config, obj_list, &new_imports, &new_objs);
|
LNK_Symbol *symbol = c->v[i].symbol;
|
||||||
|
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
||||||
// schedule new inputs
|
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
|
||||||
lnk_input_import_list_concat_in_place(&input_import_list, &new_imports);
|
if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
lnk_input_obj_list_concat_in_place(&input_obj_list, &new_objs);
|
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->u.defined.obj->header.is_big_obj);
|
||||||
|
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
|
||||||
|
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol->name);
|
||||||
|
if (member_symbol) {
|
||||||
|
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
} break;
|
} break;
|
||||||
case State_LookupEntryPoint: {
|
case State_SearchWeakAntiDep: {
|
||||||
ProfBegin("Lookup Entry Point");
|
ProfBegin("Search Weak AntiDep");
|
||||||
|
for EachIndex(worker_id, symtab->arena->count) {
|
||||||
|
for (LNK_SymbolHashTrieChunk *c = symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].first; c != 0; c = c->next) {
|
||||||
|
for EachIndex(i, c->count) {
|
||||||
|
LNK_Symbol *symbol = c->v[i].symbol;
|
||||||
|
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
||||||
|
COFF_SymbolValueInterpType symbol_interp = coff_interp_from_parsed_symbol(symbol_parsed);
|
||||||
|
if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
|
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol->u.defined.obj->header.is_big_obj);
|
||||||
|
if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
|
||||||
|
LNK_SymbolDefined dep_symbol = lnk_resolve_weak_symbol(symtab, symbol->u.defined);
|
||||||
|
COFF_ParsedSymbol dep_parsed = lnk_parsed_symbol_from_coff_symbol_idx(dep_symbol.obj, dep_symbol.symbol_idx);
|
||||||
|
COFF_SymbolValueInterpType dep_interp = coff_interp_from_parsed_symbol(dep_parsed);
|
||||||
|
if (dep_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
|
LNK_Symbol *member_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, symbol_parsed.name);
|
||||||
|
if (member_symbol) {
|
||||||
|
lnk_queue_lib_member_for_input(scratch.arena, config, symbol, member_symbol, &input_import_list, &input_obj_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ProfEnd();
|
||||||
|
} break;
|
||||||
|
case State_SearchEntryPoint: {
|
||||||
|
ProfBegin("Search Entry Point");
|
||||||
LNK_Symbol *entry_point_symbol = 0;
|
LNK_Symbol *entry_point_symbol = 0;
|
||||||
|
|
||||||
B32 is_entry_point_unspecified = config->entry_point_name.size == 0;
|
B32 is_entry_point_unspecified = config->entry_point_name.size == 0;
|
||||||
@@ -1729,9 +1752,9 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
// we don't have a subsystem and entry point name,
|
// we don't have a subsystem and entry point name,
|
||||||
// so we loop over every subsystem and search potential entry
|
// so we loop over every subsystem and search potential entry
|
||||||
// points in the symbol table
|
// points in the symbol table
|
||||||
for (U64 subsys_idx = 0; subsys_idx < PE_WindowsSubsystem_COUNT; subsys_idx += 1) {
|
for EachIndex(subsys_idx, PE_WindowsSubsystem_COUNT) {
|
||||||
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
|
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
|
||||||
for (U64 entry_idx = 0; entry_idx < name_arr.count; entry_idx += 1) {
|
for EachIndex(entry_idx, name_arr.count) {
|
||||||
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
|
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
|
||||||
if (entry_point_symbol) {
|
if (entry_point_symbol) {
|
||||||
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
|
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
|
||||||
@@ -1742,9 +1765,9 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
|
|
||||||
// search for potential entry points in libs
|
// search for potential entry points in libs
|
||||||
if (!entry_point_symbol) {
|
if (!entry_point_symbol) {
|
||||||
for (U64 subsys_idx = 0; subsys_idx < PE_WindowsSubsystem_COUNT; subsys_idx += 1) {
|
for EachIndex(subsys_idx, PE_WindowsSubsystem_COUNT) {
|
||||||
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
|
String8Array name_arr = pe_get_entry_point_names(config->machine, (PE_WindowsSubsystem)subsys_idx, config->file_characteristics);
|
||||||
for (U64 entry_idx = 0; entry_idx < name_arr.count; entry_idx += 1) {
|
for EachIndex(entry_idx, name_arr.count) {
|
||||||
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
|
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
|
||||||
if (entry_point_symbol) {
|
if (entry_point_symbol) {
|
||||||
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
|
config->subsystem = (PE_WindowsSubsystem)subsys_idx;
|
||||||
@@ -1759,7 +1782,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
// we have subsystem but no entry point name, get potential entry point names
|
// we have subsystem but no entry point name, get potential entry point names
|
||||||
// and see which is in the symbol table
|
// and see which is in the symbol table
|
||||||
String8Array name_arr = pe_get_entry_point_names(config->machine, config->subsystem, config->file_characteristics);
|
String8Array name_arr = pe_get_entry_point_names(config->machine, config->subsystem, config->file_characteristics);
|
||||||
for (U64 entry_idx = 0; entry_idx < name_arr.count; entry_idx += 1) {
|
for EachIndex(entry_idx, name_arr.count) {
|
||||||
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
|
LNK_Symbol *symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, name_arr.v[entry_idx]);
|
||||||
if (symbol) {
|
if (symbol) {
|
||||||
if (entry_point_symbol) {
|
if (entry_point_symbol) {
|
||||||
@@ -1775,7 +1798,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
|
|
||||||
// search for entry point in libs
|
// search for entry point in libs
|
||||||
if (!entry_point_symbol) {
|
if (!entry_point_symbol) {
|
||||||
for (U64 entry_idx = 0; entry_idx < name_arr.count; entry_idx += 1) {
|
for EachIndex(entry_idx, name_arr.count) {
|
||||||
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
|
entry_point_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Lib, name_arr.v[entry_idx]);
|
||||||
if (entry_point_symbol) {
|
if (entry_point_symbol) {
|
||||||
break;
|
break;
|
||||||
@@ -1869,11 +1892,11 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
String8 *dll_names = keys_from_hash_table_string(scratch.arena, delayed_imports);
|
String8 *dll_names = keys_from_hash_table_string(scratch.arena, delayed_imports);
|
||||||
String8List **dll_import_headers = values_from_hash_table_raw(scratch.arena, delayed_imports);
|
String8List **dll_import_headers = values_from_hash_table_raw(scratch.arena, delayed_imports);
|
||||||
|
|
||||||
for (U64 dll_idx = 0; dll_idx < delayed_imports->count; dll_idx += 1) {
|
for EachIndex(dll_idx, delayed_imports->count) {
|
||||||
String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_names[dll_idx]);
|
String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_names[dll_idx]);
|
||||||
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
||||||
input->input_idx = obj_list.count;
|
input->input_idx = obj_list.count;
|
||||||
input->data = pe_make_import_dll_obj_delayed(tp_arena->v[0], time_stamp, config->machine, dll_names[dll_idx], delay_load_helper_name, import_debug_symbols, *dll_import_headers[dll_idx], emit_biat, emit_uiat);
|
input->data = pe_make_import_dll_obj_delayed(tp_arena->v[0], time_stamp, config->machine, dll_names[dll_idx], config->delay_load_helper_name, import_debug_symbols, *dll_import_headers[dll_idx], emit_biat, emit_uiat);
|
||||||
input->path = dll_names[dll_idx];
|
input->path = dll_names[dll_idx];
|
||||||
input->dedup_id = input->path;
|
input->dedup_id = input->path;
|
||||||
}
|
}
|
||||||
@@ -1905,7 +1928,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
COFF_TimeStamp time_stamp = COFF_TimeStamp_Max;
|
COFF_TimeStamp time_stamp = COFF_TimeStamp_Max;
|
||||||
String8 *dll_names = keys_from_hash_table_string(scratch.arena, static_imports);
|
String8 *dll_names = keys_from_hash_table_string(scratch.arena, static_imports);
|
||||||
String8List **dll_import_headers = values_from_hash_table_raw(scratch.arena, static_imports);
|
String8List **dll_import_headers = values_from_hash_table_raw(scratch.arena, static_imports);
|
||||||
for (U64 dll_idx = 0; dll_idx < static_imports->count; dll_idx += 1) {
|
for EachIndex(dll_idx, static_imports->count) {
|
||||||
String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_names[dll_idx]);
|
String8 import_debug_symbols = lnk_make_dll_import_debug_symbols(scratch.arena, config->machine, dll_names[dll_idx]);
|
||||||
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
LNK_InputObj *input = lnk_input_obj_list_push(scratch.arena, &input_obj_list);
|
||||||
input->input_idx = obj_list.count;
|
input->input_idx = obj_list.count;
|
||||||
@@ -2090,7 +2113,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*last_disallow_lib != 0) {
|
if (*last_disallow_lib) {
|
||||||
state_list_push(scratch.arena, state_list, State_InputDisallowLibs);
|
state_list_push(scratch.arena, state_list, State_InputDisallowLibs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2098,17 +2121,17 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
state_list_push(scratch.arena, state_list, State_InputImports);
|
state_list_push(scratch.arena, state_list, State_InputImports);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*last_include_symbol != 0) {
|
if (*last_include_symbol) {
|
||||||
state_list_push(scratch.arena, state_list, State_InputSymbols);
|
state_list_push(scratch.arena, state_list, State_InputInclude);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (*last_alt_name != 0) {
|
if (*last_alt_name) {
|
||||||
state_list_push(scratch.arena, state_list, State_InputAlternateNames);
|
state_list_push(scratch.arena, state_list, State_InputAlternateNames);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
B32 have_pending_lib_inputs = 0;
|
B32 have_pending_lib_inputs = 0;
|
||||||
for (U64 i = 0; i < ArrayCount(input_libs); ++i) {
|
for EachIndex(i, ArrayCount(input_libs)) {
|
||||||
if (*input_libs[i] != 0) {
|
if (*input_libs[i] != 0) {
|
||||||
have_pending_lib_inputs = 1;
|
have_pending_lib_inputs = 1;
|
||||||
break;
|
break;
|
||||||
@@ -2123,14 +2146,28 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
state_list_push(scratch.arena, state_list, State_InputObjs);
|
state_list_push(scratch.arena, state_list, State_InputObjs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pending_refs) {
|
if (*last_delay_load_dll) {
|
||||||
pending_refs = 0;
|
state_list_push(scratch.arena, state_list, State_InputDelayLoadDlls);
|
||||||
state_list_push(scratch.arena, state_list, State_FindRefs);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (entry_point_lookup_attempts == 0) {
|
if (search_flags & SearchFlag_Undefined) {
|
||||||
state_list_push(scratch.arena, state_list, State_LookupEntryPoint);
|
search_flags &= ~SearchFlag_Undefined;
|
||||||
entry_point_lookup_attempts += 1;
|
state_list_push(scratch.arena, state_list, State_SearchUndefined);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (search_flags & SearchFlag_Weak) {
|
||||||
|
search_flags &= ~SearchFlag_Weak;
|
||||||
|
state_list_push(scratch.arena, state_list, State_SearchWeak);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (search_flags & SearchFlag_WeakAntiDep) {
|
||||||
|
search_flags &= ~SearchFlag_WeakAntiDep;
|
||||||
|
state_list_push(scratch.arena, state_list, State_SearchWeakAntiDep);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (entry_point_search_attempts == 0) {
|
||||||
|
state_list_push(scratch.arena, state_list, State_SearchEntryPoint);
|
||||||
|
entry_point_search_attempts += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (input_linker_objs) {
|
if (input_linker_objs) {
|
||||||
@@ -2142,104 +2179,83 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProfBegin("Report Unresolved Symbols");
|
|
||||||
{
|
{
|
||||||
U64 chunks_count = 0;
|
U64 chunks_count = 0;
|
||||||
LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunk_lists[LNK_SymbolScope_Defined], tp->worker_count, &chunks_count);
|
LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunk_lists[LNK_SymbolScope_Defined], symtab->arena->count, &chunks_count);
|
||||||
|
|
||||||
U64 undefs_count = 0;
|
ProfBegin("Replace Unresolved Weak Symbols With Defualt Symbol");
|
||||||
|
{
|
||||||
|
LNK_ReplaceWeakSymbolsWithDefaultSymbolTask task = { .symtab = symtab, .chunks = chunks };
|
||||||
|
tp_for_parallel(tp, 0, chunks_count, lnk_replace_weak_with_default_symbol_task, &task);
|
||||||
|
#if BUILD_DEBUG
|
||||||
for EachIndex(chunk_idx, chunks_count) {
|
for EachIndex(chunk_idx, chunks_count) {
|
||||||
LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx];
|
LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx];
|
||||||
for EachIndex(i, chunk->count) {
|
for EachIndex(i, chunk->count) {
|
||||||
LNK_Symbol *symbol = chunk->v[i].symbol;
|
LNK_Symbol *symbol = chunk->v[i].symbol;
|
||||||
if (symbol->is_live) {
|
COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol);
|
||||||
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
AssertAlways(symbol_interp != COFF_SymbolValueInterp_Weak);
|
||||||
if (coff_is_undefined_data_symbol(symbol_parsed)) {
|
|
||||||
undefs_count += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
ProfEnd();
|
||||||
|
|
||||||
U64 undefs_cursor = 0;
|
ProfBegin("Report Unresolved Symbols");
|
||||||
LNK_Symbol **undefs = push_array(scratch.arena, LNK_Symbol *, undefs_count);
|
{
|
||||||
|
U64 count = 0;
|
||||||
for EachIndex(chunk_idx, chunks_count) {
|
for EachIndex(chunk_idx, chunks_count) {
|
||||||
LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx];
|
LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx];
|
||||||
for EachIndex(i, chunk->count) {
|
for EachIndex(i, chunk->count) {
|
||||||
LNK_Symbol *symbol = chunk->v[i].symbol;
|
LNK_Symbol *symbol = chunk->v[i].symbol;
|
||||||
if (symbol->is_live) {
|
COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol);
|
||||||
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_defined(symbol);
|
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
||||||
if (coff_is_undefined_data_symbol(symbol_parsed)) {
|
count += 1;
|
||||||
undefs[undefs_cursor++] = chunk->v[i].symbol;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
radsort(undefs, undefs_count, lnk_symbol_defined_ptr_is_before);
|
U64 cursor = 0;
|
||||||
|
LNK_Symbol **unresolved = push_array(scratch.arena, LNK_Symbol *, count);
|
||||||
for EachIndex(i, undefs_count) {
|
for EachIndex(chunk_idx, chunks_count) {
|
||||||
LNK_Symbol *s = undefs[i];
|
LNK_SymbolHashTrieChunk *chunk = chunks[chunk_idx];
|
||||||
lnk_error_obj(LNK_Error_UnresolvedSymbol, s->u.defined.obj, "unresolved symbol %S", s->name);
|
for EachIndex(i, chunk->count) {
|
||||||
|
LNK_Symbol *symbol = chunk->v[i].symbol;
|
||||||
|
COFF_SymbolValueInterpType symbol_interp = lnk_interp_from_symbol(symbol);
|
||||||
|
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
||||||
|
unresolved[cursor++] = chunk->v[i].symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (undefs_count > 0) {
|
radsort(unresolved, count, lnk_symbol_defined_ptr_is_before);
|
||||||
|
|
||||||
|
for EachIndex(i, count) {
|
||||||
|
LNK_Symbol *symbol = unresolved[i];
|
||||||
|
lnk_error_obj(LNK_Error_UnresolvedSymbol, symbol->u.defined.obj, "unresolved symbol %S", symbol->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: /FORCE
|
||||||
|
if (count) {
|
||||||
lnk_exit(LNK_Error_UnresolvedSymbol);
|
lnk_exit(LNK_Error_UnresolvedSymbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
|
}
|
||||||
|
|
||||||
ProfBegin("Remove Unreachable Sections");
|
//
|
||||||
{
|
// discard COMDAT sections that are not referenced
|
||||||
for (LNK_ObjNode *obj_n = obj_list.first; obj_n != 0; obj_n = obj_n->next) {
|
//
|
||||||
LNK_Obj *obj = &obj_n->data;
|
|
||||||
for EachIndex(sect_idx, obj->header.section_count_no_null) {
|
|
||||||
U32 section_number = sect_idx+1;
|
|
||||||
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
|
|
||||||
|
|
||||||
if (lnk_is_coff_section_debug(obj, sect_idx)) { continue; }
|
|
||||||
|
|
||||||
if (config->opt_ref == LNK_SwitchState_Yes) {
|
if (config->opt_ref == LNK_SwitchState_Yes) {
|
||||||
// remove unreferenced sections
|
lnk_opt_ref(tp, symtab, config, obj_list);
|
||||||
if (~section_header->flags & LNK_SECTION_FLAG_IS_LIVE && section_header->flags & COFF_SectionFlag_LnkCOMDAT) {
|
|
||||||
section_header->flags |= COFF_SectionFlag_LnkRemove;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Reset reserved flag so it does not get propagated to the image sections.
|
|
||||||
// We need to mask out reserved flags when gathering section definitions to actually
|
|
||||||
// prevent propagation.
|
|
||||||
section_header->flags &= ~LNK_SECTION_FLAG_IS_LIVE;
|
|
||||||
|
|
||||||
if (section_header->flags & COFF_SectionFlag_LnkRemove) {
|
|
||||||
for (U32Node *section_number_n = obj->associated_sections[section_number]; section_number_n != 0; section_number_n = section_number_n->next) {
|
|
||||||
U32 section_number = section_number_n->data;
|
|
||||||
COFF_SectionHeader *section_header = lnk_coff_section_header_from_section_number(obj, section_number);
|
|
||||||
section_header->flags |= COFF_SectionFlag_LnkRemove;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProfEnd();
|
|
||||||
|
|
||||||
ProfBegin("Replace Unresolved Weak Symbols With Defualt Symbol");
|
|
||||||
{
|
|
||||||
U64 chunks_count = 0;
|
|
||||||
LNK_SymbolHashTrieChunk **chunks = lnk_array_from_symbol_hash_trie_chunk_list(scratch.arena, symtab->chunk_lists[LNK_SymbolScope_Defined], symtab->arena->count, &chunks_count);
|
|
||||||
LNK_ReplaceWeakSymbolsWithDefaultSymbolTask task = { .symtab = symtab, .chunks = chunks };
|
|
||||||
tp_for_parallel(tp, 0, chunks_count, lnk_replace_weak_symbols_with_default_symbol_task, &task);
|
|
||||||
}
|
|
||||||
ProfEnd();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// fill out link context
|
// infer minimal padding size for functions from the target machine
|
||||||
//
|
//
|
||||||
LNK_LinkContext link_ctx = {0};
|
if (config->machine != COFF_MachineType_Unknown && config->infer_function_pad_min) {
|
||||||
link_ctx.symtab = symtab;
|
config->function_pad_min = lnk_get_default_function_pad_min(config->machine);
|
||||||
link_ctx.objs_count = obj_list.count;
|
config->infer_function_pad_min = 0;
|
||||||
link_ctx.objs = lnk_array_from_obj_list(tp_arena->v[0], obj_list);
|
}
|
||||||
MemoryCopyTyped(&link_ctx.lib_index[0], &lib_index[0], ArrayCount(lib_index));
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// log
|
// log
|
||||||
@@ -2251,13 +2267,22 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
|||||||
}
|
}
|
||||||
if (lnk_get_log_status(LNK_Log_InputLib)) {
|
if (lnk_get_log_status(LNK_Log_InputLib)) {
|
||||||
U64 total_input_size = 0;
|
U64 total_input_size = 0;
|
||||||
for (U64 i = 0; i < ArrayCount(lib_index); ++i) {
|
for EachIndex(i, ArrayCount(lib_index)) {
|
||||||
LNK_LibList list = lib_index[i];
|
LNK_LibList list = lib_index[i];
|
||||||
for (LNK_LibNode *lib_n = list.first; lib_n != 0; lib_n = lib_n->next) { total_input_size += lib_n->data.data.size; }
|
for (LNK_LibNode *lib_n = list.first; lib_n != 0; lib_n = lib_n->next) { total_input_size += lib_n->data.data.size; }
|
||||||
}
|
}
|
||||||
lnk_log(LNK_Log_InputLib, "[Total Lib Input Size %M]", total_input_size);
|
lnk_log(LNK_Log_InputLib, "[Total Lib Input Size %M]", total_input_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// fill out link context
|
||||||
|
//
|
||||||
|
LNK_LinkContext link_ctx = {0};
|
||||||
|
link_ctx.symtab = symtab;
|
||||||
|
link_ctx.objs_count = obj_list.count;
|
||||||
|
link_ctx.objs = lnk_array_from_obj_list(tp_arena->v[0], obj_list);
|
||||||
|
MemoryCopyTyped(&link_ctx.lib_index[0], &lib_index[0], ArrayCount(lib_index));
|
||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return link_ctx;
|
return link_ctx;
|
||||||
@@ -2410,25 +2435,6 @@ THREAD_POOL_TASK_FUNC(lnk_gather_section_contribs_task)
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
|
||||||
THREAD_POOL_TASK_FUNC(lnk_flag_debug_symbols_task)
|
|
||||||
{
|
|
||||||
LNK_BuildImageTask *task = raw_task;
|
|
||||||
U64 obj_idx = task_id;
|
|
||||||
LNK_Obj *obj = task->objs[obj_idx];
|
|
||||||
|
|
||||||
COFF_ParsedSymbol symbol;
|
|
||||||
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
|
||||||
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
|
||||||
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
|
||||||
if (interp == COFF_SymbolValueInterp_Regular) {
|
|
||||||
if (lnk_is_coff_section_debug(obj, symbol.section_number-1)) {
|
|
||||||
task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
internal
|
||||||
THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
|
THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
|
||||||
{
|
{
|
||||||
@@ -2452,6 +2458,25 @@ THREAD_POOL_TASK_FUNC(lnk_set_comdat_leaders_contribs_task)
|
|||||||
ProfEnd();
|
ProfEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
THREAD_POOL_TASK_FUNC(lnk_flag_debug_symbols_task)
|
||||||
|
{
|
||||||
|
LNK_BuildImageTask *task = raw_task;
|
||||||
|
U64 obj_idx = task_id;
|
||||||
|
LNK_Obj *obj = task->objs[obj_idx];
|
||||||
|
|
||||||
|
COFF_ParsedSymbol symbol;
|
||||||
|
for (U64 symbol_idx = 0; symbol_idx < obj->header.symbol_count; symbol_idx += (1 + symbol.aux_symbol_count)) {
|
||||||
|
symbol = lnk_parsed_symbol_from_coff_symbol_idx(obj, symbol_idx);
|
||||||
|
COFF_SymbolValueInterpType interp = coff_interp_symbol(symbol.section_number, symbol.value, symbol.storage_class);
|
||||||
|
if (interp == COFF_SymbolValueInterp_Regular) {
|
||||||
|
if (lnk_is_coff_section_debug(obj, symbol.section_number-1)) {
|
||||||
|
task->u.patch_symtabs.was_symbol_patched[obj_idx][symbol_idx] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task)
|
THREAD_POOL_TASK_FUNC(lnk_patch_comdat_leaders_task)
|
||||||
{
|
{
|
||||||
@@ -2676,14 +2701,10 @@ lnk_patch_obj_symtab(LNK_SymbolTable *symtab, LNK_Obj *obj, B8 *was_symbol_patch
|
|||||||
if (is_resolved) {
|
if (is_resolved) {
|
||||||
COFF_ParsedSymbol fixup_src = lnk_parsed_symbol_from_coff_symbol_idx(fixup_symbol.obj, fixup_symbol.symbol_idx);
|
COFF_ParsedSymbol fixup_src = lnk_parsed_symbol_from_coff_symbol_idx(fixup_symbol.obj, fixup_symbol.symbol_idx);
|
||||||
COFF_SymbolValueInterpType fixup_type = coff_interp_symbol(fixup_src.section_number, fixup_src.value, fixup_src.storage_class);
|
COFF_SymbolValueInterpType fixup_type = coff_interp_symbol(fixup_src.section_number, fixup_src.value, fixup_src.storage_class);
|
||||||
AssertAlways(fixup_type == COFF_SymbolValueInterp_Regular ||
|
|
||||||
fixup_type == COFF_SymbolValueInterp_Abs ||
|
|
||||||
fixup_type == COFF_SymbolValueInterp_Common ||
|
|
||||||
fixup_type == COFF_SymbolValueInterp_Undefined);
|
|
||||||
|
|
||||||
U32 section_number;
|
U32 section_number;
|
||||||
U32 value;
|
U32 value;
|
||||||
if (fixup_type == COFF_SymbolValueInterp_Undefined) {
|
if (fixup_type == COFF_SymbolValueInterp_Undefined || fixup_type == COFF_SymbolValueInterp_Weak) {
|
||||||
section_number = lnk_obj_get_removed_section_number(obj);
|
section_number = lnk_obj_get_removed_section_number(obj);
|
||||||
value = 0;
|
value = 0;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user