mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 14:58:08 +00:00
rename RAD_TypeHashAlg; extend /RAD_DEBUG_TYPE_HASH with XXHASH option
This commit is contained in:
committed by
Ryan Fleury
parent
97a1fe6006
commit
fcee35f3e9
+10
-2
@@ -103,6 +103,7 @@
|
||||
|
||||
#include "lnk_log.h"
|
||||
#include "lnk_timer.h"
|
||||
#include "lnk_hasher.h"
|
||||
#include "lnk_io.h"
|
||||
#include "lnk_cmd_line.h"
|
||||
#include "lnk_config.h"
|
||||
@@ -116,6 +117,7 @@
|
||||
|
||||
#include "lnk_log.c"
|
||||
#include "lnk_timer.c"
|
||||
#include "lnk_hasher.c"
|
||||
#include "lnk_io.c"
|
||||
#include "lnk_cmd_line.c"
|
||||
#include "lnk_config.c"
|
||||
@@ -150,7 +152,6 @@ lnk_make_default_cmd_line(Arena *arena, LNK_CmdLine user_cmd_line)
|
||||
"/RAD_BOOT_MODE:LINKER",
|
||||
//"/RAD_BUILD_EXP",
|
||||
"/RAD_BUILD_IMPLIB",
|
||||
"/RAD_TPYE_HASH_ALG:BLAKE3",
|
||||
"/RAD_AGE:1",
|
||||
"/RAD_CHECK_UNUSED_DELAY_LOAD_DLL",
|
||||
"/RAD_DO_MERGE",
|
||||
@@ -173,6 +174,13 @@ lnk_make_default_cmd_line(Arena *arena, LNK_CmdLine user_cmd_line)
|
||||
(char*)str8f(scratch.arena, "/RAD_MT_PATH:%s", LNK_MANIFEST_MERGE_TOOL_NAME).str,
|
||||
(char*)str8f(scratch.arena, "/RAD_DATA_DIR_COUNT:%u", PE_DataDirectoryIndex_COUNT).str,
|
||||
|
||||
// Set BLAKE3 as the default to match the LLVM default.
|
||||
//
|
||||
// When hash kinds conflict, radlink discards any .debug$H sections
|
||||
// whose hash kind does not match the selected default.
|
||||
"/RAD_DEBUG_TYPE_HASH:BLAKE3",
|
||||
|
||||
// Use LLVM significant addresses hints for the /OPT:ICF.
|
||||
"/LLVM_ADDRSIG",
|
||||
};
|
||||
|
||||
@@ -6696,7 +6704,7 @@ lnk_run_type_server(TP_Context *tp, TP_Arena *arena, LNK_Config *config)
|
||||
include_objs = u64_array_from_list(scratch.arena, &include_obj_list);
|
||||
}
|
||||
|
||||
LNK_RRT rrt = {0};
|
||||
LNK_RRT rrt = { .debug_types_hash = config->debug_types_hash };
|
||||
ProfScope("Pack Type Data & Data Ranges")
|
||||
{
|
||||
LNK_RRTTypeDataSerializer task = { &cv_types, &rrt.type_data_raw, rrt.type_data_ranges };
|
||||
|
||||
@@ -102,7 +102,7 @@ global read_only LNK_CmdSwitch g_cmd_switch_map[] =
|
||||
{ LNK_CmdSwitch_Rad_ImageAltPath, 0, "RAD_IMAGEALTPATH", ":FILENAME", "Alternative name for the image" },
|
||||
{ LNK_CmdSwitch_Rad_WriteTempFiles, 0, "RAD_WRITE_TEMP_FILES", "[:NO]", "When speicifed linker writes image and debug info to temporary files and renames after link is done." },
|
||||
{ LNK_CmdSwitch_Rad_TimeStamp, 0, "RAD_TIME_STAMP", ":#", "Time stamp embeded in EXE and PDB." },
|
||||
{ LNK_CmdSwitch_Rad_TypeHashAlg, 0, "RAD_TPYE_HASH_ALG", ":{BLAKE3}", "Sets hashing algorithm for type merging." },
|
||||
{ LNK_CmdSwitch_Rad_DebugTypeHash, 0, "RAD_DEBUG_TYPE_HASH", ":{BLAKE3|XXHASH}", "Sets hashing algorithm for debug type merging." },
|
||||
{ LNK_CmdSwitch_Rad_UnresolvedSymbolLimit, 0, "RAD_UNRESOLVED_SYMBOL_LIMIT", ":#", "Limits number of unresolved symbol errors linker reports." },
|
||||
{ LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit, 0, "RAD_UNRESOLVED_SYMBOL_REF_LIMIT", ":#", "Limit number of unresolved symbol references linker reports." },
|
||||
{ LNK_CmdSwitch_Rad_Version, 0, "RAD_VERSION", "", "Print version and exit." },
|
||||
@@ -2325,11 +2325,13 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
||||
lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->time_stamp, 0);
|
||||
} break;
|
||||
|
||||
case LNK_CmdSwitch_Rad_TypeHashAlg: {
|
||||
case LNK_CmdSwitch_Rad_DebugTypeHash: {
|
||||
String8 alg = {0};
|
||||
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &alg)) {
|
||||
if (str8_match(alg, str8_lit("BLAKE3"), StringMatchFlag_CaseInsensitive)) {
|
||||
config->type_hash_alg = LLVM_GHashAlg_BLAKE3;
|
||||
config->debug_types_hash = LNK_HashKind_BLAKE3;
|
||||
} else if (str8_match(alg, str8_lit("XXHASH"), StringMatchFlag_CaseInsensitive)) {
|
||||
config->debug_types_hash = LNK_HashKind_XXHash;
|
||||
} else {
|
||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown hash alg: %S", alg);
|
||||
}
|
||||
@@ -2954,4 +2956,3 @@ lnk_config_init(LNK_CmdLine cmd_line)
|
||||
ProfEnd();
|
||||
return config;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ typedef enum
|
||||
LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers,
|
||||
LNK_CmdSwitch_Rad_SortImports,
|
||||
LNK_CmdSwitch_Rad_TimeStamp,
|
||||
LNK_CmdSwitch_Rad_TypeHashAlg,
|
||||
LNK_CmdSwitch_Rad_DebugTypeHash,
|
||||
LNK_CmdSwitch_Rad_UnresolvedSymbolLimit,
|
||||
LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit,
|
||||
LNK_CmdSwitch_Rad_Version,
|
||||
@@ -305,7 +305,6 @@ typedef enum
|
||||
LNK_TypeNameHashMode_Full,
|
||||
} LNK_TypeNameHashMode;
|
||||
|
||||
|
||||
typedef struct LNK_Config
|
||||
{
|
||||
Arena *arena;
|
||||
@@ -411,7 +410,7 @@ typedef struct LNK_Config
|
||||
U64 unresolved_symbol_limit;
|
||||
U64 unresolved_symbol_ref_limit;
|
||||
LNK_SwitchState map_lines_for_unresolved_symbols;
|
||||
LLVM_GHashAlg type_hash_alg;
|
||||
LNK_HashKind debug_types_hash;
|
||||
String8 type_server_name;
|
||||
LNK_SwitchState type_server;
|
||||
LNK_SwitchState sort_imports;
|
||||
@@ -616,4 +615,3 @@ internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 name, S
|
||||
internal void lnk_config_pushf(LNK_Config *config, char *fmt, ...);
|
||||
|
||||
internal LNK_Config * lnk_config_init(LNK_CmdLine cmd_line);
|
||||
|
||||
|
||||
+66
-44
@@ -107,11 +107,11 @@ THREAD_POOL_TASK_FUNC(lnk_parse_debug_h_task)
|
||||
}
|
||||
|
||||
// validate hashing algorithm
|
||||
if (ghash.hash_alg != task->config->type_hash_alg) {
|
||||
if (lnk_hash_kind_from_llvm(ghash.hash_alg) != task->config->debug_types_hash) {
|
||||
lnk_error_obj(LNK_Warning_GHash, task->obj_arr[obj_idx],
|
||||
"mismatched .debug$H hash algorithm: got %S, expected %S",
|
||||
"mismatched .debug$H hash algorithm: got %S, expected %S; types will be rehashed",
|
||||
llvm_string_from_ghash_alg(ghash.hash_alg),
|
||||
llvm_string_from_ghash_alg(task->config->type_hash_alg));
|
||||
lnk_string_hash_kind(task->config->debug_types_hash));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
@@ -320,42 +320,45 @@ lnk_string_list_from_rrt(Arena *arena, LNK_RRT *rrt)
|
||||
str8_list_push(arena, &rrt_data, g_rrt_magic);
|
||||
|
||||
// (2) version
|
||||
str8_list_push(arena, &rrt_data, str8_struct(&g_rrt_version));
|
||||
str8_list_push(arena, &rrt_data, str8_struct(push_u64(arena, g_rrt_version)));
|
||||
|
||||
// (3) type data ranges
|
||||
// (3) debug types hash
|
||||
str8_list_push(arena, &rrt_data, str8_struct(&rrt->debug_types_hash));
|
||||
|
||||
// (4) type data ranges
|
||||
str8_list_push(arena, &rrt_data, str8_array_fixed(rrt->type_data_ranges));
|
||||
|
||||
// (4) type data
|
||||
// (5) type data
|
||||
str8_list_push(arena, &rrt_data, rrt->type_data_raw);
|
||||
|
||||
// (5) type index ranges
|
||||
// (6) type index ranges
|
||||
str8_list_push(arena, &rrt_data, str8_array_fixed(rrt->ti_ranges));
|
||||
|
||||
// (6) type hashes size
|
||||
// (7) type hashes size
|
||||
U64 total_hash_count = 0;
|
||||
for EachIndex(i, CV_TypeIndexSource_COUNT) { total_hash_count += dim_1u64(rrt->ti_ranges[i]); }
|
||||
U64 type_hashes_size = sizeof(**rrt->type_hashes_unpacked) * total_hash_count;
|
||||
str8_list_push(arena, &rrt_data, str8_struct(push_u64(arena, type_hashes_size)));
|
||||
|
||||
// (7) type hashes
|
||||
// (8) type hashes
|
||||
for EachIndex(i, CV_TypeIndexSource_COUNT) {
|
||||
U64 type_count = dim_1u64(rrt->ti_ranges[i]);
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->type_hashes_unpacked[i], type_count));
|
||||
}
|
||||
|
||||
// (8) object count
|
||||
// (9) object count
|
||||
str8_list_push(arena, &rrt_data, str8_struct(&rrt->obj_count));
|
||||
|
||||
// (9) per object type index ranges
|
||||
// (10) per object type index ranges
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_ti_ranges, rrt->obj_count));
|
||||
|
||||
// (10) per object time stamps
|
||||
// (11) per object time stamps
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_time_stamps, rrt->obj_count));
|
||||
|
||||
// (11) per object leaf counts
|
||||
// (12) per object leaf counts
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_leaf_counts, rrt->obj_count));
|
||||
|
||||
// (12) per object file reverse lookup table for type indices
|
||||
// (13) per object file reverse lookup table for type indices
|
||||
for EachIndex(obj_idx, rrt->obj_count) {
|
||||
CV_TypeIndex *obj_ti_map = rrt->obj_ti_maps[obj_idx];
|
||||
U64 obj_ti_count = rrt->obj_leaf_counts[obj_idx];
|
||||
@@ -363,16 +366,16 @@ lnk_string_list_from_rrt(Arena *arena, LNK_RRT *rrt)
|
||||
str8_list_push(arena, &rrt_data, str8_array(obj_ti_map, obj_ti_count));
|
||||
}
|
||||
|
||||
// (13) object file paths size
|
||||
// (14) object file paths size
|
||||
str8_list_push(arena, &rrt_data, str8_struct(push_u64(arena, obj_paths.size)));
|
||||
|
||||
// (14) object file paths block
|
||||
// (15) object file paths block
|
||||
str8_list_push(arena, &rrt_data, obj_paths);
|
||||
|
||||
// (15) PCH type index ranges
|
||||
// (16) PCH type index ranges
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_pch_ti_ranges, rrt->obj_count));
|
||||
|
||||
// (16) PCH object indices
|
||||
// (17) PCH object indices
|
||||
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_pch_indices, rrt->obj_count));
|
||||
|
||||
ProfEnd();
|
||||
@@ -404,11 +407,27 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
|
||||
// match version
|
||||
if (version != g_rrt_version) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT version mismatch, got %llu, expected %llu", path, version, g_rrt_version);
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT version mismatch, got %llu, expected 2 or %llu", path, version, g_rrt_version);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// (3) type data ranges
|
||||
// (3) debug types hash
|
||||
LNK_HashKind debug_types_hash = LNK_HashKind_BLAKE3;
|
||||
if (version == g_rrt_version) {
|
||||
U64 debug_types_hash_size = str8_deserial_read_struct(rrt_data, cursor, &debug_types_hash);
|
||||
if (debug_types_hash_size != sizeof(debug_types_hash)) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file does not contain enough bytes to read the debug types hash", path);
|
||||
goto exit;
|
||||
}
|
||||
cursor += debug_types_hash_size;
|
||||
|
||||
if (debug_types_hash != LNK_HashKind_BLAKE3 && debug_types_hash != LNK_HashKind_XXHash) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file has invalid debug types hash %u", path, debug_types_hash);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
// (4) type data ranges
|
||||
Rng1U64 type_data_ranges[CV_TypeIndexSource_COUNT] = {0};
|
||||
U64 type_data_ranges_size = str8_deserial_read_array(rrt_data, cursor, type_data_ranges, ArrayCount(type_data_ranges));
|
||||
if (type_data_ranges_size != sizeof(type_data_ranges)) {
|
||||
@@ -421,7 +440,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
U64 total_type_data_size = 0;
|
||||
for EachElement(i, type_data_ranges) total_type_data_size += dim_1u64(type_data_ranges[i]);
|
||||
|
||||
// (4) type data
|
||||
// (5) type data
|
||||
String8 type_data_raw = {0};
|
||||
U64 type_data_raw_size = str8_deserial_read_block(rrt_data, cursor, total_type_data_size, &type_data_raw);
|
||||
if (type_data_raw_size != total_type_data_size) {
|
||||
@@ -430,7 +449,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += type_data_raw_size;
|
||||
|
||||
// (5) type index ranges
|
||||
// (6) type index ranges
|
||||
Rng1U64 ti_ranges[CV_TypeIndexSource_COUNT] = {0};
|
||||
U64 ti_ranges_size = str8_deserial_read_array(rrt_data, cursor, ti_ranges, ArrayCount(ti_ranges));
|
||||
if (ti_ranges_size != sizeof(ti_ranges)) {
|
||||
@@ -439,7 +458,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += ti_ranges_size;
|
||||
|
||||
// (6) type hashes size
|
||||
// (7) type hashes size
|
||||
U64 type_hashes_size = 0;
|
||||
U64 type_hashes_size_size = str8_deserial_read_struct(rrt_data, cursor, &type_hashes_size);
|
||||
if (type_hashes_size_size != sizeof(type_hashes_size)) {
|
||||
@@ -459,7 +478,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
}
|
||||
|
||||
// (7) type hashes
|
||||
// (8) type hashes
|
||||
String8 type_hashes = {0};
|
||||
U64 type_hashes_read_size = str8_deserial_read_block(rrt_data, cursor, type_hashes_size, &type_hashes);
|
||||
if (type_hashes_read_size != type_hashes_size) {
|
||||
@@ -479,7 +498,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
}
|
||||
|
||||
// (8) object count
|
||||
// (9) object count
|
||||
U64 obj_count = 0;
|
||||
U64 obj_count_size = str8_deserial_read_struct(rrt_data, cursor, &obj_count);
|
||||
if (obj_count_size == 0) {
|
||||
@@ -488,7 +507,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += obj_count_size;
|
||||
|
||||
// (9) per object type index ranges
|
||||
// (10) per object type index ranges
|
||||
Rng1U64 *obj_ti_ranges = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_ti_ranges) * obj_count);
|
||||
if (obj_ti_ranges == 0) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object type index ranges", path);
|
||||
@@ -496,7 +515,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += sizeof(*obj_ti_ranges) * obj_count;
|
||||
|
||||
// (10) last observed time stamp of the object files
|
||||
// (11) last observed time stamp of the object files
|
||||
U64 *obj_time_stamps = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_time_stamps) * obj_count);
|
||||
if (obj_time_stamps == 0) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object timestamps", path);
|
||||
@@ -504,7 +523,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += sizeof(*obj_time_stamps) * obj_count;
|
||||
|
||||
// (11) per object leaf counts
|
||||
// (12) per object leaf counts
|
||||
U64 *obj_leaf_counts = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_leaf_counts) * obj_count);
|
||||
if (obj_leaf_counts == 0) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object leaf counts", path);
|
||||
@@ -512,7 +531,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += sizeof(*obj_leaf_counts) * obj_count;
|
||||
|
||||
// (12) per object file reverse lookup table for type indices
|
||||
// (13) per object file reverse lookup table for type indices
|
||||
CV_TypeIndex **obj_ti_maps = push_array(arena, CV_TypeIndex *, obj_count);
|
||||
for EachIndex(obj_idx, obj_count) {
|
||||
U64 obj_ti_count = obj_leaf_counts[obj_idx];
|
||||
@@ -524,7 +543,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
cursor += obj_ti_count * sizeof(*obj_ti_maps[obj_idx]);
|
||||
}
|
||||
|
||||
// (13) object file paths size
|
||||
// (14) object file paths size
|
||||
U64 obj_file_paths_size = 0;
|
||||
U64 obj_file_paths_size_size = str8_deserial_read_struct(rrt_data, cursor, &obj_file_paths_size);
|
||||
if (obj_file_paths_size_size == 0) {
|
||||
@@ -533,7 +552,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += obj_file_paths_size_size;
|
||||
|
||||
// (14) object file paths block
|
||||
// (15) object file paths block
|
||||
String8 obj_file_paths_block = {0};
|
||||
U64 obj_file_paths_block_size = str8_deserial_read_block(rrt_data, cursor, obj_file_paths_size, &obj_file_paths_block);
|
||||
if (obj_file_paths_block_size != obj_file_paths_size) {
|
||||
@@ -542,7 +561,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
}
|
||||
cursor += obj_file_paths_block_size;
|
||||
|
||||
// (15) PCH type index ranges
|
||||
// (16) PCH type index ranges
|
||||
Rng1U64 *obj_pch_ti_ranges = str8_deserial_get_raw_ptr(rrt_data, cursor, obj_count * sizeof(*obj_pch_ti_ranges));
|
||||
if (obj_pch_ti_ranges == 0) {
|
||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is too small to read object PCH type index ranges");
|
||||
@@ -584,6 +603,7 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
||||
// fill out result
|
||||
if (rrt_out) {
|
||||
rrt_out->path = path;
|
||||
rrt_out->debug_types_hash = debug_types_hash;
|
||||
rrt_out->type_data_raw = type_data_raw;
|
||||
rrt_out->type_hashes = type_hashes;
|
||||
MemoryCopyArray(rrt_out->type_data_ranges, type_data_ranges);
|
||||
@@ -937,7 +957,7 @@ lnk_make_code_view_input(TP_Context *tp, TP_Arena *tp_arena, LNK_Config *config,
|
||||
// wire RRT hashes to type servers .debug$H
|
||||
for EachIndex(ts_idx, ts_arr.count) {
|
||||
LNK_TypeServer *ts = &ts_arr.v[ts_idx];
|
||||
if (ts->rrt) {
|
||||
if (ts->rrt && ts->rrt->debug_types_hash == config->debug_types_hash) {
|
||||
U64 ts_obj_idx = input.ts_obj_range.min + ts_idx;
|
||||
CV_DebugT *debug_t = &input.debug_t_arr[ts_obj_idx];
|
||||
CV_DebugH *debug_h = &input.debug_h_arr[ts_obj_idx];
|
||||
@@ -1248,7 +1268,8 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
CV_TypeIndex curr_ti = cv_ti_from_leaf_idx(debug_t, curr_ti_source, leaf_ref.leaf_idx);
|
||||
|
||||
// init hasher
|
||||
blake3_hasher hasher; blake3_hasher_init(&hasher);
|
||||
LNK_Hasher hasher;
|
||||
lnk_hasher_init(&hasher, input->config->debug_types_hash);
|
||||
|
||||
// hash bytes around indices
|
||||
{
|
||||
@@ -1256,14 +1277,14 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
for EachNode(ti_info, CV_TypeIndexInfo, ti_info_list.first) {
|
||||
U8 *bytes = leaf.data.str + last_ti_off;
|
||||
U64 size = ti_info->offset - last_ti_off;
|
||||
blake3_hasher_update(&hasher, bytes, size);
|
||||
lnk_hasher_update(&hasher, bytes, size);
|
||||
last_ti_off = ti_info->offset + sizeof(CV_TypeIndex);
|
||||
}
|
||||
|
||||
Assert(leaf.data.size >= last_ti_off);
|
||||
U8 *bytes = leaf.data.str + last_ti_off;
|
||||
U64 size = leaf.data.size - last_ti_off;
|
||||
blake3_hasher_update(&hasher, bytes, size);
|
||||
lnk_hasher_update(&hasher, bytes, size);
|
||||
}
|
||||
|
||||
// mix-in sub leaf hashes
|
||||
@@ -1273,7 +1294,7 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
|
||||
// simple indices are stable across compile units
|
||||
if (sub_ti < debug_t->ti_ranges[sub_ti_n->source].min) {
|
||||
blake3_hasher_update(&hasher, &sub_ti, sizeof(sub_ti));
|
||||
lnk_hasher_update_struct(&hasher, &sub_ti);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1306,7 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind));
|
||||
|
||||
// reset hasher
|
||||
blake3_hasher_init(&hasher);
|
||||
lnk_hasher_init(&hasher, input->config->debug_types_hash);
|
||||
|
||||
// log error
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
@@ -1307,7 +1328,7 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind));
|
||||
|
||||
// reset hasher
|
||||
blake3_hasher_init(&hasher);
|
||||
lnk_hasher_init(&hasher, input->config->debug_types_hash);
|
||||
|
||||
// log error
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
@@ -1324,20 +1345,21 @@ lnk_hash_cv_leaf(LNK_CodeViewInput *input, LNK_LeafRef leaf_ref, CV_TypeIndexInf
|
||||
U64 sub_hash = input->debug_h_arr[sub_ref.obj_idx].v[sub_ref.leaf_idx];
|
||||
|
||||
// mix-in sub-type hash
|
||||
blake3_hasher_update(&hasher, &sub_hash, sizeof(sub_hash));
|
||||
lnk_hasher_update_struct(&hasher, &sub_hash);
|
||||
}
|
||||
|
||||
// hash leaf header
|
||||
CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_ref.leaf_idx);
|
||||
blake3_hasher_update(&hasher, leaf_header, sizeof(*leaf_header));
|
||||
CV_LeafHeader *leaf_header_ptr = cv_debug_t_get_leaf_header(debug_t, leaf_ref.leaf_idx);
|
||||
lnk_hasher_update_struct(&hasher, leaf_header_ptr);
|
||||
|
||||
U64 hash;
|
||||
blake3_hasher_finalize(&hasher, (U8 *) &hash, sizeof(hash));
|
||||
// finalize the type hash
|
||||
U64 hash = lnk_hasher_digest(&hasher);
|
||||
|
||||
Assert(hash != 0);
|
||||
Assert(input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] == 0 ||
|
||||
input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] == 1);
|
||||
input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] = hash;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
// RRT
|
||||
|
||||
global read_only String8 g_rrt_magic = str8_lit_comp("RAD-TYPE-SERVER\0");
|
||||
global read_only U64 g_rrt_version = 2;
|
||||
global read_only U64 g_rrt_version = 3;
|
||||
|
||||
typedef struct LNK_RRT
|
||||
{
|
||||
String8 path;
|
||||
LNK_HashKind debug_types_hash;
|
||||
|
||||
String8 type_data_raw;
|
||||
union {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal void
|
||||
lnk_hasher_init(LNK_Hasher *hasher, LNK_HashKind kind)
|
||||
{
|
||||
hasher->kind = kind;
|
||||
switch (kind) {
|
||||
case LNK_HashKind_BLAKE3: blake3_hasher_init(&hasher->u.blake3); break;
|
||||
case LNK_HashKind_XXHash: XXH3_64bits_reset(&hasher->u.xxhash); break;
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
}
|
||||
|
||||
internal void
|
||||
lnk_hasher_update(LNK_Hasher *hasher, void *data, U64 size)
|
||||
{
|
||||
switch (hasher->kind) {
|
||||
case LNK_HashKind_BLAKE3: blake3_hasher_update(&hasher->u.blake3, data, size); break;
|
||||
case LNK_HashKind_XXHash: XXH3_64bits_update(&hasher->u.xxhash, data, size); break;
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
}
|
||||
|
||||
internal U64
|
||||
lnk_hasher_digest(LNK_Hasher *hasher)
|
||||
{
|
||||
U64 hash = 0;
|
||||
switch (hasher->kind) {
|
||||
case LNK_HashKind_BLAKE3: blake3_hasher_finalize(&hasher->u.blake3, (U8 *)&hash, sizeof(hash)); break;
|
||||
case LNK_HashKind_XXHash: hash = XXH3_64bits_digest(&hasher->u.xxhash); break;
|
||||
default: InvalidPath; break;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
internal String8
|
||||
lnk_string_hash_kind(LNK_HashKind hash_kind)
|
||||
{
|
||||
#define X(NAME) case LNK_HashKind_##NAME: return str8_lit(Stringify(NAME));
|
||||
switch (hash_kind) {
|
||||
LNK_HashKind_XList
|
||||
}
|
||||
#undef X
|
||||
return str8_zero();
|
||||
}
|
||||
|
||||
internal LNK_HashKind
|
||||
lnk_hash_kind_from_llvm(LLVM_GHashAlgEnum v)
|
||||
{
|
||||
switch (v) {
|
||||
case LLVM_GHashAlg_SHA1:
|
||||
case LLVM_GHashAlg_SHA1_8:
|
||||
return LNK_HashKind_Null;
|
||||
case LLVM_GHashAlg_BLAKE3:
|
||||
return LNK_HashKind_BLAKE3;
|
||||
}
|
||||
return LNK_HashKind_Null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#pragma once
|
||||
|
||||
#define LNK_HashKind_XList \
|
||||
X(Null) \
|
||||
X(BLAKE3) \
|
||||
X(XXHash)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#define X(NAME) LNK_HashKind_##NAME,
|
||||
LNK_HashKind_XList
|
||||
#undef X
|
||||
} LNK_HashKind;
|
||||
|
||||
typedef struct LNK_Hasher
|
||||
{
|
||||
LNK_HashKind kind;
|
||||
union
|
||||
{
|
||||
blake3_hasher blake3;
|
||||
XXH3_state_t xxhash;
|
||||
} u;
|
||||
} LNK_Hasher;
|
||||
|
||||
internal void lnk_hasher_init (LNK_Hasher *hasher, LNK_HashKind kind);
|
||||
internal void lnk_hasher_update(LNK_Hasher *hasher, void *data, U64 size);
|
||||
#define lnk_hasher_update_struct(hasher, ptr) lnk_hasher_update(hasher, ptr, sizeof(*ptr))
|
||||
internal U64 lnk_hasher_digest(LNK_Hasher *hasher);
|
||||
|
||||
internal String8 lnk_string_hash_kind(LNK_HashKind hash_kind);
|
||||
|
||||
// LLVM extension
|
||||
internal LNK_HashKind lnk_hash_kind_from_llvm(LLVM_GHashAlgEnum v);
|
||||
|
||||
@@ -7423,7 +7423,7 @@ TEST(ghash_check_hash_alg)
|
||||
|
||||
B32 is_warning_found = 0;
|
||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
||||
String8 expected_line = str8f(arena, "Warning(*): *: mismatched .debug$H hash algorithm: got SHA1_8, expected BLAKE3");
|
||||
String8 expected_line = str8f(arena, "Warning(*): *: mismatched .debug$H hash algorithm: got SHA1_8, expected *");
|
||||
for (String8 i = g_errors; i.size > 0 && !is_warning_found; ) {
|
||||
String8 line = t_chop_line(&i);
|
||||
is_warning_found = str8_match_wildcard(line, expected_line, StringMatchFlag_CaseInsensitive);
|
||||
|
||||
Reference in New Issue
Block a user