mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
refactored testing utility
- factored out common parts in tests into T_BeginTest and T_EndTest - separated radlink and DWARF tests
This commit is contained in:
@@ -73,6 +73,8 @@ set cl_link= /link /MANIFEST:EMBED /INCREMENTAL:NO /pdbaltpath:%%%%_PDB%%%
|
|||||||
set cl_out= /out:
|
set cl_out= /out:
|
||||||
set cl_linker=
|
set cl_linker=
|
||||||
set clang_common= -I..\src\ -I..\local\ -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-unused-parameter -Wno-writable-strings -Wno-missing-field-initializers -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000 -mcx16 -msha
|
set clang_common= -I..\src\ -I..\local\ -fdiagnostics-absolute-paths -Wall -Wno-unknown-warning-option -Wno-missing-braces -Wno-unused-function -Wno-unused-parameter -Wno-writable-strings -Wno-missing-field-initializers -Wno-unused-value -Wno-unused-variable -Wno-unused-local-typedef -Wno-deprecated-register -Wno-deprecated-declarations -Wno-unused-but-set-variable -Wno-single-bit-bitfield-constant-conversion -Wno-compare-distinct-pointer-types -Wno-initializer-overrides -Wno-incompatible-pointer-types-discards-qualifiers -Xclang -flto-visibility-public-std -D_USE_MATH_DEFINES -Dstrdup=_strdup -Dgnu_printf=printf -ferror-limit=10000 -mcx16 -msha
|
||||||
|
set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 %clang_common% %auto_compile_flags%
|
||||||
|
set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 %clang_common% %auto_compile_flags%
|
||||||
set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 -D_DEBUG %clang_common% %auto_compile_flags%
|
set clang_debug= call clang -g -O0 -DBUILD_DEBUG=1 -D_DEBUG %clang_common% %auto_compile_flags%
|
||||||
set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 -DNDEBUG %clang_common% %auto_compile_flags%
|
set clang_release= call clang -g -O2 -DBUILD_DEBUG=0 -DNDEBUG %clang_common% %auto_compile_flags%
|
||||||
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% -Xlinker /NATVIS:"%~dp0\src\natvis\base.natvis" -Xlinker /opt:ref -Xlinker /opt:icf
|
set clang_link= -fuse-ld=lld -Xlinker /MANIFEST:EMBED -Xlinker /pdbaltpath:%%%%_PDB%%%% -Xlinker /NATVIS:"%~dp0\src\natvis\base.natvis" -Xlinker /opt:ref -Xlinker /opt:icf
|
||||||
@@ -144,7 +146,7 @@ if "%strip_lib_debug%"=="1" set didbuild=1 && %compile% ..\src\strip_
|
|||||||
if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1
|
if "%mule_main%"=="1" set didbuild=1 && del vc*.pdb mule*.pdb && %compile_release% %only_compile% ..\src\mule\mule_inline.cpp && %compile_release% %only_compile% ..\src\mule\mule_o2.cpp && %compile_debug% %EHsc% ..\src\mule\mule_main.cpp ..\src\mule\mule_c.c mule_inline.obj mule_o2.obj %compile_link% %no_aslr% %out%mule_main.exe || exit /b 1
|
||||||
if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
|
if "%mule_module%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_module.cpp %compile_link% %link_dll% %out%mule_module.dll || exit /b 1
|
||||||
if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1
|
if "%mule_hotload%"=="1" set didbuild=1 && %compile% ..\src\mule\mule_hotload_main.c %compile_link% %out%mule_hotload.exe & %compile% ..\src\mule\mule_hotload_module_main.c %compile_link% %link_dll% %out%mule_hotload_module.dll || exit /b 1
|
||||||
if "%torture%"=="1" set didbuild=1 && %compile% ..\src\torture\torture.c %compile_link% %out%torture.exe || exit /b1
|
if "%torture%"=="1" set didbuild=1 && %compile% ..\src\torture\torture_main.c %compile_link% %out%torture.exe || exit /b1
|
||||||
if "%dwarf_expr_test%"=="1" set didbuild=1 && %compile% ..\src\torture\dwarf_expr_test.c %compile_link% %out%dwarf_expr_test.exe || exit /b1
|
if "%dwarf_expr_test%"=="1" set didbuild=1 && %compile% ..\src\torture\dwarf_expr_test.c %compile_link% %out%dwarf_expr_test.exe || exit /b1
|
||||||
if "%mule_peb_trample%"=="1" (
|
if "%mule_peb_trample%"=="1" (
|
||||||
set didbuild=1
|
set didbuild=1
|
||||||
|
|||||||
+35
-2
@@ -127,12 +127,45 @@ coff_section_table_from_data(Arena *arena, String8 data, Rng1U64 section_table_r
|
|||||||
U64 section_count = dim_1u64(section_table_range) / sizeof(COFF_SectionHeader);
|
U64 section_count = dim_1u64(section_table_range) / sizeof(COFF_SectionHeader);
|
||||||
COFF_SectionHeader **section_table = push_array_no_zero(arena, COFF_SectionHeader *, section_count+1);
|
COFF_SectionHeader **section_table = push_array_no_zero(arena, COFF_SectionHeader *, section_count+1);
|
||||||
section_table[0] = push_array(arena, COFF_SectionHeader, 1);
|
section_table[0] = push_array(arena, COFF_SectionHeader, 1);
|
||||||
for (U64 i = 0; i < section_count; ++i) {
|
for EachIndex(sect_idx, section_count) {
|
||||||
section_table[i+1] = str8_deserial_get_raw_ptr(data, section_table_range.min + i*sizeof(COFF_SectionHeader), sizeof(COFF_SectionHeader));
|
section_table[sect_idx + 1] = str8_deserial_get_raw_ptr(data, section_table_range.min + sect_idx*sizeof(COFF_SectionHeader), sizeof(COFF_SectionHeader));
|
||||||
}
|
}
|
||||||
return section_table;
|
return section_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal COFF_SectionHeader *
|
||||||
|
coff_section_header_from_name(String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name)
|
||||||
|
{
|
||||||
|
for EachIndex(sect_idx, section_count) {
|
||||||
|
if (str8_match(coff_name_from_section_header(string_table, §ion_table[sect_idx]), name, 0)) {
|
||||||
|
return §ion_table[sect_idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal COFF_SectionHeaderArray
|
||||||
|
coff_section_header_array_from_name(Arena *arena, String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name)
|
||||||
|
{
|
||||||
|
U64 match_count = 0;
|
||||||
|
for EachIndex(sect_idx, section_count) {
|
||||||
|
if (str8_match(coff_name_from_section_header(string_table, §ion_table[sect_idx]), name, 0)) {
|
||||||
|
match_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
COFF_SectionHeader *matches = push_array(arena, COFF_SectionHeader, match_count);
|
||||||
|
for (U64 sect_idx = 0, match_idx = 0; sect_idx < section_count; sect_idx += 1) {
|
||||||
|
if (str8_match(coff_name_from_section_header(string_table, §ion_table[sect_idx]), name, 0)) {
|
||||||
|
matches[match_idx] = section_table[sect_idx];
|
||||||
|
match_idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (COFF_SectionHeaderArray){ .count = match_count, .v = matches };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal COFF_ParsedSymbol
|
internal COFF_ParsedSymbol
|
||||||
coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
|
coff_parse_symbol32(String8 string_table, COFF_Symbol32 *sym32)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -252,6 +252,9 @@ internal COFF_FileHeaderInfo coff_file_header_info_from_data(String8 raw_coff);
|
|||||||
// Section
|
// Section
|
||||||
|
|
||||||
internal COFF_SectionHeader ** coff_section_table_from_data (Arena *arena, String8 data, Rng1U64 section_table_range);
|
internal COFF_SectionHeader ** coff_section_table_from_data (Arena *arena, String8 data, Rng1U64 section_table_range);
|
||||||
|
internal COFF_SectionHeader * coff_section_header_from_name (String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name);
|
||||||
|
internal COFF_SectionHeaderArray coff_section_header_array_from_name(Arena *arena, String8 string_table, COFF_SectionHeader *section_table, U64 section_count, String8 name);
|
||||||
|
internal String8 coff_name_from_section_header (String8 string_table, COFF_SectionHeader *header);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Symbol
|
// Symbol
|
||||||
|
|||||||
+111
-5292
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,94 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
T_RunStatus_Fail,
|
||||||
|
T_RunStatus_Crash,
|
||||||
|
T_RunStatus_Pass,
|
||||||
|
} T_RunStatus;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
T_RunStatus status;
|
||||||
|
char *fail_file;
|
||||||
|
int fail_line;
|
||||||
|
char *fail_cond;
|
||||||
|
} T_RunResult;
|
||||||
|
|
||||||
|
typedef T_RunResult (*T_Run)(void);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
T_Run run;
|
||||||
|
T_RunResult result;
|
||||||
|
} T_RunCtx;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *group;
|
||||||
|
char *label;
|
||||||
|
int decl_line;
|
||||||
|
T_Run r;
|
||||||
|
} T_Test;
|
||||||
|
|
||||||
|
extern U64 g_torture_test_count;
|
||||||
|
extern T_Test g_torture_tests[0xffffff];
|
||||||
|
|
||||||
|
#define T_AddTest(name, l, ...) \
|
||||||
|
T_RunResult t_##name(void); \
|
||||||
|
__VA_ARGS__ void t_add_test_##name(void) \
|
||||||
|
{ \
|
||||||
|
g_torture_tests[g_torture_test_count].group = T_Group; \
|
||||||
|
g_torture_tests[g_torture_test_count].label = Stringify(name); \
|
||||||
|
g_torture_tests[g_torture_test_count].r = &t_##name; \
|
||||||
|
g_torture_tests[g_torture_test_count].decl_line = l; \
|
||||||
|
g_torture_test_count += 1; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if COMPILER_MSVC
|
||||||
|
#pragma section(".CRT$XCU", read)
|
||||||
|
# define T_BeginTest_(name) \
|
||||||
|
T_AddTest(name, __LINE__) \
|
||||||
|
__declspec(allocate(".CRT$XCU")) void(*r_##name)(void) = t_add_test_##name; \
|
||||||
|
__pragma(comment(linker, "/include:" Stringify(r_##name)))
|
||||||
|
#else
|
||||||
|
# define T_BeginTest_(name) \
|
||||||
|
T_AddTest(name, __LINE__, __attribute__((constructor)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define T_BeginTest(name) \
|
||||||
|
T_BeginTest_(name) \
|
||||||
|
T_RunResult t_##name(void) { \
|
||||||
|
Temp scratch = scratch_begin(0,0); \
|
||||||
|
T_RunResult result = { .status = T_RunStatus_Fail };
|
||||||
|
|
||||||
|
#define T_EndTest \
|
||||||
|
result.status = T_RunStatus_Pass; \
|
||||||
|
exit__:; \
|
||||||
|
scratch_end(scratch); \
|
||||||
|
return result; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define T_Ok(c) do { if (!(c)) { result.fail_file = __FILE__; result.fail_line = __LINE__; result.fail_cond = Stringify(c); goto exit__; } } while(0)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
// output directory
|
||||||
|
internal B32 t_write_file_list(String8 name, String8List data);
|
||||||
|
internal B32 t_write_file(String8 name, String8 data);
|
||||||
|
internal String8 t_read_file(Arena *arena, String8 name);
|
||||||
|
internal String8 t_make_file_path(Arena *arena, String8 name);
|
||||||
|
|
||||||
|
// test runner
|
||||||
|
internal void t_run_caller(void *raw_ctx);
|
||||||
|
internal void t_run_fail_handler(void *raw_ctx);
|
||||||
|
internal T_RunResult t_run(T_Run run);
|
||||||
|
|
||||||
|
internal B32 t_invoke(String8 exe, String8 cmdline, U64 timeout);
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#define T_Group "Dwarf"
|
||||||
|
|
||||||
|
T_BeginTest(value_in_register)
|
||||||
|
{
|
||||||
|
// setup register context
|
||||||
|
REGS_RegBlockX64 regs = {0};
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_Reg3 - DW_ExprOp_Reg0);
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 value = 0xc0ffee;
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value));
|
||||||
|
|
||||||
|
// compile a simple program which reads the value from register 3
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Reg3) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
// evaluate the program
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value);
|
||||||
|
|
||||||
|
// validate eval result
|
||||||
|
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_U64);
|
||||||
|
T_Ok(expr_value.u64 == value);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(value_in_x_register)
|
||||||
|
{
|
||||||
|
// setup register context
|
||||||
|
REGS_RegBlockX64 regs = {0};
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_RegX64_FsBase);
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 value = 0xc0ffee;
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value));
|
||||||
|
|
||||||
|
// compile a simple program which reads the value from register 3
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(RegX), DW_ExprEnc_ULEB128(DW_RegX64_FsBase) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
// evaluate the program
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value);
|
||||||
|
|
||||||
|
// validate eval result
|
||||||
|
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_U64);
|
||||||
|
T_Ok(expr_value.u64 == value);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(address_of_value)
|
||||||
|
{
|
||||||
|
// compile a simple program which reads address
|
||||||
|
U64 addr = 0xdeadbeef;
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Addr), DW_ExprEnc_U64(addr) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
// evaluate the program
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value);
|
||||||
|
|
||||||
|
// validate eval result
|
||||||
|
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_Addr);
|
||||||
|
T_Ok(expr_value.addr == addr);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(register_relative_variable)
|
||||||
|
{
|
||||||
|
// setup register context
|
||||||
|
REGS_RegBlockX64 regs = {0};
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_BReg11 - DW_ExprOp_BReg0);
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 value = 1;
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value));
|
||||||
|
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BReg11), DW_ExprEnc_SLEB128(44) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value);
|
||||||
|
|
||||||
|
// validate eval result
|
||||||
|
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_Addr);
|
||||||
|
T_Ok(expr_value.addr == (1 + 44));
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(frame_relative_variable)
|
||||||
|
{
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(FBReg), DW_ExprEnc_SLEB128(-50) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
U64 frame_base = 123;
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, frame_base, 0, 0, max_U64, expr, 0, 0, 0, 0, &expr_value);
|
||||||
|
|
||||||
|
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_Addr);
|
||||||
|
T_Ok(expr_value.addr == frame_base -50);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
internal
|
||||||
|
MACHINE_OP_MEM_READ(t_machine_op_mem_read)
|
||||||
|
{
|
||||||
|
MemoryCopy(buffer, PtrFromInt(addr), buffer_size);
|
||||||
|
return MachineOpResult_Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
T_BeginTest(call_by_reference)
|
||||||
|
{
|
||||||
|
U8 *memory = push_array(scratch.arena, U8, 128);
|
||||||
|
U64 value = 0xc0ffee;
|
||||||
|
MemoryCopy(memory + 32, &value, sizeof(value));
|
||||||
|
|
||||||
|
REGS_RegBlockX64 regs = {0};
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, 58); // fsbase
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 memory_ptr = IntFromPtr(memory);
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &memory_ptr, sizeof(memory_ptr));
|
||||||
|
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(BRegX), DW_ExprEnc_ULEB128(58), DW_ExprEnc_SLEB128(32), DW_ExprEnc_Op(Deref) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
DW_ExprValue expr_value = { 0 };
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, t_machine_op_mem_read, 0, &expr_value);
|
||||||
|
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_Generic);
|
||||||
|
T_Ok(expr_value.generic.size == sizeof(U64));
|
||||||
|
T_Ok(*(U64 *)expr_value.generic.str == value);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
T_BeginTest(plus_uconst)
|
||||||
|
{
|
||||||
|
U64 struct_addr = 0x123;
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Addr), DW_ExprEnc_Addr(struct_addr), DW_ExprEnc_Op(PlusUConst), DW_ExprEnc_ULEB128(4) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, 0, 0, t_machine_op_mem_read, 0, &expr_value);
|
||||||
|
|
||||||
|
T_Ok(expr_value.type == DW_ExprValueType_Addr);
|
||||||
|
T_Ok(expr_value.addr == 0x123 + 4);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
T_BeginTest(reg_split_spill)
|
||||||
|
{
|
||||||
|
// setup register context
|
||||||
|
REGS_RegBlockX64 regs = {0};
|
||||||
|
{
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_BReg3 - DW_ExprOp_BReg0);
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 value = 0xaaaa;
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REGS_RegCode reg_code = reg_code_from_dw_reg(Arch_x64, DW_ExprOp_BReg10 - DW_ExprOp_BReg0);
|
||||||
|
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
|
||||||
|
U64 value = 0xbbbb;
|
||||||
|
MemoryCopy((U8 *)®s + reg_range.min, &value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
DW_ExprEnc expr_encs[] = { DW_ExprEnc_Op(Reg3), DW_ExprEnc_Op(Piece), DW_ExprEnc_ULEB128(4), DW_ExprEnc_Op(Reg10), DW_ExprEnc_Op(Piece), DW_ExprEnc_ULEB128(2) };
|
||||||
|
String8 expr_data = dw_encode_expr(scratch.arena, Arch_x64, DW_Format_64Bit, expr_encs, ArrayCount(expr_encs));
|
||||||
|
DW_Expr expr = dw_expr_from_data(scratch.arena, DW_Format_64Bit, byte_size_from_arch(Arch_x64), expr_data);
|
||||||
|
|
||||||
|
DW_ExprValue expr_value;
|
||||||
|
DW_ExprEvalResult expr_eval = dw_eval_expr(scratch.arena, Arch_x64, DW_Format_64Bit, 0, 0, 0, max_U64, expr, regs_read_dwarf_x64, ®s, 0, 0, &expr_value);
|
||||||
|
}
|
||||||
|
T_EndTest;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef T_Group
|
||||||
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
// Build Options
|
||||||
|
|
||||||
|
#define BUILD_CONSOLE_INTERFACE 1
|
||||||
|
#define BUILD_TITLE "TORTURE"
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
#include "base/base_inc.h"
|
||||||
|
#include "os/os_inc.h"
|
||||||
|
#include "linker/base_ext/base_core.h"
|
||||||
|
#include "linker/base_ext/base_arena.h"
|
||||||
|
#include "linker/base_ext/base_arrays.h"
|
||||||
|
#include "linker/hash_table.h"
|
||||||
|
#include "coff/coff.h"
|
||||||
|
#include "coff/coff_parse.h"
|
||||||
|
#include "coff/coff_obj_writer.h"
|
||||||
|
#include "coff/coff_lib_writer.h"
|
||||||
|
#include "pe/pe.h"
|
||||||
|
#include "pe/pe_section_flags.h"
|
||||||
|
#include "elf/elf.h"
|
||||||
|
#include "elf/elf_parse.h"
|
||||||
|
#include "dwarf/dwarf_inc.h"
|
||||||
|
#include "regs/regs.h"
|
||||||
|
#include "regs/dwarf/regs_dwarf.h"
|
||||||
|
#include "linker/lnk_cmd_line.h"
|
||||||
|
#include "linker/lnk_cmd_line.c"
|
||||||
|
#include "linker/lnk_error.h"
|
||||||
|
#include "torture.h"
|
||||||
|
#include "torture_radlink.h"
|
||||||
|
|
||||||
|
#include "base/base_inc.c"
|
||||||
|
#include "os/os_inc.c"
|
||||||
|
#include "linker/hash_table.c"
|
||||||
|
#include "linker/base_ext/base_core.c"
|
||||||
|
#include "linker/base_ext/base_arena.c"
|
||||||
|
#include "linker/base_ext/base_arrays.c"
|
||||||
|
#include "coff/coff.c"
|
||||||
|
#include "coff/coff_parse.c"
|
||||||
|
#include "coff/coff_obj_writer.c"
|
||||||
|
#include "coff/coff_lib_writer.c"
|
||||||
|
#include "pe/pe.c"
|
||||||
|
#include "elf/elf.c"
|
||||||
|
#include "elf/elf_parse.c"
|
||||||
|
#include "dwarf/dwarf_inc.c"
|
||||||
|
#include "regs/regs.c"
|
||||||
|
#include "regs/dwarf/regs_dwarf.c"
|
||||||
|
#include "torture.c"
|
||||||
|
#include "torture_radlink.c"
|
||||||
|
#include "torture_dwarf.c"
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
internal void
|
||||||
|
entry_point(CmdLine *cmdline)
|
||||||
|
{
|
||||||
|
t_entry_point(cmdline);
|
||||||
|
}
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
T_Linker_Null,
|
||||||
|
T_Linker_RAD,
|
||||||
|
T_Linker_MSVC,
|
||||||
|
T_Linker_LLVM
|
||||||
|
} T_Linker;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
T_MsvcLinkExitCode_UnresolvedExternals = 1120,
|
||||||
|
T_MsvcLinkExitCode_CorruptOrInvalidSymbolTable = 1235,
|
||||||
|
T_MsvcLinkExitCode_SectionsFoundWithDifferentAttributes = 4078,
|
||||||
|
} T_MsvcLinkExitCode;
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
|
||||||
|
#define t_invoke_linker_timeout(c, t) T_Ok(t_invoke(g_linker, c, t))
|
||||||
|
#define t_invoke_linker_timeoutf(t, f, ...) t_invoke_linker_timeout(push_str8f(scratch.arena, f, ##__VA_ARGS__), t)
|
||||||
|
#define t_invoke_linker(c) t_invoke_linker_timeout(c, max_U64)
|
||||||
|
#define t_invoke_linkerf(f, ...) t_invoke_linker(push_str8f(scratch.arena, f, ##__VA_ARGS__))
|
||||||
|
|
||||||
|
internal T_Linker t_id_linker(void);
|
||||||
|
|
||||||
|
internal COFF_ObjSection * t_push_text_section(COFF_ObjWriter *obj_writer, String8 data);
|
||||||
|
internal COFF_ObjSection * t_push_data_section(COFF_ObjWriter *obj_writer, String8 data);
|
||||||
|
internal COFF_ObjSection * t_push_rdata_section(COFF_ObjWriter *obj_writer, String8 data);
|
||||||
|
|
||||||
|
internal String8 t_make_entry_obj(Arena *arena);
|
||||||
|
internal String8 t_make_sec_defn_obj(Arena *arena, String8 payload);
|
||||||
|
|
||||||
|
internal B32 t_write_entry_obj(void);
|
||||||
|
|
||||||
Reference in New Issue
Block a user