test DWARF32 and DWARF64 unit encodings

This commit is contained in:
Nikita Smith
2026-02-22 22:34:28 -08:00
parent cc00fe7825
commit 8b7215695b
7 changed files with 98 additions and 17 deletions
+6
View File
@@ -300,6 +300,12 @@ memory_write32(void *ptr, U32 v)
MemoryCopy(ptr, &v, sizeof(v));
}
internal void UBSAN_NO_ALIGN
memory_write64(void *ptr, U64 v)
{
MemoryCopy(ptr, &v, sizeof(v));
}
internal U8 UBSAN_NO_ALIGN
memory_read8(void *ptr)
{
+1
View File
@@ -1011,6 +1011,7 @@ internal B32 memory_is_zero(void *ptr, U64 size);
internal void memory_write16(void *ptr, U16 v);
internal void memory_write32(void *ptr, U32 v);
internal void memory_write64(void *ptr, U64 v);
internal U8 memory_read8(void *ptr);
internal U16 memory_read16(void *ptr);
-1
View File
@@ -29,7 +29,6 @@ typedef enum DW_ExtEnum
DW_Ext_All = DW_Ext_GNU|DW_Ext_LLVM|DW_Ext_APPLE|DW_Ext_MIPS,
} DW_ExtEnum;
#define DW_FormatFromSize(size) ((size) >= max_U32 ? DW_Format_64Bit : DW_Format_32Bit)
typedef enum DW_Format
{
DW_Format_Null,
+1 -1
View File
@@ -35,7 +35,7 @@ dw_input_from_coff_section_table(Arena *arena,
for (U64 i = 0; i < section_count; ++i) {
COFF_SectionHeader *header = &section_table[i];
Rng1U64 raw_data_range = rng_1u64(header->foff, header->foff + header->fsize);
Rng1U64 raw_data_range = rng_1u64(header->foff, header->vsize ? header->foff + header->vsize : header->foff + header->fsize);
String8 name = coff_name_from_section_header(string_table, header);
DW_SectionKind s = dw_section_kind_from_string(name);
+28 -10
View File
@@ -12,13 +12,14 @@ internal U64
str8_deserial_read_dwarf_packed_size(String8 string, U64 off, U64 *size_out)
{
U64 bytes_read = 0;
if (str8_deserial_read(string, off, size_out, sizeof(U32), sizeof(U32))) {
if (*size_out == max_U32) {
if (str8_deserial_read_struct(string, off+sizeof(U32), size_out)) {
U32 first_four_bytes;
if (str8_deserial_read_struct(string, off, &first_four_bytes) == sizeof(first_four_bytes)) {
if (first_four_bytes == max_U32) {
if (str8_deserial_read_struct(string, off+sizeof(U32), size_out) == sizeof(U64)) {
bytes_read = sizeof(U32) + sizeof(U64);
}
} else {
*size_out &= (U64)max_U32;
*size_out = first_four_bytes;
bytes_read = sizeof(U32);
}
}
@@ -274,6 +275,10 @@ dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out)
{
U64 header_size = 0;
U32 first_four_bytes = 0;
if (str8_deserial_read_struct(unit_data, 0, &first_four_bytes) != sizeof(first_four_bytes)) { goto exit; }
DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit;
U64 unit_length = 0;
U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length);
@@ -291,12 +296,13 @@ dw_read_list_unit_header_str_offsets(String8 unit_data, DW_ListUnit *lu_out)
lu_out->version = version;
lu_out->address_size = 0;
lu_out->segment_selector_size = 0;
lu_out->entry_size = dw_size_from_format(DW_FormatFromSize(unit_length));
lu_out->entry_size = dw_size_from_format(format);
lu_out->entries = str8_skip(unit_data, header_size);
}
}
}
exit:;
return header_size;
}
@@ -305,6 +311,10 @@ dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out)
{
U64 header_size = 0;
U32 first_four_bytes = 0;
if (str8_deserial_read_struct(unit_data, 0, &first_four_bytes) != sizeof(first_four_bytes)) { goto exit; }
DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit;
U64 unit_length = 0;
U64 unit_length_size = str8_deserial_read_dwarf_packed_size(unit_data, 0, &unit_length);
@@ -330,7 +340,7 @@ dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out)
lu_out->version = version;
lu_out->address_size = address_size;
lu_out->segment_selector_size = segment_selector_size;
lu_out->entry_size = dw_size_from_format(DW_FormatFromSize(unit_length));
lu_out->entry_size = dw_size_from_format(format);
lu_out->entries = str8_skip(unit_data, header_size);
}
}
@@ -338,6 +348,7 @@ dw_read_list_unit_header_list(String8 unit_data, DW_ListUnit *lu_out)
}
}
exit:;
return header_size;
}
@@ -1973,6 +1984,10 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6
{
DW_CompUnit cu = {0};
U32 first_four_bytes = 0;
if (str8_deserial_read_struct(input->sec[DW_Section_Info].data, 0, &first_four_bytes) != sizeof(first_four_bytes)) { goto exit; }
DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit;
// read unit size in bytes
U64 length = 0;
U64 length_size = str8_deserial_read_dwarf_packed_size(input->sec[DW_Section_Info].data, cu_header_offset, &length);
@@ -1987,7 +2002,6 @@ dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U6
DW_Version version;
TryRead(str8_deserial_read_struct(info, info_cursor, &version), info_cursor, exit);
DW_Format format = DW_FormatFromSize(length);
U64 abbrev_base = max_U64;
U8 address_size = 0;
DW_CompUnitKind unit_kind = DW_CompUnitKind_Reserved;
@@ -2202,11 +2216,14 @@ dw_read_line_vm_header(Arena *arena,
{
Temp scratch = scratch_begin(&arena, 1);
U32 first_four_bytes = 0;
if (str8_deserial_read_struct(cu_stmt_list, 0, &first_four_bytes) != sizeof(U32)) { goto exit; }
// read unit length
U64 length = 0;
U64 length_size = str8_deserial_read_dwarf_packed_size(cu_stmt_list, 0, &length);
DW_Format format = DW_FormatFromSize(length);
DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit;
U64 cursor = length_size;
String8 data = str8_substr(cu_stmt_list, r1u64(0, length + length_size));
@@ -2723,6 +2740,9 @@ dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_Sect
String8 section_data = input->sec[section_kind].data;
for(U64 cursor = 0; cursor < section_data.size; ) {
U32 first_four_bytes = 0;
if (str8_deserial_read_struct(input->sec[DW_Section_Info].data, 0, &first_four_bytes) != sizeof(first_four_bytes)) { break; }
DW_Format format = first_four_bytes == max_U32 ? DW_Format_64Bit : DW_Format_32Bit;
U64 unit_length = 0;
U64 unit_length_size = str8_deserial_read_dwarf_packed_size(section_data, cursor, &unit_length);
@@ -2742,8 +2762,6 @@ dw_v4_pub_strings_table_from_section_kind(Arena *arena, DW_Input *input, DW_Sect
break;
}
DW_Format format = DW_FormatFromSize(unit_length);
U64 debug_info_off = 0;
cursor += str8_deserial_read_dwarf_uint(section_data, cursor, format, &debug_info_off);
if (cursor >= cursor_opl) {
+3 -3
View File
@@ -1212,15 +1212,15 @@ dw_writer_emit(DW_Writer *writer)
for EachElement(i, writer->sections) {
if (writer->sections[i].length) {
if (writer->format == DW_Format_64Bit) {
U64 *length = writer->sections[i].length;
U64 *length = (U64 *)((U8 *)writer->sections[i].length + sizeof(U32));
U64 length_size = sizeof(U64) + sizeof(U32);
Assert(writer->sections[i].srl.total_size >= length_size);
*length = writer->sections[i].srl.total_size - length_size;
memory_write64(length, writer->sections[i].srl.total_size - length_size);
} else {
U32 *length = writer->sections[i].length;
U32 length_size = sizeof(U32);
Assert(writer->sections[i].srl.total_size >= length_size);
*length = safe_cast_u32(writer->sections[i].srl.total_size - length_size);
memory_write32(length, safe_cast_u32(writer->sections[i].srl.total_size - length_size));
}
}
}
+58 -1
View File
@@ -135,6 +135,64 @@ dw_input_from_writer(Arena *arena, DW_Writer *writer)
return input;
}
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_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;
T_BeginTest(dwarf_64bit)
{
DW_Writer *writer = dw_writer_begin(DW_Format_64Bit, 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_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;
T_BeginTest(dwarf_line_opcodes)
{
DW_Writer *writer = dw_writer_begin(DW_Format_32Bit, DW_Version_5, DW_CompUnitKind_Compile, Arch_x64);
@@ -574,7 +632,6 @@ T_BeginTest(dwarf_writer)
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);