diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-08-22 18:30:21 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2025-08-23 13:48:52 -0700 |
| commit | d00cc100867bbb7a5e4305a5597cb45982c4593f (patch) | |
| tree | 6c04d8c2d13a72d3a2117d6723494311d53018ed /lib/std/debug/SelfInfo.zig | |
| parent | 77c09d16f9d992b19bc7cb2d2497f8009e0250ba (diff) | |
| download | zig-d00cc100867bbb7a5e4305a5597cb45982c4593f.tar.gz zig-d00cc100867bbb7a5e4305a5597cb45982c4593f.zip | |
std.debug: delete MemoryAccessor
This API is based around the unsound idea that a process can perform
checked virtual memory loads to prevent crashing. This depends on
OS-specific APIs that may be unavailable, disabled, or impossible due to
virtualization.
It also makes collecting stack traces ridiculously slow, which is a
problem for users of DebugAllocator - in other words, everybody, all the
time. It also makes strace go from being superbly clean to being awful.
Diffstat (limited to 'lib/std/debug/SelfInfo.zig')
| -rw-r--r-- | lib/std/debug/SelfInfo.zig | 47 |
1 files changed, 11 insertions, 36 deletions
diff --git a/lib/std/debug/SelfInfo.zig b/lib/std/debug/SelfInfo.zig index 3f1514a957..fe19e79588 100644 --- a/lib/std/debug/SelfInfo.zig +++ b/lib/std/debug/SelfInfo.zig @@ -1159,7 +1159,6 @@ pub fn unwindFrameMachO( allocator: Allocator, base_address: usize, context: *UnwindContext, - ma: *std.debug.MemoryAccessor, unwind_info: []const u8, eh_frame: ?[]const u8, ) !usize { @@ -1323,9 +1322,6 @@ pub fn unwindFrameMachO( const fp = (try regValueNative(context.thread_context, fpRegNum(reg_context), reg_context)).*; const new_sp = fp + 2 * @sizeOf(usize); - // Verify the stack range we're about to read register values from - if (ma.load(usize, new_sp) == null or ma.load(usize, fp - frame_offset + max_reg * @sizeOf(usize)) == null) return error.InvalidUnwindInfo; - const ip_ptr = fp + @sizeOf(usize); const new_ip = @as(*const usize, @ptrFromInt(ip_ptr)).*; const new_fp = @as(*const usize, @ptrFromInt(fp)).*; @@ -1355,7 +1351,6 @@ pub fn unwindFrameMachO( base_address + entry.function_offset + encoding.value.x86_64.frameless.stack.indirect.sub_offset; - if (ma.load(usize, sub_offset_addr) == null) return error.InvalidUnwindInfo; // `sub_offset_addr` points to the offset of the literal within the instruction const sub_operand = @as(*align(1) const u32, @ptrFromInt(sub_offset_addr)).*; @@ -1397,7 +1392,6 @@ pub fn unwindFrameMachO( } var reg_addr = sp + stack_size - @sizeOf(usize) * @as(usize, reg_count + 1); - if (ma.load(usize, reg_addr) == null) return error.InvalidUnwindInfo; for (0..reg_count) |i| { const reg_number = try Dwarf.compactUnwindToDwarfRegNumber(registers[i]); (try regValueNative(context.thread_context, reg_number, reg_context)).* = @as(*const usize, @ptrFromInt(reg_addr)).*; @@ -1409,7 +1403,6 @@ pub fn unwindFrameMachO( const new_ip = @as(*const usize, @ptrFromInt(ip_ptr)).*; const new_sp = ip_ptr + @sizeOf(usize); - if (ma.load(usize, new_sp) == null) return error.InvalidUnwindInfo; (try regValueNative(context.thread_context, spRegNum(reg_context), reg_context)).* = new_sp; (try regValueNative(context.thread_context, ip_reg_num, reg_context)).* = new_ip; @@ -1417,7 +1410,7 @@ pub fn unwindFrameMachO( break :blk new_ip; }, .DWARF => { - return unwindFrameMachODwarf(allocator, base_address, context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); + return unwindFrameMachODwarf(allocator, base_address, context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); }, }, .aarch64, .aarch64_be => switch (encoding.mode.arm64) { @@ -1426,25 +1419,16 @@ pub fn unwindFrameMachO( const sp = (try regValueNative(context.thread_context, spRegNum(reg_context), reg_context)).*; const new_sp = sp + encoding.value.arm64.frameless.stack_size * 16; const new_ip = (try regValueNative(context.thread_context, 30, reg_context)).*; - if (ma.load(usize, new_sp) == null) return error.InvalidUnwindInfo; (try regValueNative(context.thread_context, spRegNum(reg_context), reg_context)).* = new_sp; break :blk new_ip; }, .DWARF => { - return unwindFrameMachODwarf(allocator, base_address, context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); + return unwindFrameMachODwarf(allocator, base_address, context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); }, .FRAME => blk: { const fp = (try regValueNative(context.thread_context, fpRegNum(reg_context), reg_context)).*; - const new_sp = fp + 16; const ip_ptr = fp + @sizeOf(usize); - const num_restored_pairs: usize = - @popCount(@as(u5, @bitCast(encoding.value.arm64.frame.x_reg_pairs))) + - @popCount(@as(u4, @bitCast(encoding.value.arm64.frame.d_reg_pairs))); - const min_reg_addr = fp - num_restored_pairs * 2 * @sizeOf(usize); - - if (ma.load(usize, new_sp) == null or ma.load(usize, min_reg_addr) == null) return error.InvalidUnwindInfo; - var reg_addr = fp - @sizeOf(usize); inline for (@typeInfo(@TypeOf(encoding.value.arm64.frame.x_reg_pairs)).@"struct".fields, 0..) |field, i| { if (@field(encoding.value.arm64.frame.x_reg_pairs, field.name) != 0) { @@ -1566,7 +1550,6 @@ pub fn unwindFrameDwarf( di: *Dwarf, base_address: usize, context: *UnwindContext, - ma: *std.debug.MemoryAccessor, explicit_fde_offset: ?usize, ) !usize { if (!supports_unwinding) return error.UnsupportedCpuArchitecture; @@ -1584,14 +1567,14 @@ pub fn unwindFrameDwarf( .endian = di.endian, }; - const fde_entry_header = try Dwarf.EntryHeader.read(&fbr, null, dwarf_section); + const fde_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section); if (fde_entry_header.type != .fde) return error.MissingFDE; const cie_offset = fde_entry_header.type.fde; try fbr.seekTo(cie_offset); fbr.endian = native_endian; - const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, null, dwarf_section); + const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, dwarf_section); if (cie_entry_header.type != .cie) return Dwarf.bad(); const cie = try Dwarf.CommonInformationEntry.parse( @@ -1619,13 +1602,16 @@ pub fn unwindFrameDwarf( // back to loading `.eh_frame`/`.debug_frame` and using those from that point on. if (di.eh_frame_hdr) |header| hdr: { - const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null; + const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else { + try di.scanCieFdeInfo(allocator, base_address); + di.eh_frame_hdr = null; + break :hdr; + }; var cie: Dwarf.CommonInformationEntry = undefined; var fde: Dwarf.FrameDescriptionEntry = undefined; header.findEntry( - ma, eh_frame_len, @intFromPtr(di.section(.eh_frame_hdr).?.ptr), context.pc, @@ -1669,7 +1655,6 @@ pub fn unwindFrameDwarf( var expression_context: Dwarf.expression.Context = .{ .format = cie.format, - .memory_accessor = ma, .compile_unit = di.findCompileUnit(fde.pc_begin) catch null, .thread_context = context.thread_context, .reg_context = context.reg_context, @@ -1704,7 +1689,6 @@ pub fn unwindFrameDwarf( else => return error.InvalidCFARule, }; - if (ma.load(usize, context.cfa.?) == null) return error.InvalidCFA; expression_context.cfa = context.cfa; // Buffering the modifications is done because copying the thread context is not portable, @@ -1740,12 +1724,7 @@ pub fn unwindFrameDwarf( .prev = prev, }; - try column.resolveValue( - context, - expression_context, - ma, - src, - ); + try column.resolveValue(context, expression_context, src); } } @@ -1833,7 +1812,6 @@ fn unwindFrameMachODwarf( allocator: Allocator, base_address: usize, context: *UnwindContext, - ma: *std.debug.MemoryAccessor, eh_frame: []const u8, fde_offset: usize, ) !usize { @@ -1848,7 +1826,7 @@ fn unwindFrameMachODwarf( .owned = false, }; - return unwindFrameDwarf(allocator, &di, base_address, context, ma, fde_offset); + return unwindFrameDwarf(allocator, &di, base_address, context, fde_offset); } /// This is a virtual machine that runs DWARF call frame instructions. @@ -1898,7 +1876,6 @@ pub const VirtualMachine = struct { self: Column, context: *SelfInfo.UnwindContext, expression_context: std.debug.Dwarf.expression.Context, - ma: *std.debug.MemoryAccessor, out: []u8, ) !void { switch (self.rule) { @@ -1919,7 +1896,6 @@ pub const VirtualMachine = struct { .offset => |offset| { if (context.cfa) |cfa| { const addr = try applyOffset(cfa, offset); - if (ma.load(usize, addr) == null) return error.InvalidAddress; const ptr: *const usize = @ptrFromInt(addr); mem.writeInt(usize, out[0..@sizeOf(usize)], ptr.*, native_endian); } else return error.InvalidCFA; @@ -1942,7 +1918,6 @@ pub const VirtualMachine = struct { break :blk v.generic; } else return error.NoExpressionValue; - if (ma.load(usize, addr) == null) return error.InvalidExpressionAddress; const ptr: *usize = @ptrFromInt(addr); mem.writeInt(usize, out[0..@sizeOf(usize)], ptr.*, native_endian); }, |
