authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-02 23:46:45-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-12-02 23:46:45-05:00
log3a1612a0f5a41f5cfc9598dc4512b43ee17d030a
treefcf6317c6d6f59694ba1345b342cf796ed4080cc
parent5c3b8cb3659172b539423972d996a66221c0e4a0
signaturelock-open Commit is signed but in an unrecognized format.

std.debug: fix some issues with freestanding debug info


1 files changed, 71 insertions(+), 61 deletions(-)

std/debug/index.zig+71-61
......@@ -200,12 +200,10 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
200200
201201pub const StackIterator = struct {
202202 first_addr: ?usize,
203 debug_info: *DebugInfo,
204203 fp: usize,
205204
206 pub fn init(debug_info: *DebugInfo, first_addr: ?usize) StackIterator {
205 pub fn init(first_addr: ?usize) StackIterator {
207206 return StackIterator{
208 .debug_info = debug_info,
209207 .first_addr = first_addr,
210208 .fp = @ptrToInt(@frameAddress()),
211209 };
......@@ -236,7 +234,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
236234 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
237235 else => {},
238236 }
239 var it = StackIterator.init(debug_info, start_addr);
237 var it = StackIterator.init(start_addr);
240238 while (it.next()) |return_address| {
241239 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
242240 }
......@@ -596,7 +594,6 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
596594 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
597595 defer line_info.deinit();
598596 try printLineInfo(
599 di,
600597 out_stream,
601598 line_info,
602599 address,
......@@ -620,7 +617,7 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
620617/// This function works in freestanding mode.
621618/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void
622619pub fn printSourceAtAddressDwarf(
623 debug_info: *DebugInfo,
620 debug_info: *DwarfInfo,
624621 out_stream: var,
625622 address: usize,
626623 tty_color: bool,
......@@ -639,7 +636,6 @@ pub fn printSourceAtAddressDwarf(
639636 defer line_info.deinit();
640637 const symbol_name = "???";
641638 try printLineInfo(
642 debug_info,
643639 out_stream,
644640 line_info,
645641 address,
......@@ -665,7 +661,6 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
665661}
666662
667663fn printLineInfo(
668 debug_info: *DebugInfo,
669664 out_stream: var,
670665 line_info: LineInfo,
671666 address: usize,
......@@ -900,36 +895,50 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
900895 return list.toOwnedSlice();
901896}
902897
903pub fn openDwarfDebugInfo(
898fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section {
899 const elf_header = (try elf_file.findSection(name)) orelse return null;
900 return DwarfInfo.Section{
901 .offset = elf_header.offset,
902 .size = elf_header.size,
903 };
904}
905
906/// Initialize DWARF info. The caller has the responsibility to initialize most
907/// the DwarfInfo fields before calling. These fields can be left undefined:
908/// * abbrev_table_list
909/// * compile_unit_list
910pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
911 di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator);
912 di.compile_unit_list = ArrayList(CompileUnit).init(allocator);
913 try scanAllCompileUnits(di);
914}
915
916pub fn openElfDebugInfo(
904917 allocator: *mem.Allocator,
905 dwarf_seekable_stream: *DwarfSeekableStream,
906 dwarf_in_stream: *DwarfInStream,
907) !DebugInfo {
908 var di = DebugInfo{
909 .dwarf_seekable_stream = dwarf_seekable_stream,
910 .dwarf_in_stream = dwarf_in_stream,
911 .elf = undefined,
912 .debug_info = undefined,
913 .debug_abbrev = undefined,
914 .debug_str = undefined,
915 .debug_line = undefined,
916 .debug_ranges = null,
917 .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),
918 .compile_unit_list = ArrayList(CompileUnit).init(allocator),
918 elf_seekable_stream: *DwarfSeekableStream,
919 elf_in_stream: *DwarfInStream,
920) !DwarfInfo {
921 var efile: elf.Elf = undefined;
922 try efile.openStream(allocator, elf_seekable_stream, elf_in_stream);
923 errdefer efile.close();
924
925 var di = DwarfInfo{
926 .dwarf_seekable_stream = elf_seekable_stream,
927 .dwarf_in_stream = elf_in_stream,
928 .endian = efile.endian,
929 .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
930 .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
931 .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo,
932 .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo,
933 .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
934 .abbrev_table_list = undefined,
935 .compile_unit_list = undefined,
919936 };
920 try di.elf.openStream(allocator, dwarf_seekable_stream, dwarf_in_stream);
921 errdefer di.elf.close();
922
923 di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo;
924 di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo;
925 di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo;
926 di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo;
927 di.debug_ranges = (try di.elf.findSection(".debug_ranges"));
928 try scanAllCompileUnits(&di);
937 try openDwarfDebugInfo(&di, allocator);
929938 return di;
930939}
931940
932fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
941fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
933942 const S = struct {
934943 var self_exe_file: os.File = undefined;
935944 var self_exe_seekable_stream: os.File.SeekableStream = undefined;
......@@ -941,7 +950,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
941950 S.self_exe_seekable_stream = S.self_exe_file.seekableStream();
942951 S.self_exe_in_stream = S.self_exe_file.inStream();
943952
944 return openDwarfDebugInfo(
953 return openElfDebugInfo(
945954 allocator,
946955 // TODO https://github.com/ziglang/zig/issues/764
947956 @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),
......@@ -1086,26 +1095,27 @@ pub const DwarfInStream = io.InStream(anyerror);
10861095pub const DwarfInfo = struct {
10871096 dwarf_seekable_stream: *DwarfSeekableStream,
10881097 dwarf_in_stream: *DwarfInStream,
1089 elf: elf.Elf,
1090 debug_info: *elf.SectionHeader,
1091 debug_abbrev: *elf.SectionHeader,
1092 debug_str: *elf.SectionHeader,
1093 debug_line: *elf.SectionHeader,
1094 debug_ranges: ?*elf.SectionHeader,
1098 endian: builtin.Endian,
1099 debug_info: Section,
1100 debug_abbrev: Section,
1101 debug_str: Section,
1102 debug_line: Section,
1103 debug_ranges: ?Section,
10951104 abbrev_table_list: ArrayList(AbbrevTableHeader),
10961105 compile_unit_list: ArrayList(CompileUnit),
10971106
1098 pub fn allocator(self: DebugInfo) *mem.Allocator {
1107 pub const Section = struct {
1108 offset: usize,
1109 size: usize,
1110 };
1111
1112 pub fn allocator(self: DwarfInfo) *mem.Allocator {
10991113 return self.abbrev_table_list.allocator;
11001114 }
11011115
1102 pub fn readString(self: *DebugInfo) ![]u8 {
1116 pub fn readString(self: *DwarfInfo) ![]u8 {
11031117 return readStringRaw(self.allocator(), self.dwarf_in_stream);
11041118 }
1105
1106 pub fn close(self: *DebugInfo) void {
1107 self.elf.close();
1108 }
11091119};
11101120
11111121pub const DebugInfo = switch (builtin.os) {
......@@ -1236,7 +1246,7 @@ const Die = struct {
12361246 };
12371247 }
12381248
1239 fn getAttrString(self: *const Die, di: *DebugInfo, id: u64) ![]u8 {
1249 fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
12401250 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
12411251 return switch (form_value.*) {
12421252 FormValue.String => |value| value,
......@@ -1253,7 +1263,7 @@ const FileEntry = struct {
12531263 len_bytes: usize,
12541264};
12551265
1256const LineInfo = struct {
1266pub const LineInfo = struct {
12571267 line: usize,
12581268 column: usize,
12591269 file_name: []const u8,
......@@ -1352,7 +1362,7 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
13521362 return buf.toSlice();
13531363}
13541364
1355fn getString(di: *DebugInfo, offset: u64) ![]u8 {
1365fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
13561366 const pos = di.debug_str.offset + offset;
13571367 try di.dwarf_seekable_stream.seekTo(pos);
13581368 return di.readString();
......@@ -1452,7 +1462,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
14521462 };
14531463}
14541464
1455fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable {
1465fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
14561466 var result = AbbrevTable.init(di.allocator());
14571467 while (true) {
14581468 const abbrev_code = try readULeb128(di.dwarf_in_stream);
......@@ -1479,7 +1489,7 @@ fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable {
14791489
14801490/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
14811491/// seeks in the stream and parses it.
1482fn getAbbrevTable(di: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable {
1492fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable {
14831493 for (di.abbrev_table_list.toSlice()) |*header| {
14841494 if (header.offset == abbrev_offset) {
14851495 return &header.table;
......@@ -1500,7 +1510,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
15001510 return null;
15011511}
15021512
1503fn parseDie(di: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
1513fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die {
15041514 const abbrev_code = try readULeb128(di.dwarf_in_stream);
15051515 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
15061516
......@@ -1717,7 +1727,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17171727 return error.MissingDebugInfo;
17181728}
17191729
1720fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
1730fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
17211731 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
17221732
17231733 const debug_line_end = di.debug_line.offset + di.debug_line.size;
......@@ -1737,11 +1747,11 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
17371747 continue;
17381748 }
17391749
1740 const version = try di.dwarf_in_stream.readInt(di.elf.endian, u16);
1750 const version = try di.dwarf_in_stream.readInt(di.endian, u16);
17411751 // TODO support 3 and 5
17421752 if (version != 2 and version != 4) return error.InvalidDebugInfo;
17431753
1744 const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.elf.endian, u64) else try di.dwarf_in_stream.readInt(di.elf.endian, u32);
1754 const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
17451755 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
17461756
17471757 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
......@@ -1810,7 +1820,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
18101820 return error.MissingDebugInfo;
18111821 },
18121822 DW.LNE_set_address => {
1813 const addr = try di.dwarf_in_stream.readInt(di.elf.endian, usize);
1823 const addr = try di.dwarf_in_stream.readInt(di.endian, usize);
18141824 prog.address = addr;
18151825 },
18161826 DW.LNE_define_file => {
......@@ -1872,7 +1882,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
18721882 prog.address += inc_addr;
18731883 },
18741884 DW.LNS_fixed_advance_pc => {
1875 const arg = try di.dwarf_in_stream.readInt(di.elf.endian, u16);
1885 const arg = try di.dwarf_in_stream.readInt(di.endian, u16);
18761886 prog.address += arg;
18771887 },
18781888 DW.LNS_set_prologue_end => {},
......@@ -1891,7 +1901,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
18911901 return error.MissingDebugInfo;
18921902}
18931903
1894fn scanAllCompileUnits(di: *DebugInfo) !void {
1904fn scanAllCompileUnits(di: *DwarfInfo) !void {
18951905 const debug_info_end = di.debug_info.offset + di.debug_info.size;
18961906 var this_unit_offset = di.debug_info.offset;
18971907 var cu_index: usize = 0;
......@@ -1904,10 +1914,10 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {
19041914 if (unit_length == 0) return;
19051915 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));
19061916
1907 const version = try di.dwarf_in_stream.readInt(di.elf.endian, u16);
1917 const version = try di.dwarf_in_stream.readInt(di.endian, u16);
19081918 if (version < 2 or version > 5) return error.InvalidDebugInfo;
19091919
1910 const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.elf.endian, u64) else try di.dwarf_in_stream.readInt(di.elf.endian, u32);
1920 const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(di.endian, u64) else try di.dwarf_in_stream.readInt(di.endian, u32);
19111921
19121922 const address_size = try di.dwarf_in_stream.readByte();
19131923 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
......@@ -1958,7 +1968,7 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {
19581968 }
19591969}
19601970
1961fn findCompileUnit(di: *DebugInfo, target_address: u64) !*const CompileUnit {
1971fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
19621972 for (di.compile_unit_list.toSlice()) |*compile_unit| {
19631973 if (compile_unit.pc_range) |range| {
19641974 if (target_address >= range.start and target_address < range.end) return compile_unit;