mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
implement /WHOLEARCHIVE
This commit is contained in:
+21
-1
@@ -1604,13 +1604,33 @@ lnk_link_inputs(TP_Context *tp,
|
||||
hash_table_push_raw_raw(link->arena, link->lib_member_infos_ht, lib, lib_member_infos);
|
||||
}
|
||||
|
||||
B32 link_whole_archive = config->whole_archive_all;
|
||||
if ( ! link_whole_archive) {
|
||||
String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(lib->path));
|
||||
link_whole_archive = hash_table_search_path(config->whole_archive_ht, lib_name) != 0;
|
||||
}
|
||||
|
||||
ProfBeginV("Search %S", str8_skip_last_slash(lib->path));
|
||||
do {
|
||||
lnk_load_inputs(tp, arena, config, inputer, symtab, link);
|
||||
|
||||
if (link_whole_archive) {
|
||||
LNK_LibMemberRef *member_refs = push_array(scratch.arena, LNK_LibMemberRef, lib->member_count);
|
||||
for EachIndex(member_idx, lib->member_count) {
|
||||
static LNK_Symbol *null_symbol = 0;
|
||||
if (null_symbol == 0) {
|
||||
null_symbol = push_array(inputer->arena, LNK_Symbol, 1);
|
||||
null_symbol->refs = push_array(inputer->arena, LNK_ObjSymbolRefNode, 1);
|
||||
null_symbol->refs->v.obj = &link->objs.first->data;
|
||||
}
|
||||
lnk_queue_lib_member(scratch.arena, &member_ref_lists[0], null_symbol, lib, lib_member_infos, member_idx);
|
||||
}
|
||||
} else {
|
||||
// search symbols in lib
|
||||
MemoryZeroTyped(member_ref_lists, tp->worker_count);
|
||||
tp_for_parallel(tp, arena, tp->worker_count, lnk_search_lib_task, &(LNK_SearchLibTask){ .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, .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);
|
||||
}
|
||||
|
||||
LNK_LibMemberRefList queued_members = {0};
|
||||
lnk_lib_member_ref_list_concat_in_place_array(&queued_members, member_ref_lists, tp->worker_count);
|
||||
|
||||
@@ -58,6 +58,7 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] =
|
||||
{ LNK_CmdSwitch_SubSystem, 1, "SUBSYSTEM", ":{CONSOLE|NATIVE|WINDOWS}[,#[.##]]", "Set subsystem for the image." },
|
||||
{ LNK_CmdSwitch_TsAware, 0, "TSAWARE", "[:NO]", "Image is terminal server aware." },
|
||||
{ LNK_CmdSwitch_Version, 0, "VERSION", "", "Image version." },
|
||||
{ LNK_CmdSwitch_WholeArchive, 0, "WHOLEARCHIVE", "[:LIBNAME]", "Force linker to pull in all objs from the specified lib." },
|
||||
|
||||
{ LNK_CmdSwitch_Rad_Age, 0, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." },
|
||||
{ LNK_CmdSwitch_Rad_AltPchDir, 0, "RAD_ALT_PCH_DIR", ":PATH", "Alternative directory to search for PCH object files." },
|
||||
@@ -1775,6 +1776,18 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_cmd_switch_parse_version(obj, cmd_switch, value_strings, &config->image_ver);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_WholeArchive: {
|
||||
if (value_strings.node_count == 0) {
|
||||
config->whole_archive_all = 1;
|
||||
} else {
|
||||
String8 lib_name;
|
||||
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &lib_name)) {
|
||||
lib_name = str8_chop_last_dot(str8_skip_last_slash(lib_name));
|
||||
hash_table_push_path_string(config->arena, config->whole_archive_ht, lib_name, str8_zero());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_Age: {
|
||||
lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->age, 0);
|
||||
} break;
|
||||
@@ -2086,6 +2099,7 @@ lnk_config_from_cmd_line(String8List raw_cmd_line, LNK_CmdLine cmd_line)
|
||||
config->delay_load_ht = hash_table_init(arena, 0x100);
|
||||
config->disallow_lib_ht = hash_table_init(arena, 0x100);
|
||||
config->fail_if_mismatch_ht = hash_table_init(arena, 0x100);
|
||||
config->whole_archive_ht = hash_table_init(arena, 0x100);
|
||||
|
||||
// process command line switches
|
||||
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
|
||||
|
||||
@@ -85,6 +85,7 @@ typedef enum
|
||||
LNK_CmdSwitch_Time,
|
||||
LNK_CmdSwitch_TsAware,
|
||||
LNK_CmdSwitch_Version,
|
||||
LNK_CmdSwitch_WholeArchive,
|
||||
|
||||
LNK_CmdSwitch_Rad_Age,
|
||||
LNK_CmdSwitch_Rad_AltPchDir,
|
||||
@@ -350,6 +351,8 @@ typedef struct LNK_Config
|
||||
HashTable *delay_load_ht;
|
||||
HashTable *disallow_lib_ht;
|
||||
HashTable *fail_if_mismatch_ht;
|
||||
HashTable *whole_archive_ht;
|
||||
B32 whole_archive_all;
|
||||
U64 unresolved_symbol_limit;
|
||||
U64 unresolved_symbol_ref_limit;
|
||||
LNK_SwitchState map_lines_for_unresolved_symbols;
|
||||
|
||||
@@ -4758,6 +4758,85 @@ T_BeginTest(patch_cv_symbol_tree)
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
T_BeginTest(whole_archive)
|
||||
{
|
||||
String8 a_obj;
|
||||
{
|
||||
COFF_ObjWriter *cow = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
coff_obj_writer_push_section(cow, str8_lit(".a"), PE_DATA_SECTION_FLAGS, str8_lit("a"));
|
||||
a_obj = coff_obj_writer_serialize(scratch.arena, cow);
|
||||
coff_obj_writer_release(&cow);
|
||||
}
|
||||
|
||||
String8 b_obj;
|
||||
{
|
||||
COFF_ObjWriter *cow = coff_obj_writer_alloc(0, COFF_MachineType_X64);
|
||||
coff_obj_writer_push_section(cow, str8_lit(".b"), PE_DATA_SECTION_FLAGS, str8_lit("b"));
|
||||
b_obj = coff_obj_writer_serialize(scratch.arena, cow);
|
||||
coff_obj_writer_release(&cow);
|
||||
}
|
||||
|
||||
String8 a_lib;
|
||||
{
|
||||
COFF_LibWriter *ciw = coff_lib_writer_alloc();
|
||||
coff_lib_writer_push_obj(ciw, str8_lit("a.obj"), a_obj);
|
||||
a_lib = coff_lib_writer_serialize(scratch.arena, ciw, 0, 0, 1);
|
||||
coff_lib_writer_release(&ciw);
|
||||
}
|
||||
|
||||
String8 b_lib;
|
||||
{
|
||||
COFF_LibWriter *ciw = coff_lib_writer_alloc();
|
||||
coff_lib_writer_push_obj(ciw, str8_lit("b.obj"), b_obj);
|
||||
b_lib = coff_lib_writer_serialize(scratch.arena, ciw, 0, 0, 1);
|
||||
coff_lib_writer_release(&ciw);
|
||||
}
|
||||
|
||||
T_Ok(t_write_entry_obj());
|
||||
T_Ok(t_write_file(str8_lit("a.lib"), a_lib));
|
||||
T_Ok(t_write_file(str8_lit("b.lib"), b_lib));
|
||||
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:all_libs.exe entry.obj /wholearchive a.lib b.lib");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
{
|
||||
String8 exe = t_read_file(scratch.arena, str8_lit("all_libs.exe"));
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.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 *a_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a"));
|
||||
COFF_SectionHeader *b_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".b"));
|
||||
T_Ok(a_sect != 0);
|
||||
T_Ok(b_sect != 0);
|
||||
}
|
||||
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:only_a.exe entry.obj /wholearchive:a.lib a.lib b.lib");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
{
|
||||
String8 exe = t_read_file(scratch.arena, str8_lit("only_a.exe"));
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.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 *a_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a"));
|
||||
COFF_SectionHeader *b_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".b"));
|
||||
T_Ok(a_sect != 0);
|
||||
T_Ok(b_sect == 0);
|
||||
}
|
||||
|
||||
t_invoke_linkerf("/subsystem:console /entry:entry /out:only_b.exe /wholearchive:b.lib a.lib b.lib entry.obj");
|
||||
T_Ok(g_last_exit_code == 0);
|
||||
{
|
||||
String8 exe = t_read_file(scratch.arena, str8_lit("only_b.exe"));
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.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 *a_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".a"));
|
||||
COFF_SectionHeader *b_sect = coff_section_header_from_name(exe, section_table, pe.section_count, str8_lit(".b"));
|
||||
T_Ok(a_sect == 0);
|
||||
T_Ok(b_sect != 0);
|
||||
}
|
||||
}
|
||||
T_EndTest;
|
||||
|
||||
#if 0
|
||||
T_BeginTest(pdb_determ_test)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user