authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-16 12:10:37+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-06-16 12:12:05+02:00
log42618257666727aaf51957966ec88ef54242f840
tree3faff1eee48091297303b70f831764634d067043
parentcf13ecab29a2aa3b8616e03e4ec50f4b89f73c7b
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.debug.Dwarf: fix unwinding when address size is smaller than register size


2 files changed, 10 insertions(+), 15 deletions(-)

lib/std/debug/Dwarf/SelfUnwinder.zig+8-13
...@@ -168,7 +168,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -168,7 +168,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
168 .none => return error.InvalidDebugInfo,168 .none => return error.InvalidDebugInfo,
169 .reg_off => |ro| cfa: {169 .reg_off => |ro| cfa: {
170 const ptr = try regNative(&unwinder.cpu_state, ro.register);170 const ptr = try regNative(&unwinder.cpu_state, ro.register);
171 break :cfa try applyOffset(ptr.*, ro.offset);171 break :cfa try applyOffset(@intCast(ptr.*), ro.offset);
172 },172 },
173 .expression => |expr| cfa: {173 .expression => |expr| cfa: {
174 // On most implemented architectures, the CFA is defined to be the previous frame's SP.174 // On most implemented architectures, the CFA is defined to be the previous frame's SP.
...@@ -181,7 +181,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -181,7 +181,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
181 const value = try unwinder.expr_vm.run(expr, gpa, .{181 const value = try unwinder.expr_vm.run(expr, gpa, .{
182 .format = format,182 .format = format,
183 .cpu_context = &unwinder.cpu_state,183 .cpu_context = &unwinder.cpu_state,
184 }, prev_cfa_val) orelse return error.InvalidDebugInfo;184 }, @intCast(prev_cfa_val)) orelse return error.InvalidDebugInfo;
185 switch (value) {185 switch (value) {
186 .generic => |g| break :cfa g,186 .generic => |g| break :cfa g,
187 else => return error.InvalidDebugInfo,187 else => return error.InvalidDebugInfo,
...@@ -203,7 +203,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -203,7 +203,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
203 const new_val: union(enum) {203 const new_val: union(enum) {
204 same,204 same,
205 undefined,205 undefined,
206 val: usize,206 val: std.debug.cpu_context.Native.Gpr,
207 bytes: []const u8,207 bytes: []const u8,
208 } = switch (rule) {208 } = switch (rule) {
209 .default => val: {209 .default => val: {
...@@ -219,7 +219,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -219,7 +219,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
219 .undefined => .undefined,219 .undefined => .undefined,
220 .same_value => .same,220 .same_value => .same,
221 .offset => |offset| val: {221 .offset => |offset| val: {
222 const ptr: *const usize = @ptrFromInt(try applyOffset(cfa, offset));222 const ptr: *const std.debug.cpu_context.Native.Gpr = @ptrFromInt(try applyOffset(cfa, offset));
223 break :val .{ .val = ptr.* };223 break :val .{ .val = ptr.* };
224 },224 },
225 .val_offset => |offset| .{ .val = try applyOffset(cfa, offset) },225 .val_offset => |offset| .{ .val = try applyOffset(cfa, offset) },
...@@ -260,12 +260,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -260,12 +260,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
260 has_return_address = false;260 has_return_address = false;
261 }261 }
262 },262 },
263 .val => |val| {263 .val => |val| (try regNative(&new_cpu_state, register)).* = val,
264 const dest = try new_cpu_state.dwarfRegisterBytes(@intCast(register));
265 if (dest.len != @sizeOf(usize)) return error.InvalidDebugInfo;
266 const dest_ptr: *align(1) usize = @ptrCast(dest);
267 dest_ptr.* = val;
268 },
269 .bytes => |src| {264 .bytes => |src| {
270 const dest = try new_cpu_state.dwarfRegisterBytes(@intCast(register));265 const dest = try new_cpu_state.dwarfRegisterBytes(@intCast(register));
271 if (dest.len != src.len) return error.InvalidDebugInfo;266 if (dest.len != src.len) return error.InvalidDebugInfo;
...@@ -275,7 +270,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE...@@ -275,7 +270,7 @@ fn nextInner(unwinder: *SelfUnwinder, gpa: Allocator, cache_entry: *const CacheE
275 }270 }
276271
277 const return_address = if (has_return_address)272 const return_address = if (has_return_address)
278 stripInstructionPtrAuthCode((try regNative(&new_cpu_state, return_address_register)).*)273 stripInstructionPtrAuthCode(@intCast((try regNative(&new_cpu_state, return_address_register)).*))
279 else274 else
280 0;275 0;
281276
...@@ -303,9 +298,9 @@ pub fn regNative(ctx: *std.debug.cpu_context.Native, num: u16) error{...@@ -303,9 +298,9 @@ pub fn regNative(ctx: *std.debug.cpu_context.Native, num: u16) error{
303 InvalidRegister,298 InvalidRegister,
304 UnsupportedRegister,299 UnsupportedRegister,
305 IncompatibleRegisterSize,300 IncompatibleRegisterSize,
306}!*align(1) usize {301}!*align(1) std.debug.cpu_context.Native.Gpr {
307 const bytes = try ctx.dwarfRegisterBytes(num);302 const bytes = try ctx.dwarfRegisterBytes(num);
308 if (bytes.len != @sizeOf(usize)) return error.IncompatibleRegisterSize;303 if (bytes.len != @sizeOf(std.debug.cpu_context.Native.Gpr)) return error.IncompatibleRegisterSize;
309 return @ptrCast(bytes);304 return @ptrCast(bytes);
310}305}
311306
lib/std/debug/Dwarf/expression.zig+2-2
...@@ -387,7 +387,7 @@ pub fn StackMachine(comptime options: Options) type {...@@ -387,7 +387,7 @@ pub fn StackMachine(comptime options: Options) type {
387 .regval_type = .{387 .regval_type = .{
388 .type_offset = rt.type_offset,388 .type_offset = rt.type_offset,
389 .type_size = @sizeOf(addr_type),389 .type_size = @sizeOf(addr_type),
390 .value = (try regNative(cpu_context, rt.register)).*,390 .value = @intCast((try regNative(cpu_context, rt.register)).*),
391 },391 },
392 });392 });
393 },393 },
...@@ -738,7 +738,7 @@ pub fn StackMachine(comptime options: Options) type {...@@ -738,7 +738,7 @@ pub fn StackMachine(comptime options: Options) type {
738 var block_stream: std.Io.Reader = .fixed(block);738 var block_stream: std.Io.Reader = .fixed(block);
739 const register = (try readOperand(&block_stream, block[0], context)).?.register;739 const register = (try readOperand(&block_stream, block[0], context)).?.register;
740 const value = (try regNative(cpu_context, register)).*;740 const value = (try regNative(cpu_context, register)).*;
741 try self.stack.append(allocator, .{ .generic = value });741 try self.stack.append(allocator, .{ .generic = @intCast(value) });
742 } else {742 } else {
743 var stack_machine: Self = .{};743 var stack_machine: Self = .{};
744 defer stack_machine.deinit(allocator);744 defer stack_machine.deinit(allocator);