| ... | ... | @@ -113,6 +113,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 113 | 113 | .debug_abbrev = undefined, |
| 114 | 114 | .debug_str = undefined, |
| 115 | 115 | .debug_line = undefined, |
| 116 | .debug_ranges = null, |
| 116 | 117 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), |
| 117 | 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 | 128 | st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; |
| 128 | 129 | st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo; |
| 129 | 130 | st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; |
| 131 | st.debug_ranges = (%return st.elf.findSection(".debug_ranges")); |
| 130 | 132 | %return scanAllCompileUnits(st); |
| 131 | 133 | |
| 132 | 134 | var ignored_count: usize = 0; |
| ... | ... | @@ -144,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 144 | 146 | // at compile time. I'll call it issue #313 |
| 145 | 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 | 150 | %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", |
| 149 | 151 | return_address); |
| 150 | 152 | continue; |
| ... | ... | @@ -233,6 +235,7 @@ const ElfStackTrace = struct { |
| 233 | 235 | debug_abbrev: &elf.SectionHeader, |
| 234 | 236 | debug_str: &elf.SectionHeader, |
| 235 | 237 | debug_line: &elf.SectionHeader, |
| 238 | debug_ranges: ?&elf.SectionHeader, |
| 236 | 239 | abbrev_table_list: ArrayList(AbbrevTableHeader), |
| 237 | 240 | compile_unit_list: ArrayList(CompileUnit), |
| 238 | 241 | |
| ... | ... | @@ -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 | 348 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { |
| 337 | 349 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 338 | 350 | return switch (*form_value) { |
| ... | ... | @@ -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 | 918 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| 905 | 919 | if (compile_unit.pc_range) |range| { |
| 906 | 920 | if (target_address >= range.start and target_address < range.end) |
| 907 | 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 | 951 | fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 { |