diff options
| -rw-r--r-- | std/debug.zig | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/std/debug.zig b/std/debug.zig index f5768ef199..a6229f88da 100644 --- a/std/debug.zig +++ b/std/debug.zig @@ -113,6 +113,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty .debug_abbrev = undefined, .debug_str = undefined, .debug_line = undefined, + .debug_ranges = null, .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), .compile_unit_list = ArrayList(CompileUnit).init(allocator), }; @@ -127,6 +128,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; + st.debug_ranges = (%return st.elf.findSection(".debug_ranges")); %return scanAllCompileUnits(st); var ignored_count: usize = 0; @@ -144,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty // at compile time. I'll call it issue #313 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; - const compile_unit = findCompileUnit(st, return_address) ?? { + const compile_unit = findCompileUnit(st, return_address) %% { %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", return_address); continue; @@ -233,6 +235,7 @@ const ElfStackTrace = struct { debug_abbrev: &elf.SectionHeader, debug_str: &elf.SectionHeader, debug_line: &elf.SectionHeader, + debug_ranges: ?&elf.SectionHeader, abbrev_table_list: ArrayList(AbbrevTableHeader), compile_unit_list: ArrayList(CompileUnit), @@ -333,6 +336,15 @@ const Die = struct { }; } + fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 { + const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; + return switch (*form_value) { + FormValue.Const => |value| value.asUnsignedLe(), + FormValue.SecOffset => |value| value, + else => error.InvalidDebugInfo, + }; + } + fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; return switch (*form_value) { @@ -900,14 +912,40 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { } } -fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit { +fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit { + var in_file_stream = io.FileInStream.init(&st.self_exe_file); + const in_stream = &in_file_stream.stream; for (st.compile_unit_list.toSlice()) |*compile_unit| { if (compile_unit.pc_range) |range| { if (target_address >= range.start and target_address < range.end) return compile_unit; } + if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { + var base_address: usize = 0; + if (st.debug_ranges) |debug_ranges| { + %return st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); + while (true) { + const begin_addr = %return in_stream.readIntLe(usize); + const end_addr = %return in_stream.readIntLe(usize); + if (begin_addr == 0 and end_addr == 0) { + break; + } + if (begin_addr == @maxValue(usize)) { + base_address = begin_addr; + continue; + } + if (target_address >= begin_addr and target_address < end_addr) { + return compile_unit; + } + } + } + } else |err| { + if (err != error.MissingDebugInfo) + return err; + continue; + } } - return null; + return error.MissingDebugInfo; } fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { |
