diff --git a/src/base/base_core.c b/src/base/base_core.c index 372fd6f3..80fc9682 100644 --- a/src/base/base_core.c +++ b/src/base/base_core.c @@ -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) { diff --git a/src/base/base_core.h b/src/base/base_core.h index cace62da..b99139ff 100644 --- a/src/base/base_core.h +++ b/src/base/base_core.h @@ -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); diff --git a/src/dwarf/dwarf.h b/src/dwarf/dwarf.h index 09b87e27..7ddd9f1a 100644 --- a/src/dwarf/dwarf.h +++ b/src/dwarf/dwarf.h @@ -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, diff --git a/src/dwarf/dwarf_coff.c b/src/dwarf/dwarf_coff.c index 2c6614f9..3cf7bea3 100644 --- a/src/dwarf/dwarf_coff.c +++ b/src/dwarf/dwarf_coff.c @@ -35,7 +35,7 @@ dw_input_from_coff_section_table(Arena *arena, for (U64 i = 0; i < section_count; ++i) { COFF_SectionHeader *header = §ion_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); diff --git a/src/dwarf/dwarf_parse.c b/src/dwarf/dwarf_parse.c index 628099fa..6e0c5849 100644 --- a/src/dwarf/dwarf_parse.c +++ b/src/dwarf/dwarf_parse.c @@ -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); } } @@ -273,6 +274,10 @@ internal U64 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; } @@ -304,6 +310,10 @@ internal U64 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; } @@ -1972,6 +1983,10 @@ internal DW_CompUnit dw_cu_from_info_off(Arena *arena, DW_Input *input, DW_ListUnitInput lu_input, U64 cu_header_offset, B32 relaxed) { 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; @@ -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,7 +2740,10 @@ 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); if (unit_length_size == 0) { @@ -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) { diff --git a/src/dwarf/dwarf_writer.c b/src/dwarf/dwarf_writer.c index e534d1d9..b5746c1c 100644 --- a/src/dwarf/dwarf_writer.c +++ b/src/dwarf/dwarf_writer.c @@ -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)); } } } diff --git a/src/torture/torture_dwarf.c b/src/torture/torture_dwarf.c index 820cdfd3..421d5b98 100644 --- a/src/torture/torture_dwarf.c +++ b/src/torture/torture_dwarf.c @@ -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);