mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 09:18:09 +00:00
fix duplicate defer import link
This commit is contained in:
@@ -757,6 +757,19 @@ hash_map_push_path_raw(Arena *arena, HashMap *hm, String8 path, void *value)
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
internal void *
|
||||||
|
hash_map_search_stringf_raw(HashMap *hm, char *fmt, ...)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0,0);
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
String8 string = push_str8fv(scratch.arena, fmt, args);
|
||||||
|
void *raw = hash_map_search_string_raw(hm, string);
|
||||||
|
va_end(args);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
internal void *
|
internal void *
|
||||||
hash_map_search_string_raw(HashMap *hm, String8 key)
|
hash_map_search_string_raw(HashMap *hm, String8 key)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ internal HashMapNode * hash_map_push_path_u64 (Arena *arena, HashMap *hm, St
|
|||||||
internal HashMapNode * hash_map_push_path_string (Arena *arena, HashMap *hm, String8 path, String8 value);
|
internal HashMapNode * hash_map_push_path_string (Arena *arena, HashMap *hm, String8 path, String8 value);
|
||||||
internal HashMapNode * hash_map_push_path_raw (Arena *arena, HashMap *hm, String8 path, void *value);
|
internal HashMapNode * hash_map_push_path_raw (Arena *arena, HashMap *hm, String8 path, void *value);
|
||||||
|
|
||||||
|
internal void * hash_map_search_stringf_raw(HashMap *hm, char *fmt, ...);
|
||||||
internal void * hash_map_search_string_raw(HashMap *hm, String8 key);
|
internal void * hash_map_search_string_raw(HashMap *hm, String8 key);
|
||||||
internal U32 * hash_map_search_string_u32(HashMap *hm, String8 key);
|
internal U32 * hash_map_search_string_u32(HashMap *hm, String8 key);
|
||||||
internal U64 * hash_map_search_string_u64(HashMap *hm, String8 key);
|
internal U64 * hash_map_search_string_u64(HashMap *hm, String8 key);
|
||||||
|
|||||||
+71
-23
@@ -1487,7 +1487,14 @@ lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnk_queue_lib_member(Arena *arena, LNK_LibMemberRefList *queued_members, LNK_Symbol *link_symbol, LNK_Lib *lib, LNK_LibMemberInfo *member_infos, U32 member_idx)
|
lnk_queue_lib_member(Arena *arena,
|
||||||
|
HashMap *imports_hm,
|
||||||
|
HashMap lib_member_info_hm,
|
||||||
|
LNK_LibMemberRefList *queued_members,
|
||||||
|
LNK_Symbol *link_symbol,
|
||||||
|
LNK_Lib *lib,
|
||||||
|
LNK_LibMemberInfo *member_infos,
|
||||||
|
U32 member_idx)
|
||||||
{
|
{
|
||||||
// associate link symbol to lib member
|
// associate link symbol to lib member
|
||||||
for (LNK_Symbol *leader = link_symbol;;) {
|
for (LNK_Symbol *leader = link_symbol;;) {
|
||||||
@@ -1511,23 +1518,43 @@ lnk_queue_lib_member(Arena *arena, LNK_LibMemberRefList *queued_members, LNK_Sym
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
B32 was_linked;
|
LNK_LibMemberRef *is_thunk_import;
|
||||||
|
LNK_LibMemberRef *is_addr_import;
|
||||||
|
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
||||||
|
is_thunk_import = hash_map_search_string_raw(imports_hm, str8_skip(link_symbol->name, 6));
|
||||||
|
is_addr_import = hash_map_search_string_raw(imports_hm, link_symbol->name);
|
||||||
|
} else {
|
||||||
|
is_thunk_import = hash_map_search_string_raw(imports_hm, link_symbol->name);
|
||||||
|
is_addr_import = hash_map_search_stringf_raw(imports_hm, "__imp_%S", link_symbol->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
LNK_LibMemberRef *is_queued_import = is_thunk_import ? is_thunk_import :
|
||||||
|
is_addr_import ? is_addr_import : 0;
|
||||||
|
|
||||||
|
if (is_queued_import) {
|
||||||
|
// do not queue second import member link -- flag member and continue
|
||||||
|
U8 flag = str8_starts_with(link_symbol->name, str8_lit("__imp_")) ? LNK_LibMemberFlag_LinkedImp : LNK_LibMemberFlag_LinkedRegular;
|
||||||
|
LNK_LibMemberInfo *import_member_infos = hash_map_search_raw_raw(&lib_member_info_hm, is_queued_import->lib);
|
||||||
|
ins_atomic_u8_or(&import_member_infos[member_idx].flags, flag);
|
||||||
|
} else {
|
||||||
|
B32 do_queue;
|
||||||
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
||||||
U8 member_flags = ins_atomic_u8_or(&member_infos[member_idx].flags, LNK_LibMemberFlag_LinkedImp);
|
U8 member_flags = ins_atomic_u8_or(&member_infos[member_idx].flags, LNK_LibMemberFlag_LinkedImp);
|
||||||
was_linked = !(member_flags & LNK_LibMemberFlag_LinkedImp);
|
do_queue = !(member_flags & LNK_LibMemberFlag_LinkedImp);
|
||||||
} else {
|
} else {
|
||||||
U8 flag = LNK_LibMemberFlag_LinkedRegular;
|
U8 flag = LNK_LibMemberFlag_LinkedRegular;
|
||||||
U8 member_flags = ins_atomic_u8_or(&member_infos[member_idx].flags, LNK_LibMemberFlag_LinkedRegular);
|
U8 member_flags = ins_atomic_u8_or(&member_infos[member_idx].flags, LNK_LibMemberFlag_LinkedRegular);
|
||||||
was_linked = !(member_flags & LNK_LibMemberFlag_LinkedRegular);
|
do_queue = !(member_flags & LNK_LibMemberFlag_LinkedRegular);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (was_linked) {
|
if (do_queue) {
|
||||||
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;
|
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);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal
|
internal
|
||||||
@@ -1550,14 +1577,14 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
|
|||||||
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
if (symbol_interp == COFF_SymbolValueInterp_Undefined) {
|
||||||
U32 member_idx;
|
U32 member_idx;
|
||||||
if (lnk_search_lib(lib, symbol->name, &member_idx)) {
|
if (lnk_search_lib(lib, symbol->name, &member_idx)) {
|
||||||
lnk_queue_lib_member(arena, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
||||||
}
|
}
|
||||||
} else if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
} else if (symbol_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol_ref.obj->header.is_big_obj);
|
COFF_SymbolWeakExt *weak_ext = coff_parse_weak_tag(symbol_parsed, symbol_ref.obj->header.is_big_obj);
|
||||||
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
|
if (weak_ext->characteristics == COFF_WeakExt_SearchLibrary) {
|
||||||
U32 member_idx;
|
U32 member_idx;
|
||||||
if (lnk_search_lib(lib, symbol->name, &member_idx)) {
|
if (lnk_search_lib(lib, symbol->name, &member_idx)) {
|
||||||
lnk_queue_lib_member(arena, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
||||||
}
|
}
|
||||||
} else if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
|
} else if (weak_ext->characteristics == COFF_WeakExt_AntiDependency) {
|
||||||
if (search_anti_deps) {
|
if (search_anti_deps) {
|
||||||
@@ -1568,7 +1595,7 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
|
|||||||
if (dep_interp == COFF_SymbolValueInterp_Weak) {
|
if (dep_interp == COFF_SymbolValueInterp_Weak) {
|
||||||
U32 member_idx;
|
U32 member_idx;
|
||||||
if (lnk_search_lib(lib, symbol_parsed.name, &member_idx)) {
|
if (lnk_search_lib(lib, symbol_parsed.name, &member_idx)) {
|
||||||
lnk_queue_lib_member(arena, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
lnk_queue_lib_member(arena, task->imports_hm, task->link->lib_member_infos_hm, member_ref_list, symbol, lib, lib_member_infos, member_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1624,6 +1651,8 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
ProfBeginFunction();
|
ProfBeginFunction();
|
||||||
Temp scratch = scratch_begin(arena->v, arena->count);
|
Temp scratch = scratch_begin(arena->v, arena->count);
|
||||||
|
|
||||||
|
HashMap imports_hm = {0};
|
||||||
|
|
||||||
LNK_LibMemberRefList *member_ref_lists = push_array(scratch.arena, LNK_LibMemberRefList, tp->worker_count);
|
LNK_LibMemberRefList *member_ref_lists = push_array(scratch.arena, LNK_LibMemberRefList, tp->worker_count);
|
||||||
B32 search_anti_deps = 0;
|
B32 search_anti_deps = 0;
|
||||||
for (U64 resolved_members_count = 0; ; resolved_members_count = 0) {
|
for (U64 resolved_members_count = 0; ; resolved_members_count = 0) {
|
||||||
@@ -1683,10 +1712,10 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LNK_LibMemberInfo *lib_member_infos = hash_table_search_raw_raw(link->lib_member_infos_ht, lib);
|
LNK_LibMemberInfo *lib_member_infos = hash_map_search_raw_raw(&link->lib_member_infos_hm, lib);
|
||||||
if (lib_member_infos == 0) {
|
if (lib_member_infos == 0) {
|
||||||
lib_member_infos = push_array(link->arena, LNK_LibMemberInfo, lib->member_count);
|
lib_member_infos = push_array(link->arena, LNK_LibMemberInfo, lib->member_count);
|
||||||
hash_table_push_raw_raw(link->arena, link->lib_member_infos_ht, lib, lib_member_infos);
|
hash_map_push_raw_raw(link->arena, &link->lib_member_infos_hm, lib, lib_member_infos);
|
||||||
}
|
}
|
||||||
|
|
||||||
B32 link_whole_archive = config->whole_archive_all;
|
B32 link_whole_archive = config->whole_archive_all;
|
||||||
@@ -1708,12 +1737,20 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
}
|
}
|
||||||
LNK_LibMemberRef *member_refs = push_array(scratch.arena, LNK_LibMemberRef, lib->member_count);
|
LNK_LibMemberRef *member_refs = push_array(scratch.arena, LNK_LibMemberRef, lib->member_count);
|
||||||
for EachIndex(member_idx, lib->member_count) {
|
for EachIndex(member_idx, lib->member_count) {
|
||||||
lnk_queue_lib_member(arena->v[0], &member_ref_lists[0], null_symbol, lib, lib_member_infos, member_idx);
|
lnk_queue_lib_member(arena->v[0], &imports_hm, link->lib_member_infos_hm, &member_ref_lists[0], null_symbol, lib, lib_member_infos, member_idx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// search symbols in lib
|
// search symbols in lib
|
||||||
MemoryZeroTyped(member_ref_lists, tp->worker_count);
|
MemoryZeroTyped(member_ref_lists, tp->worker_count);
|
||||||
LNK_SearchLibTask search_task = { .search_anti_deps = search_anti_deps, .lib = lib, .symtab = symtab, .lib_member_infos = lib_member_infos, .member_ref_lists = member_ref_lists };
|
LNK_SearchLibTask search_task = {
|
||||||
|
.search_anti_deps = search_anti_deps,
|
||||||
|
.link = link,
|
||||||
|
.imports_hm = &imports_hm,
|
||||||
|
.lib = lib,
|
||||||
|
.symtab = symtab,
|
||||||
|
.lib_member_infos = lib_member_infos,
|
||||||
|
.member_ref_lists = member_ref_lists
|
||||||
|
};
|
||||||
tp_for_parallel(tp, arena, tp->worker_count, lnk_search_lib_task, &search_task);
|
tp_for_parallel(tp, arena, tp->worker_count, lnk_search_lib_task, &search_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1765,6 +1802,25 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
|
|
||||||
switch (member_type) {
|
switch (member_type) {
|
||||||
case COFF_DataType_Import: {
|
case COFF_DataType_Import: {
|
||||||
|
{
|
||||||
|
LNK_LibMemberRef *is_thunk_import;
|
||||||
|
LNK_LibMemberRef *is_addr_import;
|
||||||
|
if (str8_starts_with(member_ref->link_symbol->name, str8_lit("__imp_"))) {
|
||||||
|
is_thunk_import = hash_map_search_string_raw(&imports_hm, str8_skip(member_ref->link_symbol->name, 6));
|
||||||
|
is_addr_import = hash_map_search_string_raw(&imports_hm, member_ref->link_symbol->name);
|
||||||
|
} else {
|
||||||
|
is_thunk_import = hash_map_search_string_raw(&imports_hm, member_ref->link_symbol->name);
|
||||||
|
is_addr_import = hash_map_search_stringf_raw(&imports_hm, "__imp_%S", member_ref->link_symbol->name);
|
||||||
|
}
|
||||||
|
if (is_thunk_import != 0 || is_addr_import != 0) {
|
||||||
|
lnk_invalid_path("duplicate import member queue detected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store lib member ref to import
|
||||||
|
hash_map_push_string_raw(scratch.arena, &imports_hm, member_ref->link_symbol->name, member_ref);
|
||||||
|
|
||||||
// find import stub
|
// find import stub
|
||||||
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));
|
||||||
|
|
||||||
@@ -1775,10 +1831,8 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
member_ref->link_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
|
||||||
if (!(lib_member_infos[member_ref->member_idx].flags & LNK_LibMemberFlag_WasGenQueued)) {
|
|
||||||
lib_member_infos[member_ref->member_idx].flags |= LNK_LibMemberFlag_WasGenQueued;
|
|
||||||
lnk_lib_member_ref_list_push_node(&link->imports, member_ref);
|
lnk_lib_member_ref_list_push_node(&link->imports, member_ref);
|
||||||
}
|
lib_member_infos[member_ref->member_idx].flags |= LNK_LibMemberFlag_WasGenQueued;
|
||||||
} break;
|
} break;
|
||||||
case COFF_DataType_BigObj:
|
case COFF_DataType_BigObj:
|
||||||
case COFF_DataType_Obj: {
|
case COFF_DataType_Obj: {
|
||||||
@@ -1867,7 +1921,6 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
|||||||
link->last_default_lib = &config->input_default_lib_list.first;
|
link->last_default_lib = &config->input_default_lib_list.first;
|
||||||
link->last_obj_lib = &config->input_obj_lib_list.first;
|
link->last_obj_lib = &config->input_obj_lib_list.first;
|
||||||
link->last_cmd_lib = &config->input_list[LNK_Input_Lib].first;
|
link->last_cmd_lib = &config->input_list[LNK_Input_Lib].first;
|
||||||
link->lib_member_infos_ht = hash_table_init(link->arena, Max(config->input_list[LNK_Input_Lib].node_count * 2, 1024));
|
|
||||||
link->try_to_resolve_entry_point = 1;
|
link->try_to_resolve_entry_point = 1;
|
||||||
|
|
||||||
// input :null_obj
|
// input :null_obj
|
||||||
@@ -1909,7 +1962,7 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
|||||||
for EachNode(member_ref, LNK_LibMemberRef, link->imports.first) {
|
for EachNode(member_ref, LNK_LibMemberRef, link->imports.first) {
|
||||||
LNK_Lib *lib = member_ref->lib;
|
LNK_Lib *lib = member_ref->lib;
|
||||||
U64 member_idx = member_ref->member_idx;
|
U64 member_idx = member_ref->member_idx;
|
||||||
LNK_LibMemberInfo *member_infos = hash_table_search_raw_raw(link->lib_member_infos_ht, lib);
|
LNK_LibMemberInfo *member_infos = hash_map_search_raw_raw(&link->lib_member_infos_hm, lib);
|
||||||
LNK_Symbol *link_symbol = member_infos[member_idx].link;
|
LNK_Symbol *link_symbol = member_infos[member_idx].link;
|
||||||
|
|
||||||
U32 member_offset = memory_read32(lib->member_offsets + member_idx);
|
U32 member_offset = memory_read32(lib->member_offsets + member_idx);
|
||||||
@@ -1944,13 +1997,8 @@ lnk_link_image(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
|||||||
hash_table_push_path_raw(scratch.arena, imports_ht, import_header.dll_name, import_symbols);
|
hash_table_push_path_raw(scratch.arena, imports_ht, import_header.dll_name, import_symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
B32 make_jump_thunk = 1;
|
|
||||||
if (str8_starts_with(link_symbol->name, str8_lit("__imp_"))) {
|
|
||||||
LNK_Symbol *thunk_symbol = lnk_symbol_table_search(symtab, str8_skip(link_symbol->name, str8_lit("__imp_").size));
|
|
||||||
make_jump_thunk = thunk_symbol != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// push make import info
|
// push make import info
|
||||||
|
B32 make_jump_thunk = !!(member_infos[member_idx].flags & LNK_LibMemberFlag_LinkedRegular);
|
||||||
pe_make_import_header_list_push(scratch.arena, import_symbols, (PE_MakeImport){ .header = member_info.data, .make_jump_thunk = make_jump_thunk });
|
pe_make_import_header_list_push(scratch.arena, import_symbols, (PE_MakeImport){ .header = member_info.data, .make_jump_thunk = make_jump_thunk });
|
||||||
}
|
}
|
||||||
AssertAlways(delayed_dll_names.node_count == delayed_imports_ht->count);
|
AssertAlways(delayed_dll_names.node_count == delayed_imports_ht->count);
|
||||||
|
|||||||
+3
-1
@@ -99,7 +99,7 @@ typedef struct LNK_Link
|
|||||||
String8Node **last_cmd_lib;
|
String8Node **last_cmd_lib;
|
||||||
String8Node **last_default_lib;
|
String8Node **last_default_lib;
|
||||||
String8Node **last_obj_lib;
|
String8Node **last_obj_lib;
|
||||||
HashTable *lib_member_infos_ht;
|
HashMap lib_member_infos_hm;
|
||||||
LNK_LibMemberRefList imports;
|
LNK_LibMemberRefList imports;
|
||||||
B32 try_to_resolve_entry_point;
|
B32 try_to_resolve_entry_point;
|
||||||
B32 asan_libs_resolved;
|
B32 asan_libs_resolved;
|
||||||
@@ -204,6 +204,8 @@ typedef struct LNK_BaseRelocPageArray
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
B32 search_anti_deps;
|
B32 search_anti_deps;
|
||||||
|
LNK_Link *link;
|
||||||
|
HashMap *imports_hm;
|
||||||
LNK_SymbolTable *symtab;
|
LNK_SymbolTable *symtab;
|
||||||
LNK_Symbol *import_stub;
|
LNK_Symbol *import_stub;
|
||||||
LNK_Lib *lib;
|
LNK_Lib *lib;
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
// Copyright (c) Epic Games Tools
|
// Copyright (c) Epic Games Tools
|
||||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
internal T_Linker
|
// TODO:
|
||||||
t_id_linker(void)
|
// [x] defer_duplicate_imp_link
|
||||||
{
|
// [ ] opt_ref_comdat_undef_section
|
||||||
String8 name = str8_chop_last_dot(str8_skip_last_slash(g_linker));
|
// [ ] opt_ref_weak_alias_comdat
|
||||||
if (str8_match(name, str8_lit("radlink"), StringMatchFlag_CaseInsensitive)) { return T_Linker_RAD; }
|
// [ ] reloc_apply_off_out_of_bounds
|
||||||
if (str8_match(name, str8_lit("link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_MSVC; }
|
// [ ] lib_member_reloc_apply_off_out_of_bounds
|
||||||
if (str8_match(name, str8_lit("lld-link"), StringMatchFlag_CaseInsensitive)) { return T_Linker_LLVM; }
|
// [ ] fold_two_funcs
|
||||||
return T_Linker_Null;
|
// [ ] same_but_different
|
||||||
}
|
// [ ] fold_diamond
|
||||||
|
// [ ] cyclic_icf
|
||||||
|
// [ ] fold_with_largest_align
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Def -> COFF
|
// Def -> COFF
|
||||||
@@ -4553,6 +4555,118 @@ TEST(defer_impl_link_to_second_search_pass)
|
|||||||
T_Ok(g_last_exit_code == 0);
|
T_Ok(g_last_exit_code == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(defer_duplicate_imp_link)
|
||||||
|
{
|
||||||
|
T_COFF_DefLib bar_lib_any = {
|
||||||
|
.members = (T_COFF_DefLibMember[]){
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_DllImportStatic,
|
||||||
|
.dll_import = { .name = "bar.dll" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_Import,
|
||||||
|
.import = { "bar.dll", "bar", COFF_ImportBy_Name, COFF_ImportHeader_Code, .hit_or_ordinal = 0 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_Obj,
|
||||||
|
.obj = {
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"text", ".text", str8_lit_comp("\xff\x25\x00\x00\x00\x00"), .flags = "rx:code"
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Undef("__imp_bar"),
|
||||||
|
T_COFF_DefSymbol_ExternFunc("qwe", "text", 0),
|
||||||
|
{0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
T_COFF_DefLib foo_lib_any = {
|
||||||
|
.members = (T_COFF_DefLibMember[]){
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_DllImportStatic,
|
||||||
|
.dll_import = { .name = "foo.dll" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_Import,
|
||||||
|
.import = { "foo.dll", "bar", COFF_ImportBy_Name, COFF_ImportHeader_Code, .hit_or_ordinal = 0 }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_Obj,
|
||||||
|
.obj = {
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"text", ".text",
|
||||||
|
str8_lit_comp("\xff\x25\x00\x00\x00\x00"),
|
||||||
|
.flags = "rx:code",
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Rel32, 2, "bar"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Undef("bar"),
|
||||||
|
T_COFF_DefSymbol_Undef("qwe"),
|
||||||
|
T_COFF_DefSymbol_ExternFunc("thunk", "text", 0),
|
||||||
|
{0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
String8 bar_lib = t_coff_from_def_lib(arena, bar_lib_any);
|
||||||
|
String8 foo_lib = t_coff_from_def_lib(arena, foo_lib_any);
|
||||||
|
|
||||||
|
T_Ok(t_write_file(str8_lit("bar.lib"), bar_lib));
|
||||||
|
T_Ok(t_write_file(str8_lit("foo.lib"), foo_lib));
|
||||||
|
T_Ok(t_write_entry_obj());
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe bar.lib foo.lib entry.obj /include:thunk");
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
|
||||||
|
String8 exe = t_read_file(arena, str8_lit("a.exe"));
|
||||||
|
PE_BinInfo pe = pe_bin_info_from_data(arena, exe);
|
||||||
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str;
|
||||||
|
PE_ParsedStaticImportTable static_imptab = pe_static_imports_from_data(arena, pe.is_pe32, pe.section_count, section_table, exe, pe.data_dir_franges[PE_DataDirectoryIndex_IMPORT]);
|
||||||
|
COFF_SectionHeader *data_sect = coff_section_header_from_name(str8_zero(), section_table, pe.section_count, str8_lit(".data"));
|
||||||
|
|
||||||
|
T_Ok(static_imptab.count == 1);
|
||||||
|
|
||||||
|
PE_ParsedStaticDLLImport *dll = &static_imptab.v[0];
|
||||||
|
T_Ok(str8_matchi(dll->name, str8_lit("foo.dll")));
|
||||||
|
|
||||||
|
T_Ok(dll->import_count == 1);
|
||||||
|
PE_ParsedImport *imp = &dll->imports[0];
|
||||||
|
T_Ok(imp->type == PE_ParsedImport_Name);
|
||||||
|
T_Ok(str8_match(imp->u.name.string, str8_lit("bar"), 0));
|
||||||
|
|
||||||
|
U64 iat_foff = pe_foff_from_voff(exe, &pe, dll->import_address_table_voff);
|
||||||
|
U64 ilt_foff = pe_foff_from_voff(exe, &pe, dll->import_name_table_voff);
|
||||||
|
|
||||||
|
U64 bar_idx = 0;
|
||||||
|
U64 bar_iat_addr = 0;
|
||||||
|
U64 bar_ilt_addr = 0;
|
||||||
|
str8_deserial_read_struct(exe, iat_foff + bar_idx * sizeof(U64), &bar_iat_addr);
|
||||||
|
str8_deserial_read_struct(exe, ilt_foff + bar_idx * sizeof(U64), &bar_ilt_addr);
|
||||||
|
|
||||||
|
T_Ok(bar_iat_addr != 0);
|
||||||
|
T_Ok(bar_ilt_addr != 0);
|
||||||
|
T_Ok(bar_iat_addr == bar_ilt_addr);
|
||||||
|
T_Ok(data_sect->voff <= bar_iat_addr && bar_iat_addr < data_sect->voff + data_sect->vsize);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(opt_ref_dangling_section)
|
TEST(opt_ref_dangling_section)
|
||||||
{
|
{
|
||||||
T_Ok(t_write_def_obj("entry.obj", (T_COFF_DefObj){
|
T_Ok(t_write_def_obj("entry.obj", (T_COFF_DefObj){
|
||||||
@@ -6893,4 +7007,194 @@ TEST(fold_with_largest_align)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(reloc_apply_off_out_of_bounds)
|
||||||
|
{
|
||||||
|
T_Ok(t_write_def_obj("bad.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"text", ".text", str8_lit_comp("\x00\x00\x00\x00"), .flags = "rx:code@1",
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Addr32, max_U32, "target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_AbsStatic("target", 0),
|
||||||
|
T_COFF_DefSymbol_Extern("entry", "text", 0),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe bad.obj");
|
||||||
|
T_Ok(g_last_exit_code != 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(lib_member_reloc_apply_off_out_of_bounds)
|
||||||
|
{
|
||||||
|
T_Ok(t_write_def_lib("bad.lib", (T_COFF_DefLib){
|
||||||
|
.emit_second_member = 1,
|
||||||
|
.members = (T_COFF_DefLibMember[]){
|
||||||
|
{
|
||||||
|
.type = T_COFF_DefLibMember_Obj,
|
||||||
|
.obj = {
|
||||||
|
.path = str8_lit("bad_member.obj"),
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"data", ".data", str8_lit_comp("\x00\x00\x00\x00"), .flags = "rw:data@1",
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Addr32, max_U32, "target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_AbsStatic("target", 0),
|
||||||
|
T_COFF_DefSymbol_Extern("bad", "data", 0),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
T_Ok(t_write_def_obj("entry.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{ "text", ".text", str8_lit_comp("\xC3"), .flags = "rx:code@1" },
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Extern("entry", "text", 0),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe /include:bad entry.obj bad.lib");
|
||||||
|
T_Ok(g_last_exit_code != 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(opt_ref_comdat_undef_section)
|
||||||
|
{
|
||||||
|
T_Ok(t_write_def_obj("entry.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"text", ".text", str8_lit_comp("\x48\xC7\xC0\x00\x00\x00\x00\xC3"), .flags = "rx:code@1",
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Addr32Nb, 3, "caller"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Extern("entry", "text", 0),
|
||||||
|
T_COFF_DefSymbol_Undef("caller"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
T_Ok(t_write_def_obj("caller.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"caller", ".caller", str8_lit_comp("\x00\x00\x00\x00"), .flags = "rw:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT,
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Addr32Nb, 0, ".target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Secdef("caller", COFF_ComdatSelect_Any),
|
||||||
|
T_COFF_DefSymbol_Extern("caller", "caller", 0),
|
||||||
|
T_COFF_DefSymbol_UndefSec(".target", COFF_SectionFlag_CntInitializedData|COFF_SectionFlag_MemRead),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
T_Ok(t_write_def_obj("target.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{ "target", ".target", str8_lit("target"), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Secdef("target", COFF_ComdatSelect_Any),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj caller.obj target.obj");
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
|
||||||
|
String8 exe = t_read_file(arena, str8_lit("a.exe"));
|
||||||
|
PE_BinInfo pe = pe_bin_info_from_data(arena, exe);
|
||||||
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str;
|
||||||
|
String8 string_table = str8_substr(exe, pe.string_table_range);
|
||||||
|
COFF_SectionHeader *target_sect = coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".target"));
|
||||||
|
T_Ok(target_sect != 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
TEST(opt_ref_weak_alias_comdat)
|
||||||
|
{
|
||||||
|
T_Ok(t_write_def_obj("weak.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{ "target", ".target", str8_lit("target"), .flags = "r:data@1", .raw_flags = COFF_SectionFlag_LnkCOMDAT },
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Secdef("target", COFF_ComdatSelect_Any),
|
||||||
|
T_COFF_DefSymbol_Extern("target", "target", 0),
|
||||||
|
T_COFF_DefSymbol_Weak("weak_target", COFF_WeakExt_SearchAlias, "target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
T_Ok(t_write_def_obj("entry.obj", (T_COFF_DefObj){
|
||||||
|
.machine = T_COFF_DefSetMachine(X64),
|
||||||
|
.sections = (T_COFF_DefSection[]){
|
||||||
|
{
|
||||||
|
"text", ".text", str8_lit_comp("\x48\xC7\xC0\x00\x00\x00\x00\xC3"), .flags = "rx:code@1",
|
||||||
|
.relocs = (T_COFF_DefReloc[]){
|
||||||
|
T_COFF_DefReloc(X64_Addr32Nb, 3, "weak_target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{0}
|
||||||
|
},
|
||||||
|
.symbols = (T_COFF_DefSymbol[]){
|
||||||
|
T_COFF_DefSymbol_Extern("entry", "text", 0),
|
||||||
|
T_COFF_DefSymbol_Undef("weak_target"),
|
||||||
|
{0}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
t_invoke_linkerf("/subsystem:console /entry:entry /out:a.exe entry.obj weak.obj");
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
|
||||||
|
String8 exe = t_read_file(arena, str8_lit("a.exe"));
|
||||||
|
PE_BinInfo pe = pe_bin_info_from_data(arena, exe);
|
||||||
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)str8_substr(exe, pe.section_table_range).str;
|
||||||
|
String8 string_table = str8_substr(exe, pe.string_table_range);
|
||||||
|
COFF_SectionHeader *target_sect = coff_section_header_from_name(string_table, section_table, pe.section_count, str8_lit(".target"));
|
||||||
|
T_Ok(target_sect != 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef T_Group
|
#undef T_Group
|
||||||
|
|||||||
Reference in New Issue
Block a user