replace type names with hashes

This commit is contained in:
Nikita Smith
2024-10-29 10:19:55 -07:00
parent 4a2e1dd8d0
commit f3fbf10754
5 changed files with 204 additions and 37 deletions
+5
View File
@@ -4131,6 +4131,11 @@ l.count += 1; \
// strings in $$FILE_CHECKSUM step in `lnk_process_c13_data_task`.
if (config->debug_mode == LNK_DebugMode_Full || config->debug_mode == LNK_DebugMode_GHash) {
lnk_timer_begin(LNK_Timer_Pdb);
if (config->pdb_hash_type_names == LNK_SwitchState_Yes) {
lnk_replace_type_names_with_hashes(tp, tp_arena, types[CV_TypeIndexSource_TPI], config->pdb_hash_type_name_length, config->pdb_hash_type_name_map);
}
String8List pdb_data = lnk_build_pdb(tp,
tp_arena,
config->guid,
+53 -37
View File
@@ -120,34 +120,37 @@ read_only struct
{ LNK_CmdSwitch_NotImplemented, "WX", "", "" },
//- internal switches
{ LNK_CmdSwitch_Rad_Age, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." },
{ LNK_CmdSwitch_Rad_BuildInfo, "RAD_BUILD_INFO", "", "Print build info and exit." },
{ LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Debug, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." },
{ LNK_CmdSwitch_Rad_DebugName, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." },
{ LNK_CmdSwitch_Rad_DebugAltPath, "RAD_DEBUGALTPATH", "", "" },
{ LNK_CmdSwitch_Rad_DelayBind, "RAD_DELAY_BIND", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_DoMerge, "RAD_DO_MERGE", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_EnvLib, "RAD_ENV_LIB", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Exe, "RAD_EXE", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Guid, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" },
{ LNK_CmdSwitch_Rad_LargePages, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." },
{ LNK_CmdSwitch_Rad_LinkVer, "RAD_LINK_VER", ":##,##", "" },
{ LNK_CmdSwitch_Rad_Log, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" },
{ LNK_CmdSwitch_Rad_MtPath, "RAD_MT_PATH", ":EXEPATH", "Path to manifest tool." },
{ LNK_CmdSwitch_Rad_OsVer, "RAD_OS_VER", ":##,##", "" },
{ LNK_CmdSwitch_Rad_PageSize, "RAD_PAGE_SIZE", ":#", "Must be power of two." },
{ LNK_CmdSwitch_Rad_PathStyle, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" },
{ LNK_CmdSwitch_Rad_SectVirtOff, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." },
{ LNK_CmdSwitch_Rad_SuppressError, "RAD_SUPPRESS_ERROR", ":#", "" },
{ LNK_CmdSwitch_Rad_SymbolTableCapDefined, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapInternal, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapWeak, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapLib, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." },
{ LNK_CmdSwitch_Rad_TargetOs, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" },
{ LNK_CmdSwitch_Rad_TimeStamp, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
{ LNK_CmdSwitch_Rad_Version, "RAD_VERSION", "", "Print version and exit." },
{ LNK_CmdSwitch_Rad_Workers, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024." },
{ LNK_CmdSwitch_Rad_Age, "RAD_AGE", ":#", "Age embeded in EXE and PDB, used to validate incremental build. Default is 1." },
{ LNK_CmdSwitch_Rad_BuildInfo, "RAD_BUILD_INFO", "", "Print build info and exit." },
{ LNK_CmdSwitch_Rad_CheckUnusedDelayLoadDll, "RAD_CHECK_UNUSED_DELAY_LOAD_DLL", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Debug, "RAD_DEBUG", "[:NO]", "Emit RAD debug info file." },
{ LNK_CmdSwitch_Rad_DebugName, "RAD_DEBUG_NAME", ":FILENAME", "Sets file name for RAD debug info file." },
{ LNK_CmdSwitch_Rad_DebugAltPath, "RAD_DEBUGALTPATH", "", "" },
{ LNK_CmdSwitch_Rad_DelayBind, "RAD_DELAY_BIND", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_DoMerge, "RAD_DO_MERGE", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_EnvLib, "RAD_ENV_LIB", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Exe, "RAD_EXE", "[:NO]", "" },
{ LNK_CmdSwitch_Rad_Guid, "RAD_GUID", ":{IMAGEBLAKE3|XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXXX}", "" },
{ LNK_CmdSwitch_Rad_LargePages, "RAD_LARGE_PAGES", "[:NO]", "Disabled by default on Windows." },
{ LNK_CmdSwitch_Rad_LinkVer, "RAD_LINK_VER", ":##,##", "" },
{ LNK_CmdSwitch_Rad_Log, "RAD_LOG", ":{ALL,INPUT_OBJ,INPUT_LIB,IO,LINK_STATS,TIMERS}", "" },
{ LNK_CmdSwitch_Rad_MtPath, "RAD_MT_PATH", ":EXEPATH", "Path to manifest tool." },
{ LNK_CmdSwitch_Rad_OsVer, "RAD_OS_VER", ":##,##", "" },
{ LNK_CmdSwitch_Rad_PageSize, "RAD_PAGE_SIZE", ":#", "Must be power of two." },
{ LNK_CmdSwitch_Rad_PdbHashTypeNames, "RAD_PDB_HASH_TYPE_NAMES", ":[NO]", "Replace type names in LF_STRUCTURE and LF_CLASS with hashes." },
{ LNK_CmdSwitch_Rad_PdbHashTypeNameMap, "RAD_PDB_HASH_TYPE_NAME_MAP", ":FILENAME", "Produce map file with hash -> type name mappings." },
{ LNK_CmdSwitch_Rad_PdbHashTypeNameLength, "RAD_PDB_HASH_TYPE_NAME_LENGTH", ":#", "Number of hash bytes to use to replace type name. Default 8 bytes (Max 16)." },
{ LNK_CmdSwitch_Rad_PathStyle, "RAD_PATH_STYLE", ":{WindowsAbsolute|UnixAbsolute}", "" },
{ LNK_CmdSwitch_Rad_SectVirtOff, "RAD_SECT_VIRT_OFF", ":#", "Set RVA where section data is placed in memory. For internal use only." },
{ LNK_CmdSwitch_Rad_SuppressError, "RAD_SUPPRESS_ERROR", ":#", "" },
{ LNK_CmdSwitch_Rad_SymbolTableCapDefined, "RAD_SYMBOL_TABLE_CAP_DEFINED", ":#", "Number of buckets allocated in the symbol table for defined symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapInternal, "RAD_SYMBOL_TABLE_CAP_INTERNAL", ":#", "Number of buckets allocated in the symbol table for internal symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapWeak, "RAD_SYMBOL_TABLE_CAP_WEAK", ":#", "Number of buckets allocated in the symbol table for weak symbols." },
{ LNK_CmdSwitch_Rad_SymbolTableCapLib, "RAD_SYMBOL_TABLE_CAP_LIB", ":#", "Number of buckets allocated in the symbol table for library symbols." },
{ LNK_CmdSwitch_Rad_TargetOs, "RAD_TARGET_OS", ":{WINDOWS,LINUX,MAC}" },
{ LNK_CmdSwitch_Rad_TimeStamp, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
{ LNK_CmdSwitch_Rad_Version, "RAD_VERSION", "", "Print version and exit." },
{ LNK_CmdSwitch_Rad_Workers, "RAD_WORKERS", ":#", "Sets number of workers created in the pool. Number is capped at 1024." },
{ LNK_CmdSwitch_Help, "HELP", "", "" },
{ LNK_CmdSwitch_Help, "?", "", "" },
@@ -916,15 +919,16 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
lnk_cmd_line_push_option_if_not_presentf(scratch.arena, &cmd_line, LNK_CmdSwitch_Rad_MtPath, "%S", mt_path);
}
LNK_Config *config = push_array(arena, LNK_Config, 1);
config->raw_cmd_line = raw_cmd_line;
config->work_dir = os_get_current_path(arena);
config->build_imp_lib = 1;
config->build_exp = 1;
config->heap_reserve = MB(1);
config->heap_commit = KB(1);
config->stack_reserve = MB(1);
config->stack_commit = KB(1);
LNK_Config *config = push_array(arena, LNK_Config, 1);
config->raw_cmd_line = raw_cmd_line;
config->work_dir = os_get_current_path(arena);
config->build_imp_lib = 1;
config->build_exp = 1;
config->heap_reserve = MB(1);
config->heap_commit = KB(1);
config->stack_reserve = MB(1);
config->stack_commit = KB(1);
config->pdb_hash_type_name_length = 8;
// process command line switches
for (LNK_CmdOption *cmd = cmd_line.first_option; cmd != 0; cmd = cmd->next) {
@@ -1585,6 +1589,18 @@ lnk_config_from_cmd_line(Arena *arena, String8List raw_cmd_line)
}
} break;
case LNK_CmdSwitch_Rad_PdbHashTypeNames: {
lnk_cmd_switch_parse_flag(cmd->value_strings, cmd_switch, &config->pdb_hash_type_names);
} break;
case LNK_CmdSwitch_Rad_PdbHashTypeNameMap: {
lnk_cmd_switch_parse_string_copy(arena, cmd->value_strings, cmd_switch, &config->pdb_hash_type_name_map);
} break;
case LNK_CmdSwitch_Rad_PdbHashTypeNameLength: {
lnk_cmd_switch_parse_u64(cmd->value_strings, cmd_switch, &config->pdb_hash_type_name_length, 0);
} break;
case LNK_CmdSwitch_Rad_SectVirtOff: {
U64 sect_virt_off;
if (lnk_cmd_switch_parse_u64(cmd->value_strings, cmd_switch, &sect_virt_off, LNK_ParseU64Flag_CheckUnder32bit)) {
+6
View File
@@ -137,6 +137,9 @@ typedef enum
LNK_CmdSwitch_Rad_OsVer,
LNK_CmdSwitch_Rad_PageSize,
LNK_CmdSwitch_Rad_PathStyle,
LNK_CmdSwitch_Rad_PdbHashTypeNames,
LNK_CmdSwitch_Rad_PdbHashTypeNameMap,
LNK_CmdSwitch_Rad_PdbHashTypeNameLength,
LNK_CmdSwitch_Rad_SectVirtOff,
LNK_CmdSwitch_Rad_SuppressError,
LNK_CmdSwitch_Rad_SymbolTableCapDefined,
@@ -271,6 +274,9 @@ typedef struct LNK_Config
String8 pdb_name;
String8 pdb_alt_path;
String8 mt_path;
LNK_SwitchState pdb_hash_type_names;
String8 pdb_hash_type_name_map;
U64 pdb_hash_type_name_length;
String8List input_list[LNK_Input_Count];
String8List input_default_lib_list;
String8List disallow_lib_list;
+128
View File
@@ -2476,6 +2476,134 @@ lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input)
return types;
}
internal U64
lnk_format_u128(U8 *buf, U64 buf_max, U64 length, U128 v)
{
U64 size = 0;
if (length > 0 && buf_max > 0) {
if (length <= 8) {
U64 mask = length == 8 ? max_U32 : (1ull << (length*8)) - 1;
size = raddbg_snprintf((char*)buf, buf_max - 1, "%llX", v.u64[0] & mask);
} else {
U64 mask1 = length == 16 ? max_U64 : (1ull << (length*8)) - 1;
size = raddbg_snprintf((char*)buf, buf_max, "%llX%llX", v.u64[1] & mask1, v.u64[0]);
}
}
return size;
}
internal
THREAD_POOL_TASK_FUNC(lnk_replace_type_names_with_hashes_task)
{
ProfBeginFunction();
LNK_TypeNameReplacer *task = raw_task;
Rng1U64 range = task->ranges[task_id];
CV_DebugT debug_t = task->debug_t;
U64 hash_length = task->hash_length;
B32 make_map = task->make_map;
Arena *map_arena = 0;
String8List *map = 0;
if (make_map) {
map_arena = task->map_arena->v[task_id];
map = &task->maps[task_id];
}
U64 hash_max_chars = hash_length*2;
U8 temp[128];
for (U64 leaf_idx = range.min; leaf_idx < range.max; ++leaf_idx) {
CV_Leaf leaf = cv_debug_t_get_leaf(debug_t, leaf_idx);
if (leaf.kind == CV_LeafKind_STRUCTURE || leaf.kind == CV_LeafKind_CLASS) {
CV_UDTInfo udt_info = cv_get_udt_info(leaf.kind, leaf.data);
CV_NumericParsed dummy;
U64 numeric_size = cv_read_numeric(leaf.data, sizeof(CV_LeafStruct), &dummy);
U128 name_hash;
if (udt_info.props & CV_TypeProp_HasUniqueName) {
blake3_hasher hasher; blake3_hasher_init(&hasher);
blake3_hasher_update(&hasher, udt_info.unique_name.str, udt_info.unique_name.size);
blake3_hasher_finalize(&hasher, (U8*)&name_hash, sizeof(name_hash));
if (make_map) {
lnk_format_u128(temp, sizeof(temp), hash_length, name_hash);
str8_list_pushf(map_arena, map, "%s %.*s\n", temp, str8_varg(udt_info.unique_name));
}
} else {
blake3_hasher hasher; blake3_hasher_init(&hasher);
blake3_hasher_update(&hasher, udt_info.name.str, udt_info.name.size);
blake3_hasher_finalize(&hasher, (U8*)&name_hash, sizeof(name_hash));
if (make_map) {
lnk_format_u128(temp, sizeof(temp), hash_length, name_hash);
str8_list_pushf(map_arena, map, "%s %.*s\n", temp, str8_varg(udt_info.name));
}
}
if (udt_info.name.size < hash_max_chars) {
U64 buf_size = sizeof(CV_LeafHeader) + sizeof(CV_LeafStruct) + numeric_size + (hash_max_chars + 1) * 2;
U8 *buf = push_array(arena, U8, buf_size);
MemoryCopy(buf + sizeof(CV_LeafHeader), leaf.data.str, sizeof(CV_LeafStruct) + numeric_size);
CV_LeafStruct *lf = (CV_LeafStruct *)(buf + sizeof(CV_LeafHeader));
lf->props &= ~CV_TypeProp_HasUniqueName;
udt_info.name.str = buf + sizeof(CV_LeafHeader) + sizeof(CV_LeafStruct) + numeric_size;
udt_info.name.size = lnk_format_u128(udt_info.name.str, hash_max_chars + 1, hash_length, name_hash);
CV_LeafHeader *new_header = (CV_LeafHeader *)buf;
new_header->size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1;
new_header->kind = leaf.kind;
debug_t.v[leaf_idx] = buf;
} else {
udt_info.name.size = lnk_format_u128(udt_info.name.str, udt_info.name.size, hash_length, name_hash);
CV_LeafHeader *header = cv_debug_t_get_leaf_header(debug_t, leaf_idx);
header->size = sizeof(CV_LeafKind) + sizeof(CV_LeafStruct) + numeric_size + udt_info.name.size + 1;
CV_LeafStruct *lf = (CV_LeafStruct *)(header + 1);
lf->props &= ~CV_TypeProp_HasUniqueName;
}
}
}
ProfEnd();
}
internal void
lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 hash_length, String8 map_name)
{
ProfBeginFunction();
Temp scratch = scratch_begin(arena->v, arena->count);
LNK_TypeNameReplacer task = {0};
task.debug_t = debug_t;
task.ranges = tp_divide_work(scratch.arena, debug_t.count, tp->worker_count);
task.hash_length = Clamp(1, hash_length, 16);
if (map_name.size > 0) {
task.make_map = 1;
task.map_arena = tp_arena_alloc(tp);
task.maps = push_array(scratch.arena, String8List, tp->worker_count);
}
tp_for_parallel(tp, arena, tp->worker_count, lnk_replace_type_names_with_hashes_task, &task);
if (task.make_map) {
String8List map = {0};
str8_list_concat_in_place_array(&map, task.maps, tp->worker_count);
lnk_write_data_list_to_file_path(map_name, map);
tp_arena_release(&task.map_arena);
}
scratch_end(scratch);
ProfEnd();
}
////////////////////////////////
// PDB Builder
+12
View File
@@ -367,6 +367,16 @@ typedef struct
CV_SymbolNode **symbol_arr;
} LNK_GsiUnbucket;
typedef struct
{
CV_DebugT debug_t;
Rng1U64 *ranges;
U64 hash_length;
B32 make_map;
TP_Arena *map_arena;
String8List *maps;
} LNK_TypeNameReplacer;
////////////////////////////////
// RAD Debug Info
@@ -524,6 +534,8 @@ internal void lnk_patch_leaves(TP_Context *tp, LNK_CodeViewInput
internal String8Node * lnk_copy_raw_leaf_arr_to_type_server(TP_Context *tp, CV_DebugT types, PDB_TypeServer *type_server);
internal CV_DebugT * lnk_import_types(TP_Context *tp, TP_Arena *tp_temp, LNK_CodeViewInput *input);
internal void lnk_replace_type_names_with_hashes(TP_Context *tp, TP_Arena *arena, CV_DebugT debug_t, U64 hash_length, String8 map_name);
////////////////////////////////
// RAD Debug info