Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions lib/std/debug.zig
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const native_os = builtin.os.tag;
const native_endian = native_arch.endian();
const Writer = std.io.Writer;

pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
pub const Dwarf = @import("debug/Dwarf.zig");
pub const Pdb = @import("debug/Pdb.zig");
Expand Down Expand Up @@ -501,6 +500,11 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
// TODO: This should use the DWARF unwinder if .eh_frame_hdr is available (so that full debug info parsing isn't required).
// A new path for loading SelfInfo needs to be created which will only attempt to parse in-memory sections, because
// stopping to load other debug info (ie. source line info) from disk here is not required for unwinding.
if (builtin.cpu.arch == .powerpc64) {
// https://github.com/ziglang/zig/issues/24970
stack_trace.index = 0;
return;
}
var it = StackIterator.init(first_address, null);
defer it.deinit();
for (stack_trace.instruction_addresses, 0..) |*addr, i| {
Expand Down Expand Up @@ -773,7 +777,6 @@ pub const StackIterator = struct {
first_address: ?usize,
// Last known value of the frame pointer register.
fp: usize,
ma: MemoryAccessor = MemoryAccessor.init,

// When SelfInfo and a register context is available, this iterator can unwind
// stacks with frames that don't use a frame pointer (ie. -fomit-frame-pointer),
Expand All @@ -795,7 +798,7 @@ pub const StackIterator = struct {
::: .{ .memory = true });
}

return StackIterator{
return .{
.first_address = first_address,
// TODO: this is a workaround for #16876
//.fp = fp orelse @frameAddress(),
Expand Down Expand Up @@ -825,7 +828,6 @@ pub const StackIterator = struct {
}

pub fn deinit(it: *StackIterator) void {
it.ma.deinit();
if (have_ucontext and it.unwind_state != null) it.unwind_state.?.dwarf_context.deinit();
}

Expand Down Expand Up @@ -896,7 +898,6 @@ pub const StackIterator = struct {
unwind_state.debug_info.allocator,
module.base_address,
&unwind_state.dwarf_context,
&it.ma,
unwind_info,
module.eh_frame,
)) |return_address| {
Expand All @@ -915,7 +916,6 @@ pub const StackIterator = struct {
di,
module.base_address,
&unwind_state.dwarf_context,
&it.ma,
null,
);
} else return error.MissingDebugInfo;
Expand Down Expand Up @@ -951,16 +951,15 @@ pub const StackIterator = struct {

// Sanity check.
if (fp == 0 or !mem.isAligned(fp, @alignOf(usize))) return null;
const new_fp = math.add(usize, it.ma.load(usize, fp) orelse return null, fp_bias) catch
const new_fp = math.add(usize, @as(*usize, @ptrFromInt(fp)).*, fp_bias) catch
return null;

// Sanity check: the stack grows down thus all the parent frames must be
// be at addresses that are greater (or equal) than the previous one.
// A zero frame pointer often signals this is the last frame, that case
// is gracefully handled by the next call to next_internal.
if (new_fp != 0 and new_fp < it.fp) return null;
const new_pc = it.ma.load(usize, math.add(usize, fp, pc_offset) catch return null) orelse
return null;
const new_pc = @as(*usize, @ptrFromInt(math.add(usize, fp, pc_offset) catch return null)).*;

it.fp = new_fp;

Expand Down Expand Up @@ -1774,7 +1773,6 @@ pub inline fn inValgrind() bool {

test {
_ = &Dwarf;
_ = &MemoryAccessor;
_ = &FixedBufferReader;
_ = &Pdb;
_ = &SelfInfo;
Expand Down
59 changes: 14 additions & 45 deletions lib/std/debug/Dwarf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ const UT = DW.UT;
const assert = std.debug.assert;
const cast = std.math.cast;
const maxInt = std.math.maxInt;
const MemoryAccessor = std.debug.MemoryAccessor;
const Path = std.Build.Cache.Path;
const FixedBufferReader = std.debug.FixedBufferReader;
const ArrayList = std.ArrayList;
Expand Down Expand Up @@ -349,29 +348,9 @@ pub const ExceptionFrameHeader = struct {
};
}

fn isValidPtr(
self: ExceptionFrameHeader,
comptime T: type,
ptr: usize,
ma: *MemoryAccessor,
eh_frame_len: ?usize,
) bool {
if (eh_frame_len) |len| {
return ptr >= self.eh_frame_ptr and ptr <= self.eh_frame_ptr + len - @sizeOf(T);
} else {
return ma.load(T, ptr) != null;
}
}

/// Find an entry by binary searching the eh_frame_hdr section.
///
/// Since the length of the eh_frame section (`eh_frame_len`) may not be known by the caller,
/// MemoryAccessor will be used to verify readability of the header entries.
/// If `eh_frame_len` is provided, then these checks can be skipped.
pub fn findEntry(
self: ExceptionFrameHeader,
ma: *MemoryAccessor,
eh_frame_len: ?usize,
eh_frame_len: usize,
eh_frame_hdr_ptr: usize,
pc: usize,
cie: *CommonInformationEntry,
Expand Down Expand Up @@ -421,8 +400,7 @@ pub const ExceptionFrameHeader = struct {

if (fde_ptr < self.eh_frame_ptr) return bad();

// Even if eh_frame_len is not specified, all ranges accssed are checked via MemoryAccessor
const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0 .. eh_frame_len orelse maxInt(u32)];
const eh_frame = @as([*]const u8, @ptrFromInt(self.eh_frame_ptr))[0..eh_frame_len];

const fde_offset = fde_ptr - self.eh_frame_ptr;
var eh_frame_fbr: FixedBufferReader = .{
Expand All @@ -431,15 +409,13 @@ pub const ExceptionFrameHeader = struct {
.endian = native_endian,
};

const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame);
if (fde_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
if (fde_entry_header.type != .fde) return bad();

// CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable
const cie_offset = fde_entry_header.type.fde;
try eh_frame_fbr.seekTo(cie_offset);
const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame);
if (cie_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad();
const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, .eh_frame);
if (cie_entry_header.type != .cie) return bad();

cie.* = try CommonInformationEntry.parse(
Expand Down Expand Up @@ -486,15 +462,11 @@ pub const EntryHeader = struct {

/// Reads a header for either an FDE or a CIE, then advances the fbr to the position after the trailing structure.
/// `fbr` must be a FixedBufferReader backed by either the .eh_frame or .debug_frame sections.
pub fn read(
fbr: *FixedBufferReader,
opt_ma: ?*MemoryAccessor,
dwarf_section: Section.Id,
) !EntryHeader {
pub fn read(fbr: *FixedBufferReader, dwarf_section: Section.Id) !EntryHeader {
assert(dwarf_section == .eh_frame or dwarf_section == .debug_frame);

const length_offset = fbr.pos;
const unit_header = try readUnitHeader(fbr, opt_ma);
const unit_header = try readUnitHeader(fbr);
const unit_length = cast(usize, unit_header.unit_length) orelse return bad();
if (unit_length == 0) return .{
.length_offset = length_offset,
Expand All @@ -506,10 +478,7 @@ pub const EntryHeader = struct {
const end_offset = start_offset + unit_length;
defer fbr.pos = end_offset;

const id = try if (opt_ma) |ma|
fbr.readAddressChecked(unit_header.format, ma)
else
fbr.readAddress(unit_header.format);
const id = try fbr.readAddress(unit_header.format);
const entry_bytes = fbr.buf[fbr.pos..end_offset];
const cie_id: u64 = switch (dwarf_section) {
.eh_frame => CommonInformationEntry.eh_id,
Expand Down Expand Up @@ -856,7 +825,7 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void {
while (this_unit_offset < fbr.buf.len) {
try fbr.seekTo(this_unit_offset);

const unit_header = try readUnitHeader(&fbr, null);
const unit_header = try readUnitHeader(&fbr);
if (unit_header.unit_length == 0) return;
const next_offset = unit_header.header_length + unit_header.unit_length;

Expand Down Expand Up @@ -1045,7 +1014,7 @@ fn scanAllCompileUnits(di: *Dwarf, allocator: Allocator) ScanError!void {
while (this_unit_offset < fbr.buf.len) {
try fbr.seekTo(this_unit_offset);

const unit_header = try readUnitHeader(&fbr, null);
const unit_header = try readUnitHeader(&fbr);
if (unit_header.unit_length == 0) return;
const next_offset = unit_header.header_length + unit_header.unit_length;

Expand Down Expand Up @@ -1427,7 +1396,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) !
};
try fbr.seekTo(line_info_offset);

const unit_header = try readUnitHeader(&fbr, null);
const unit_header = try readUnitHeader(&fbr);
if (unit_header.unit_length == 0) return missing();

const next_offset = unit_header.header_length + unit_header.unit_length;
Expand Down Expand Up @@ -1815,7 +1784,7 @@ pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !vo
if (di.section(frame_section)) |section_data| {
var fbr: FixedBufferReader = .{ .buf = section_data, .endian = di.endian };
while (fbr.pos < fbr.buf.len) {
const entry_header = try EntryHeader.read(&fbr, null, frame_section);
const entry_header = try EntryHeader.read(&fbr, frame_section);
switch (entry_header.type) {
.cie => {
const cie = try CommonInformationEntry.parse(
Expand Down Expand Up @@ -1988,8 +1957,8 @@ const UnitHeader = struct {
unit_length: u64,
};

fn readUnitHeader(fbr: *FixedBufferReader, opt_ma: ?*MemoryAccessor) ScanError!UnitHeader {
return switch (try if (opt_ma) |ma| fbr.readIntChecked(u32, ma) else fbr.readInt(u32)) {
fn readUnitHeader(fbr: *FixedBufferReader) ScanError!UnitHeader {
return switch (try fbr.readInt(u32)) {
0...0xfffffff0 - 1 => |unit_length| .{
.format = .@"32",
.header_length = 4,
Expand All @@ -1999,7 +1968,7 @@ fn readUnitHeader(fbr: *FixedBufferReader, opt_ma: ?*MemoryAccessor) ScanError!U
0xffffffff => .{
.format = .@"64",
.header_length = 12,
.unit_length = try if (opt_ma) |ma| fbr.readIntChecked(u64, ma) else fbr.readInt(u64),
.unit_length = try fbr.readInt(u64),
},
};
}
Expand Down
12 changes: 0 additions & 12 deletions lib/std/debug/Dwarf/expression.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ const assert = std.debug.assert;
pub const Context = struct {
/// The dwarf format of the section this expression is in
format: std.dwarf.Format = .@"32",
/// If specified, any addresses will pass through before being accessed
memory_accessor: ?*std.debug.MemoryAccessor = null,
/// The compilation unit this expression relates to, if any
compile_unit: ?*const std.debug.Dwarf.CompileUnit = null,
/// When evaluating a user-presented expression, this is the address of the object being evaluated
Expand Down Expand Up @@ -465,16 +463,6 @@ pub fn StackMachine(comptime options: Options) type {
else => unreachable,
};

if (context.memory_accessor) |memory_accessor| {
if (!switch (size) {
1 => memory_accessor.load(u8, addr) != null,
2 => memory_accessor.load(u16, addr) != null,
4 => memory_accessor.load(u32, addr) != null,
8 => memory_accessor.load(u64, addr) != null,
else => return error.InvalidExpression,
}) return error.InvalidExpression;
}

const value: addr_type = std.math.cast(addr_type, @as(u64, switch (size) {
1 => @as(*const u8, @ptrFromInt(addr)).*,
2 => @as(*const u16, @ptrFromInt(addr)).*,
Expand Down
23 changes: 0 additions & 23 deletions lib/std/debug/FixedBufferReader.zig
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Optimized for performance in debug builds.

const std = @import("../std.zig");
const MemoryAccessor = std.debug.MemoryAccessor;

const FixedBufferReader = @This();

Expand Down Expand Up @@ -38,17 +37,6 @@ pub fn readInt(fbr: *FixedBufferReader, comptime T: type) Error!T {
return std.mem.readInt(T, fbr.buf[fbr.pos..][0..size], fbr.endian);
}

pub fn readIntChecked(
fbr: *FixedBufferReader,
comptime T: type,
ma: *MemoryAccessor,
) Error!T {
if (ma.load(T, @intFromPtr(fbr.buf[fbr.pos..].ptr)) == null)
return error.InvalidBuffer;

return fbr.readInt(T);
}

pub fn readUleb128(fbr: *FixedBufferReader, comptime T: type) Error!T {
return std.leb.readUleb128(T, fbr);
}
Expand All @@ -64,17 +52,6 @@ pub fn readAddress(fbr: *FixedBufferReader, format: std.dwarf.Format) Error!u64
};
}

pub fn readAddressChecked(
fbr: *FixedBufferReader,
format: std.dwarf.Format,
ma: *MemoryAccessor,
) Error!u64 {
return switch (format) {
.@"32" => try fbr.readIntChecked(u32, ma),
.@"64" => try fbr.readIntChecked(u64, ma),
};
}

pub fn readBytes(fbr: *FixedBufferReader, len: usize) Error![]const u8 {
if (fbr.buf.len - fbr.pos < len) return error.EndOfBuffer;
defer fbr.pos += len;
Expand Down
Loading