From 371e52ad421c3bf55d4aca2e67bac11a7e6d4acd Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Wed, 17 Sep 2025 18:49:48 -0700 Subject: [PATCH] add /rad_alt_pch_dir for remapping objs in the local folder for pgo builds --- src/linker/lnk.c | 2 +- src/linker/lnk_config.c | 10 ++++++++++ src/linker/lnk_config.h | 2 ++ src/linker/lnk_debug_info.c | 20 ++++++++++++++++---- src/linker/lnk_debug_info.h | 4 ++-- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/linker/lnk.c b/src/linker/lnk.c index c8926852..cb463e94 100644 --- a/src/linker/lnk.c +++ b/src/linker/lnk.c @@ -5032,7 +5032,7 @@ lnk_run(TP_Context *tp, TP_Arena *arena, LNK_Config *config) // // CodeView // - LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, debug_info_objs_count, debug_info_objs); + LNK_CodeViewInput input = lnk_make_code_view_input(tp, arena, config->io_flags, config->lib_dir_list, config->alt_pch_dirs, debug_info_objs_count, debug_info_objs); CV_DebugT *types = lnk_import_types(tp, arena, &input); // diff --git a/src/linker/lnk_config.c b/src/linker/lnk_config.c index eb9b1f7d..a06de23b 100644 --- a/src/linker/lnk_config.c +++ b/src/linker/lnk_config.c @@ -124,6 +124,7 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] = //- internal switches { 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." }, { LNK_CmdSwitch_Rad_BuildInfo, 0, "RAD_BUILD_INFO", "", "Print build info and exit." }, { LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, 0, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" }, { LNK_CmdSwitch_Rad_Map, 0, "RAD_MAP", ":FILENAME", "Emit file with the output image's layout description." }, @@ -1779,6 +1780,15 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->age, 0); } break; + case LNK_CmdSwitch_Rad_AltPchDir: { + if (value_strings.node_count == 0) { + lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "missing parameters"); + break; + } + String8List dirs = str8_list_copy(config->arena, &value_strings); + str8_list_concat_in_place(&config->alt_pch_dirs, &dirs); + } break; + case LNK_CmdSwitch_Rad_BuildInfo: { lnk_print_build_info(); os_abort(0); diff --git a/src/linker/lnk_config.h b/src/linker/lnk_config.h index 32fc0fa0..3638ea29 100644 --- a/src/linker/lnk_config.h +++ b/src/linker/lnk_config.h @@ -151,6 +151,7 @@ typedef enum LNK_CmdSwitch_Wx, LNK_CmdSwitch_Rad_Age, + LNK_CmdSwitch_Rad_AltPchDir, LNK_CmdSwitch_Rad_BuildInfo, LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, LNK_CmdSwitch_Rad_Debug, @@ -417,6 +418,7 @@ typedef struct LNK_Config U64 unresolved_symbol_limit; U64 unresolved_symbol_ref_limit; LNK_SwitchState map_lines_for_unresolved_symbols; + String8List alt_pch_dirs; } LNK_Config; // --- MSVC Error Codes -------------------------------------------------------- diff --git a/src/linker/lnk_debug_info.c b/src/linker/lnk_debug_info.c index f0fdf62d..3a86eb4f 100644 --- a/src/linker/lnk_debug_info.c +++ b/src/linker/lnk_debug_info.c @@ -140,7 +140,7 @@ THREAD_POOL_TASK_FUNC(lnk_parse_cv_symbols_task) } internal LNK_PchInfo * -lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols) +lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols, String8List alt_pch_dirs) { Temp scratch = scratch_begin(&arena, 1); @@ -180,9 +180,20 @@ lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t String8 obj_path = path_absolute_dst_from_relative_dst_src(scratch.arena, precomp.obj_name, work_dir); + // map obj name in LF_PRECOMP to obj index - U64 debug_p_obj_idx; + U64 debug_p_obj_idx = max_U64; if (!hash_table_search_path_u64(debug_p_ht, obj_path, &debug_p_obj_idx)) { + String8 obj_name = str8_skip_last_slash(obj_path); + for EachNode(alt_dir_n, String8Node, alt_pch_dirs.first) { + String8 alt_obj_path = str8f(scratch.arena, "%S/%S", alt_dir_n->string, obj_name); + if (hash_table_search_path_u64(debug_p_ht, alt_obj_path, &debug_p_obj_idx)) { + break; + } + } + } + + if (debug_p_obj_idx == max_U64) { lnk_error_obj(LNK_Error_PrecompObjNotFound, obj_arr[obj_idx], "LF_PRECOMP references non-existent obj %S", obj_path); lnk_exit(LNK_Error_PrecompObjNotFound); } @@ -358,7 +369,7 @@ lnk_merge_debug_t_and_debug_p(Arena *arena, U64 obj_count, CV_DebugT *debug_t_ar } internal LNK_CodeViewInput -lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, U64 obj_count, LNK_Obj **obj_arr) +lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, String8List alt_pch_dirs, U64 obj_count, LNK_Obj **obj_arr) { ProfBegin("Extract CodeView"); Temp scratch = scratch_begin(0,0); @@ -522,7 +533,8 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_fla internal_obj_arr, internal_debug_t_arr, internal_debug_p_arr, - internal_parsed_symbols); + internal_parsed_symbols, + alt_pch_dirs); CV_DebugT *merged_debug_t_p_arr = lnk_merge_debug_t_and_debug_p(tp_arena->v[0], internal_count, internal_debug_t_arr, internal_debug_p_arr); diff --git a/src/linker/lnk_debug_info.h b/src/linker/lnk_debug_info.h index 8f086ba3..ba8990b3 100644 --- a/src/linker/lnk_debug_info.h +++ b/src/linker/lnk_debug_info.h @@ -496,9 +496,9 @@ typedef struct internal CV_DebugS * lnk_parse_debug_s_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *sect_list_arr); internal CV_DebugT * lnk_parse_debug_t_sections(TP_Context *tp, TP_Arena *arena, U64 obj_count, LNK_Obj **obj_arr, String8List *debug_t_list_arr); internal CV_SymbolList * lnk_cv_symbol_list_arr_from_debug_s_arr(TP_Context *tp, TP_Arena *arena, U64 obj_count, CV_DebugS *debug_s_arr); -internal LNK_PchInfo * lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols); +internal LNK_PchInfo * lnk_setup_pch(Arena *arena, U64 obj_count, LNK_Obj **obj_arr, CV_DebugT *debug_t_arr, CV_DebugT *debug_p_arr, CV_SymbolListArray *parsed_symbols, String8List alt_pch_dirs); -internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, U64 objs_count, LNK_Obj **objs); +internal LNK_CodeViewInput lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_IO_Flags io_flags, String8List lib_dir_list, String8List alt_pch_dirs, U64 objs_count, LNK_Obj **objs); internal LNK_LeafRef lnk_leaf_ref(U32 idx, U32 leaf_idx); internal LNK_LeafRef lnk_obj_leaf_ref(U32 obj_idx, U32 leaf_idx);