mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
bugfix import linking
This commit is contained in:
@@ -266,6 +266,7 @@
|
|||||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((LONG *)(x),(k),(c))
|
# define ins_atomic_u32_eval_cond_assign(x,k,c) InterlockedCompareExchange((LONG *)(x),(k),(c))
|
||||||
# define ins_atomic_u32_add_eval(x,c) InterlockedAdd((LONG *)(x), (c))
|
# define ins_atomic_u32_add_eval(x,c) InterlockedAdd((LONG *)(x), (c))
|
||||||
# define ins_atomic_u8_eval_assign(x,c) InterlockedExchange8((CHAR *)(x), (c))
|
# define ins_atomic_u8_eval_assign(x,c) InterlockedExchange8((CHAR *)(x), (c))
|
||||||
|
# define ins_atomic_u8_or(x,c) InterlockedOr8((char *)(x), (char)c)
|
||||||
# else
|
# else
|
||||||
# error Atomic intrinsics not defined for this compiler / architecture combination.
|
# error Atomic intrinsics not defined for this compiler / architecture combination.
|
||||||
# endif
|
# endif
|
||||||
@@ -284,6 +285,7 @@
|
|||||||
# define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST)
|
# define ins_atomic_u32_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST)
|
||||||
# define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
|
# define ins_atomic_u32_eval_cond_assign(x,k,c) ({ U32 _new = (c); __atomic_compare_exchange_n((U32 *)(x),&_new,(k),0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); _new; })
|
||||||
# define ins_atomic_u8_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST)
|
# define ins_atomic_u8_eval_assign(x,c) __atomic_exchange_n((x), (c), __ATOMIC_SEQ_CST)
|
||||||
|
# define ins_atomic_u8_or(x,c) __atomic_fetch_or((U8 *)(x), (U8)(c), __ATOMIC_SEQ_CST)
|
||||||
#else
|
#else
|
||||||
# error Atomic intrinsics not defined for this compiler / architecture.
|
# error Atomic intrinsics not defined for this compiler / architecture.
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+9
-22
@@ -1488,6 +1488,7 @@ lnk_queue_lib_member(Arena *arena, LNK_LibMemberRefList *queued_members, LNK_Sym
|
|||||||
LNK_LibMemberRef *member_ref = push_array(arena, LNK_LibMemberRef, 1);
|
LNK_LibMemberRef *member_ref = push_array(arena, LNK_LibMemberRef, 1);
|
||||||
member_ref->lib = lib;
|
member_ref->lib = lib;
|
||||||
member_ref->member_idx = member_idx;
|
member_ref->member_idx = member_idx;
|
||||||
|
member_ref->link_symbol = link_symbol;
|
||||||
lnk_lib_member_ref_list_push_node(queued_members, member_ref);
|
lnk_lib_member_ref_list_push_node(queued_members, member_ref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1583,7 +1584,7 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
|
|
||||||
LNK_LibMemberRef *member_ref = member_refs[i];
|
LNK_LibMemberRef *member_ref = member_refs[i];
|
||||||
LNK_Lib *lib = member_ref->lib;
|
LNK_Lib *lib = member_ref->lib;
|
||||||
LNK_Symbol *link_symbol = lib->member_links[member_ref->member_idx];
|
LNK_Symbol *link_symbol = member_ref->link_symbol;
|
||||||
|
|
||||||
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_ref->member_idx]);
|
COFF_ArchiveMember member_info = coff_archive_member_from_offset(lib->data, lib->member_offsets[member_ref->member_idx]);
|
||||||
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
|
COFF_DataType member_type = coff_data_type_from_data(member_info.data);
|
||||||
@@ -1612,35 +1613,21 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
|
|
||||||
switch (member_type) {
|
switch (member_type) {
|
||||||
case COFF_DataType_Import: {
|
case COFF_DataType_Import: {
|
||||||
LNK_Symbol *link_symbol = lib->member_links[member_idx];
|
// find import stub
|
||||||
|
|
||||||
LNK_Symbol *import_symbols[2] = {0};
|
|
||||||
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
|
||||||
import_symbols[0] = link_symbol;
|
|
||||||
import_symbols[1] = lnk_symbol_table_search(symtab, str8_skip(link_symbol->name, str8_lit("__imp_").size));
|
|
||||||
} else {
|
|
||||||
Temp temp = temp_begin(scratch.arena);
|
|
||||||
String8 imp_name = push_str8f(temp.arena, "__imp_%S", link_symbol->name);
|
|
||||||
import_symbols[0] = lnk_symbol_table_search(symtab, imp_name);
|
|
||||||
import_symbols[1] = link_symbol;
|
|
||||||
temp_end(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for EachIndex(i, ArrayCount(import_symbols)) {
|
|
||||||
LNK_Symbol *import_symbol = import_symbols[i];
|
|
||||||
if (import_symbol == 0) { continue; }
|
|
||||||
|
|
||||||
LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, str8_lit(LNK_IMPORT_STUB));
|
LNK_Symbol *import_stub = lnk_symbol_table_search(symtab, str8_lit(LNK_IMPORT_STUB));
|
||||||
|
|
||||||
// same import symbol must never be queued more than once, if it is, there is a bug in the link set logic
|
// same import symbol must never be queued more than once, if it is, there is a bug in the link set logic
|
||||||
AssertAlways(import_symbol->refs != import_stub->refs);
|
AssertAlways(member_ref->link_symbol->refs != import_stub->refs);
|
||||||
|
|
||||||
// replace the import symbol with a stub, which is later replaced with the real import symbol once import obj is ready
|
// replace the import symbol with a stub, which is later replaced with the real import symbol once import obj is ready
|
||||||
import_symbol->refs = import_stub->refs;
|
member_ref->link_symbol->refs = import_stub->refs;
|
||||||
}
|
|
||||||
|
|
||||||
// push import member for import obj generation
|
// push import member for import obj generation
|
||||||
|
LNK_LibMemberFlags member_flags = lib->member_flags[member_ref->member_idx];
|
||||||
|
B32 is_first_link = member_flags != (LNK_LibMemberFlag_LinkedRegular | LNK_LibMemberFlag_LinkedImp);
|
||||||
|
if (is_first_link) {
|
||||||
lnk_lib_member_ref_list_push_node(&link->imports, member_ref);
|
lnk_lib_member_ref_list_push_node(&link->imports, member_ref);
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
case COFF_DataType_BigObj:
|
case COFF_DataType_BigObj:
|
||||||
case COFF_DataType_Obj: {
|
case COFF_DataType_Obj: {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ typedef struct LNK_LibMemberRef
|
|||||||
{
|
{
|
||||||
LNK_Lib *lib;
|
LNK_Lib *lib;
|
||||||
U32 member_idx;
|
U32 member_idx;
|
||||||
|
LNK_Symbol *link_symbol;
|
||||||
struct LNK_LibMemberRef *next;
|
struct LNK_LibMemberRef *next;
|
||||||
} LNK_LibMemberRef;
|
} LNK_LibMemberRef;
|
||||||
|
|
||||||
@@ -183,6 +184,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
B32 search_anti_deps;
|
B32 search_anti_deps;
|
||||||
LNK_SymbolTable *symtab;
|
LNK_SymbolTable *symtab;
|
||||||
|
LNK_Symbol *import_stub;
|
||||||
LNK_Lib *lib;
|
LNK_Lib *lib;
|
||||||
LNK_LibMemberRefList *member_ref_lists;
|
LNK_LibMemberRefList *member_ref_lists;
|
||||||
} LNK_SearchLibTask;
|
} LNK_SearchLibTask;
|
||||||
|
|||||||
+15
-11
@@ -142,6 +142,7 @@ lnk_lib_from_data(Arena *arena, String8 data, String8 path, U64 input_idx, LNK_L
|
|||||||
lib_out->member_offsets = member_offsets;
|
lib_out->member_offsets = member_offsets;
|
||||||
lib_out->symbol_indices = symbol_indices;
|
lib_out->symbol_indices = symbol_indices;
|
||||||
lib_out->member_links = push_array(arena, LNK_Symbol *, member_count);
|
lib_out->member_links = push_array(arena, LNK_Symbol *, member_count);
|
||||||
|
lib_out->member_flags = push_array(arena, LNK_LibMemberFlags, member_count);
|
||||||
lib_out->symbol_names = symbol_names;
|
lib_out->symbol_names = symbol_names;
|
||||||
lib_out->long_names = parse.long_names;
|
lib_out->long_names = parse.long_names;
|
||||||
lib_out->input_idx = input_idx;
|
lib_out->input_idx = input_idx;
|
||||||
@@ -224,15 +225,21 @@ lnk_lib_list_push_parallel(TP_Context *tp, TP_Arena *arena, LNK_LibList *list, U
|
|||||||
internal B32
|
internal B32
|
||||||
lnk_lib_set_link_symbol(LNK_Lib *lib, U32 member_idx, LNK_Symbol *link_symbol)
|
lnk_lib_set_link_symbol(LNK_Lib *lib, U32 member_idx, LNK_Symbol *link_symbol)
|
||||||
{
|
{
|
||||||
local_persist LNK_Symbol null_symbol;
|
B32 was_linked;
|
||||||
|
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
||||||
LNK_Symbol *slot = ins_atomic_ptr_eval_assign(&lib->member_links[member_idx], &null_symbol);
|
U8 member_flags = ins_atomic_u8_or(&lib->member_flags[member_idx], LNK_LibMemberFlag_LinkedImp);
|
||||||
|
was_linked = !!(~member_flags & LNK_LibMemberFlag_LinkedImp);
|
||||||
B32 was_linked = (slot == 0);
|
} else {
|
||||||
|
U8 flag = LNK_LibMemberFlag_LinkedRegular;
|
||||||
|
U8 member_flags = ins_atomic_u8_or(&lib->member_flags[member_idx], LNK_LibMemberFlag_LinkedRegular);
|
||||||
|
was_linked = !!(~member_flags & LNK_LibMemberFlag_LinkedRegular);
|
||||||
|
}
|
||||||
|
|
||||||
for (LNK_Symbol *leader = link_symbol;;) {
|
for (LNK_Symbol *leader = link_symbol;;) {
|
||||||
|
LNK_Symbol *slot = ins_atomic_ptr_eval_assign(&lib->member_links[member_idx], 0);
|
||||||
|
|
||||||
// update slot symbol if it is empty or link symbol comes before symbol in the slot
|
// update slot symbol if it is empty or link symbol comes before symbol in the slot
|
||||||
if (slot && slot != &null_symbol) {
|
if (slot) {
|
||||||
if (lnk_symbol_is_before(slot, leader)) {
|
if (lnk_symbol_is_before(slot, leader)) {
|
||||||
leader = slot;
|
leader = slot;
|
||||||
}
|
}
|
||||||
@@ -241,15 +248,12 @@ lnk_lib_set_link_symbol(LNK_Lib *lib, U32 member_idx, LNK_Symbol *link_symbol)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to insert back updated slot symbol
|
// try to insert back updated slot symbol
|
||||||
LNK_Symbol *swap = ins_atomic_ptr_eval_cond_assign(&lib->member_links[member_idx], leader, &null_symbol);
|
LNK_Symbol *swap = ins_atomic_ptr_eval_cond_assign(&lib->member_links[member_idx], leader, 0);
|
||||||
|
|
||||||
// exit if slot symbol was null
|
// exit if slot symbol was null
|
||||||
if (swap == &null_symbol) {
|
if (swap == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reload slot symbol
|
|
||||||
slot = ins_atomic_ptr_eval_assign(&lib->member_links[member_idx], &null_symbol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return was_linked;
|
return was_linked;
|
||||||
|
|||||||
@@ -3,6 +3,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
typedef U8 LNK_LibMemberFlags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
LNK_LibMemberFlag_LinkedRegular = (1 << 0),
|
||||||
|
LNK_LibMemberFlag_LinkedImp = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct LNK_Lib
|
typedef struct LNK_Lib
|
||||||
{
|
{
|
||||||
String8 path;
|
String8 path;
|
||||||
@@ -13,6 +20,7 @@ typedef struct LNK_Lib
|
|||||||
U32 *member_offsets;
|
U32 *member_offsets;
|
||||||
U16 *symbol_indices;
|
U16 *symbol_indices;
|
||||||
LNK_Symbol **member_links;
|
LNK_Symbol **member_links;
|
||||||
|
LNK_LibMemberFlags *member_flags;
|
||||||
String8Array symbol_names;
|
String8Array symbol_names;
|
||||||
String8 long_names;
|
String8 long_names;
|
||||||
U64 input_idx;
|
U64 input_idx;
|
||||||
|
|||||||
Reference in New Issue
Block a user