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
signature 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,...@@ -200,12 +200,10 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var,
200200
201pub const StackIterator = struct {201pub const StackIterator = struct {
202 first_addr: ?usize,202 first_addr: ?usize,
203 debug_info: *DebugInfo,
204 fp: usize,203 fp: usize,
205204
206 pub fn init(debug_info: *DebugInfo, first_addr: ?usize) StackIterator {205 pub fn init(first_addr: ?usize) StackIterator {
207 return StackIterator{206 return StackIterator{
208 .debug_info = debug_info,
209 .first_addr = first_addr,207 .first_addr = first_addr,
210 .fp = @ptrToInt(@frameAddress()),208 .fp = @ptrToInt(@frameAddress()),
211 };209 };
...@@ -236,7 +234,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color...@@ -236,7 +234,7 @@ pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color
236 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),234 builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr),
237 else => {},235 else => {},
238 }236 }
239 var it = StackIterator.init(debug_info, start_addr);237 var it = StackIterator.init(start_addr);
240 while (it.next()) |return_address| {238 while (it.next()) |return_address| {
241 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);239 try printSourceAtAddress(debug_info, out_stream, return_address, tty_color);
242 }240 }
...@@ -596,7 +594,6 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt...@@ -596,7 +594,6 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
596 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {594 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
597 defer line_info.deinit();595 defer line_info.deinit();
598 try printLineInfo(596 try printLineInfo(
599 di,
600 out_stream,597 out_stream,
601 line_info,598 line_info,
602 address,599 address,
...@@ -620,7 +617,7 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt...@@ -620,7 +617,7 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
620/// This function works in freestanding mode.617/// This function works in freestanding mode.
621/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void618/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void
622pub fn printSourceAtAddressDwarf(619pub fn printSourceAtAddressDwarf(
623 debug_info: *DebugInfo,620 debug_info: *DwarfInfo,
624 out_stream: var,621 out_stream: var,
625 address: usize,622 address: usize,
626 tty_color: bool,623 tty_color: bool,
...@@ -639,7 +636,6 @@ pub fn printSourceAtAddressDwarf(...@@ -639,7 +636,6 @@ pub fn printSourceAtAddressDwarf(
639 defer line_info.deinit();636 defer line_info.deinit();
640 const symbol_name = "???";637 const symbol_name = "???";
641 try printLineInfo(638 try printLineInfo(
642 debug_info,
643 out_stream,639 out_stream,
644 line_info,640 line_info,
645 address,641 address,
...@@ -665,7 +661,6 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres...@@ -665,7 +661,6 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres
665}661}
666662
667fn printLineInfo(663fn printLineInfo(
668 debug_info: *DebugInfo,
669 out_stream: var,664 out_stream: var,
670 line_info: LineInfo,665 line_info: LineInfo,
671 address: usize,666 address: usize,
...@@ -900,36 +895,50 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {...@@ -900,36 +895,50 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize {
900 return list.toOwnedSlice();895 return list.toOwnedSlice();
901}896}
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(
904 allocator: *mem.Allocator,917 allocator: *mem.Allocator,
905 dwarf_seekable_stream: *DwarfSeekableStream,918 elf_seekable_stream: *DwarfSeekableStream,
906 dwarf_in_stream: *DwarfInStream,919 elf_in_stream: *DwarfInStream,
907) !DebugInfo {920) !DwarfInfo {
908 var di = DebugInfo{921 var efile: elf.Elf = undefined;
909 .dwarf_seekable_stream = dwarf_seekable_stream,922 try efile.openStream(allocator, elf_seekable_stream, elf_in_stream);
910 .dwarf_in_stream = dwarf_in_stream,923 errdefer efile.close();
911 .elf = undefined,924
912 .debug_info = undefined,925 var di = DwarfInfo{
913 .debug_abbrev = undefined,926 .dwarf_seekable_stream = elf_seekable_stream,
914 .debug_str = undefined,927 .dwarf_in_stream = elf_in_stream,
915 .debug_line = undefined,928 .endian = efile.endian,
916 .debug_ranges = null,929 .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
917 .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator),930 .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
918 .compile_unit_list = ArrayList(CompileUnit).init(allocator),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,
919 };936 };
920 try di.elf.openStream(allocator, dwarf_seekable_stream, dwarf_in_stream);937 try openDwarfDebugInfo(&di, allocator);
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);
929 return di;938 return di;
930}939}
931940
932fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {941fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo {
933 const S = struct {942 const S = struct {
934 var self_exe_file: os.File = undefined;943 var self_exe_file: os.File = undefined;
935 var self_exe_seekable_stream: os.File.SeekableStream = undefined;944 var self_exe_seekable_stream: os.File.SeekableStream = undefined;
...@@ -941,7 +950,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {...@@ -941,7 +950,7 @@ fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo {
941 S.self_exe_seekable_stream = S.self_exe_file.seekableStream();950 S.self_exe_seekable_stream = S.self_exe_file.seekableStream();
942 S.self_exe_in_stream = S.self_exe_file.inStream();951 S.self_exe_in_stream = S.self_exe_file.inStream();
943952
944 return openDwarfDebugInfo(953 return openElfDebugInfo(
945 allocator,954 allocator,
946 // TODO https://github.com/ziglang/zig/issues/764955 // TODO https://github.com/ziglang/zig/issues/764
947 @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),956 @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream),
...@@ -1086,26 +1095,27 @@ pub const DwarfInStream = io.InStream(anyerror);...@@ -1086,26 +1095,27 @@ pub const DwarfInStream = io.InStream(anyerror);
1086pub const DwarfInfo = struct {1095pub const DwarfInfo = struct {
1087 dwarf_seekable_stream: *DwarfSeekableStream,1096 dwarf_seekable_stream: *DwarfSeekableStream,
1088 dwarf_in_stream: *DwarfInStream,1097 dwarf_in_stream: *DwarfInStream,
1089 elf: elf.Elf,1098 endian: builtin.Endian,
1090 debug_info: *elf.SectionHeader,1099 debug_info: Section,
1091 debug_abbrev: *elf.SectionHeader,1100 debug_abbrev: Section,
1092 debug_str: *elf.SectionHeader,1101 debug_str: Section,
1093 debug_line: *elf.SectionHeader,1102 debug_line: Section,
1094 debug_ranges: ?*elf.SectionHeader,1103 debug_ranges: ?Section,
1095 abbrev_table_list: ArrayList(AbbrevTableHeader),1104 abbrev_table_list: ArrayList(AbbrevTableHeader),
1096 compile_unit_list: ArrayList(CompileUnit),1105 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 {
1099 return self.abbrev_table_list.allocator;1113 return self.abbrev_table_list.allocator;
1100 }1114 }
11011115
1102 pub fn readString(self: *DebugInfo) ![]u8 {1116 pub fn readString(self: *DwarfInfo) ![]u8 {
1103 return readStringRaw(self.allocator(), self.dwarf_in_stream);1117 return readStringRaw(self.allocator(), self.dwarf_in_stream);
1104 }1118 }
1105
1106 pub fn close(self: *DebugInfo) void {
1107 self.elf.close();
1108 }
1109};1119};
11101120
1111pub const DebugInfo = switch (builtin.os) {1121pub const DebugInfo = switch (builtin.os) {
...@@ -1236,7 +1246,7 @@ const Die = struct {...@@ -1236,7 +1246,7 @@ const Die = struct {
1236 };1246 };
1237 }1247 }
12381248
1239 fn getAttrString(self: *const Die, di: *DebugInfo, id: u64) ![]u8 {1249 fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 {
1240 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;1250 const form_value = self.getAttr(id) orelse return error.MissingDebugInfo;
1241 return switch (form_value.*) {1251 return switch (form_value.*) {
1242 FormValue.String => |value| value,1252 FormValue.String => |value| value,
...@@ -1253,7 +1263,7 @@ const FileEntry = struct {...@@ -1253,7 +1263,7 @@ const FileEntry = struct {
1253 len_bytes: usize,1263 len_bytes: usize,
1254};1264};
12551265
1256const LineInfo = struct {1266pub const LineInfo = struct {
1257 line: usize,1267 line: usize,
1258 column: usize,1268 column: usize,
1259 file_name: []const u8,1269 file_name: []const u8,
...@@ -1352,7 +1362,7 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {...@@ -1352,7 +1362,7 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 {
1352 return buf.toSlice();1362 return buf.toSlice();
1353}1363}
13541364
1355fn getString(di: *DebugInfo, offset: u64) ![]u8 {1365fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
1356 const pos = di.debug_str.offset + offset;1366 const pos = di.debug_str.offset + offset;
1357 try di.dwarf_seekable_stream.seekTo(pos);1367 try di.dwarf_seekable_stream.seekTo(pos);
1358 return di.readString();1368 return di.readString();
...@@ -1452,7 +1462,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64...@@ -1452,7 +1462,7 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64
1452 };1462 };
1453}1463}
14541464
1455fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable {1465fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
1456 var result = AbbrevTable.init(di.allocator());1466 var result = AbbrevTable.init(di.allocator());
1457 while (true) {1467 while (true) {
1458 const abbrev_code = try readULeb128(di.dwarf_in_stream);1468 const abbrev_code = try readULeb128(di.dwarf_in_stream);
...@@ -1479,7 +1489,7 @@ fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable {...@@ -1479,7 +1489,7 @@ fn parseAbbrevTable(di: *DebugInfo) !AbbrevTable {
14791489
1480/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,1490/// Gets an already existing AbbrevTable given the abbrev_offset, or if not found,
1481/// seeks in the stream and parses it.1491/// 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 {
1483 for (di.abbrev_table_list.toSlice()) |*header| {1493 for (di.abbrev_table_list.toSlice()) |*header| {
1484 if (header.offset == abbrev_offset) {1494 if (header.offset == abbrev_offset) {
1485 return &header.table;1495 return &header.table;
...@@ -1500,7 +1510,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con...@@ -1500,7 +1510,7 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
1500 return null;1510 return null;
1501}1511}
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 {
1504 const abbrev_code = try readULeb128(di.dwarf_in_stream);1514 const abbrev_code = try readULeb128(di.dwarf_in_stream);
1505 const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;1515 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...@@ -1717,7 +1727,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1717 return error.MissingDebugInfo;1727 return error.MissingDebugInfo;
1718}1728}
17191729
1720fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {1730fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
1721 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);1731 const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
17221732
1723 const debug_line_end = di.debug_line.offset + di.debug_line.size;1733 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...@@ -1737,11 +1747,11 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
1737 continue;1747 continue;
1738 }1748 }
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);
1741 // TODO support 3 and 51751 // TODO support 3 and 5
1742 if (version != 2 and version != 4) return error.InvalidDebugInfo;1752 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);
1745 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;1755 const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
17461756
1747 const minimum_instruction_length = try di.dwarf_in_stream.readByte();1757 const minimum_instruction_length = try di.dwarf_in_stream.readByte();
...@@ -1810,7 +1820,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr...@@ -1810,7 +1820,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
1810 return error.MissingDebugInfo;1820 return error.MissingDebugInfo;
1811 },1821 },
1812 DW.LNE_set_address => {1822 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);
1814 prog.address = addr;1824 prog.address = addr;
1815 },1825 },
1816 DW.LNE_define_file => {1826 DW.LNE_define_file => {
...@@ -1872,7 +1882,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr...@@ -1872,7 +1882,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
1872 prog.address += inc_addr;1882 prog.address += inc_addr;
1873 },1883 },
1874 DW.LNS_fixed_advance_pc => {1884 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);
1876 prog.address += arg;1886 prog.address += arg;
1877 },1887 },
1878 DW.LNS_set_prologue_end => {},1888 DW.LNS_set_prologue_end => {},
...@@ -1891,7 +1901,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr...@@ -1891,7 +1901,7 @@ fn getLineNumberInfoDwarf(di: *DebugInfo, compile_unit: CompileUnit, target_addr
1891 return error.MissingDebugInfo;1901 return error.MissingDebugInfo;
1892}1902}
18931903
1894fn scanAllCompileUnits(di: *DebugInfo) !void {1904fn scanAllCompileUnits(di: *DwarfInfo) !void {
1895 const debug_info_end = di.debug_info.offset + di.debug_info.size;1905 const debug_info_end = di.debug_info.offset + di.debug_info.size;
1896 var this_unit_offset = di.debug_info.offset;1906 var this_unit_offset = di.debug_info.offset;
1897 var cu_index: usize = 0;1907 var cu_index: usize = 0;
...@@ -1904,10 +1914,10 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {...@@ -1904,10 +1914,10 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {
1904 if (unit_length == 0) return;1914 if (unit_length == 0) return;
1905 const next_offset = unit_length + (if (is_64) usize(12) else usize(4));1915 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);
1908 if (version < 2 or version > 5) return error.InvalidDebugInfo;1918 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
1912 const address_size = try di.dwarf_in_stream.readByte();1922 const address_size = try di.dwarf_in_stream.readByte();
1913 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;1923 if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
...@@ -1958,7 +1968,7 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {...@@ -1958,7 +1968,7 @@ fn scanAllCompileUnits(di: *DebugInfo) !void {
1958 }1968 }
1959}1969}
19601970
1961fn findCompileUnit(di: *DebugInfo, target_address: u64) !*const CompileUnit {1971fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit {
1962 for (di.compile_unit_list.toSlice()) |*compile_unit| {1972 for (di.compile_unit_list.toSlice()) |*compile_unit| {
1963 if (compile_unit.pc_range) |range| {1973 if (compile_unit.pc_range) |range| {
1964 if (target_address >= range.start and target_address < range.end) return compile_unit;1974 if (target_address >= range.start and target_address < range.end) return compile_unit;