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...@@ -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);
131133
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 #313146 // 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}";
146148
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),
238241
...@@ -333,6 +336,15 @@ const Die = struct {...@@ -333,6 +336,15 @@ const Die = struct {
333 };336 };
334 }337 }
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
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}
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;
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}
912950
913fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {951fn readInitialLength(in_stream: &io.InStream, is_64: &bool) -> %u64 {