diff options
Diffstat (limited to 'std/debug')
| -rw-r--r-- | std/debug/index.zig | 451 |
1 files changed, 235 insertions, 216 deletions
diff --git a/std/debug/index.zig b/std/debug/index.zig index c317432654..4a96e9d259 100644 --- a/std/debug/index.zig +++ b/std/debug/index.zig @@ -198,49 +198,44 @@ pub fn writeStackTrace(stack_trace: *const builtin.StackTrace, out_stream: var, } } -pub inline fn getReturnAddress(frame_count: usize) usize { - var fp = @ptrToInt(@frameAddress()); - var i: usize = 0; - while (fp != 0 and i < frame_count) { - fp = @intToPtr(*const usize, fp).*; - i += 1; +pub const StackIterator = struct { + first_addr: ?usize, + fp: usize, + + pub fn init(first_addr: ?usize) StackIterator { + return StackIterator{ + .first_addr = first_addr, + .fp = @ptrToInt(@frameAddress()), + }; } - return @intToPtr(*const usize, fp + @sizeOf(usize)).*; -} + + fn next(self: *StackIterator) ?usize { + if (self.fp == 0) return null; + self.fp = @intToPtr(*const usize, self.fp).*; + if (self.fp == 0) return null; + + if (self.first_addr) |addr| { + while (self.fp != 0) : (self.fp = @intToPtr(*const usize, self.fp).*) { + const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; + if (addr == return_address) { + self.first_addr = null; + return return_address; + } + } + } + + const return_address = @intToPtr(*const usize, self.fp + @sizeOf(usize)).*; + return return_address; + } +}; pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void { switch (builtin.os) { builtin.Os.windows => return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr), else => {}, } - const AddressState = union(enum) { - NotLookingForStartAddress, - LookingForStartAddress: usize, - }; - // TODO: I want to express like this: - //var addr_state = if (start_addr) |addr| AddressState { .LookingForStartAddress = addr } - // else AddressState.NotLookingForStartAddress; - var addr_state: AddressState = undefined; - if (start_addr) |addr| { - addr_state = AddressState{ .LookingForStartAddress = addr }; - } else { - addr_state = AddressState.NotLookingForStartAddress; - } - - var fp = @ptrToInt(@frameAddress()); - while (fp != 0) : (fp = @intToPtr(*const usize, fp).*) { - const return_address = @intToPtr(*const usize, fp + @sizeOf(usize)).*; - - switch (addr_state) { - AddressState.NotLookingForStartAddress => {}, - AddressState.LookingForStartAddress => |addr| { - if (return_address == addr) { - addr_state = AddressState.NotLookingForStartAddress; - } else { - continue; - } - }, - } + var it = StackIterator.init(start_addr); + while (it.next()) |return_address| { try printSourceAtAddress(debug_info, out_stream, return_address, tty_color); } } @@ -284,7 +279,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres const mod_index = for (di.sect_contribs) |sect_contrib| { if (sect_contrib.Section > di.coff.sections.len) continue; // Remember that SectionContribEntry.Section is 1-based. - coff_section = &di.coff.sections.toSlice()[sect_contrib.Section-1]; + coff_section = &di.coff.sections.toSlice()[sect_contrib.Section - 1]; const vaddr_start = coff_section.header.virtual_address + sect_contrib.Offset; const vaddr_end = vaddr_start + sect_contrib.Size; @@ -414,7 +409,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres if (opt_line_info) |line_info| { try out_stream.print("\n"); - if (printLineFromFile(out_stream, line_info)) { + if (printLineFromFileAnyOs(out_stream, line_info)) { if (line_info.column == 0) { try out_stream.write("\n"); } else { @@ -598,7 +593,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt } else "???"; if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| { defer line_info.deinit(); - try printLineInfo(di, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color); + try printLineInfo( + out_stream, + line_info, + address, + symbol_name, + compile_unit_name, + tty_color, + printLineFromFileAnyOs, + ); } else |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => { if (tty_color) { @@ -611,7 +614,15 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt } } -pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { +/// This function works in freestanding mode. +/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void +pub fn printSourceAtAddressDwarf( + debug_info: *DwarfInfo, + out_stream: var, + address: usize, + tty_color: bool, + comptime printLineFromFile: var, +) !void { const compile_unit = findCompileUnit(debug_info, address) catch { if (tty_color) { try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", address); @@ -621,10 +632,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres return; }; const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); - if (getLineNumberInfoLinux(debug_info, compile_unit, address - 1)) |line_info| { + if (getLineNumberInfoDwarf(debug_info, compile_unit.*, address - 1)) |line_info| { defer line_info.deinit(); const symbol_name = "???"; - try printLineInfo(debug_info, out_stream, line_info, address, symbol_name, compile_unit_name, tty_color); + try printLineInfo( + out_stream, + line_info, + address, + symbol_name, + compile_unit_name, + tty_color, + printLineFromFile, + ); } else |err| switch (err) { error.MissingDebugInfo, error.InvalidDebugInfo => { if (tty_color) { @@ -637,14 +656,18 @@ pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, addres } } +pub fn printSourceAtAddressLinux(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void { + return printSourceAtAddressDwarf(debug_info, out_stream, address, tty_color, printLineFromFileAnyOs); +} + fn printLineInfo( - debug_info: *DebugInfo, out_stream: var, line_info: LineInfo, address: usize, symbol_name: []const u8, compile_unit_name: []const u8, tty_color: bool, + comptime printLineFromFile: var, ) !void { if (tty_color) { try out_stream.print( @@ -872,55 +895,68 @@ fn readSparseBitVector(stream: var, allocator: *mem.Allocator) ![]usize { return list.toOwnedSlice(); } -fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DebugInfo { - var di = DebugInfo{ - .self_exe_file = undefined, - .elf = undefined, - .debug_info = undefined, - .debug_abbrev = undefined, - .debug_str = undefined, - .debug_line = undefined, - .debug_ranges = null, - .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), - .compile_unit_list = ArrayList(CompileUnit).init(allocator), +fn findDwarfSectionFromElf(elf_file: *elf.Elf, name: []const u8) !?DwarfInfo.Section { + const elf_header = (try elf_file.findSection(name)) orelse return null; + return DwarfInfo.Section{ + .offset = elf_header.offset, + .size = elf_header.size, }; - di.self_exe_file = try os.openSelfExe(); - errdefer di.self_exe_file.close(); - - try di.elf.openFile(allocator, di.self_exe_file); - errdefer di.elf.close(); - - di.debug_info = (try di.elf.findSection(".debug_info")) orelse return error.MissingDebugInfo; - di.debug_abbrev = (try di.elf.findSection(".debug_abbrev")) orelse return error.MissingDebugInfo; - di.debug_str = (try di.elf.findSection(".debug_str")) orelse return error.MissingDebugInfo; - di.debug_line = (try di.elf.findSection(".debug_line")) orelse return error.MissingDebugInfo; - di.debug_ranges = (try di.elf.findSection(".debug_ranges")); - try scanAllCompileUnits(&di); - return di; } -pub fn findElfSection(elf: *Elf, name: []const u8) ?*elf.Shdr { - var file_stream = elf.in_file.inStream(); - const in = &file_stream.stream; - - section_loop: for (elf.section_headers) |*elf_section| { - if (elf_section.sh_type == SHT_NULL) continue; - - const name_offset = elf.string_section.offset + elf_section.name; - try elf.in_file.seekTo(name_offset); - - for (name) |expected_c| { - const target_c = try in.readByte(); - if (target_c == 0 or expected_c != target_c) continue :section_loop; - } +/// Initialize DWARF info. The caller has the responsibility to initialize most +/// the DwarfInfo fields before calling. These fields can be left undefined: +/// * abbrev_table_list +/// * compile_unit_list +pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void { + di.abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator); + di.compile_unit_list = ArrayList(CompileUnit).init(allocator); + try scanAllCompileUnits(di); +} - { - const null_byte = try in.readByte(); - if (null_byte == 0) return elf_section; - } - } +pub fn openElfDebugInfo( + allocator: *mem.Allocator, + elf_seekable_stream: *DwarfSeekableStream, + elf_in_stream: *DwarfInStream, +) !DwarfInfo { + var efile: elf.Elf = undefined; + try efile.openStream(allocator, elf_seekable_stream, elf_in_stream); + errdefer efile.close(); + + var di = DwarfInfo{ + .dwarf_seekable_stream = elf_seekable_stream, + .dwarf_in_stream = elf_in_stream, + .endian = efile.endian, + .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo, + .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo, + .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo, + .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo, + .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")), + .abbrev_table_list = undefined, + .compile_unit_list = undefined, + }; + try openDwarfDebugInfo(&di, allocator); + return di; +} - return null; +fn openSelfDebugInfoLinux(allocator: *mem.Allocator) !DwarfInfo { + const S = struct { + var self_exe_file: os.File = undefined; + var self_exe_seekable_stream: os.File.SeekableStream = undefined; + var self_exe_in_stream: os.File.InStream = undefined; + }; + S.self_exe_file = try os.openSelfExe(); + errdefer S.self_exe_file.close(); + + S.self_exe_seekable_stream = S.self_exe_file.seekableStream(); + S.self_exe_in_stream = S.self_exe_file.inStream(); + + return openElfDebugInfo( + allocator, + // TODO https://github.com/ziglang/zig/issues/764 + @ptrCast(*DwarfSeekableStream, &S.self_exe_seekable_stream.stream), + // TODO https://github.com/ziglang/zig/issues/764 + @ptrCast(*DwarfInStream, &S.self_exe_in_stream.stream), + ); } fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { @@ -1000,7 +1036,7 @@ fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo { }; } -fn printLineFromFile(out_stream: var, line_info: LineInfo) !void { +fn printLineFromFileAnyOs(out_stream: var, line_info: LineInfo) !void { var f = try os.File.openRead(line_info.file_name); defer f.close(); // TODO fstat and make sure that the file has the correct size @@ -1053,6 +1089,35 @@ const MachOFile = struct { sect_debug_line: ?*const macho.section_64, }; +pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror); +pub const DwarfInStream = io.InStream(anyerror); + +pub const DwarfInfo = struct { + dwarf_seekable_stream: *DwarfSeekableStream, + dwarf_in_stream: *DwarfInStream, + endian: builtin.Endian, + debug_info: Section, + debug_abbrev: Section, + debug_str: Section, + debug_line: Section, + debug_ranges: ?Section, + abbrev_table_list: ArrayList(AbbrevTableHeader), + compile_unit_list: ArrayList(CompileUnit), + + pub const Section = struct { + offset: usize, + size: usize, + }; + + pub fn allocator(self: DwarfInfo) *mem.Allocator { + return self.abbrev_table_list.allocator; + } + + pub fn readString(self: *DwarfInfo) ![]u8 { + return readStringRaw(self.allocator(), self.dwarf_in_stream); + } +}; + pub const DebugInfo = switch (builtin.os) { builtin.Os.macosx => struct { symbols: []const MachoSymbol, @@ -1076,32 +1141,7 @@ pub const DebugInfo = switch (builtin.os) { sect_contribs: []pdb.SectionContribEntry, modules: []Module, }, - builtin.Os.linux => struct { - self_exe_file: os.File, - elf: elf.Elf, - debug_info: *elf.SectionHeader, - debug_abbrev: *elf.SectionHeader, - debug_str: *elf.SectionHeader, - debug_line: *elf.SectionHeader, - debug_ranges: ?*elf.SectionHeader, - abbrev_table_list: ArrayList(AbbrevTableHeader), - compile_unit_list: ArrayList(CompileUnit), - - pub fn allocator(self: DebugInfo) *mem.Allocator { - return self.abbrev_table_list.allocator; - } - - pub fn readString(self: *DebugInfo) ![]u8 { - var in_file_stream = self.self_exe_file.inStream(); - const in_stream = &in_file_stream.stream; - return readStringRaw(self.allocator(), in_stream); - } - - pub fn close(self: *DebugInfo) void { - self.self_exe_file.close(); - self.elf.close(); - } - }, + builtin.Os.linux => DwarfInfo, builtin.Os.freebsd => struct {}, else => @compileError("Unsupported OS"), }; @@ -1206,11 +1246,11 @@ const Die = struct { }; } - fn getAttrString(self: *const Die, st: *DebugInfo, id: u64) ![]u8 { + fn getAttrString(self: *const Die, di: *DwarfInfo, id: u64) ![]u8 { const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; return switch (form_value.*) { FormValue.String => |value| value, - FormValue.StrPtr => |offset| getString(st, offset), + FormValue.StrPtr => |offset| getString(di, offset), else => error.InvalidDebugInfo, }; } @@ -1223,14 +1263,15 @@ const FileEntry = struct { len_bytes: usize, }; -const LineInfo = struct { +pub const LineInfo = struct { line: usize, column: usize, - file_name: []u8, - allocator: *mem.Allocator, + file_name: []const u8, + allocator: ?*mem.Allocator, - fn deinit(self: *const LineInfo) void { - self.allocator.free(self.file_name); + fn deinit(self: LineInfo) void { + const allocator = self.allocator orelse return; + allocator.free(self.file_name); } }; @@ -1321,10 +1362,10 @@ fn readStringRaw(allocator: *mem.Allocator, in_stream: var) ![]u8 { return buf.toSlice(); } -fn getString(st: *DebugInfo, offset: u64) ![]u8 { - const pos = st.debug_str.offset + offset; - try st.self_exe_file.seekTo(pos); - return st.readString(); +fn getString(di: *DwarfInfo, offset: u64) ![]u8 { + const pos = di.debug_str.offset + offset; + try di.dwarf_seekable_stream.seekTo(pos); + return di.readString(); } fn readAllocBytes(allocator: *mem.Allocator, in_stream: var, size: usize) ![]u8 { @@ -1371,14 +1412,7 @@ fn parseFormValueRef(allocator: *mem.Allocator, in_stream: var, comptime T: type return parseFormValueRefLen(allocator, in_stream, block_len); } -const ParseFormValueError = error{ - EndOfStream, - InvalidDebugInfo, - EndOfFile, - OutOfMemory, -} || std.os.File.ReadError; - -fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) ParseFormValueError!FormValue { +fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64: bool) anyerror!FormValue { return switch (form_id) { DW.FORM_addr => FormValue{ .Address = try parseFormValueTargetAddrSize(in_stream) }, DW.FORM_block1 => parseFormValueBlock(allocator, in_stream, 1), @@ -1428,25 +1462,22 @@ fn parseFormValue(allocator: *mem.Allocator, in_stream: var, form_id: u64, is_64 }; } -fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { - const in_file = st.self_exe_file; - var in_file_stream = in_file.inStream(); - const in_stream = &in_file_stream.stream; - var result = AbbrevTable.init(st.allocator()); +fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable { + var result = AbbrevTable.init(di.allocator()); while (true) { - const abbrev_code = try readULeb128(in_stream); + const abbrev_code = try readULeb128(di.dwarf_in_stream); if (abbrev_code == 0) return result; try result.append(AbbrevTableEntry{ .abbrev_code = abbrev_code, - .tag_id = try readULeb128(in_stream), - .has_children = (try in_stream.readByte()) == DW.CHILDREN_yes, - .attrs = ArrayList(AbbrevAttr).init(st.allocator()), + .tag_id = try readULeb128(di.dwarf_in_stream), + .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes, + .attrs = ArrayList(AbbrevAttr).init(di.allocator()), }); const attrs = &result.items[result.len - 1].attrs; while (true) { - const attr_id = try readULeb128(in_stream); - const form_id = try readULeb128(in_stream); + const attr_id = try readULeb128(di.dwarf_in_stream); + const form_id = try readULeb128(di.dwarf_in_stream); if (attr_id == 0 and form_id == 0) break; try attrs.append(AbbrevAttr{ .attr_id = attr_id, @@ -1458,18 +1489,18 @@ fn parseAbbrevTable(st: *DebugInfo) !AbbrevTable { /// Gets an already existing AbbrevTable given the abbrev_offset, or if not found, /// seeks in the stream and parses it. -fn getAbbrevTable(st: *DebugInfo, abbrev_offset: u64) !*const AbbrevTable { - for (st.abbrev_table_list.toSlice()) |*header| { +fn getAbbrevTable(di: *DwarfInfo, abbrev_offset: u64) !*const AbbrevTable { + for (di.abbrev_table_list.toSlice()) |*header| { if (header.offset == abbrev_offset) { return &header.table; } } - try st.self_exe_file.seekTo(st.debug_abbrev.offset + abbrev_offset); - try st.abbrev_table_list.append(AbbrevTableHeader{ + try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset); + try di.abbrev_table_list.append(AbbrevTableHeader{ .offset = abbrev_offset, - .table = try parseAbbrevTable(st), + .table = try parseAbbrevTable(di), }); - return &st.abbrev_table_list.items[st.abbrev_table_list.len - 1].table; + return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table; } fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*const AbbrevTableEntry { @@ -1479,23 +1510,20 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con return null; } -fn parseDie(st: *DebugInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { - const in_file = st.self_exe_file; - var in_file_stream = in_file.inStream(); - const in_stream = &in_file_stream.stream; - const abbrev_code = try readULeb128(in_stream); +fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !Die { + const abbrev_code = try readULeb128(di.dwarf_in_stream); const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo; var result = Die{ .tag_id = table_entry.tag_id, .has_children = table_entry.has_children, - .attrs = ArrayList(Die.Attr).init(st.allocator()), + .attrs = ArrayList(Die.Attr).init(di.allocator()), }; try result.attrs.resize(table_entry.attrs.len); for (table_entry.attrs.toSliceConst()) |attr, i| { result.attrs.items[i] = Die.Attr{ .id = attr.attr_id, - .value = try parseFormValue(st.allocator(), in_stream, attr.form_id, is_64), + .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64), }; } return result; @@ -1699,22 +1727,18 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u return error.MissingDebugInfo; } -fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, target_address: usize) !LineInfo { +fn getLineNumberInfoDwarf(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo { const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir); - const in_file = di.self_exe_file; const debug_line_end = di.debug_line.offset + di.debug_line.size; var this_offset = di.debug_line.offset; var this_index: usize = 0; - var in_file_stream = in_file.inStream(); - const in_stream = &in_file_stream.stream; - while (this_offset < debug_line_end) : (this_index += 1) { - try in_file.seekTo(this_offset); + try di.dwarf_seekable_stream.seekTo(this_offset); var is_64: bool = undefined; - const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); + const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); if (unit_length == 0) return error.MissingDebugInfo; const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); @@ -1723,35 +1747,35 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ continue; } - const version = try in_stream.readInt(di.elf.endian, u16); + const version = try di.dwarf_in_stream.readInt(di.endian, u16); // TODO support 3 and 5 if (version != 2 and version != 4) return error.InvalidDebugInfo; - const prologue_length = if (is_64) try in_stream.readInt(di.elf.endian, u64) else try in_stream.readInt(di.elf.endian, u32); - const prog_start_offset = (try in_file.getPos()) + prologue_length; + 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); + const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length; - const minimum_instruction_length = try in_stream.readByte(); + const minimum_instruction_length = try di.dwarf_in_stream.readByte(); if (minimum_instruction_length == 0) return error.InvalidDebugInfo; if (version >= 4) { // maximum_operations_per_instruction - _ = try in_stream.readByte(); + _ = try di.dwarf_in_stream.readByte(); } - const default_is_stmt = (try in_stream.readByte()) != 0; - const line_base = try in_stream.readByteSigned(); + const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0; + const line_base = try di.dwarf_in_stream.readByteSigned(); - const line_range = try in_stream.readByte(); + const line_range = try di.dwarf_in_stream.readByte(); if (line_range == 0) return error.InvalidDebugInfo; - const opcode_base = try in_stream.readByte(); + const opcode_base = try di.dwarf_in_stream.readByte(); const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1); { var i: usize = 0; while (i < opcode_base - 1) : (i += 1) { - standard_opcode_lengths[i] = try in_stream.readByte(); + standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte(); } } @@ -1769,9 +1793,9 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ while (true) { const file_name = try di.readString(); if (file_name.len == 0) break; - const dir_index = try readULeb128(in_stream); - const mtime = try readULeb128(in_stream); - const len_bytes = try readULeb128(in_stream); + const dir_index = try readULeb128(di.dwarf_in_stream); + const mtime = try readULeb128(di.dwarf_in_stream); + const len_bytes = try readULeb128(di.dwarf_in_stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1780,15 +1804,15 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ }); } - try in_file.seekTo(prog_start_offset); + try di.dwarf_seekable_stream.seekTo(prog_start_offset); while (true) { - const opcode = try in_stream.readByte(); + const opcode = try di.dwarf_in_stream.readByte(); if (opcode == DW.LNS_extended_op) { - const op_size = try readULeb128(in_stream); + const op_size = try readULeb128(di.dwarf_in_stream); if (op_size < 1) return error.InvalidDebugInfo; - var sub_op = try in_stream.readByte(); + var sub_op = try di.dwarf_in_stream.readByte(); switch (sub_op) { DW.LNE_end_sequence => { prog.end_sequence = true; @@ -1796,14 +1820,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ return error.MissingDebugInfo; }, DW.LNE_set_address => { - const addr = try in_stream.readInt(di.elf.endian, usize); + const addr = try di.dwarf_in_stream.readInt(di.endian, usize); prog.address = addr; }, DW.LNE_define_file => { const file_name = try di.readString(); - const dir_index = try readULeb128(in_stream); - const mtime = try readULeb128(in_stream); - const len_bytes = try readULeb128(in_stream); + const dir_index = try readULeb128(di.dwarf_in_stream); + const mtime = try readULeb128(di.dwarf_in_stream); + const len_bytes = try readULeb128(di.dwarf_in_stream); try file_entries.append(FileEntry{ .file_name = file_name, .dir_index = dir_index, @@ -1813,7 +1837,7 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ }, else => { const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo; - try in_file.seekForward(fwd_amt); + try di.dwarf_seekable_stream.seekForward(fwd_amt); }, } } else if (opcode >= opcode_base) { @@ -1832,19 +1856,19 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ prog.basic_block = false; }, DW.LNS_advance_pc => { - const arg = try readULeb128(in_stream); + const arg = try readULeb128(di.dwarf_in_stream); prog.address += arg * minimum_instruction_length; }, DW.LNS_advance_line => { - const arg = try readILeb128(in_stream); + const arg = try readILeb128(di.dwarf_in_stream); prog.line += arg; }, DW.LNS_set_file => { - const arg = try readULeb128(in_stream); + const arg = try readULeb128(di.dwarf_in_stream); prog.file = arg; }, DW.LNS_set_column => { - const arg = try readULeb128(in_stream); + const arg = try readULeb128(di.dwarf_in_stream); prog.column = arg; }, DW.LNS_negate_stmt => { @@ -1858,14 +1882,14 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ prog.address += inc_addr; }, DW.LNS_fixed_advance_pc => { - const arg = try in_stream.readInt(di.elf.endian, u16); + const arg = try di.dwarf_in_stream.readInt(di.endian, u16); prog.address += arg; }, DW.LNS_set_prologue_end => {}, else => { if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo; const len_bytes = standard_opcode_lengths[opcode - 1]; - try in_file.seekForward(len_bytes); + try di.dwarf_seekable_stream.seekForward(len_bytes); }, } } @@ -1877,36 +1901,33 @@ fn getLineNumberInfoLinux(di: *DebugInfo, compile_unit: *const CompileUnit, targ return error.MissingDebugInfo; } -fn scanAllCompileUnits(st: *DebugInfo) !void { - const debug_info_end = st.debug_info.offset + st.debug_info.size; - var this_unit_offset = st.debug_info.offset; +fn scanAllCompileUnits(di: *DwarfInfo) !void { + const debug_info_end = di.debug_info.offset + di.debug_info.size; + var this_unit_offset = di.debug_info.offset; var cu_index: usize = 0; - var in_file_stream = st.self_exe_file.inStream(); - const in_stream = &in_file_stream.stream; - while (this_unit_offset < debug_info_end) { - try st.self_exe_file.seekTo(this_unit_offset); + try di.dwarf_seekable_stream.seekTo(this_unit_offset); var is_64: bool = undefined; - const unit_length = try readInitialLength(@typeOf(in_stream.readFn).ReturnType.ErrorSet, in_stream, &is_64); + const unit_length = try readInitialLength(@typeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64); if (unit_length == 0) return; const next_offset = unit_length + (if (is_64) usize(12) else usize(4)); - const version = try in_stream.readInt(st.elf.endian, u16); + const version = try di.dwarf_in_stream.readInt(di.endian, u16); if (version < 2 or version > 5) return error.InvalidDebugInfo; - const debug_abbrev_offset = if (is_64) try in_stream.readInt(st.elf.endian, u64) else try in_stream.readInt(st.elf.endian, u32); + 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); - const address_size = try in_stream.readByte(); + const address_size = try di.dwarf_in_stream.readByte(); if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo; - const compile_unit_pos = try st.self_exe_file.getPos(); - const abbrev_table = try getAbbrevTable(st, debug_abbrev_offset); + const compile_unit_pos = try di.dwarf_seekable_stream.getPos(); + const abbrev_table = try getAbbrevTable(di, debug_abbrev_offset); - try st.self_exe_file.seekTo(compile_unit_pos); + try di.dwarf_seekable_stream.seekTo(compile_unit_pos); - const compile_unit_die = try st.allocator().create(try parseDie(st, abbrev_table, is_64)); + const compile_unit_die = try di.allocator().create(try parseDie(di, abbrev_table, is_64)); if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo; @@ -1934,7 +1955,7 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { } }; - try st.compile_unit_list.append(CompileUnit{ + try di.compile_unit_list.append(CompileUnit{ .version = version, .is_64 = is_64, .pc_range = pc_range, @@ -1947,20 +1968,18 @@ fn scanAllCompileUnits(st: *DebugInfo) !void { } } -fn findCompileUnit(st: *DebugInfo, target_address: u64) !*const CompileUnit { - var in_file_stream = st.self_exe_file.inStream(); - const in_stream = &in_file_stream.stream; - for (st.compile_unit_list.toSlice()) |*compile_unit| { +fn findCompileUnit(di: *DwarfInfo, target_address: u64) !*const CompileUnit { + for (di.compile_unit_list.toSlice()) |*compile_unit| { if (compile_unit.pc_range) |range| { if (target_address >= range.start and target_address < range.end) return compile_unit; } if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| { var base_address: usize = 0; - if (st.debug_ranges) |debug_ranges| { - try st.self_exe_file.seekTo(debug_ranges.offset + ranges_offset); + if (di.debug_ranges) |debug_ranges| { + try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset); while (true) { - const begin_addr = try in_stream.readIntLe(usize); - const end_addr = try in_stream.readIntLe(usize); + const begin_addr = try di.dwarf_in_stream.readIntLe(usize); + const end_addr = try di.dwarf_in_stream.readIntLe(usize); if (begin_addr == 0 and end_addr == 0) { break; } |
