authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-18 01:21:45-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:16-04:00
logd99b40d38b48f046b8d7faa7698315d6c93bf685
treefe55508c44f064175bbc44541f3bebb826a98100
parent1a2bb70956df44e9c1dd2f06e1e98b4b7ff265d6

dwarf: fix the unwinder using the incorrect row from the FDE in certain cases


2 files changed, 19 insertions(+), 11 deletions(-)

lib/std/dwarf.zig+15-3
......@@ -1740,8 +1740,20 @@ pub const DwarfInfo = struct {
17401740 context.reg_context.eh_frame = cie.version != 4;
17411741 context.reg_context.is_macho = di.is_macho;
17421742
1743 _ = try context.vm.runToNative(context.allocator, context.pc, cie, fde);
1744 const row = &context.vm.current_row;
1743 if (comptime builtin.target.isDarwin()) {
1744 std.debug.print(" state before:\n", .{});
1745 std.debug.print(" cfa {?x}:\n", .{context.cfa});
1746 for (context.thread_context.mcontext.ss.regs, 0..) |reg, i| {
1747 std.debug.print(" {}:0x{x}\n", .{i, reg});
1748 }
1749 std.debug.print(" fp:0x{x}\n", .{context.thread_context.mcontext.ss.fp});
1750 std.debug.print(" lr:0x{x}\n", .{context.thread_context.mcontext.ss.lr});
1751 std.debug.print(" sp:0x{x}\n", .{context.thread_context.mcontext.ss.sp});
1752 std.debug.print(" pc:0x{x}\n", .{context.thread_context.mcontext.ss.pc});
1753 }
1754
1755 const row = try context.vm.runToNative(context.allocator, context.pc, cie, fde);
1756 std.debug.print(" ran to 0x{x}\n", .{row.offset + fde.pc_begin});
17451757
17461758 context.cfa = switch (row.cfa.rule) {
17471759 .val_offset => |offset| blk: {
......@@ -1785,7 +1797,7 @@ pub const DwarfInfo = struct {
17851797
17861798 var update_tail: ?*RegisterUpdate = null;
17871799 var has_next_ip = false;
1788 for (context.vm.rowColumns(row.*)) |column| {
1800 for (context.vm.rowColumns(row)) |column| {
17891801 if (column.register) |register| {
17901802 if (register == cie.return_address_register) {
17911803 has_next_ip = column.rule != .undefined;
lib/std/dwarf/call_frame.zig+4-8
......@@ -395,9 +395,7 @@ pub const VirtualMachine = struct {
395395 }
396396
397397 /// Runs the CIE instructions, then the FDE instructions. Execution halts
398 /// once the row that corresponds to `pc` is known (and set as `current_row`).
399 ///
400 /// The state of the row prior to the last execution step is returned.
398 /// once the row that corresponds to `pc` is known, and the row is returned.
401399 pub fn runTo(
402400 self: *VirtualMachine,
403401 allocator: std.mem.Allocator,
......@@ -419,17 +417,15 @@ pub const VirtualMachine = struct {
419417 &fde_stream,
420418 };
421419
422 outer: for (&streams, 0..) |stream, i| {
420 for (&streams, 0..) |stream, i| {
423421 while (stream.pos < stream.buffer.len) {
424422 const instruction = try dwarf.call_frame.Instruction.read(stream, addr_size_bytes, endian);
425423 prev_row = try self.step(allocator, cie, i == 0, instruction);
426 if (pc < fde.pc_begin + self.current_row.offset) {
427 break :outer;
428 }
424 if (pc < fde.pc_begin + self.current_row.offset) return prev_row;
429425 }
430426 }
431427
432 return prev_row;
428 return self.current_row;
433429 }
434430
435431 pub fn runToNative(