mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
implement /INFERASANLIBS
This commit is contained in:
+90
-5
@@ -1350,7 +1350,7 @@ lnk_load_inputs(TP_Context *tp, TP_Arena *arena, LNK_Config *config, LNK_Inputer
|
|||||||
AssertAlways(include_obj_count == 1);
|
AssertAlways(include_obj_count == 1);
|
||||||
|
|
||||||
if (obj_with_includes) {
|
if (obj_with_includes) {
|
||||||
DLLInsert(link->objs.first, link->objs.last, obj_with_includes->node, include_obj);
|
DLLInsert(link->objs.first, link->objs.last, obj_with_includes->self, include_obj);
|
||||||
link->objs.count += 1;
|
link->objs.count += 1;
|
||||||
} else {
|
} else {
|
||||||
lnk_obj_list_push_node(&link->objs, include_obj);
|
lnk_obj_list_push_node(&link->objs, include_obj);
|
||||||
@@ -1579,6 +1579,40 @@ THREAD_POOL_TASK_FUNC(lnk_search_lib_task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal LNK_Lib *
|
||||||
|
lnk_find_first_crt_lib(LNK_Config *config, LNK_Inputer *inputer)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0, 0);
|
||||||
|
|
||||||
|
LNK_Lib *result = 0;
|
||||||
|
|
||||||
|
String8 crt_lib_names[] = {
|
||||||
|
str8_lit("msvcrt"),
|
||||||
|
str8_lit("msvcrtd"),
|
||||||
|
str8_lit("libcmt"),
|
||||||
|
str8_lit("libcmtd"),
|
||||||
|
};
|
||||||
|
|
||||||
|
for EachNode(n, LNK_Input, inputer->libs.first) {
|
||||||
|
String8 lib_name = str8_chop_last_dot(str8_skip_last_slash(n->path));
|
||||||
|
for EachElement(i, crt_lib_names) {
|
||||||
|
if (str8_match(lib_name, crt_lib_names[i], StringMatchFlag_CaseInsensitive)) {
|
||||||
|
if (result == 0) {
|
||||||
|
result = hash_table_search_path_raw(inputer->libs_ht, n->path);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
LNK_Lib *lib = hash_table_search_path_raw(inputer->libs_ht, n->path);
|
||||||
|
result = lib->input_idx < result->input_idx ? lib : result;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnk_link_inputs(TP_Context *tp,
|
lnk_link_inputs(TP_Context *tp,
|
||||||
TP_Arena *arena,
|
TP_Arena *arena,
|
||||||
@@ -1598,6 +1632,57 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
for EachNode(lib_n, LNK_LibNode, link->libs.first) {
|
for EachNode(lib_n, LNK_LibNode, link->libs.first) {
|
||||||
LNK_Lib *lib = &lib_n->data;
|
LNK_Lib *lib = &lib_n->data;
|
||||||
|
|
||||||
|
if (config->machine != COFF_MachineType_Unknown) {
|
||||||
|
if (config->infer_asan_libs == LNK_SwitchState_Yes) {
|
||||||
|
if ( ! link->asan_libs_resolved) {
|
||||||
|
LNK_Lib *crt_lib = lnk_find_first_crt_lib(config, inputer);
|
||||||
|
if (crt_lib != 0) {
|
||||||
|
String8 crt_lib_name = str8_chop_last_dot(str8_skip_last_slash(crt_lib->path));
|
||||||
|
|
||||||
|
String8 arch_name = {0};
|
||||||
|
if (config->machine == COFF_MachineType_X64) {
|
||||||
|
arch_name = str8_lit("x86_64");
|
||||||
|
} else if (config->machine == COFF_MachineType_X86) {
|
||||||
|
arch_name = str8_lit("i386");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arch_name.size) {
|
||||||
|
B32 link_vc_libs = lnk_symbol_table_searchf(symtab, "__you_must_link_with_VCAsan_lib") != 0 ||
|
||||||
|
lnk_symbol_table_searchf(symtab, "___you_must_link_with_VCAsan_lib") != 0;
|
||||||
|
if (str8_match(crt_lib_name, str8_lit("msvcrt"), StringMatchFlag_CaseInsensitive) || str8_match(crt_lib_name, str8_lit("msvcrtd"), StringMatchFlag_CaseInsensitive)) {
|
||||||
|
String8 dynamic_lib_name = str8f(inputer->arena, "clang_rt.asan_dynamic-%S.lib", arch_name);
|
||||||
|
String8 thunk_lib_name = str8f(inputer->arena, "clang_rt.asan_static_runtime_thunk-%S.lib", arch_name);
|
||||||
|
lnk_whole_archive(config, thunk_lib_name);
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, dynamic_lib_name);
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, thunk_lib_name);
|
||||||
|
if (link_vc_libs) {
|
||||||
|
if (str8_match(crt_lib_name, str8_lit("msvcrtd"), StringMatchFlag_CaseInsensitive)) {
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, str8_lit("libvcasand.lib"));
|
||||||
|
} else {
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, str8_lit("libvcasan.lib"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (str8_match(crt_lib_name, str8_lit("libcmt"), StringMatchFlag_CaseInsensitive) || str8_match(crt_lib_name, str8_lit("libcmtd"), StringMatchFlag_CaseInsensitive)) {
|
||||||
|
String8 dynamic_lib_name = str8f(inputer->arena, "clang_rt.asan_dynamic-%S.lib", arch_name);
|
||||||
|
String8 thunk_lib_name = str8f(inputer->arena, "clang_rt.asan_dynamic_runtime_thunk-%S.lib", arch_name);
|
||||||
|
lnk_whole_archive(config, thunk_lib_name);
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, dynamic_lib_name);
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, thunk_lib_name);
|
||||||
|
if (link_vc_libs) {
|
||||||
|
if (str8_match(crt_lib_name, str8_lit("libcmtd"), StringMatchFlag_CaseInsensitive)) {
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, str8_lit("vcasand.lib"));
|
||||||
|
} else {
|
||||||
|
lnk_inputer_push_lib_thin(inputer, config, LNK_InputSource_Obj, str8_lit("vcasan.lib"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
link->asan_libs_resolved = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LNK_LibMemberInfo *lib_member_infos = hash_table_search_raw_raw(link->lib_member_infos_ht, lib);
|
LNK_LibMemberInfo *lib_member_infos = hash_table_search_raw_raw(link->lib_member_infos_ht, lib);
|
||||||
if (lib_member_infos == 0) {
|
if (lib_member_infos == 0) {
|
||||||
lib_member_infos = push_array(link->arena, LNK_LibMemberInfo, lib->member_count);
|
lib_member_infos = push_array(link->arena, LNK_LibMemberInfo, lib->member_count);
|
||||||
@@ -1615,15 +1700,15 @@ lnk_link_inputs(TP_Context *tp,
|
|||||||
lnk_load_inputs(tp, arena, config, inputer, symtab, link);
|
lnk_load_inputs(tp, arena, config, inputer, symtab, link);
|
||||||
|
|
||||||
if (link_whole_archive) {
|
if (link_whole_archive) {
|
||||||
LNK_LibMemberRef *member_refs = push_array(scratch.arena, LNK_LibMemberRef, lib->member_count);
|
local_persist LNK_Symbol *null_symbol = 0;
|
||||||
for EachIndex(member_idx, lib->member_count) {
|
|
||||||
static LNK_Symbol *null_symbol = 0;
|
|
||||||
if (null_symbol == 0) {
|
if (null_symbol == 0) {
|
||||||
null_symbol = push_array(inputer->arena, LNK_Symbol, 1);
|
null_symbol = push_array(inputer->arena, LNK_Symbol, 1);
|
||||||
null_symbol->refs = push_array(inputer->arena, LNK_ObjSymbolRefNode, 1);
|
null_symbol->refs = push_array(inputer->arena, LNK_ObjSymbolRefNode, 1);
|
||||||
null_symbol->refs->v.obj = &link->objs.first->data;
|
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);
|
LNK_LibMemberRef *member_refs = push_array(scratch.arena, LNK_LibMemberRef, lib->member_count);
|
||||||
|
for EachIndex(member_idx, lib->member_count) {
|
||||||
|
lnk_queue_lib_member(arena->v[0], &member_ref_lists[0], null_symbol, lib, lib_member_infos, member_idx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// search symbols in lib
|
// search symbols in lib
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,6 @@ typedef struct LNK_Input
|
|||||||
B32 has_disk_read_failed;
|
B32 has_disk_read_failed;
|
||||||
B32 exclude_from_debug_info;
|
B32 exclude_from_debug_info;
|
||||||
LNK_LibMemberRef *link_member;
|
LNK_LibMemberRef *link_member;
|
||||||
void *loaded_input;
|
|
||||||
|
|
||||||
struct LNK_Input *next;
|
struct LNK_Input *next;
|
||||||
} LNK_Input;
|
} LNK_Input;
|
||||||
@@ -104,6 +103,7 @@ typedef struct LNK_Link
|
|||||||
HashTable *lib_member_infos_ht;
|
HashTable *lib_member_infos_ht;
|
||||||
LNK_LibMemberRefList imports;
|
LNK_LibMemberRefList imports;
|
||||||
B32 try_to_resolve_entry_point;
|
B32 try_to_resolve_entry_point;
|
||||||
|
B32 asan_libs_resolved;
|
||||||
} LNK_Link;
|
} LNK_Link;
|
||||||
|
|
||||||
typedef struct LNK_LinkResult
|
typedef struct LNK_LinkResult
|
||||||
|
|||||||
@@ -974,6 +974,15 @@ lnk_include_symbol(LNK_Config *config, String8 name, LNK_Obj *obj)
|
|||||||
hash_table_push_string_raw(config->arena, config->include_symbol_ht, name, node);
|
hash_table_push_string_raw(config->arena, config->include_symbol_ht, name, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
lnk_whole_archive(LNK_Config *config, String8 lib_name)
|
||||||
|
{
|
||||||
|
String8Node value = { .string = lib_name };
|
||||||
|
String8List value_strings = {0};
|
||||||
|
str8_list_push_node(&value_strings, &value);
|
||||||
|
lnk_apply_cmd_option_to_config(config, str8_lit("wholearchive"), value_strings, 0);
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
lnk_print_build_info()
|
lnk_print_build_info()
|
||||||
{
|
{
|
||||||
@@ -1443,6 +1452,10 @@ lnk_apply_cmd_option_to_config(LNK_Config *config, String8 cmd_name, String8List
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case LNK_CmdSwitch_InferAsanLibs: {
|
||||||
|
lnk_cmd_switch_parse_flag(obj, cmd_switch, value_strings, &config->infer_asan_libs);
|
||||||
|
} break;
|
||||||
|
|
||||||
case LNK_CmdSwitch_LargeAddressAware: {
|
case LNK_CmdSwitch_LargeAddressAware: {
|
||||||
lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE);
|
lnk_cmd_switch_set_flag_16(obj, cmd_switch, value_strings, &config->file_characteristics, PE_ImageFileCharacteristic_LARGE_ADDRESS_AWARE);
|
||||||
} break;
|
} break;
|
||||||
|
|||||||
@@ -293,6 +293,7 @@ typedef struct LNK_Config
|
|||||||
U64 function_pad_min;
|
U64 function_pad_min;
|
||||||
U64 *manifest_resource_id;
|
U64 *manifest_resource_id;
|
||||||
B32 no_default_libs;
|
B32 no_default_libs;
|
||||||
|
LNK_SwitchState infer_asan_libs;
|
||||||
Version link_ver;
|
Version link_ver;
|
||||||
Version os_ver;
|
Version os_ver;
|
||||||
Version image_ver;
|
Version image_ver;
|
||||||
@@ -550,6 +551,8 @@ internal B32 lnk_is_lib_disallowed(LNK_Config *config, String8 path);
|
|||||||
|
|
||||||
internal void lnk_include_symbol(LNK_Config *config, String8 name, struct LNK_Obj *obj);
|
internal void lnk_include_symbol(LNK_Config *config, String8 name, struct LNK_Obj *obj);
|
||||||
|
|
||||||
|
internal void lnk_whole_archive(LNK_Config *config, String8 lib_name);
|
||||||
|
|
||||||
// --- Config ------------------------------------------------------------------
|
// --- Config ------------------------------------------------------------------
|
||||||
|
|
||||||
internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 name, String8List value_list, struct LNK_Obj *obj);
|
internal void lnk_apply_cmd_option_to_config(LNK_Config *config, String8 name, String8List value_list, struct LNK_Obj *obj);
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ typedef enum
|
|||||||
LNK_Warning_DirectiveSectionWithRelocs,
|
LNK_Warning_DirectiveSectionWithRelocs,
|
||||||
LNK_Warning_NoLargeAddressAwarenessForDll,
|
LNK_Warning_NoLargeAddressAwarenessForDll,
|
||||||
LNK_Warning_TryingToExportEntryPoint,
|
LNK_Warning_TryingToExportEntryPoint,
|
||||||
|
LNK_Warning_InferAsanFail,
|
||||||
LNK_Warning_Last,
|
LNK_Warning_Last,
|
||||||
|
|
||||||
LNK_Error_Count
|
LNK_Error_Count
|
||||||
|
|||||||
@@ -336,7 +336,7 @@ THREAD_POOL_TASK_FUNC(lnk_obj_initer)
|
|||||||
obj->exclude_from_debug_info = input->exclude_from_debug_info;
|
obj->exclude_from_debug_info = input->exclude_from_debug_info;
|
||||||
obj->hotpatch = hotpatch;
|
obj->hotpatch = hotpatch;
|
||||||
obj->associated_sections = associated_sections;
|
obj->associated_sections = associated_sections;
|
||||||
obj->node = &task->objs[task_id];
|
obj->self = &task->objs[task_id];
|
||||||
obj->link_member = input->link_member;
|
obj->link_member = input->link_member;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ typedef struct LNK_Obj
|
|||||||
B8 exclude_from_debug_info;
|
B8 exclude_from_debug_info;
|
||||||
U32Node **associated_sections;
|
U32Node **associated_sections;
|
||||||
LNK_SymbolHashTrie **symlinks;
|
LNK_SymbolHashTrie **symlinks;
|
||||||
|
|
||||||
struct LNK_LibMemberRef *link_member;
|
struct LNK_LibMemberRef *link_member;
|
||||||
|
struct LNK_ObjNode *self;
|
||||||
struct LNK_ObjNode *node;
|
|
||||||
} LNK_Obj;
|
} LNK_Obj;
|
||||||
|
|
||||||
typedef struct LNK_ObjNode
|
typedef struct LNK_ObjNode
|
||||||
|
|||||||
@@ -119,6 +119,24 @@ t_radbin_path(void)
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
t_cl_path(void)
|
||||||
|
{
|
||||||
|
local_persist String8 path = {0};
|
||||||
|
if (path.size == 0) {
|
||||||
|
local_persist U8 buffer[4096];
|
||||||
|
ArenaParams params = { .reserve_size = sizeof(buffer), .commit_size = sizeof(buffer), .optional_backing_buffer = buffer };
|
||||||
|
Arena *arena = arena_alloc_(¶ms);
|
||||||
|
#if OS_WINDOWS
|
||||||
|
path = str8_lit("cl.exe");
|
||||||
|
#else
|
||||||
|
path = str8_lit("cl");
|
||||||
|
#endif
|
||||||
|
AssertAlways(path.size);
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
internal String8
|
internal String8
|
||||||
t_radlink_path(void)
|
t_radlink_path(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ internal void t_run_caller(void *raw_ctx);
|
|||||||
internal void t_run_fail_handler(void *raw_ctx);
|
internal void t_run_fail_handler(void *raw_ctx);
|
||||||
internal T_RunResult t_run(T_Run run);
|
internal T_RunResult t_run(T_Run run);
|
||||||
|
|
||||||
|
internal String8 t_radbin_path(void);
|
||||||
|
internal String8 t_cl_path(void);
|
||||||
|
internal String8 t_radlink_path(void);
|
||||||
|
|
||||||
internal B32 t_invoke(String8 exe, String8 cmdline, U64 timeout);
|
internal B32 t_invoke(String8 exe, String8 cmdline, U64 timeout);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4837,19 +4837,111 @@ T_BeginTest(whole_archive)
|
|||||||
}
|
}
|
||||||
T_EndTest;
|
T_EndTest;
|
||||||
|
|
||||||
|
#if OS_WINDOWS
|
||||||
|
|
||||||
|
internal B32
|
||||||
|
t_radlink_validate_asan_out(String8 obj_name)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(0,0);
|
||||||
|
B32 is_ok = 0;
|
||||||
|
|
||||||
|
t_invoke_(t_radlink_path(), str8f(scratch.arena, "%S /debug:full", obj_name), max_U64, 0, 0);
|
||||||
|
if (g_last_exit_code != 0) { goto exit; }
|
||||||
|
|
||||||
|
String8 exe_path = t_make_file_path(scratch.arena, str8f(scratch.arena, "%S.exe", str8_chop_last_dot(obj_name)));
|
||||||
|
String8 out = {0};
|
||||||
|
t_invoke_(exe_path, str8_zero(), max_U64, scratch.arena, &out);
|
||||||
|
if (g_last_exit_code == 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 s = out;
|
||||||
|
|
||||||
|
String8 header = t_chop_line(&s);
|
||||||
|
if ( ! str8_match(header, str8_lit("================================================================="), 0)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
String8 cause = t_chop_line(&s);
|
||||||
|
if ( str8_find_needle(cause, 0, str8_lit("AddressSanitizer: heap-use-after-free on address"), 0) >= cause.size) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_ok = 1;
|
||||||
|
exit:;
|
||||||
|
scratch_end(scratch);
|
||||||
|
return is_ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_BeginTest(infer_asan)
|
||||||
|
{
|
||||||
|
char *program =
|
||||||
|
"#include <stdlib.h>\n"
|
||||||
|
" int main(void) {\n"
|
||||||
|
"int *foo = malloc(sizeof(*foo));\n"
|
||||||
|
"free(foo);\n"
|
||||||
|
"*foo = 1;\n"
|
||||||
|
"}\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
// /MD
|
||||||
|
{
|
||||||
|
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||||
|
String8 cl_output = {0};
|
||||||
|
t_invoke_(t_cl_path(), str8_lit("/MD /fsanitize=address /Z7 /c /Fo:main_md.obj main.c"), max_U64, scratch.arena, &cl_output);
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
T_Ok(t_radlink_validate_asan_out(str8_lit("main_md.obj")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// /MDd
|
||||||
|
{
|
||||||
|
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||||
|
String8 cl_output = {0};
|
||||||
|
t_invoke_(t_cl_path(), str8_lit("/MDd /fsanitize=address /Z7 /c /Fo:main_mdd.obj main.c"), max_U64, scratch.arena, &cl_output);
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mdd.obj")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// /MT
|
||||||
|
{
|
||||||
|
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||||
|
String8 cl_output = {0};
|
||||||
|
t_invoke_(t_cl_path(), str8_lit("/MT /fsanitize=address /Z7 /c /Fo:main_mt.obj main.c"), max_U64, scratch.arena, &cl_output);
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mt.obj")));
|
||||||
|
}
|
||||||
|
|
||||||
|
// /MTd
|
||||||
|
{
|
||||||
|
T_Ok(t_write_file(str8_lit("main.c"), str8_cstring(program)));
|
||||||
|
String8 cl_output = {0};
|
||||||
|
t_invoke_(t_cl_path(), str8_lit("/MT /fsanitize=address /Z7 /c /Fo:main_mtd.obj main.c"), max_U64, scratch.arena, &cl_output);
|
||||||
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
T_Ok(t_radlink_validate_asan_out(str8_lit("main_mtd.obj")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
T_BeginTest(pdb_determ_test)
|
T_BeginTest(determ_test)
|
||||||
{
|
{
|
||||||
T_Ok(os_copy_file_path(t_make_file_path(scratch.arena, str8_lit("torture_main.obj")), str8_lit("torture_main.obj")));
|
T_Ok(os_copy_file_path(t_make_file_path(scratch.arena, str8_lit("torture_main.obj")), str8_lit("torture_main.obj")));
|
||||||
|
|
||||||
|
t_delete_file(str8_lit("a.exe"));
|
||||||
|
t_delete_file(str8_lit("b.exe"));
|
||||||
t_delete_file(str8_lit("a.pdb"));
|
t_delete_file(str8_lit("a.pdb"));
|
||||||
t_delete_file(str8_lit("b.pdb"));
|
t_delete_file(str8_lit("b.pdb"));
|
||||||
|
|
||||||
String8 refs_path = t_make_file_path(scratch.arena, str8_lit("b.types"));
|
String8 refs_path = t_make_file_path(scratch.arena, str8_lit("b.types"));
|
||||||
t_invoke_linkerf("torture_main.obj /debug:full /rad_time_stamp:0 /rad_workers:1 /rad_store_types:%S /out:a.exe", refs_path);
|
t_invoke_linkerf("torture_main.obj /debug:full /rad_time_stamp:0 /rad_workers:1 /rad_store_types:%S /out:a.exe", refs_path);
|
||||||
T_Ok(g_last_exit_code == 0);
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
|
||||||
|
T_Ok(os_move_file_path(t_make_file_path(scratch.arena, str8_lit("b.exe")), t_make_file_path(scratch.arena, str8_lit("a.exe"))));
|
||||||
T_Ok(os_move_file_path(t_make_file_path(scratch.arena, str8_lit("b.pdb")), t_make_file_path(scratch.arena, str8_lit("a.pdb"))));
|
T_Ok(os_move_file_path(t_make_file_path(scratch.arena, str8_lit("b.pdb")), t_make_file_path(scratch.arena, str8_lit("a.pdb"))));
|
||||||
String8 b = t_read_file(scratch.arena, str8_lit("b.pdb"));
|
|
||||||
|
String8 b_exe = t_read_file(scratch.arena, str8_lit("b.exe"));
|
||||||
|
String8 b_pdb = t_read_file(scratch.arena, str8_lit("b.pdb"));
|
||||||
|
|
||||||
for EachIndex(i, 50) {
|
for EachIndex(i, 50) {
|
||||||
Temp temp = temp_begin(scratch.arena);
|
Temp temp = temp_begin(scratch.arena);
|
||||||
@@ -4858,8 +4950,10 @@ T_BeginTest(pdb_determ_test)
|
|||||||
t_invoke_linkerf("torture_main.obj /debug:full /rad_time_stamp:0 /out:a.exe");
|
t_invoke_linkerf("torture_main.obj /debug:full /rad_time_stamp:0 /out:a.exe");
|
||||||
T_Ok(g_last_exit_code == 0);
|
T_Ok(g_last_exit_code == 0);
|
||||||
|
|
||||||
String8 a = t_read_file(temp.arena, str8_lit("a.pdb"));
|
String8 a_exe = t_read_file(temp.arena, str8_lit("a.exe"));
|
||||||
T_Ok(str8_match(a, b, 0));
|
String8 a_pdb = t_read_file(temp.arena, str8_lit("a.pdb"));
|
||||||
|
T_Ok(str8_match(a_exe, b_exe, 0));
|
||||||
|
T_Ok(str8_match(a_pdb, b_pdb, 0));
|
||||||
|
|
||||||
temp_end(temp);
|
temp_end(temp);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user