| ... | ... | @@ -185,12 +185,17 @@ const ElfStackTrace = struct { |
| 185 | 185 | } |
| 186 | 186 | }; |
| 187 | 187 | |
| 188 | const PcRange = struct { |
| 189 | start: u64, |
| 190 | end: u64, |
| 191 | }; |
| 192 | |
| 188 | 193 | const CompileUnit = struct { |
| 194 | version: u16, |
| 189 | 195 | is_64: bool, |
| 190 | 196 | die: &Die, |
| 191 | | pc_start: u64, |
| 192 | | pc_end: u64, |
| 193 | 197 | index: usize, |
| 198 | pc_range: ?PcRange, |
| 194 | 199 | }; |
| 195 | 200 | |
| 196 | 201 | const AbbrevTable = List(AbbrevTableEntry); |
| ... | ... | @@ -259,7 +264,7 @@ const Die = struct { |
| 259 | 264 | } |
| 260 | 265 | |
| 261 | 266 | fn getAttrAddr(self: &const Die, id: u64) -> %u64 { |
| 262 | | const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo; |
| 267 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 263 | 268 | return switch (*form_value) { |
| 264 | 269 | FormValue.Address => |value| value, |
| 265 | 270 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -267,7 +272,7 @@ const Die = struct { |
| 267 | 272 | } |
| 268 | 273 | |
| 269 | 274 | fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 { |
| 270 | | const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo; |
| 275 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 271 | 276 | return switch (*form_value) { |
| 272 | 277 | FormValue.Const => |value| value.asUnsignedLe(), |
| 273 | 278 | else => error.InvalidDebugInfo, |
| ... | ... | @@ -275,7 +280,7 @@ const Die = struct { |
| 275 | 280 | } |
| 276 | 281 | |
| 277 | 282 | fn getAttrString(self: &const Die, st: &ElfStackTrace, id: u64) -> %[]u8 { |
| 278 | | const form_value = self.getAttr(id) ?? return error.InvalidDebugInfo; |
| 283 | const form_value = self.getAttr(id) ?? return error.MissingDebugInfo; |
| 279 | 284 | return switch (*form_value) { |
| 280 | 285 | FormValue.String => |value| value, |
| 281 | 286 | FormValue.StrPtr => |offset| getString(st, offset), |
| ... | ... | @@ -794,7 +799,7 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 794 | 799 | const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); |
| 795 | 800 | |
| 796 | 801 | const version = %return st.self_exe_stream.readInt(st.elf.is_big_endian, u16); |
| 797 | | if (version != 4) return error.InvalidDebugInfo; |
| 802 | if (version < 2 or version > 5) return error.InvalidDebugInfo; |
| 798 | 803 | |
| 799 | 804 | const debug_abbrev_offset = if (is_64) { |
| 800 | 805 | %return st.self_exe_stream.readInt(st.elf.is_big_endian, u64) |
| ... | ... | @@ -815,22 +820,36 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 815 | 820 | |
| 816 | 821 | if (compile_unit_die.tag_id != DW.TAG_compile_unit) |
| 817 | 822 | return error.InvalidDebugInfo; |
| 818 | | const low_pc = %return compile_unit_die.getAttrAddr(DW.AT_low_pc); |
| 819 | 823 | |
| 820 | | const high_pc_value = compile_unit_die.getAttr(DW.AT_high_pc) ?? return error.MissingDebugInfo; |
| 821 | | const pc_end = switch (*high_pc_value) { |
| 822 | | FormValue.Address => |value| value, |
| 823 | | FormValue.Const => |value| { |
| 824 | | const offset = %return value.asUnsignedLe(); |
| 825 | | low_pc + offset |
| 826 | | }, |
| 827 | | else => return error.InvalidDebugInfo, |
| 824 | const pc_range = { |
| 825 | try (compile_unit_die.getAttrAddr(DW.AT_low_pc)) |low_pc| { |
| 826 | test (compile_unit_die.getAttr(DW.AT_high_pc)) |high_pc_value| { |
| 827 | const pc_end = switch (*high_pc_value) { |
| 828 | FormValue.Address => |value| value, |
| 829 | FormValue.Const => |value| { |
| 830 | const offset = %return value.asUnsignedLe(); |
| 831 | low_pc + offset |
| 832 | }, |
| 833 | else => return error.InvalidDebugInfo, |
| 834 | }; |
| 835 | PcRange { |
| 836 | .start = low_pc, |
| 837 | .end = pc_end, |
| 838 | } |
| 839 | } else { |
| 840 | null |
| 841 | } |
| 842 | } else |err| { |
| 843 | if (err != error.MissingDebugInfo) |
| 844 | return err; |
| 845 | null |
| 846 | } |
| 828 | 847 | }; |
| 829 | 848 | |
| 830 | 849 | %return st.compile_unit_list.append(CompileUnit { |
| 850 | .version = version, |
| 831 | 851 | .is_64 = is_64, |
| 832 | | .pc_start = low_pc, |
| 833 | | .pc_end = pc_end, |
| 852 | .pc_range = pc_range, |
| 834 | 853 | .die = compile_unit_die, |
| 835 | 854 | .index = cu_index, |
| 836 | 855 | }); |
| ... | ... | @@ -842,8 +861,10 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void { |
| 842 | 861 | |
| 843 | 862 | fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit { |
| 844 | 863 | for (st.compile_unit_list.toSlice()) |*compile_unit| { |
| 845 | | if (target_address >= compile_unit.pc_start and target_address < compile_unit.pc_end) |
| 846 | | return compile_unit; |
| 864 | test (compile_unit.pc_range) |range| { |
| 865 | if (target_address >= range.start and target_address < range.end) |
| 866 | return compile_unit; |
| 867 | } |
| 847 | 868 | } |
| 848 | 869 | return null; |
| 849 | 870 | } |