first pass at (rdi -> loose rdim) path, used in (rdi * ... * rdi) -> rdi joining in radbin; plug in regular conversion path before voff -> line & breakpad paths in radbin, such that PDBs, DWARFs, RDIs, etc. can be used as input; fix up voff -> line path to plug into regular output systems; remove String8 union thing - three reasons: (a) it was only ever introduced for convenience in Linux layers, so let's just keep zero-terminated Linux nonsense in Linux land, (b) it was just alternate syntax for a cast, so let's just cast, (c) it was misleading - 'cstr' implies null-termination, which String8 of course doesn't guarantee. this led to some misuses, where .cstr was trusted to be zero-terminated, when that was not necessarily true (semaphore opening).

This commit is contained in:
Ryan Fleury
2026-03-03 16:24:54 -08:00
parent 2af3990971
commit 4312ee14fd
17 changed files with 1797 additions and 1508 deletions
+22 -22
View File
@@ -40,39 +40,39 @@ 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; \
}
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)))
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)))
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 };
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; \
}
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)
#define T_MatchLinef(out, ...) T_Ok(t_match_linef(out, __VA_ARGS__))
+262 -262
View File
@@ -7,7 +7,7 @@ internal RDI_Parsed *
d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
{
Temp scratch = scratch_begin(&arena, 1);
String8 raw_coff;
{
OBJ *obj = obj_alloc(0, Arch_x64);
@@ -18,26 +18,26 @@ d2r_rdi_from_dwarf_writer(Arena *arena, DW_Writer *writer)
raw_coff = coff_from_obj(scratch.arena, obj);
obj_release(&obj);
}
Assert(t_write_file(str8_lit("a.obj"), raw_coff));
t_invoke(t_radlink_path(), str8_lit("/subsystem:console /out:a.exe /entry:main /DEBUG:FULL /opt:noref /opt:noicf a.obj"), max_U64);
Assert(g_last_exit_code == 0);
String8 exe = t_read_file(scratch.arena, str8_lit("a.exe"));
Assert(exe.size > 0);
B32 was_pdb_deleted = os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
Assert(was_pdb_deleted);
t_invoke_(t_radbin_path(), str8_lit("-rdi a.exe -out:a.rdi"), max_U64, 0, 0);
Assert(g_last_exit_code == 0);
String8 raw_rdi = t_read_file(arena, str8_lit("a.rdi"));
Assert(raw_rdi.size > 0);
RDI_Parsed *rdi = push_array(arena, RDI_Parsed, 1);
RDI_ParseStatus rdi_parse_status = rdi_parse(raw_rdi.str, raw_rdi.size, rdi);
Assert(rdi_parse_status == RDI_ParseStatus_Good);
scratch_end(scratch);
return rdi;
}
@@ -47,10 +47,10 @@ d2rt_type_from_name(RDI_Parsed *rdi, RDI_ParsedNameMap *map, char *name)
{
String8 s = str8_cstring(name);
RDI_NameMapNode *node = rdi_name_map_lookup(rdi, map, s.str, s.size);
U32 id_count = 0;
U32 *ids = rdi_matches_from_map_node(rdi, node, &id_count);
if (id_count == 1) {
return rdi_element_from_name_idx(rdi, TypeNodes, ids[0]);
}
@@ -63,104 +63,104 @@ T_BeginTest(d2r_types)
{
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test");
#define DeclBaseType(tt, n, e, s) \
DW_WriterTag *tt = dw_writer_tag_begin(writer, DW_TagKind_BaseType); \
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, s); \
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_##e); \
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \
dw_writer_tag_end(writer);
DeclBaseType(char_type, "char", SignedChar, 1);
DeclBaseType(unsigned_char_type, "unsigned char", UnsignedChar, 1);
DeclBaseType(char8_type, "char8_t", Utf, 1);
DeclBaseType(char16_type, "char16_t", Utf, 2);
DeclBaseType(char32_type, "char32_t", Utf, 4);
DeclBaseType(wchar_type, "wchar_t", Signed, 4);
DeclBaseType(bool_type, "_Bool", Boolean, 1);
DeclBaseType(short_type, "short", Signed, 2);
DeclBaseType(unsigned_short_type, "unsigned short", Unsigned, 2);
DeclBaseType(short_unsigned_int_type, "short unsigned int", Unsigned, 2);
DeclBaseType(short_int_type, "short int", Signed, 2);
DeclBaseType(unsigned_int_type, "unsigned int", Unsigned, 4);
DeclBaseType(int_type, "int", Signed, 4);
DeclBaseType(long_int_type, "long int", Signed, 8);
DeclBaseType(long_unsigned_int_type, "long unsigned int", Unsigned, 8);
DeclBaseType(long_long_int_type, "long long int", Signed, 8);
DeclBaseType(long_long_unsigned_int, "long long unsigned int", Unsigned, 8);
DeclBaseType(float_type, "float", Float, 4);
DeclBaseType(double_type, "double", Float, 8);
DeclBaseType(long_double_type, "long double", Float, 16);
DeclBaseType(int128_type, "__int128", Signed, 16);
DeclBaseType(uint128_type, "__int128 unsigned", Unsigned, 16);
DeclBaseType(float16_type, "_Float16", Float, 2);
DeclBaseType(bfloat16_type, "__bf16", Float, 2);
DeclBaseType(float80_type, "__float80", Float, 16);
DeclBaseType(float128_type, "_float128", Float, 16);
DeclBaseType(complex_float_type, "complex float", ComplexFloat, 8);
DeclBaseType(complex_doulbe_type, "complex double", ComplexFloat, 16);
DeclBaseType(complex_long_double_type, "complex long double", ComplexFloat, 32);
DeclBaseType(decimal32_type, "_Decimal32", DecimalFloat, 4);
DeclBaseType(decimal64_type, "_Decimal64", DecimalFloat, 8);
DeclBaseType(decimal128_type, "_Decimal128", DecimalFloat, 16);
DW_WriterTag *tt = dw_writer_tag_begin(writer, DW_TagKind_BaseType); \
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, s); \
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_##e); \
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \
dw_writer_tag_end(writer);
DeclBaseType(char_type, "char", SignedChar, 1);
DeclBaseType(unsigned_char_type, "unsigned char", UnsignedChar, 1);
DeclBaseType(char8_type, "char8_t", Utf, 1);
DeclBaseType(char16_type, "char16_t", Utf, 2);
DeclBaseType(char32_type, "char32_t", Utf, 4);
DeclBaseType(wchar_type, "wchar_t", Signed, 4);
DeclBaseType(bool_type, "_Bool", Boolean, 1);
DeclBaseType(short_type, "short", Signed, 2);
DeclBaseType(unsigned_short_type, "unsigned short", Unsigned, 2);
DeclBaseType(short_unsigned_int_type, "short unsigned int", Unsigned, 2);
DeclBaseType(short_int_type, "short int", Signed, 2);
DeclBaseType(unsigned_int_type, "unsigned int", Unsigned, 4);
DeclBaseType(int_type, "int", Signed, 4);
DeclBaseType(long_int_type, "long int", Signed, 8);
DeclBaseType(long_unsigned_int_type, "long unsigned int", Unsigned, 8);
DeclBaseType(long_long_int_type, "long long int", Signed, 8);
DeclBaseType(long_long_unsigned_int, "long long unsigned int", Unsigned, 8);
DeclBaseType(float_type, "float", Float, 4);
DeclBaseType(double_type, "double", Float, 8);
DeclBaseType(long_double_type, "long double", Float, 16);
DeclBaseType(int128_type, "__int128", Signed, 16);
DeclBaseType(uint128_type, "__int128 unsigned", Unsigned, 16);
DeclBaseType(float16_type, "_Float16", Float, 2);
DeclBaseType(bfloat16_type, "__bf16", Float, 2);
DeclBaseType(float80_type, "__float80", Float, 16);
DeclBaseType(float128_type, "_float128", Float, 16);
DeclBaseType(complex_float_type, "complex float", ComplexFloat, 8);
DeclBaseType(complex_doulbe_type, "complex double", ComplexFloat, 16);
DeclBaseType(complex_long_double_type, "complex long double", ComplexFloat, 32);
DeclBaseType(decimal32_type, "_Decimal32", DecimalFloat, 4);
DeclBaseType(decimal64_type, "_Decimal64", DecimalFloat, 8);
DeclBaseType(decimal128_type, "_Decimal128", DecimalFloat, 16);
#undef DeclBaseType
#define DeclStdint(n, a) \
do { \
dw_writer_tag_begin(writer, DW_TagKind_Typedef); \
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, a); \
dw_writer_tag_end(writer); \
} while (0)
DeclStdint("uint8_t", unsigned_char_type);
DeclStdint("uint16_t", unsigned_short_type);
DeclStdint("uint32_t", unsigned_int_type);
DeclStdint("uint64_t", long_unsigned_int_type);
DeclStdint("int8_t", char_type);
DeclStdint("int16_t", short_type);
DeclStdint("int32_t", int_type);
DeclStdint("int64_t", long_int_type);
do { \
dw_writer_tag_begin(writer, DW_TagKind_Typedef); \
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, n); \
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, a); \
dw_writer_tag_end(writer); \
} while (0)
DeclStdint("uint8_t", unsigned_char_type);
DeclStdint("uint16_t", unsigned_short_type);
DeclStdint("uint32_t", unsigned_int_type);
DeclStdint("uint64_t", long_unsigned_int_type);
DeclStdint("int8_t", char_type);
DeclStdint("int16_t", short_type);
DeclStdint("int32_t", int_type);
DeclStdint("int64_t", long_int_type);
#undef DeclStdInt
// TODO: @native_vector_support
//
// typedef int __attribute__((vector_size(32))) int256
// typedef unsigned int __attribute__((vector_size(32))) uint256
// typedef int __attribute__((vector_size(64))) int512
// typedef unsigned int __attribute__((vector_size(64))) uint512
//
// TODO: @native_vector_support
//
// typedef int __attribute__((vector_size(32))) int256
// typedef unsigned int __attribute__((vector_size(32))) uint256
// typedef int __attribute__((vector_size(64))) int512
// typedef unsigned int __attribute__((vector_size(64))) uint512
//
#if 0
dw_writer_tag_begin(writer, DW_TagKind_ArrayType);
dw_writer_push_attrib_flag(writer, DW_AttribKind_GNU_Vector, 1);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, int_type);
dw_writer_tag_begin(writer, DW_TagKind_SubrangeType);
dw_writer_push_attrib_uint(writer, DW_AttribKind_UpperBound, 15);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_ArrayType);
dw_writer_push_attrib_flag(writer, DW_AttribKind_GNU_Vector, 1);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, int_type);
dw_writer_tag_begin(writer, DW_TagKind_SubrangeType);
dw_writer_push_attrib_uint(writer, DW_AttribKind_UpperBound, 15);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
#endif
dw_writer_tag_end(writer);
}
RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer);
RDI_NameMap *types_nm = rdi_element_from_name_idx(rdi, NameMaps, RDI_NameMapKind_Types);
T_Ok(types_nm);
RDI_ParsedNameMap types_map = {0};
rdi_parsed_from_name_map(rdi, types_nm, &types_map);
#define TestBuiltinType(n, bs, r) \
do { \
RDI_TypeNode *alias = d2rt_type_from_name(rdi, &types_map, n); \
T_Ok(alias); \
T_Ok(alias->kind == RDI_TypeKind_Alias); \
T_Ok(alias->flags == 0); \
T_Ok(alias->byte_size == bs); \
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, alias->user_defined.direct_type_idx); \
T_Ok(type); \
T_Ok(type->kind == RDI_TypeKind_##r); \
T_Ok(type->flags == 0); \
T_Ok(type->byte_size == alias->byte_size); \
T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(Stringify(r)), 0)); \
} while (0)
do { \
RDI_TypeNode *alias = d2rt_type_from_name(rdi, &types_map, n); \
T_Ok(alias); \
T_Ok(alias->kind == RDI_TypeKind_Alias); \
T_Ok(alias->flags == 0); \
T_Ok(alias->byte_size == bs); \
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, alias->user_defined.direct_type_idx); \
T_Ok(type); \
T_Ok(type->kind == RDI_TypeKind_##r); \
T_Ok(type->flags == 0); \
T_Ok(type->byte_size == alias->byte_size); \
T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(Stringify(r)), 0)); \
} while (0)
TestBuiltinType("char", 1, Char8);
TestBuiltinType("char8_t", 1, UChar8);
TestBuiltinType("char16_t", 2, UChar16);
@@ -193,21 +193,21 @@ T_BeginTest(d2r_types)
TestBuiltinType("_Decimal64", 8, Decimal64);
TestBuiltinType("_Decimal128", 16, Decimal128);
#undef TestBuiltinType
#define TestStdint(n, s, t) \
do { \
RDI_TypeNode *td = d2rt_type_from_name(rdi, &types_map, n); \
T_Ok(td); \
T_Ok(td->kind == RDI_TypeKind_Alias); \
T_Ok(td->flags == 0); \
T_Ok(td->byte_size == s); \
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, td->user_defined.direct_type_idx); \
T_Ok(type); \
T_Ok(type->kind == RDI_TypeKind_Alias); \
T_Ok(type->flags == 0); \
T_Ok(type->byte_size = td->byte_size); \
T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(t), 0)); \
} while (0)
do { \
RDI_TypeNode *td = d2rt_type_from_name(rdi, &types_map, n); \
T_Ok(td); \
T_Ok(td->kind == RDI_TypeKind_Alias); \
T_Ok(td->flags == 0); \
T_Ok(td->byte_size == s); \
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, td->user_defined.direct_type_idx); \
T_Ok(type); \
T_Ok(type->kind == RDI_TypeKind_Alias); \
T_Ok(type->flags == 0); \
T_Ok(type->byte_size = td->byte_size); \
T_Ok(str8_match(str8_from_rdi_string_idx(rdi, type->built_in.name_string_idx), str8_lit(t), 0)); \
} while (0)
TestStdint("uint8_t", 1, "unsigned char");
TestStdint("uint16_t", 2, "unsigned short");
TestStdint("uint32_t", 4, "unsigned int");
@@ -217,7 +217,7 @@ T_BeginTest(d2r_types)
TestStdint("int32_t", 4, "int");
TestStdint("int64_t", 8, "long int");
#undef TestStdint
dw_writer_end(&writer);
}
T_EndTest;
@@ -227,10 +227,10 @@ T_BeginTest(d2r_line_table)
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
String8 comp_dir = str8_lit("c:/DEVEL/");
String8 comp_name = str8_lit("test.c");
DW_WriterFile *foo_file = dw_writer_new_file(writer, str8_lit("/mnt/C/Devel/foo.c"));
DW_WriterFile *comp_file = dw_writer_new_file(writer, str8f(scratch.arena, "%S%S", comp_dir, comp_name));
struct {
DW_WriterFile *file; U64 ln; U64 line_size; U64 voff;
} test_table[] = {
@@ -243,7 +243,7 @@ T_BeginTest(d2r_line_table)
{ foo_file, 100, 1 },
{ comp_file, max_U32 - 0x100, 10 },
};
U64 exe_base = coff_default_exe_base_from_machine(COFF_MachineType_X64);
U64 voff = 0x1000;
for EachElement(i, test_table) {
@@ -251,25 +251,25 @@ T_BeginTest(d2r_line_table)
dw_writer_line_emit(writer, test_table[i].file, test_table[i].ln, 0, exe_base + voff);
voff += test_table[i].line_size;
}
// emit one past last line
dw_writer_line_emit(writer,
test_table[ArrayCount(test_table) - 1].file,
test_table[ArrayCount(test_table) - 1].ln,
0,
exe_base + voff);
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, exe_base);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, exe_base + voff);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, exe_base);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, exe_base + voff);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_tag_end(writer);
d2r_rdi_from_dwarf_writer(scratch.arena, writer);
for EachElement(i, test_table) {
for EachIndex(k, test_table[i].line_size) {
String8 cmd_line = str8f(scratch.arena, "-voff2line -voff:0x%llx a.rdi", test_table[i].voff + k);
@@ -279,7 +279,7 @@ T_BeginTest(d2r_line_table)
T_MatchLinef(&output, "%S:%llu", test_table[i].file->path, test_table[i].ln);
}
}
dw_writer_end(&writer);
}
T_EndTest;
@@ -287,35 +287,35 @@ T_EndTest;
T_BeginTest(d2r_checksums)
{
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
DW_WriterFile *foo_file = dw_writer_new_file(writer, str8_lit("/mnt/c/devel/foo.c"));
DW_WriterFile *comp_file = dw_writer_new_file(writer, str8_lit("/home/main.c"));
foo_file->md5 = *(U128 *)&(U8[16]){ 0x04, 0x70, 0xe9, 0x6b, 0xa3, 0x05, 0x2c, 0xc8, 0x2d, 0x70, 0xc5, 0xe9, 0x80, 0x8e, 0x8a, 0x4e, };
comp_file->md5 = *(U128 *)&(U8[16]){ 0x82, 0x3c, 0xc6, 0x02, 0x82, 0x9e, 0xf6, 0xce, 0x53, 0xff, 0x5a, 0x93, 0xb6, 0x6e, 0x59, 0x38 };
comp_file->time_stamp = 123; // convert must pick MD5 checksum over time stamp
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, str8_chop_last_slash(comp_file->path));
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_skip_last_slash(comp_file->path));
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, str8_chop_last_slash(comp_file->path));
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_skip_last_slash(comp_file->path));
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_tag_end(writer);
RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer);
U64 checksum_count = 0;
RDI_MD5 *checksums = rdi_table_from_name(rdi, MD5Checksums, &checksum_count);
T_Ok(checksum_count == writer->line.file_count + 1);
RDI_SourceFile *foo_src_file = rdi_source_file_from_normal_path_cstr(rdi, foo_file->path.cstr);
RDI_SourceFile *foo_src_file = rdi_source_file_from_normal_path_cstr(rdi, (char *)foo_file->path.str);
T_Ok(foo_src_file);
T_Ok(foo_src_file->checksum_kind == RDI_ChecksumKind_MD5);
T_Ok(MemoryMatch(&foo_file->md5, &checksums[foo_src_file->checksum_idx], sizeof(U128)));
RDI_SourceFile *comp_src_file = rdi_source_file_from_normal_path_cstr(rdi, comp_file->path.cstr);
RDI_SourceFile *comp_src_file = rdi_source_file_from_normal_path_cstr(rdi, (char *)comp_file->path.str);
T_Ok(comp_src_file);
T_Ok(comp_src_file->checksum_kind == RDI_ChecksumKind_MD5);
T_Ok(MemoryMatch(&comp_file->md5, &checksums[comp_src_file->checksum_idx], sizeof(U128)));
dw_writer_end(&writer);
}
T_EndTest;
@@ -324,7 +324,7 @@ T_EndTest;
T_BeginTest(d2r_subprogram)
{
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
U64 image_lo = coff_default_exe_base_from_machine(COFF_MachineType_X64);
U64 image_hi = image_lo + 0x10000;
U64 subprogram_lo = image_lo + 0x1000;
@@ -332,111 +332,111 @@ T_BeginTest(d2r_subprogram)
U64 subprogram_entry_addr = subprogram_lo + 5;
String8 subprogram_link_name = str8_lit("@FOOBAR!");
String8 subprogram_name = str8_lit("foobar");
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string (writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, image_lo);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, image_hi);
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 1);
dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char");
dw_writer_tag_end(writer);
DW_WriterTag *char_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 8);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_type);
dw_writer_tag_end(writer);
DW_WriterTag *int_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 4);
dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_Signed);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "int");
dw_writer_tag_end(writer);
DW_WriterTag *int_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_uint(writer, DW_AttribKind_ByteSize, 8);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type);
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Accessibility, DW_AccessKind_Private);
dw_writer_push_attrib_enum (writer, DW_AttribKind_AddressClass, DW_AddrClassKind_None);
dw_writer_push_attrib_uint (writer, DW_AttribKind_Alignment, 32);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Artificial, 1);
dw_writer_push_attrib_enum (writer, DW_AttribKind_CallingConvention, DW_CallingConventionKind_Program);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Deleted, 1);
dw_writer_push_attrib_address(writer, DW_AttribKind_EntryPc, subprogram_entry_addr);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Explicit, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_External, 1);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_FrameBase, DW_ExprEnc_Op(Reg7));
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, subprogram_hi);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Inline, DW_Inl_DeclaredNotInlined);
dw_writer_push_attrib_string (writer, DW_AttribKind_LinkageName, subprogram_link_name);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, subprogram_lo);
dw_writer_push_attrib_flag (writer, DW_AttribKind_MainSubProgram, 1);
dw_writer_push_attrib_string (writer, DW_AttribKind_Name, subprogram_name);
dw_writer_push_attrib_flag (writer, DW_AttribKind_NoReturn, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Prototyped, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Pure, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Recursive, 1);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Visibility, DW_Vis_Local);
// TODO: DW_AttribKind_ObjectPointer
// TODO: DW_AttribKind_Ranges
// TODO: DW_AttribKind_StartScope
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "a");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg2)); // rcx
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "b");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_ptr_type);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg5)); // rdi
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_UnspecifiedParameters);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
// --------------------------------------------------------------------------------
DW_WriterTag *my_struct_type = dw_writer_tag_reserve(writer, DW_TagKind_StructureType);
DW_WriterTag *const_my_struct_type = dw_writer_tag_begin(writer, DW_TagKind_ConstType);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_type);
dw_writer_tag_end(writer);
DW_WriterTag *my_struct_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, const_my_struct_type);
dw_writer_tag_end(writer);
dw_writer_tag_begin_reserved(writer, my_struct_type);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyStructure");
dw_writer_push_attrib_uint (writer, DW_AttribKind_ByteSize, 0x100);
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyMethod");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type);
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_ptr_type);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
// --------------------------------------------------------------------------------
dw_writer_push_attrib_string (writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, image_lo);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, image_hi);
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 1);
dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char");
dw_writer_tag_end(writer);
DW_WriterTag *char_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 8);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_type);
dw_writer_tag_end(writer);
DW_WriterTag *int_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint (writer, DW_AttribKind_ByteSize, 4);
dw_writer_push_attrib_sint (writer, DW_AttribKind_Encoding, DW_ATE_Signed);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "int");
dw_writer_tag_end(writer);
DW_WriterTag *int_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_uint(writer, DW_AttribKind_ByteSize, 8);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type);
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Accessibility, DW_AccessKind_Private);
dw_writer_push_attrib_enum (writer, DW_AttribKind_AddressClass, DW_AddrClassKind_None);
dw_writer_push_attrib_uint (writer, DW_AttribKind_Alignment, 32);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Artificial, 1);
dw_writer_push_attrib_enum (writer, DW_AttribKind_CallingConvention, DW_CallingConventionKind_Program);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Deleted, 1);
dw_writer_push_attrib_address(writer, DW_AttribKind_EntryPc, subprogram_entry_addr);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Explicit, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_External, 1);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_FrameBase, DW_ExprEnc_Op(Reg7));
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, subprogram_hi);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Inline, DW_Inl_DeclaredNotInlined);
dw_writer_push_attrib_string (writer, DW_AttribKind_LinkageName, subprogram_link_name);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, subprogram_lo);
dw_writer_push_attrib_flag (writer, DW_AttribKind_MainSubProgram, 1);
dw_writer_push_attrib_string (writer, DW_AttribKind_Name, subprogram_name);
dw_writer_push_attrib_flag (writer, DW_AttribKind_NoReturn, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Prototyped, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Pure, 1);
dw_writer_push_attrib_flag (writer, DW_AttribKind_Recursive, 1);
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_type);
dw_writer_push_attrib_enum (writer, DW_AttribKind_Visibility, DW_Vis_Local);
// TODO: DW_AttribKind_ObjectPointer
// TODO: DW_AttribKind_Ranges
// TODO: DW_AttribKind_StartScope
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "a");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg2)); // rcx
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "b");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, char_ptr_type);
dw_writer_push_attrib_exprv (writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg5)); // rdi
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_UnspecifiedParameters);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
// --------------------------------------------------------------------------------
DW_WriterTag *my_struct_type = dw_writer_tag_reserve(writer, DW_TagKind_StructureType);
DW_WriterTag *const_my_struct_type = dw_writer_tag_begin(writer, DW_TagKind_ConstType);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_type);
dw_writer_tag_end(writer);
DW_WriterTag *my_struct_ptr_type = dw_writer_tag_begin(writer, DW_TagKind_PointerType);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, const_my_struct_type);
dw_writer_tag_end(writer);
dw_writer_tag_begin_reserved(writer, my_struct_type);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyStructure");
dw_writer_push_attrib_uint (writer, DW_AttribKind_ByteSize, 0x100);
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "MyMethod");
dw_writer_push_attrib_ref (writer, DW_AttribKind_Type, int_ptr_type);
dw_writer_tag_begin(writer, DW_TagKind_FormalParameter);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, my_struct_ptr_type);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
// --------------------------------------------------------------------------------
dw_writer_tag_end(writer);
RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer);
RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, subprogram_name.cstr);
RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, (char *)subprogram_name.str);
RDI_TypeNode *proc_type = rdi_element_from_name_idx(rdi, TypeNodes, proc->type_idx);
String8 proc_string = rdi_string_from_type(scratch.arena, rdi, proc, proc_type);
dw_writer_end(&writer);
}
T_EndTest;
@@ -448,53 +448,53 @@ T_BeginTest(d2r_general)
{
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Producer, "Test");
// declare char type
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char");
dw_writer_tag_end(writer);
// declare function
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b);
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar");
// declare variable
dw_writer_tag_begin(writer, DW_TagKind_Variable);
dw_writer_push_attrib_exprv(writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg7));
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal");
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
// declare char type
DW_WriterTag *char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "char");
dw_writer_tag_end(writer);
// declare function
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_address(writer, DW_AttribKind_LowPc, 0x140173f9);
dw_writer_push_attrib_address(writer, DW_AttribKind_HighPc, 0x14017474b);
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "FooBar");
// declare variable
dw_writer_tag_begin(writer, DW_TagKind_Variable);
dw_writer_push_attrib_exprv(writer, DW_AttribKind_Location, DW_ExprEnc_Op(Reg7));
dw_writer_push_attrib_stringf(writer, DW_AttribKind_Name, "TestLocal");
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
dw_writer_tag_end(writer);
dw_writer_tag_end(writer);
}
RDI_Parsed *rdi = d2r_rdi_from_dwarf_writer(scratch.arena, writer);
RDI_Procedure *proc = rdi_procedure_from_name_cstr(rdi, "FooBar");
T_Ok(proc);
T_Ok(proc->link_flags == RDI_LinkFlag_External);
String8 proc_name = str8_from_rdi_string_idx(rdi, proc->name_string_idx);
T_Ok(str8_match(proc_name, str8_lit("FooBar"), 0));
RDI_Scope *root_scope = rdi_root_scope_from_procedure(rdi, proc);
T_Ok(root_scope);
T_Ok(root_scope->local_count == 1);
RDI_Local *test_local = rdi_element_from_name_idx(rdi, Locals, root_scope->local_first + 0);
T_Ok(test_local);
T_Ok(test_local->kind == RDI_LocalKind_Variable);
String8 test_local_name = str8_from_rdi_string_idx(rdi, test_local->name_string_idx);
T_Ok(str8_match(test_local_name, str8_lit("TestLocal"), 0));
RDI_TypeNode *test_local_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local->type_idx);
T_Ok(test_local_type);
T_Ok(test_local_type->kind == RDI_TypeKind_Alias);
T_Ok(test_local_type->flags == 0);
String8 alias_name = str8_from_rdi_string_idx(rdi, test_local_type->user_defined.name_string_idx);
T_Ok(str8_match(alias_name, str8_lit("char"), 0));
RDI_TypeNode *char_type = rdi_element_from_name_idx(rdi, TypeNodes, test_local_type->user_defined.direct_type_idx);
T_Ok(char_type);
T_Ok(char_type->kind == RDI_TypeKind_Char8);
@@ -502,7 +502,7 @@ T_BeginTest(d2r_general)
T_Ok(char_type->byte_size == 1);
String8 char_type_name = str8_from_rdi_string_idx(rdi, char_type->built_in.name_string_idx);
T_Ok(str8_match(char_type_name, str8_lit("Char8"), 0));
dw_writer_end(&writer);
}
T_EndTest;
+161 -161
View File
@@ -8,18 +8,18 @@ t_dw_test_uleb128(U64 v, U64 expected_length)
{
Temp scratch = scratch_begin(0, 0);
B32 is_ok = 0;
U64 v0 = v;
String8 e = dw_write_uleb128(scratch.arena, v0);
if (!(expected_length == e.size)) { goto exit; }
U64 v1;
U64 bytes_read = str8_deserial_read_uleb128(e, 0, &v1);
if (!(bytes_read == e.size)) { goto exit; }
if (!(v0 == v1)) { goto exit; }
is_ok = 1;
exit:;
exit:;
scratch_end(scratch);
return is_ok;
}
@@ -29,18 +29,18 @@ t_dw_test_sleb128(U64 v, U64 expected_length)
{
Temp scratch = scratch_begin(0,0);
B32 is_ok = 0;
U64 v0 = v;
String8 e = dw_write_sleb128(scratch.arena, v0);
if (!(expected_length == e.size)) { goto exit; }
S64 v1;
U64 bytes_read = str8_deserial_read_sleb128(e, 0, &v1);
if (!(bytes_read == e.size)) { goto exit; }
if (!(v0 == v1)) { goto exit; }
is_ok = 1;
exit:;
exit:;
scratch_end(scratch);
return is_ok;
}
@@ -50,13 +50,13 @@ T_BeginTest(test_leb128)
T_Ok(t_dw_test_uleb128(0, 1));
T_Ok(t_dw_test_sleb128(0, 1));
T_Ok(t_dw_test_sleb128(-1, 1));
T_Ok(t_dw_test_uleb128(max_U64, 10));
T_Ok(t_dw_test_sleb128(min_S64, 10));
T_Ok(t_dw_test_sleb128(max_S64, 10));
T_Ok(t_dw_test_uleb128(0xDEADBEEFCAFEBABE, 10));
for EachIndex(i, 64) {
T_Ok(t_dw_test_uleb128((1ull << i), 1 + (i / 7)));
}
@@ -70,7 +70,7 @@ internal B32
dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
{
B32 is_match = 0;
// match headers
B32 writer_has_children = writer_tag->first_child != 0;
if (writer_tag->kind != reader_tag->tag.kind) { goto exit; }
@@ -78,7 +78,7 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
if (writer_tag->attrib_count != reader_tag->tag.attribs.count) { goto exit; }
if (writer_tag->info_off != reader_tag->tag.info_off) { goto exit; }
if (writer_has_children != reader_tag->tag.has_children) { goto exit; }
// match attribs
DW_WriterAttrib *writer_attrib = writer_tag->first_attrib;
DW_AttribNode *reader_attrib = reader_tag->tag.attribs.first;
@@ -89,7 +89,7 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
writer_attrib = writer_attrib->next;
reader_attrib = reader_attrib->next;
}
// visit children
DW_WriterTag *writer_child = writer_tag->first_child;
DW_TagNode *reader_child = reader_tag->first_child;
@@ -98,9 +98,9 @@ dwt_tags_must_match(DW_WriterTag *writer_tag, DW_TagNode *reader_tag)
writer_child = writer_child->next;
reader_child = reader_child->sibling;
}
is_match = 1;
exit:;
exit:;
return is_match;
}
@@ -108,7 +108,7 @@ internal DW_Input
dw_input_from_writer(Arena *arena, DW_Writer *writer)
{
Temp scratch = scratch_begin(&arena, 1);
OBJ *obj = obj_alloc(0, Arch_x64);
OBJ_Section *text_section = obj_push_section(obj, str8_lit(".text"), OBJ_SectionFlag_Read|OBJ_SectionFlag_Exec|OBJ_SectionFlag_Load);
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
@@ -116,20 +116,20 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
str8_serial_push_u8(obj->arena, &text_section->data, 0x90);
str8_serial_push_u8(obj->arena, &text_section->data, 0xc3);
obj_push_symbol(obj, str8_lit("entry"), OBJ_SymbolScope_Global, OBJ_RefKind_Section, text_section);
dw_writer_emit_to_obj(writer, obj);
String8 raw_coff = coff_from_obj(scratch.arena, obj);
t_write_file(str8_lit("dwarf.obj"), raw_coff);
t_invoke(str8_lit("radlink"), str8_lit("/subsystem:console /entry:entry /out:a.exe /debug:full dwarf.obj"), max_U64);
os_delete_file_at_path(t_make_file_path(scratch.arena, str8_lit("a.pdb")));
String8 exe = t_read_file(arena, str8_lit("a.exe"));
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, exe);
COFF_SectionHeader *section_table = (COFF_SectionHeader *)(exe.str + pe.section_table_range.min);
String8 string_table = str8_substr(exe, pe.string_table_range);
DW_Input input = dw_input_from_coff_section_table(arena, exe, string_table, pe.section_count, section_table);
obj_release(&obj);
scratch_end(scratch);
return input;
@@ -139,27 +139,27 @@ T_BeginTest(dwarf_32bit)
{
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_tag_end(writer);
DW_Input input = dw_input_from_writer(scratch.arena, writer);
for EachElement(sec_idx, input.sec) {
if (sec_idx == DW_Section_Abbrev) continue;
Rng1U64Array unit_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[sec_idx].data);
for EachIndex(range_idx, unit_ranges.count) {
Rng1U64 range = unit_ranges.v[range_idx];
U32 first_four_bytes = 0;
T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &first_four_bytes) == sizeof(first_four_bytes));
T_Ok(first_four_bytes + 4 == dim_1u64(range));
U32 unit_length = 0;
T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &unit_length) == sizeof(U32));
T_Ok(unit_length + 4 == dim_1u64(range));
}
}
dw_writer_end(&writer);
}
T_EndTest;
@@ -170,25 +170,25 @@ T_BeginTest(dwarf_64bit)
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_tag_end(writer);
DW_Input input = dw_input_from_writer(scratch.arena, writer);
for EachElement(sec_idx, input.sec) {
if (sec_idx == DW_Section_Abbrev) continue;
Rng1U64Array unit_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[sec_idx].data);
for EachIndex(range_idx, unit_ranges.count) {
Rng1U64 range = unit_ranges.v[range_idx];
U32 first_four_bytes = 0;
T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min, &first_four_bytes) == sizeof(first_four_bytes));
T_Ok(first_four_bytes == max_U32);
U64 unit_length = 0;
T_Ok(str8_deserial_read_struct(input.sec[sec_idx].data, range.min + sizeof(U32), &unit_length) == sizeof(U64));
T_Ok(unit_length + 12 == dim_1u64(range));
}
}
dw_writer_end(&writer);
}
T_EndTest;
@@ -200,12 +200,12 @@ T_BeginTest(dwarf_line_opcodes)
String8 comp_name = str8_lit("test.c");
U64 address = 0xDEADBEEFCAFEBABE;
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_tag_end(writer);
// test directory table and file table
DW_WriterFile *file2 = dw_writer_new_file(writer, str8_lit("d:/foobar/qwe.c"));
file2->time_stamp = 123;
@@ -217,7 +217,7 @@ T_BeginTest(dwarf_line_opcodes)
file->size = 314;
file->md5 = *(U128 *)&((U8[sizeof(U128)]) { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, });
file->source = str8_lit("int main() { return 057; }\n");
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_copy());
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(7));
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_pc(-7));
@@ -237,32 +237,32 @@ T_BeginTest(dwarf_line_opcodes)
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_address(address));
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_set_discriminator(2));
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNE_end_sequence());
DW_Input input = dw_input_from_writer(scratch.arena, writer);
Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data);
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0);
DW_LineVM *line_vm = dw_line_vm_init(&input, &cu);
T_Ok(line_vm->header.dir_table.count == 2);
T_Ok(line_vm->header.file_table.count == 2);
T_Ok(str8_match(line_vm->header.dir_table.v[0], str8_lit("c:/devel"), 0));
T_Ok(str8_match(line_vm->header.dir_table.v[1], str8_lit("d:/foobar"), 0));
DW_LineFile *file_reader = &line_vm->header.file_table.v[0];
T_Ok(str8_match(file_reader->path, comp_name, 0));
T_Ok(file_reader->dir_idx == 0);
T_Ok(file_reader->time_stamp == file->time_stamp);
T_Ok(u128_match(file_reader->md5, file->md5));
T_Ok(str8_match(file_reader->source, file->source, 0));
DW_LineFile *file2_reader = &line_vm->header.file_table.v[1];
T_Ok(str8_match(file2_reader->path, str8_lit("qwe.c"), 0));
T_Ok(file2_reader->dir_idx == 1);
T_Ok(file2_reader->time_stamp == file2->time_stamp);
T_Ok(u128_match(file2_reader->md5, file2->md5));
T_Ok(str8_match(file2_reader->source, file2->source, 0));
T_Ok(line_vm->new_line == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
@@ -271,48 +271,48 @@ T_BeginTest(dwarf_line_opcodes)
T_Ok(line_vm->state.basic_block == 0);
T_Ok(line_vm->state.prologue_end == 0);
T_Ok(line_vm->state.epilogue_begin == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
T_Ok(line_vm->state.address == 7);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
T_Ok(line_vm->state.address == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 5);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 1);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetFile);
T_Ok(line_vm->state.file_index == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn);
T_Ok(line_vm->state.column == max_U64);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetColumn);
T_Ok(line_vm->state.column == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt);
T_Ok(line_vm->state.is_stmt == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_NegateStmt);
T_Ok(line_vm->state.is_stmt == 1);
T_Ok(line_vm->state.basic_block == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetBasicBlock);
T_Ok(line_vm->state.basic_block == 1);
{
U64 addr_before = line_vm->state.address;
U64 const_advance = (0xffu - line_vm->header.opcode_base) / line_vm->header.line_range;
@@ -320,45 +320,45 @@ T_BeginTest(dwarf_line_opcodes)
T_Ok(!line_vm->new_line);
T_Ok(line_vm->state.address == addr_before + const_advance);
}
T_Ok(line_vm->state.address == 0x11);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_FixedAdvancePc);
T_Ok(line_vm->state.address == max_U16 + 0x11);
T_Ok(line_vm->state.prologue_end == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetPrologueEnd);
T_Ok(line_vm->state.prologue_end == 1);
T_Ok(line_vm->state.epilogue_begin == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetEpilogueBegin);
T_Ok(line_vm->state.epilogue_begin == 1);
T_Ok(line_vm->state.isa == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetIsa);
T_Ok(line_vm->state.isa == max_U64);
T_Ok(line_vm->state.address != address);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetAddress);
T_Ok(line_vm->state.address == address);
T_Ok(line_vm->state.discriminator == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_SetDiscriminator);
T_Ok(line_vm->state.discriminator == 2);
T_Ok(!line_vm->state.end_sequence);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
T_Ok(line_vm->state.end_sequence);
dw_writer_end(&writer);
}
T_EndTest;
@@ -369,39 +369,39 @@ T_BeginTest(dwarf_line_emit)
String8 comp_dir = str8_lit("c:/devel/");
String8 comp_name = str8_lit("test.c");
dw_writer_tag_begin(writer, DW_TagKind_CompileUnit);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_push_attrib_string(writer, DW_AttribKind_Producer, str8_lit("RAD DWARF WRITER"));
dw_writer_push_attrib_string(writer, DW_AttribKind_CompDir, comp_dir);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, comp_name);
dw_writer_push_attrib_line_ptr(writer, DW_AttribKind_StmtList, 0);
dw_writer_tag_end(writer);
// test special opcode writer and reader
DW_WriterFile *file = dw_writer_new_file(writer, comp_name);
// init sequence
dw_writer_line_emit(writer, file, 10000, 0, 1000);
for EachIndex(i, abs_s64(writer->line.line_base) + 1) {
dw_writer_line_emit(writer, file, writer->line.ln-i, 0, writer->line.addr+1);
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(i));
writer->line.ln += i;
}
// special opcode line window underflow, must emit three instructions to advance
dw_writer_line_emit(writer, file, (writer->line.ln + writer->line.line_base) - 1, 0, writer->line.addr + 1);
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-(writer->line.line_base - 1)));
for EachIndex(i, (writer->line.line_range + writer->line.line_base) + 1) {
dw_writer_line_emit(writer, file, writer->line.ln+i, 0, writer->line.addr+1);
dw_line_inst_list_push(writer->arena, &writer->line.line_insts, DW_LNS_advance_line(-i));
writer->line.ln -= i;
}
dw_writer_line_end_sequence(writer);
dw_writer_line_emit(writer, file, 1000, 0, writer->line.addr+1);
// test address window
S64 c = writer->line.line_range + writer->line.line_base;
U64 line_addr_count = 0;
@@ -414,40 +414,40 @@ T_BeginTest(dwarf_line_emit)
line_addr_count += 1;
}
}
DW_Input input = dw_input_from_writer(scratch.arena, writer);
Rng1U64Array cu_ranges = dw_unit_ranges_from_data_arr(scratch.arena, input.sec[DW_Section_Info].data);
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, (DW_ListUnitInput){0}, cu_ranges.v[0].min, 0);
DW_LineVM *line_vm = dw_line_vm_init(&input, &cu);
// check init sequence
{
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_SetFile);
T_Ok(line_vm->state.file_index == 0);
T_Ok(line_vm->new_line == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
T_Ok(line_vm->state.address == 1000);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->new_line == 0);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == 1000);
T_Ok(line_vm->new_line == 1);
}
{
U64 pc = line_vm->state.address;
for EachIndex(i, abs_s64(writer->line.line_base) + 1) {
pc += 1;
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == 0x20 - i);
T_Ok(line_vm->state.line == 10000 - i);
@@ -459,81 +459,81 @@ T_BeginTest(dwarf_line_emit)
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
}
// line window underflow check
{
pc += 1;
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 9994);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
T_Ok(line_vm->state.line == 9994);
T_Ok(line_vm->state.address == pc);
T_Ok(line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
}
for EachIndex(i, writer->line.line_range + writer->line.line_base) {
pc += 1;
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == 0x20 + i);
T_Ok(line_vm->state.line == 10000 + i);
T_Ok(line_vm->state.address == pc);
T_Ok(line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
}
// line window overflow check
{
pc += 1;
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvancePc);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 10009);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_Copy);
T_Ok(line_vm->state.address == pc);
T_Ok(line_vm->state.line == 10009);
T_Ok(line_vm->new_line);
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_AdvanceLine);
T_Ok(line_vm->state.line == 10000);
T_Ok(line_vm->state.address == pc);
T_Ok(!line_vm->new_line);
}
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
@@ -541,19 +541,19 @@ T_BeginTest(dwarf_line_emit)
T_Ok(line_vm->state.address == pc);
T_Ok(line_vm->new_line);
}
{
T_Ok(dw_line_vm_step(line_vm));
T_Ok(dw_line_vm_step(line_vm));
T_Ok(dw_line_vm_step(line_vm));
T_Ok(dw_line_vm_step(line_vm));
for EachIndex(i, line_addr_count/*first line is a noop*/-1) {
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->header.opcode_base < line_vm->opcode);
T_Ok(line_vm->new_line);
}
T_Ok(dw_line_vm_step(line_vm));
T_Ok(line_vm->opcode == DW_StdOpcode_ExtendedOpcode);
T_Ok(line_vm->ext_opcode == DW_ExtOpcode_EndSequence);
@@ -581,18 +581,18 @@ T_BeginTest(dwarf_writer)
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char"));
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_ConstType);
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
dw_writer_tag_end(writer);
// test abbrev dedup
DW_WriterTag *dup_char_type = dw_writer_tag_begin(writer, DW_TagKind_BaseType);
dw_writer_push_attrib_sint(writer, DW_AttribKind_ByteSize, 1);
dw_writer_push_attrib_enum(writer, DW_AttribKind_Encoding, DW_ATE_SignedChar);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("char"));
dw_writer_tag_end(writer);
// simple struct test
DW_WriterTag *simple_struct_tag = dw_writer_tag_begin(writer, DW_TagKind_StructureType);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("FooBar"));
@@ -603,7 +603,7 @@ T_BeginTest(dwarf_writer)
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
dw_writer_push_attrib_sint(writer, DW_AttribKind_DataMemberLocation, 0);
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_Member);
dw_writer_push_attrib_string(writer, DW_AttribKind_Name, str8_lit("m1"));
dw_writer_push_attrib_ref(writer, DW_AttribKind_Type, char_type);
@@ -612,7 +612,7 @@ T_BeginTest(dwarf_writer)
dw_writer_tag_end(writer);
}
dw_writer_tag_end(writer);
dw_writer_tag_begin(writer, DW_TagKind_SubProgram);
dw_writer_push_attrib_flag(writer, DW_AttribKind_External, 1);
dw_writer_push_attrib_flag(writer, DW_AttribKind_Prototyped, 1);
@@ -625,15 +625,15 @@ T_BeginTest(dwarf_writer)
}
dw_writer_tag_end(writer);
}
DW_Input input = dw_input_from_writer(scratch.arena, writer);
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &input);
DW_CompUnit cu = dw_cu_from_info_off(scratch.arena, &input, lu_input, 0, 1);
DW_TagTree tag_tree = dw_tag_tree_from_cu(scratch.arena, &input, &cu);
AssertAlways(dwt_tags_must_match(writer->root, tag_tree.root));
// validate the writer
T_Ok(writer->current == 0);
T_Ok(writer->format == DW_Format_32Bit);
T_Ok(writer->cu_kind == DW_CompUnitKind_Compile);
@@ -642,7 +642,7 @@ T_BeginTest(dwarf_writer)
T_Ok(writer->abbrev_base_info_off == 8);
T_Ok(writer->fixups.count == 0);
T_Ok(writer->abbrev_id_map->count == 7);
DW_WriterTag *comp_unit_tag = writer->root;
{
T_Ok(comp_unit_tag->kind == DW_TagKind_CompileUnit);
@@ -651,24 +651,24 @@ T_BeginTest(dwarf_writer)
T_Ok(comp_unit_tag->attrib_count == 5);
T_Ok(comp_unit_tag->abbrev_id == 1);
T_Ok(comp_unit_tag->info_off == 0xc);
DW_WriterAttrib *producer_attrib = comp_unit_tag->first_attrib;
T_Ok(producer_attrib->kind == DW_AttribKind_Producer);
T_Ok(producer_attrib->form.reader.kind == DW_Form_String);
T_Ok(str8_match(producer_attrib->form.writer.string, str8_lit("RAD DWARF WRITER"), 0));
DW_WriterAttrib *language_attrib = producer_attrib->next;
T_Ok(language_attrib->kind == DW_AttribKind_Language);
T_Ok(language_attrib->form.reader.kind == DW_Form_Data1);
T_Ok(language_attrib->form.reader.data.size == 1);
T_Ok(*(U8 *)language_attrib->form.reader.data.str == DW_Language_C99);
DW_WriterAttrib *use_utf8_attrib = language_attrib->next;
T_Ok(use_utf8_attrib->kind == DW_AttribKind_UseUtf8);
T_Ok(use_utf8_attrib->form.reader.kind == DW_Form_Flag);
T_Ok(use_utf8_attrib->form.reader.flag == 1);
}
DW_WriterTag *char_type_tag = comp_unit_tag->first_child;
{
T_Ok(char_type_tag->kind == DW_TagKind_BaseType);
@@ -678,25 +678,25 @@ T_BeginTest(dwarf_writer)
T_Ok(char_type_tag->abbrev_id == 2);
T_Ok(char_type_tag->info_off == 0x30);
T_Ok(char_type_tag->first_attrib != char_type_tag->last_attrib);
DW_WriterAttrib *byte_size_attrib = char_type_tag->first_attrib;
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1);
T_Ok(byte_size_attrib->form.reader.data.size == 1);
T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1);
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1);
T_Ok(encoding_attrib->form.reader.data.size == 1);
T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar);
DW_WriterAttrib *name_attrib = encoding_attrib->next;
T_Ok(name_attrib->kind == DW_AttribKind_Name);
T_Ok(name_attrib->form.reader.kind == DW_Form_String);
T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0));
}
DW_WriterTag *const_type_tag = char_type_tag->next;
{
T_Ok(const_type_tag->kind == DW_TagKind_ConstType);
@@ -706,13 +706,13 @@ T_BeginTest(dwarf_writer)
T_Ok(const_type_tag->abbrev_id == 3);
T_Ok(const_type_tag->info_off == 0x38);
T_Ok(const_type_tag->first_attrib && const_type_tag->first_attrib == const_type_tag->last_attrib);
DW_WriterAttrib *type_attrib = const_type_tag->first_attrib;
T_Ok(type_attrib->kind == DW_AttribKind_Type);
T_Ok(type_attrib->form.writer.kind == DW_WriterFormKind_Ref);
T_Ok(type_attrib->form.writer.ref == char_type_tag);
}
DW_WriterTag *dup_char_type_tag = const_type_tag->next;
{
T_Ok(dup_char_type_tag->kind == DW_TagKind_BaseType);
@@ -722,25 +722,25 @@ T_BeginTest(dwarf_writer)
T_Ok(dup_char_type_tag->abbrev_id == 2);
T_Ok(dup_char_type_tag->info_off == 0x3a);
T_Ok(dup_char_type_tag->first_attrib != dup_char_type_tag->last_attrib);
DW_WriterAttrib *byte_size_attrib = dup_char_type_tag->first_attrib;
T_Ok(byte_size_attrib->kind == DW_AttribKind_ByteSize);
T_Ok(byte_size_attrib->form.reader.kind == DW_Form_Data1);
T_Ok(byte_size_attrib->form.reader.data.size == 1);
T_Ok(*(U8 *)byte_size_attrib->form.reader.data.str == 1);
DW_WriterAttrib *encoding_attrib = byte_size_attrib->next;
T_Ok(encoding_attrib->kind == DW_AttribKind_Encoding);
T_Ok(encoding_attrib->form.reader.kind == DW_Form_Data1);
T_Ok(encoding_attrib->form.reader.data.size == 1);
T_Ok(*(U8 *)encoding_attrib->form.reader.data.str == DW_ATE_SignedChar);
DW_WriterAttrib *name_attrib = encoding_attrib->next;
T_Ok(name_attrib->kind == DW_AttribKind_Name);
T_Ok(name_attrib->form.reader.kind == DW_Form_String);
T_Ok(str8_match(name_attrib->form.reader.string, str8_lit("char"), 0));
}
DW_WriterTag *simple_struct_tag = dup_char_type_tag->next;
{
T_Ok(simple_struct_tag->kind == DW_TagKind_StructureType);
@@ -749,12 +749,12 @@ T_BeginTest(dwarf_writer)
T_Ok(simple_struct_tag->attrib_count == 2);
T_Ok(simple_struct_tag->abbrev_id == 4);
T_Ok(simple_struct_tag->info_off == 0x42);
DW_WriterAttrib *simple_struct_name = simple_struct_tag->first_attrib;
T_Ok(simple_struct_name->kind == DW_AttribKind_Name);
T_Ok(simple_struct_name->form.reader.kind == DW_Form_String);
T_Ok(str8_match(simple_struct_name->form.reader.string, str8_lit("FooBar"), 0));
DW_WriterTag *m0_tag = simple_struct_tag->first_child;
{
T_Ok(m0_tag->kind == DW_TagKind_Member);
@@ -762,24 +762,24 @@ T_BeginTest(dwarf_writer)
T_Ok(m0_tag->attrib_count == 3);
T_Ok(m0_tag->info_off == 0x4b);
T_Ok(m0_tag->abbrev_id == 5);
DW_WriterAttrib *name = m0_tag->first_attrib;
T_Ok(name->kind == DW_AttribKind_Name);
T_Ok(name->form.reader.kind == DW_Form_String);
T_Ok(str8_match(name->form.reader.string, str8_lit("m0"), 0));
DW_WriterAttrib *type = name->next;
T_Ok(type->kind == DW_AttribKind_Type);
T_Ok(type->form.reader.kind == DW_Form_Ref1);
T_Ok(type->form.reader.ref == 0x30);
DW_WriterAttrib *data_loc = type->next;
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
T_Ok(data_loc->form.reader.kind == DW_Form_Data1);
T_Ok(data_loc->form.reader.data.size == 1);
T_Ok(*(U8 *)data_loc->form.reader.data.str == 0);
}
DW_WriterTag *m1_tag = m0_tag->next;
{
T_Ok(m1_tag->kind == DW_TagKind_Member);
@@ -787,30 +787,30 @@ T_BeginTest(dwarf_writer)
T_Ok(m1_tag->attrib_count == 4);
T_Ok(m1_tag->info_off == 0x51);
T_Ok(m1_tag->abbrev_id == 6);
DW_WriterAttrib *name = m1_tag->first_attrib;
T_Ok(name->kind == DW_AttribKind_Name);
T_Ok(name->form.reader.kind == DW_Form_String);
T_Ok(str8_match(name->form.reader.string, str8_lit("m1"), 0));
DW_WriterAttrib *type = name->next;
T_Ok(type->kind == DW_AttribKind_Type);
T_Ok(type->form.reader.kind == DW_Form_Ref1);
T_Ok(type->form.reader.ref == 0x30);
DW_WriterAttrib *data_loc = type->next;
T_Ok(data_loc->kind == DW_AttribKind_DataMemberLocation);
T_Ok(data_loc->form.reader.kind == DW_Form_Data1);
T_Ok(data_loc->form.reader.data.size == 1);
T_Ok(*(U8 *)data_loc->form.reader.data.str == 10);
DW_WriterAttrib *byte_size = data_loc->next;
T_Ok(byte_size->kind == DW_AttribKind_ByteSize);
T_Ok(byte_size->form.reader.kind == DW_Form_ImplicitConst);
T_Ok(byte_size->form.reader.implicit_const == 123);
}
}
DW_WriterTag *main_tag = simple_struct_tag->next;
T_Ok(main_tag->next == 0);
T_Ok(main_tag->kind == DW_TagKind_SubProgram);
@@ -821,34 +821,34 @@ T_BeginTest(dwarf_writer)
T_Ok(external->kind == DW_AttribKind_External);
T_Ok(external->form.reader.kind == DW_Form_Flag);
T_Ok(external->form.reader.flag);
DW_WriterAttrib *prototyped = external->next;
T_Ok(prototyped->kind == DW_AttribKind_Prototyped);
T_Ok(prototyped->form.reader.kind == DW_Form_Flag);
T_Ok(prototyped->form.reader.flag);
DW_WriterAttrib *low_pc = prototyped->next;
T_Ok(low_pc->kind == DW_AttribKind_LowPc);
T_Ok(low_pc->form.reader.kind == DW_Form_Addr);
T_Ok(low_pc->form.reader.addr.size == sizeof(U64));
T_Ok(*(U64 *)low_pc->form.reader.addr.str == 0x140001000);
DW_WriterAttrib *high_pc = low_pc->next;
T_Ok(high_pc->kind == DW_AttribKind_HighPc);
T_Ok(high_pc->form.reader.kind == DW_Form_Addr);
T_Ok(high_pc->form.reader.addr.size == sizeof(U64));
T_Ok(*(U64 *)high_pc->form.reader.addr.str == 0x140001004);
DW_WriterAttrib *name = high_pc->next;
T_Ok(name->kind == DW_AttribKind_Name);
T_Ok(name->form.reader.kind == DW_Form_String);
T_Ok(str8_match(name->form.reader.string, str8_lit("main"), 0));
DW_WriterAttrib *type = name->next;
T_Ok(type->kind == DW_AttribKind_Type);
T_Ok(type->form.reader.kind == DW_Form_Ref1);
T_Ok(type->form.reader.ref == simple_struct_tag->info_off);
DW_WriterAttrib *frame_base = type->next;
T_Ok(frame_base->kind == DW_AttribKind_FrameBase);
T_Ok(frame_base->form.reader.kind == DW_Form_ExprLoc);
@@ -860,7 +860,7 @@ T_BeginTest(dwarf_writer)
T_Ok(frame_base_expr.first->next == 0);
T_Ok(frame_base_expr.first->prev == 0);
}
dw_writer_end(&writer);
}
T_EndTest;
@@ -873,7 +873,7 @@ T_BeginTest(value_in_register)
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
U64 value = 0xc0ffee;
MemoryCopy((U8 *)&regs + 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));
@@ -882,7 +882,7 @@ T_BeginTest(value_in_register)
// 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, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
T_Ok(expr_value.type == DW_ExprValueType_U64);
@@ -898,16 +898,16 @@ T_BeginTest(value_in_x_register)
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
U64 value = 0xc0ffee;
MemoryCopy((U8 *)&regs + 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, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
T_Ok(expr_value.type == DW_ExprValueType_U64);
@@ -922,11 +922,11 @@ T_BeginTest(address_of_value)
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);
@@ -942,14 +942,14 @@ T_BeginTest(register_relative_variable)
Rng1U64 reg_range = regs_range_from_code(Arch_x64, 0, reg_code);
U64 value = 1;
MemoryCopy((U8 *)&regs + 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, &regs, 0, 0, &expr_value);
// validate eval result
T_Ok(expr_eval == DW_ExprEvalResult_Ok);
T_Ok(expr_value.type == DW_ExprValueType_Addr);
@@ -962,11 +962,11 @@ 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);
@@ -985,20 +985,20 @@ 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 *)&regs + 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, &regs, 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);
@@ -1011,10 +1011,10 @@ T_BeginTest(plus_uconst)
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);
}
@@ -1037,11 +1037,11 @@ T_BeginTest(reg_split_spill)
U64 value = 0xbbbb;
MemoryCopy((U8 *)&regs + 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, &regs, 0, 0, &expr_value);
}