mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
make use of undocumented anti-dependency search property on weak symbols
to implement alternate name using weak symbols
This commit is contained in:
committed by
Ryan Fleury
parent
8d246d0c6a
commit
c1958809eb
+4
-3
@@ -294,9 +294,10 @@ typedef struct COFF_Symbol32
|
||||
typedef U32 COFF_WeakExtType;
|
||||
enum
|
||||
{
|
||||
COFF_WeakExt_NoLibrary = 1,
|
||||
COFF_WeakExt_SearchLibrary = 2,
|
||||
COFF_WeakExt_SearchAlias = 3
|
||||
COFF_WeakExt_NoLibrary = 1,
|
||||
COFF_WeakExt_SearchLibrary = 2,
|
||||
COFF_WeakExt_SearchAlias = 3,
|
||||
COFF_WeakExt_AntiDependency = 4, // default symbol must not reference a weak symbol
|
||||
};
|
||||
|
||||
// storage class: External
|
||||
|
||||
+30
-6
@@ -1076,6 +1076,7 @@ THREAD_POOL_TASK_FUNC(lnk_weak_symbol_finder)
|
||||
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(task->symtab, LNK_SymbolScope_Lib, symbol->name);
|
||||
} break;
|
||||
@@ -1550,9 +1551,32 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_InputAlternateNames: {
|
||||
ProfBegin("Input Alternate Names");
|
||||
COFF_ObjWriter *obj_writer = 0;
|
||||
for (; *last_alt_name; last_alt_name = &(*last_alt_name)->next) {
|
||||
lnk_symbol_table_push_alt_name(symtab, 0, (*last_alt_name)->data.from, (*last_alt_name)->data.to);
|
||||
// make object writer if it was reset
|
||||
if (obj_writer == 0) {
|
||||
obj_writer = coff_obj_writer_alloc(0, COFF_MachineType_Unknown);
|
||||
}
|
||||
|
||||
// append weak symbol
|
||||
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);
|
||||
|
||||
// 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);
|
||||
input->path = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->path : str8_lit("RADLINK");
|
||||
input->dedup_id = push_str8f(scratch.arena, "* ALTERNATE NAMES FOR %S *", input->path);
|
||||
input->data = coff_obj_writer_serialize(tp_arena->v[0], obj_writer);
|
||||
input->lib = (*last_alt_name)->data.obj ? (*last_alt_name)->data.obj->lib : 0;
|
||||
|
||||
// reset obj writer
|
||||
coff_obj_writer_release(&obj_writer);
|
||||
obj_writer = 0;
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
} break;
|
||||
case State_PushDllHelperUndefSymbol: {
|
||||
ProfBegin("Push Dll Helper Undef Symbol");
|
||||
@@ -1997,6 +2021,10 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
state_list_push(scratch.arena, state_list, State_InputSymbols);
|
||||
continue;
|
||||
}
|
||||
if (*last_alt_name != 0) {
|
||||
state_list_push(scratch.arena, state_list, State_InputAlternateNames);
|
||||
continue;
|
||||
}
|
||||
if (input_obj_list.count) {
|
||||
state_list_push(scratch.arena, state_list, State_InputObjs);
|
||||
continue;
|
||||
@@ -2014,10 +2042,6 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*last_alt_name != 0) {
|
||||
state_list_push(scratch.arena, state_list, State_InputAlternateNames);
|
||||
continue;
|
||||
}
|
||||
if (lookup_undef_list.count) {
|
||||
state_list_push(scratch.arena, state_list, State_LookupUndef);
|
||||
continue;
|
||||
@@ -2054,7 +2078,7 @@ lnk_build_link_context(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config)
|
||||
}
|
||||
|
||||
// pass over symbol table and replace weak symbols without a strong definition with fallback definitions
|
||||
lnk_finalize_weak_symbols(tp, symtab);
|
||||
lnk_finalize_weak_symbols(tp_arena, tp, symtab);
|
||||
|
||||
// log
|
||||
{
|
||||
|
||||
+21
-6
@@ -609,6 +609,7 @@ lnk_parse_alt_name_directive(String8 string, LNK_Obj *obj, LNK_AltName *alt_out)
|
||||
if (pair.node_count == 2) {
|
||||
alt_out->from = pair.first->string;
|
||||
alt_out->to = pair.last->string;
|
||||
alt_out->obj = obj;
|
||||
is_parse_ok = 1;
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, LNK_CmdSwitch_AlternateName, "syntax error in \"%S\", expected format \"FROM=TO\"", string);
|
||||
@@ -1092,12 +1093,25 @@ lnk_apply_cmd_option_to_config(Arena *arena, LNK_Config *config, String8 cmd_nam
|
||||
if (value_strings.node_count == 1) {
|
||||
LNK_AltName alt_name;
|
||||
if (lnk_parse_alt_name_directive(value_strings.first->string, obj, &alt_name)) {
|
||||
alt_name.from = push_str8_copy(arena, alt_name.from);
|
||||
alt_name.to = push_str8_copy(arena, alt_name.to);
|
||||
LNK_AltNameNode *alt_name_n = push_array(arena, LNK_AltNameNode, 1);
|
||||
alt_name_n->data = alt_name;
|
||||
SLLQueuePush(config->alt_name_list.first, config->alt_name_list.last, alt_name_n);
|
||||
config->alt_name_list.count += 1;
|
||||
String8 to_extant = {0};
|
||||
if (hash_table_search_string_string(config->alt_name_ht, alt_name.from, &to_extant)) {
|
||||
if (str8_match(to_extant, alt_name.to, 0)) {
|
||||
// ignore, duplicate
|
||||
} else {
|
||||
lnk_error_obj(LNK_Error_AlternateNameConflict, obj, "conflicting alternative name: existing '%S=%S' vs. new '%S=%S'", alt_name.from, to_extant, alt_name.from, alt_name.to);
|
||||
}
|
||||
} else {
|
||||
hash_table_push_string_string(arena, config->alt_name_ht, alt_name.from, alt_name.to);
|
||||
|
||||
alt_name.from = push_str8_copy(arena, alt_name.from);
|
||||
alt_name.to = push_str8_copy(arena, alt_name.to);
|
||||
|
||||
LNK_AltNameNode *alt_name_n = push_array(arena, LNK_AltNameNode, 1);
|
||||
alt_name_n->data = alt_name;
|
||||
|
||||
SLLQueuePush(config->alt_name_list.first, config->alt_name_list.last, alt_name_n);
|
||||
config->alt_name_list.count += 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "invalid number of parameters");
|
||||
@@ -1973,6 +1987,7 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line, LNK_CmdLine cmd
|
||||
config->pdb_hash_type_name_length = 8;
|
||||
config->data_dir_count = PE_DataDirectoryIndex_COUNT;
|
||||
config->export_ht = hash_table_init(scratch.arena, max_U16/2);
|
||||
config->alt_name_ht = hash_table_init(scratch.arena, 0x100);
|
||||
|
||||
// process command line switches
|
||||
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
|
||||
|
||||
@@ -253,6 +253,7 @@ typedef struct LNK_AltName
|
||||
{
|
||||
String8 from;
|
||||
String8 to;
|
||||
struct LNK_Obj *obj;
|
||||
} LNK_AltName;
|
||||
|
||||
typedef struct LNK_AltNameNode
|
||||
@@ -392,6 +393,7 @@ typedef struct LNK_Config
|
||||
String8List remove_sections;
|
||||
LNK_IO_Flags io_flags;
|
||||
HashTable *export_ht;
|
||||
HashTable *alt_name_ht;
|
||||
} LNK_Config;
|
||||
|
||||
// --- MSVC Error Codes --------------------------------------------------------
|
||||
@@ -563,6 +565,7 @@ internal B32 lnk_parse_merge_directive (String8 string, struct LNK_Obj *obj,
|
||||
internal B32 lnk_parse_export_directive (Arena *arena, String8 directive, struct LNK_Obj *obj, PE_ExportParse *export_out);
|
||||
internal B32 lnk_parse_export_directive_ex(Arena *arena, String8List directive, struct LNK_Obj *obj, PE_ExportParse *export_out);
|
||||
|
||||
internal LNK_AltNameNode * lnk_alt_name_list_push(Arena *arena, LNK_AltNameList *list, LNK_AltName data);
|
||||
internal LNK_MergeDirectiveNode * lnk_merge_directive_list_push(Arena *arena, LNK_MergeDirectiveList *list, LNK_MergeDirective data);
|
||||
|
||||
// --- Getters -----------------------------------------------------------------
|
||||
|
||||
@@ -75,6 +75,12 @@ lnk_symbol_list_concat_in_place(LNK_SymbolList *list, LNK_SymbolList *to_concat)
|
||||
SLLConcatInPlace(list, to_concat);
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_symbol_concat_in_place_array(LNK_SymbolList *list, LNK_SymbolList *to_concat, U64 to_concat_count)
|
||||
{
|
||||
SLLConcatInPlaceArray(list, to_concat, to_concat_count);
|
||||
}
|
||||
|
||||
internal LNK_SymbolList
|
||||
lnk_symbol_list_from_array(Arena *arena, LNK_SymbolArray arr)
|
||||
{
|
||||
@@ -467,7 +473,6 @@ lnk_symbol_table_init(TP_Arena *arena)
|
||||
for (U64 i = 0; i < LNK_SymbolScope_Count; ++i) {
|
||||
symtab->chunk_lists[i] = push_array(arena->v[0], LNK_SymbolHashTrieChunkList, arena->count);
|
||||
}
|
||||
symtab->alt_names = hash_table_init(arena->v[0], 1024);
|
||||
return symtab;
|
||||
}
|
||||
|
||||
@@ -487,15 +492,8 @@ lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_SymbolScope scope, LNK_Symbol
|
||||
internal LNK_Symbol *
|
||||
lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name)
|
||||
{
|
||||
U64 hash = lnk_symbol_hash(name);
|
||||
U64 hash = lnk_symbol_hash(name);
|
||||
LNK_SymbolHashTrie *trie = lnk_symbol_hash_trie_search(symtab->scopes[scope], hash, name);
|
||||
if (trie == 0) {
|
||||
String8 alt_name = {0};
|
||||
if (hash_table_search_string_string(symtab->alt_names, name, &alt_name)) {
|
||||
U64 alt_hash = lnk_symbol_hash(alt_name);
|
||||
trie = lnk_symbol_hash_trie_search(symtab->scopes[scope], alt_hash, alt_name);
|
||||
}
|
||||
}
|
||||
return trie ? trie->symbol : 0;
|
||||
}
|
||||
|
||||
@@ -514,16 +512,39 @@ lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *f
|
||||
return symbol;
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_symbol_table_push_alt_name(LNK_SymbolTable *symtab, LNK_Obj *obj, String8 from, String8 to)
|
||||
internal
|
||||
THREAD_POOL_TASK_FUNC(lnk_check_anti_dependecy_task)
|
||||
{
|
||||
String8 to_extant;
|
||||
if (hash_table_search_string_string(symtab->alt_names, from, &to_extant)) {
|
||||
if (!str8_match(to_extant, to, 0)) {
|
||||
lnk_error_obj(LNK_Error_AlternateNameConflict, obj, "conflicting alternative name: existing '%S=%S' vs. new '%S=%S'", from, to_extant, from, to);
|
||||
LNK_FinalizeWeakSymbolsTask *task = raw_task;
|
||||
LNK_SymbolTable *symtab = task->symtab;
|
||||
LNK_SymbolHashTrieChunk *chunk = task->chunks[task_id];
|
||||
|
||||
for EachIndex(i, chunk->count) {
|
||||
LNK_Symbol *symbol = chunk->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) {
|
||||
COFF_ParsedSymbol default_symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, weak_ext->tag_index);
|
||||
COFF_SymbolValueInterpType default_symbol_interp = coff_interp_from_parsed_symbol(default_symbol_parsed);
|
||||
|
||||
COFF_SymbolValueInterpType actual_default_symbol_interp = default_symbol_interp;
|
||||
if (default_symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
||||
LNK_Symbol *actual_default_symbol = lnk_symbol_table_search(symtab, LNK_SymbolScope_Defined, default_symbol_parsed.name);
|
||||
if (actual_default_symbol) {
|
||||
COFF_ParsedSymbol actual_default_symbol_parsed = lnk_parsed_symbol_from_defined(actual_default_symbol);
|
||||
actual_default_symbol_interp = coff_interp_from_parsed_symbol(actual_default_symbol_parsed);
|
||||
}
|
||||
}
|
||||
|
||||
if (actual_default_symbol_interp == COFF_SymbolValueInterp_Weak) {
|
||||
LNK_SymbolNode *symbol_n = push_array(arena, LNK_SymbolNode, 1);
|
||||
symbol_n->data = symbol;
|
||||
lnk_symbol_list_push_node(&task->anti_dependency_symbols[task_id], symbol_n);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hash_table_push_string_string(symtab->arena->v[0], symtab->alt_names, from, to);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,10 +559,10 @@ THREAD_POOL_TASK_FUNC(lnk_finalize_weak_symbols_task)
|
||||
|
||||
for EachIndex(i, chunk->count) {
|
||||
LNK_Symbol *symbol = chunk->v[i].symbol;
|
||||
COFF_ParsedSymbol symbol_parsed = lnk_parsed_symbol_from_coff_symbol_idx(symbol->u.defined.obj, symbol->u.defined.symbol_idx);
|
||||
COFF_SymbolValueInterpType symbol_interp = coff_interp_symbol(symbol_parsed.section_number, symbol_parsed.value, symbol_parsed.storage_class);
|
||||
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) {
|
||||
struct LookupLocation { struct LookupLocation *next; LNK_SymbolDefined symbol; };
|
||||
struct LookupLocation { struct LookupLocation *next; LNK_SymbolDefined symbol; B32 is_anti_dependency; };
|
||||
struct LookupLocation *lookup_first = 0, *lookup_last = 0;
|
||||
|
||||
LNK_SymbolDefined current_symbol = symbol->u.defined;
|
||||
@@ -615,10 +636,10 @@ THREAD_POOL_TASK_FUNC(lnk_finalize_weak_symbols_task)
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_finalize_weak_symbols(TP_Context *tp, LNK_SymbolTable *symtab)
|
||||
lnk_finalize_weak_symbols(TP_Arena *arena, TP_Context *tp, LNK_SymbolTable *symtab)
|
||||
{
|
||||
ProfBeginFunction();
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
Temp scratch = scratch_begin(arena->v, arena->count);
|
||||
|
||||
U64 chunks_count = 0;
|
||||
for EachIndex(worker_id, tp->worker_count) { chunks_count += symtab->chunk_lists[LNK_SymbolScope_Defined][worker_id].count; }
|
||||
@@ -632,6 +653,25 @@ lnk_finalize_weak_symbols(TP_Context *tp, LNK_SymbolTable *symtab)
|
||||
}
|
||||
|
||||
LNK_FinalizeWeakSymbolsTask task = { .symtab = symtab, .chunks = chunks };
|
||||
|
||||
{
|
||||
TP_Temp temp = tp_temp_begin(arena);
|
||||
task.anti_dependency_symbols = push_array(scratch.arena, LNK_SymbolList, tp->worker_count);
|
||||
tp_for_parallel(tp, arena, chunks_count, lnk_check_anti_dependecy_task, &task);
|
||||
|
||||
LNK_SymbolList anti_dependency_symbol_list = {0};
|
||||
lnk_symbol_concat_in_place_array(&anti_dependency_symbol_list, task.anti_dependency_symbols, tp->worker_count);
|
||||
LNK_SymbolArray anti_dependency_symbols = lnk_symbol_array_from_list(scratch.arena, anti_dependency_symbol_list);
|
||||
radsort(anti_dependency_symbols.v, anti_dependency_symbols.count, lnk_symbol_defined_is_before);
|
||||
|
||||
for EachIndex(symbol_idx, anti_dependency_symbols.count) {
|
||||
LNK_Symbol *s = &anti_dependency_symbols.v[symbol_idx];
|
||||
lnk_error_obj(LNK_Error_UnresolvedSymbol, s->u.defined.obj, "unresolved symbol %S", s->name);
|
||||
}
|
||||
|
||||
tp_temp_end(temp);
|
||||
}
|
||||
|
||||
tp_for_parallel(tp, 0, chunks_count, lnk_finalize_weak_symbols_task, &task);
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
@@ -104,7 +104,6 @@ typedef struct LNK_SymbolTable
|
||||
TP_Arena *arena;
|
||||
LNK_SymbolHashTrie *scopes[LNK_SymbolScope_Count];
|
||||
LNK_SymbolHashTrieChunkList *chunk_lists[LNK_SymbolScope_Count];
|
||||
HashTable *alt_names;
|
||||
} LNK_SymbolTable;
|
||||
|
||||
// --- Workers Contensts -------------------------------------------------------
|
||||
@@ -113,6 +112,7 @@ typedef struct
|
||||
{
|
||||
LNK_SymbolTable *symtab;
|
||||
LNK_SymbolHashTrieChunk **chunks;
|
||||
LNK_SymbolList *anti_dependency_symbols;
|
||||
} LNK_FinalizeWeakSymbolsTask;
|
||||
|
||||
// --- Symbol Make -------------------------------------------------------------
|
||||
@@ -127,6 +127,7 @@ internal LNK_Symbol * lnk_make_import_symbol(Arena *arena, String8 name, String8
|
||||
internal void lnk_symbol_list_push_node(LNK_SymbolList *list, LNK_SymbolNode *node);
|
||||
internal LNK_SymbolNode * lnk_symbol_list_push(Arena *arena, LNK_SymbolList *list, LNK_Symbol *symbol);
|
||||
internal void lnk_symbol_list_concat_in_place(LNK_SymbolList *list, LNK_SymbolList *to_concat);
|
||||
internal void lnk_symbol_concat_in_place_array(LNK_SymbolList *list, LNK_SymbolList *to_concat, U64 to_concat_count);
|
||||
internal LNK_SymbolList lnk_symbol_list_from_array(Arena *arena, LNK_SymbolArray arr);
|
||||
internal LNK_SymbolNodeArray lnk_symbol_node_array_from_list(Arena *arena, LNK_SymbolList list);
|
||||
internal LNK_SymbolArray lnk_symbol_array_from_list(Arena *arena, LNK_SymbolList list);
|
||||
@@ -146,9 +147,7 @@ internal void lnk_symbol_table_push(LNK_SymbolTable *symtab, LNK_Sy
|
||||
internal LNK_Symbol * lnk_symbol_table_search(LNK_SymbolTable *symtab, LNK_SymbolScope scope, String8 name);
|
||||
internal LNK_Symbol * lnk_symbol_table_searchf(LNK_SymbolTable *symtab, LNK_SymbolScope scope, char *fmt, ...);
|
||||
|
||||
internal void lnk_symbol_table_push_alt_name(LNK_SymbolTable *symtab, struct LNK_Obj *obj, String8 from, String8 to);
|
||||
|
||||
internal void lnk_finalize_weak_symbols(TP_Context *tp, LNK_SymbolTable *symtab);
|
||||
internal void lnk_finalize_weak_symbols(TP_Arena *arena, TP_Context *tp, LNK_SymbolTable *symtab);
|
||||
|
||||
// --- Symbol Contrib Helpers --------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user