authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-12 11:33:14-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-12-12 12:05:28-05:00
logcaa6433b5636af968aa7018a3bea8e658bca05a3
treea21636f98e36253d6639604426878807ccb2d05e
parent23058d8b435266852d4ca69ee89f8c3d27f52e24

stack traces: support DW_AT_ranges

This makes some cases print stack traces where it previously failed.

1 files changed, 41 insertions(+), 3 deletions(-)

std/debug.zig+41-3
......@@ -113,6 +113,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
113113 .debug_abbrev = undefined,
114114 .debug_str = undefined,
115115 .debug_line = undefined,
116 .debug_ranges = null,
116117 .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),
117118 .compile_unit_list = ArrayList(CompileUnit).init(allocator),
118119 };
......@@ -127,6 +128,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
127128 st.debug_abbrev = (%return st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo;
128129 st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo;
129130 st.debug_line = (%return st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo;
131 st.debug_ranges = (%return st.elf.findSection(".debug_ranges"));
130132 %return scanAllCompileUnits(st);
131133
132134 var ignored_count: usize = 0;
......@@ -144,7 +146,7 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
144146 // at compile time. I'll call it issue #313
145147 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
146148
147 const compile_unit = findCompileUnit(st, return_address) ?? {
149 const compile_unit = findCompileUnit(st, return_address) %% {
148150 %return out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n",
149151 return_address);
150152 continue;
......@@ -233,6 +235,7 @@ const ElfStackTrace = struct {
233235 debug_abbrev: &elf.SectionHeader,
234236 debug_str: &elf.SectionHeader,
235237 debug_line: &elf.SectionHeader,
238 debug_ranges: ?&elf.SectionHeader,
236239 abbrev_table_list: ArrayList(AbbrevTableHeader),
237240 compile_unit_list: ArrayList(CompileUnit),
238241
......@@ -333,6 +336,15 @@ const Die = struct {
333336 };
334337 }
335338
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
336348 fn getAttrUnsignedLe(self: &const Die, id: u64) -> %u64 {
337349 const form_value = self.getAttr(id) ?? return error.MissingDebugInfo;
338350 return switch (*form_value) {
......@@ -900,14 +912,40 @@ fn scanAllCompileUnits(st: &ElfStackTrace) -> %void {
900912 }
901913}
902914
903fn findCompileUnit(st: &ElfStackTrace, target_address: u64) -> ?&const CompileUnit {
915fn 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;
904918 for (st.compile_unit_list.toSlice()) |*compile_unit| {
905919 if (compile_unit.pc_range) |range| {
906920 if (target_address >= range.start and target_address < range.end)
907921 return compile_unit;
908922 }
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 }
909947 }
910 return null;
948 return error.MissingDebugInfo;
911949}
912950
913951fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {