| ... | @@ -113,6 +113,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty | ... | @@ -113,6 +113,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 113 | .debug_abbrev = undefined, | 113 | .debug_abbrev = undefined, |
| 114 | .debug_str = undefined, | 114 | .debug_str = undefined, |
| 115 | .debug_line = undefined, | 115 | .debug_line = undefined, |
| | 116 | .debug_ranges = null, |
| 116 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | 117 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), |
| 117 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | 118 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), |
| 118 | }; | 119 | }; |
| ... | @@ -127,6 +128,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty | ... | @@ -127,6 +128,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 127 | st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; | 128 | st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; |
| 128 | st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; | 129 | st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; |
| 129 | st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; | 130 | st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; |
| | 131 | st.debug_ranges = (%return st.elf.findSection(".debug_ranges")); |
| 130 | %return scanAllCompileUnits(st); | 132 | %return scanAllCompileUnits(st); |
| 131 | | 133 | |
| 132 | var ignored_count: usize = 0; | 134 | var ignored_count: usize = 0; |
| ... | @@ -144,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty | ... | @@ -144,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 144 | // at compile time. I'll call it issue #313 | 146 | // at compile time. I'll call it issue #313 |
| 145 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | 147 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; |
| 146 | | 148 | |
| 147 | const compile_unit = findCompileUnit(st, return_address) ?? { | 149 | const compile_unit = findCompileUnit(st, return_address) %% { |
| 148 | %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", | 150 | %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", |
| 149 | return_address); | 151 | return_address); |
| 150 | continue; | 152 | continue; |
| ... | @@ -233,6 +235,7 @@ const ElfStackTrace = struct { | ... | @@ -233,6 +235,7 @@ const ElfStackTrace = struct { |
| 233 | debug_abbrev: &elf.SectionHeader, | 235 | debug_abbrev: &elf.SectionHeader, |
| 234 | debug_str: &elf.SectionHeader, | 236 | debug_str: &elf.SectionHeader, |
| 235 | debug_line: &elf.SectionHeader, | 237 | debug_line: &elf.SectionHeader, |
| | 238 | debug_ranges: ?&elf.SectionHeader, |
| 236 | abbrev_table_list: ArrayList(AbbrevTableHeader), | 239 | abbrev_table_list: ArrayList(AbbrevTableHeader), |
| 237 | compile_unit_list: ArrayList(CompileUnit), | 240 | compile_unit_list: ArrayList(CompileUnit), |
| 238 | | 241 | |
| ... | @@ -333,6 +336,15 @@ const Die = struct { | ... | @@ -333,6 +336,15 @@ const Die = struct { |
| 333 | }; | 336 | }; |
| 334 | } | 337 | } |
| 335 | | 338 | |
| | 339 | fn getAttrSecOffset(self: &const Die, id: u64) -> %u64 { |
| | 340 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| | 341 | return switch (*form_value) { |
| | 342 | FormValue.Const => |value| value.asUnsignedLe(), |
| | 343 | FormValue.SecOffset => |value| value, |
| | 344 | else => error.InvalidDebugInfo, |
| | 345 | }; |
| | 346 | } |
| | 347 | |
| 336 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { | 348 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { |
| 337 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; | 349 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 338 | return switch (*form_value) { | 350 | return switch (*form_value) { |
| ... | @@ -900,14 +912,40 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { | ... | @@ -900,14 +912,40 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 900 | } | 912 | } |
| 901 | } | 913 | } |
| 902 | | 914 | |
| 903 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit { | 915 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> %&const CompileUnit { |
| | 916 | var in_file_stream = io.FileInStream.init(&st.self_exe_file); |
| | 917 | const in_stream = &in_file_stream.stream; |
| 904 | for (st.compile_unit_list.toSlice()) |*compile_unit| { | 918 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| 905 | if (compile_unit.pc_range) |range| { | 919 | if (compile_unit.pc_range) |range| { |
| 906 | if (target_address >= range.start and target_address < range.end) | 920 | if (target_address >= range.start and target_address < range.end) |
| 907 | return compile_unit; | 921 | return compile_unit; |
| 908 | } | 922 | } |
| | 923 | if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { |
| | 924 | var base_address: usize = 0; |
| | 925 | if (st.debug_ranges) |debug_ranges| { |
| | 926 | %return st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); |
| | 927 | while (true) { |
| | 928 | const begin_addr = %return in_stream.readIntLe(usize); |
| | 929 | const end_addr = %return in_stream.readIntLe(usize); |
| | 930 | if (begin_addr == 0 and end_addr == 0) { |
| | 931 | break; |
| | 932 | } |
| | 933 | if (begin_addr == @maxValue(usize)) { |
| | 934 | base_address = begin_addr; |
| | 935 | continue; |
| | 936 | } |
| | 937 | if (target_address >= begin_addr and target_address < end_addr) { |
| | 938 | return compile_unit; |
| | 939 | } |
| | 940 | } |
| | 941 | } |
| | 942 | } else |err| { |
| | 943 | if (err != error.MissingDebugInfo) |
| | 944 | return err; |
| | 945 | continue; |
| | 946 | } |
| 909 | } | 947 | } |
| 910 | return null; | 948 | return error.MissingDebugInfo; |
| 911 | } | 949 | } |
| 912 | | 950 | |
| 913 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { | 951 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { |