authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-05-27 07:25:29+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-05-28 04:03:47+02:00
log7ee6e7d61edcd19c594cb40fdb64703f58e32994
tree3ad19eb23e896631be5d29e75cb8ae92f2a8fe35
parenta3508c4b3a66b15eaa543768b1ea7157f5e5f75b

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`.

1 files changed, 11 insertions(+), 5 deletions(-)

lib/std/debug/Dwarf/Unwind/VirtualMachine.zig+11-5
...@@ -247,10 +247,15 @@ fn evalInstructions(...@@ -247,10 +247,15 @@ fn evalInstructions(
247 .val_expr => |len| .{ .val_expression = try takeExprBlock(&fr, len) },247 .val_expr => |len| .{ .val_expression = try takeExprBlock(&fr, len) },
248 };248 };
249 },249 },
250 .def_cfa => |cfa| vm.current_row.cfa = .{ .reg_off = .{250 .def_cfa => |cfa| vm.current_row.cfa = .{
251 .register = cfa.register,251 .reg_off = .{
252 .offset = @intCast(cfa.offset),252 .register = cfa.register,
253 } },253 // Unfortunately, LLVM emits negative CFI directives as their unsigned variants
254 // rather than the signed variants that DWARF has for exactly that purpose, hence
255 // `@bitCast` instead of `@intCast`.
256 .offset = @bitCast(cfa.offset),
257 },
258 },
254 .def_cfa_sf => |cfa| vm.current_row.cfa = .{ .reg_off = .{259 .def_cfa_sf => |cfa| vm.current_row.cfa = .{ .reg_off = .{
255 .register = cfa.register,260 .register = cfa.register,
256 .offset = cfa.offset_sf * cie.data_alignment_factor,261 .offset = cfa.offset_sf * cie.data_alignment_factor,
...@@ -272,7 +277,8 @@ fn evalInstructions(...@@ -272,7 +277,8 @@ fn evalInstructions(
272 },277 },
273 .def_cfa_offset => |offset| switch (vm.current_row.cfa) {278 .def_cfa_offset => |offset| switch (vm.current_row.cfa) {
274 .none, .expression => return error.InvalidOperation,279 .none, .expression => return error.InvalidOperation,
275 .reg_off => |*ro| ro.offset = @intCast(offset),280 // See the comment for `def_cfa` above.
281 .reg_off => |*ro| ro.offset = @bitCast(offset),
276 },282 },
277 .def_cfa_offset_sf => |offset_sf| switch (vm.current_row.cfa) {283 .def_cfa_offset_sf => |offset_sf| switch (vm.current_row.cfa) {
278 .none, .expression => return error.InvalidOperation,284 .none, .expression => return error.InvalidOperation,