mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-08 06:48:41 +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_log.h"
|
||||||
#include "lnk_timer.h"
|
#include "lnk_timer.h"
|
||||||
|
#include "lnk_hasher.h"
|
||||||
#include "lnk_io.h"
|
#include "lnk_io.h"
|
||||||
#include "lnk_cmd_line.h"
|
#include "lnk_cmd_line.h"
|
||||||
#include "lnk_config.h"
|
#include "lnk_config.h"
|
||||||
@@ -116,6 +117,7 @@
|
|||||||
|
|
||||||
#include "lnk_log.c"
|
#include "lnk_log.c"
|
||||||
#include "lnk_timer.c"
|
#include "lnk_timer.c"
|
||||||
|
#include "lnk_hasher.c"
|
||||||
#include "lnk_io.c"
|
#include "lnk_io.c"
|
||||||
#include "lnk_cmd_line.c"
|
#include "lnk_cmd_line.c"
|
||||||
#include "lnk_config.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_BOOT_MODE:LINKER",
|
||||||
//"/RAD_BUILD_EXP",
|
//"/RAD_BUILD_EXP",
|
||||||
"/RAD_BUILD_IMPLIB",
|
"/RAD_BUILD_IMPLIB",
|
||||||
"/RAD_TPYE_HASH_ALG:BLAKE3",
|
|
||||||
"/RAD_AGE:1",
|
"/RAD_AGE:1",
|
||||||
"/RAD_CHECK_UNUSED_DELAY_LOAD_DLL",
|
"/RAD_CHECK_UNUSED_DELAY_LOAD_DLL",
|
||||||
"/RAD_DO_MERGE",
|
"/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_MT_PATH:%s", LNK_MANIFEST_MERGE_TOOL_NAME).str,
|
||||||
(char*)str8f(scratch.arena, "/RAD_DATA_DIR_COUNT:%u", PE_DataDirectoryIndex_COUNT).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",
|
"/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);
|
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")
|
ProfScope("Pack Type Data & Data Ranges")
|
||||||
{
|
{
|
||||||
LNK_RRTTypeDataSerializer task = { &cv_types, &rrt.type_data_raw, rrt.type_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_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_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_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_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_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." },
|
{ 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);
|
lnk_cmd_switch_parse_u32(obj, cmd_switch, value_strings, &config->time_stamp, 0);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case LNK_CmdSwitch_Rad_TypeHashAlg: {
|
case LNK_CmdSwitch_Rad_DebugTypeHash: {
|
||||||
String8 alg = {0};
|
String8 alg = {0};
|
||||||
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &alg)) {
|
if (lnk_cmd_switch_parse_string(obj, cmd_switch, value_strings, &alg)) {
|
||||||
if (str8_match(alg, str8_lit("BLAKE3"), StringMatchFlag_CaseInsensitive)) {
|
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 {
|
} else {
|
||||||
lnk_error_cmd_switch(LNK_Error_Cmdl, obj, cmd_switch, "unknown hash alg: %S", alg);
|
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();
|
ProfEnd();
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ typedef enum
|
|||||||
LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers,
|
LNK_CmdSwitch_Rad_SharedThreadPoolMaxWorkers,
|
||||||
LNK_CmdSwitch_Rad_SortImports,
|
LNK_CmdSwitch_Rad_SortImports,
|
||||||
LNK_CmdSwitch_Rad_TimeStamp,
|
LNK_CmdSwitch_Rad_TimeStamp,
|
||||||
LNK_CmdSwitch_Rad_TypeHashAlg,
|
LNK_CmdSwitch_Rad_DebugTypeHash,
|
||||||
LNK_CmdSwitch_Rad_UnresolvedSymbolLimit,
|
LNK_CmdSwitch_Rad_UnresolvedSymbolLimit,
|
||||||
LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit,
|
LNK_CmdSwitch_Rad_UnresolvedSymbolRefLimit,
|
||||||
LNK_CmdSwitch_Rad_Version,
|
LNK_CmdSwitch_Rad_Version,
|
||||||
@@ -305,7 +305,6 @@ typedef enum
|
|||||||
LNK_TypeNameHashMode_Full,
|
LNK_TypeNameHashMode_Full,
|
||||||
} LNK_TypeNameHashMode;
|
} LNK_TypeNameHashMode;
|
||||||
|
|
||||||
|
|
||||||
typedef struct LNK_Config
|
typedef struct LNK_Config
|
||||||
{
|
{
|
||||||
Arena *arena;
|
Arena *arena;
|
||||||
@@ -411,7 +410,7 @@ typedef struct LNK_Config
|
|||||||
U64 unresolved_symbol_limit;
|
U64 unresolved_symbol_limit;
|
||||||
U64 unresolved_symbol_ref_limit;
|
U64 unresolved_symbol_ref_limit;
|
||||||
LNK_SwitchState map_lines_for_unresolved_symbols;
|
LNK_SwitchState map_lines_for_unresolved_symbols;
|
||||||
LLVM_GHashAlg type_hash_alg;
|
LNK_HashKind debug_types_hash;
|
||||||
String8 type_server_name;
|
String8 type_server_name;
|
||||||
LNK_SwitchState type_server;
|
LNK_SwitchState type_server;
|
||||||
LNK_SwitchState sort_imports;
|
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 void lnk_config_pushf(LNK_Config *config, char *fmt, ...);
|
||||||
|
|
||||||
internal LNK_Config * lnk_config_init(LNK_CmdLine cmd_line);
|
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
|
// 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],
|
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(ghash.hash_alg),
|
||||||
llvm_string_from_ghash_alg(task->config->type_hash_alg));
|
lnk_string_hash_kind(task->config->debug_types_hash));
|
||||||
goto exit;
|
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);
|
str8_list_push(arena, &rrt_data, g_rrt_magic);
|
||||||
|
|
||||||
// (2) version
|
// (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));
|
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);
|
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));
|
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;
|
U64 total_hash_count = 0;
|
||||||
for EachIndex(i, CV_TypeIndexSource_COUNT) { total_hash_count += dim_1u64(rrt->ti_ranges[i]); }
|
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;
|
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)));
|
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) {
|
for EachIndex(i, CV_TypeIndexSource_COUNT) {
|
||||||
U64 type_count = dim_1u64(rrt->ti_ranges[i]);
|
U64 type_count = dim_1u64(rrt->ti_ranges[i]);
|
||||||
str8_list_push(arena, &rrt_data, str8_array(rrt->type_hashes_unpacked[i], type_count));
|
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));
|
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));
|
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));
|
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));
|
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) {
|
for EachIndex(obj_idx, rrt->obj_count) {
|
||||||
CV_TypeIndex *obj_ti_map = rrt->obj_ti_maps[obj_idx];
|
CV_TypeIndex *obj_ti_map = rrt->obj_ti_maps[obj_idx];
|
||||||
U64 obj_ti_count = rrt->obj_leaf_counts[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));
|
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)));
|
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);
|
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));
|
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));
|
str8_list_push(arena, &rrt_data, str8_array(rrt->obj_pch_indices, rrt->obj_count));
|
||||||
|
|
||||||
ProfEnd();
|
ProfEnd();
|
||||||
@@ -404,11 +407,27 @@ lnk_rrt_from_string(Arena *arena, String8 rrt_data, String8 path, LNK_RRT *rrt_o
|
|||||||
|
|
||||||
// match version
|
// match version
|
||||||
if (version != g_rrt_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;
|
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};
|
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));
|
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)) {
|
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;
|
U64 total_type_data_size = 0;
|
||||||
for EachElement(i, type_data_ranges) total_type_data_size += dim_1u64(type_data_ranges[i]);
|
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};
|
String8 type_data_raw = {0};
|
||||||
U64 type_data_raw_size = str8_deserial_read_block(rrt_data, cursor, total_type_data_size, &type_data_raw);
|
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) {
|
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;
|
cursor += type_data_raw_size;
|
||||||
|
|
||||||
// (5) type index ranges
|
// (6) type index ranges
|
||||||
Rng1U64 ti_ranges[CV_TypeIndexSource_COUNT] = {0};
|
Rng1U64 ti_ranges[CV_TypeIndexSource_COUNT] = {0};
|
||||||
U64 ti_ranges_size = str8_deserial_read_array(rrt_data, cursor, ti_ranges, ArrayCount(ti_ranges));
|
U64 ti_ranges_size = str8_deserial_read_array(rrt_data, cursor, ti_ranges, ArrayCount(ti_ranges));
|
||||||
if (ti_ranges_size != sizeof(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;
|
cursor += ti_ranges_size;
|
||||||
|
|
||||||
// (6) type hashes size
|
// (7) type hashes size
|
||||||
U64 type_hashes_size = 0;
|
U64 type_hashes_size = 0;
|
||||||
U64 type_hashes_size_size = str8_deserial_read_struct(rrt_data, cursor, &type_hashes_size);
|
U64 type_hashes_size_size = str8_deserial_read_struct(rrt_data, cursor, &type_hashes_size);
|
||||||
if (type_hashes_size_size != sizeof(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};
|
String8 type_hashes = {0};
|
||||||
U64 type_hashes_read_size = str8_deserial_read_block(rrt_data, cursor, type_hashes_size, &type_hashes);
|
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) {
|
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 = 0;
|
||||||
U64 obj_count_size = str8_deserial_read_struct(rrt_data, cursor, &obj_count);
|
U64 obj_count_size = str8_deserial_read_struct(rrt_data, cursor, &obj_count);
|
||||||
if (obj_count_size == 0) {
|
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;
|
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);
|
Rng1U64 *obj_ti_ranges = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_ti_ranges) * obj_count);
|
||||||
if (obj_ti_ranges == 0) {
|
if (obj_ti_ranges == 0) {
|
||||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object type index ranges", path);
|
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;
|
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);
|
U64 *obj_time_stamps = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_time_stamps) * obj_count);
|
||||||
if (obj_time_stamps == 0) {
|
if (obj_time_stamps == 0) {
|
||||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object timestamps", path);
|
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;
|
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);
|
U64 *obj_leaf_counts = str8_deserial_get_raw_ptr(rrt_data, cursor, sizeof(*obj_leaf_counts) * obj_count);
|
||||||
if (obj_leaf_counts == 0) {
|
if (obj_leaf_counts == 0) {
|
||||||
lnk_error(LNK_Error_IllData, "ERROR: %S: RRT file is missing the object leaf counts", path);
|
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;
|
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);
|
CV_TypeIndex **obj_ti_maps = push_array(arena, CV_TypeIndex *, obj_count);
|
||||||
for EachIndex(obj_idx, obj_count) {
|
for EachIndex(obj_idx, obj_count) {
|
||||||
U64 obj_ti_count = obj_leaf_counts[obj_idx];
|
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]);
|
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 = 0;
|
||||||
U64 obj_file_paths_size_size = str8_deserial_read_struct(rrt_data, cursor, &obj_file_paths_size);
|
U64 obj_file_paths_size_size = str8_deserial_read_struct(rrt_data, cursor, &obj_file_paths_size);
|
||||||
if (obj_file_paths_size_size == 0) {
|
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;
|
cursor += obj_file_paths_size_size;
|
||||||
|
|
||||||
// (14) object file paths block
|
// (15) object file paths block
|
||||||
String8 obj_file_paths_block = {0};
|
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);
|
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) {
|
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;
|
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));
|
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) {
|
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");
|
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
|
// fill out result
|
||||||
if (rrt_out) {
|
if (rrt_out) {
|
||||||
rrt_out->path = path;
|
rrt_out->path = path;
|
||||||
|
rrt_out->debug_types_hash = debug_types_hash;
|
||||||
rrt_out->type_data_raw = type_data_raw;
|
rrt_out->type_data_raw = type_data_raw;
|
||||||
rrt_out->type_hashes = type_hashes;
|
rrt_out->type_hashes = type_hashes;
|
||||||
MemoryCopyArray(rrt_out->type_data_ranges, type_data_ranges);
|
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
|
// wire RRT hashes to type servers .debug$H
|
||||||
for EachIndex(ts_idx, ts_arr.count) {
|
for EachIndex(ts_idx, ts_arr.count) {
|
||||||
LNK_TypeServer *ts = &ts_arr.v[ts_idx];
|
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;
|
U64 ts_obj_idx = input.ts_obj_range.min + ts_idx;
|
||||||
CV_DebugT *debug_t = &input.debug_t_arr[ts_obj_idx];
|
CV_DebugT *debug_t = &input.debug_t_arr[ts_obj_idx];
|
||||||
CV_DebugH *debug_h = &input.debug_h_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);
|
CV_TypeIndex curr_ti = cv_ti_from_leaf_idx(debug_t, curr_ti_source, leaf_ref.leaf_idx);
|
||||||
|
|
||||||
// init hasher
|
// 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
|
// 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) {
|
for EachNode(ti_info, CV_TypeIndexInfo, ti_info_list.first) {
|
||||||
U8 *bytes = leaf.data.str + last_ti_off;
|
U8 *bytes = leaf.data.str + last_ti_off;
|
||||||
U64 size = ti_info->offset - 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);
|
last_ti_off = ti_info->offset + sizeof(CV_TypeIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert(leaf.data.size >= last_ti_off);
|
Assert(leaf.data.size >= last_ti_off);
|
||||||
U8 *bytes = leaf.data.str + last_ti_off;
|
U8 *bytes = leaf.data.str + last_ti_off;
|
||||||
U64 size = leaf.data.size - 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
|
// 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
|
// simple indices are stable across compile units
|
||||||
if (sub_ti < debug_t->ti_ranges[sub_ti_n->source].min) {
|
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;
|
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));
|
memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind));
|
||||||
|
|
||||||
// reset hasher
|
// reset hasher
|
||||||
blake3_hasher_init(&hasher);
|
lnk_hasher_init(&hasher, input->config->debug_types_hash);
|
||||||
|
|
||||||
// log error
|
// log error
|
||||||
Temp scratch = scratch_begin(0,0);
|
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));
|
memory_write16(leaf_header + OffsetOf(CV_LeafHeader, size), sizeof(CV_LeafKind));
|
||||||
|
|
||||||
// reset hasher
|
// reset hasher
|
||||||
blake3_hasher_init(&hasher);
|
lnk_hasher_init(&hasher, input->config->debug_types_hash);
|
||||||
|
|
||||||
// log error
|
// log error
|
||||||
Temp scratch = scratch_begin(0,0);
|
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];
|
U64 sub_hash = input->debug_h_arr[sub_ref.obj_idx].v[sub_ref.leaf_idx];
|
||||||
|
|
||||||
// mix-in sub-type hash
|
// mix-in sub-type hash
|
||||||
blake3_hasher_update(&hasher, &sub_hash, sizeof(sub_hash));
|
lnk_hasher_update_struct(&hasher, &sub_hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash leaf header
|
// hash leaf header
|
||||||
CV_LeafHeader *leaf_header = cv_debug_t_get_leaf_header(debug_t, leaf_ref.leaf_idx);
|
CV_LeafHeader *leaf_header_ptr = cv_debug_t_get_leaf_header(debug_t, leaf_ref.leaf_idx);
|
||||||
blake3_hasher_update(&hasher, leaf_header, sizeof(*leaf_header));
|
lnk_hasher_update_struct(&hasher, leaf_header_ptr);
|
||||||
|
|
||||||
U64 hash;
|
// finalize the type hash
|
||||||
blake3_hasher_finalize(&hasher, (U8 *) &hash, sizeof(hash));
|
U64 hash = lnk_hasher_digest(&hasher);
|
||||||
|
|
||||||
Assert(hash != 0);
|
Assert(hash != 0);
|
||||||
Assert(input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] == 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] == 1);
|
||||||
input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] = hash;
|
input->debug_h_arr[leaf_ref.obj_idx].v[leaf_ref.leaf_idx] = hash;
|
||||||
|
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,12 @@
|
|||||||
// RRT
|
// RRT
|
||||||
|
|
||||||
global read_only String8 g_rrt_magic = str8_lit_comp("RAD-TYPE-SERVER\0");
|
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
|
typedef struct LNK_RRT
|
||||||
{
|
{
|
||||||
String8 path;
|
String8 path;
|
||||||
|
LNK_HashKind debug_types_hash;
|
||||||
|
|
||||||
String8 type_data_raw;
|
String8 type_data_raw;
|
||||||
union {
|
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;
|
B32 is_warning_found = 0;
|
||||||
String8 debug_obj_path = t_make_file_path(arena, str8_lit("debug.obj"));
|
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; ) {
|
for (String8 i = g_errors; i.size > 0 && !is_warning_found; ) {
|
||||||
String8 line = t_chop_line(&i);
|
String8 line = t_chop_line(&i);
|
||||||
is_warning_found = str8_match_wildcard(line, expected_line, StringMatchFlag_CaseInsensitive);
|
is_warning_found = str8_match_wildcard(line, expected_line, StringMatchFlag_CaseInsensitive);
|
||||||
|
|||||||
Reference in New Issue
Block a user