commit 7ee6e7d61edcd19c594cb40fdb64703f58e32994 (tree)
parent a3508c4b3a66b15eaa543768b1ea7157f5e5f75b
Author: Alex Rønne Petersen <alex@alexrp.com>
Date: Wed, 27 May 2026 07:25:29 +0200
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`.
Diffstat:
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
@@ -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,