From 7ee6e7d61edcd19c594cb40fdb64703f58e32994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 27 May 2026 07:25:29 +0200 Subject: [PATCH] std.debug.Dwarf.Unwind.VM: deal with negative offsets in unsigned CFI insns The DWARF spec has CFI instructions that take signed offsets, but at least LLVM always emits the unsigned variants, even for e.g. `.cfi_def_cfa_offset -4`. --- lib/std/debug/Dwarf/Unwind/VirtualMachine.zig | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/std/debug/Dwarf/Unwind/VirtualMachine.zig b/lib/std/debug/Dwarf/Unwind/VirtualMachine.zig index ccb674b565605360ced1acc444f00e3943956fd4..ff4d0967e9d8524f61c24ae89e2620eaa5c24f9f 100644 --- a/lib/std/debug/Dwarf/Unwind/VirtualMachine.zig +++ b/lib/std/debug/Dwarf/Unwind/VirtualMachine.zig @@ -247,10 +247,15 @@ fn evalInstructions( .val_expr => |len| .{ .val_expression = try takeExprBlock(&fr, len) }, }; }, - .def_cfa => |cfa| vm.current_row.cfa = .{ .reg_off = .{ - .register = cfa.register, - .offset = @intCast(cfa.offset), - } }, + .def_cfa => |cfa| vm.current_row.cfa = .{ + .reg_off = .{ + .register = cfa.register, + // Unfortunately, LLVM emits negative CFI directives as their unsigned variants + // rather than the signed variants that DWARF has for exactly that purpose, hence + // `@bitCast` instead of `@intCast`. + .offset = @bitCast(cfa.offset), + }, + }, .def_cfa_sf => |cfa| vm.current_row.cfa = .{ .reg_off = .{ .register = cfa.register, .offset = cfa.offset_sf * cie.data_alignment_factor, @@ -272,7 +277,8 @@ fn evalInstructions( }, .def_cfa_offset => |offset| switch (vm.current_row.cfa) { .none, .expression => return error.InvalidOperation, - .reg_off => |*ro| ro.offset = @intCast(offset), + // See the comment for `def_cfa` above. + .reg_off => |*ro| ro.offset = @bitCast(offset), }, .def_cfa_offset_sf => |offset_sf| switch (vm.current_row.cfa) { .none, .expression => return error.InvalidOperation, -- 2.54.0