| ... | @@ -1740,21 +1740,7 @@ pub const DwarfInfo = struct { | ... | @@ -1740,21 +1740,7 @@ pub const DwarfInfo = struct { |
| 1740 | context.reg_context.eh_frame = cie.version != 4; | 1740 | context.reg_context.eh_frame = cie.version != 4; |
| 1741 | context.reg_context.is_macho = di.is_macho; | 1741 | context.reg_context.is_macho = di.is_macho; |
| 1742 | | 1742 | |
| 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); | 1743 | 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}); | | |
| 1757 | | | |
| 1758 | context.cfa = switch (row.cfa.rule) { | 1744 | context.cfa = switch (row.cfa.rule) { |
| 1759 | .val_offset => |offset| blk: { | 1745 | .val_offset => |offset| blk: { |
| 1760 | const register = row.cfa.register orelse return error.InvalidCFARule; | 1746 | const register = row.cfa.register orelse return error.InvalidCFARule; |
| ... | @@ -1789,47 +1775,48 @@ pub const DwarfInfo = struct { | ... | @@ -1789,47 +1775,48 @@ pub const DwarfInfo = struct { |
| 1789 | | 1775 | |
| 1790 | const RegisterUpdate = struct { | 1776 | const RegisterUpdate = struct { |
| 1791 | // Backed by thread_context | 1777 | // Backed by thread_context |
| 1792 | old_value: []u8, | 1778 | dest: []u8, |
| 1793 | // Backed by arena | 1779 | // Backed by arena |
| 1794 | new_value: []const u8, | 1780 | src: []const u8, |
| 1795 | prev: ?*@This(), | 1781 | prev: ?*@This(), |
| 1796 | }; | 1782 | }; |
| 1797 | | 1783 | |
| 1798 | var update_tail: ?*RegisterUpdate = null; | 1784 | var update_tail: ?*RegisterUpdate = null; |
| 1799 | var has_next_ip = true; | 1785 | var has_return_address= true; |
| 1800 | for (context.vm.rowColumns(row)) |column| { | 1786 | for (context.vm.rowColumns(row)) |column| { |
| 1801 | if (column.register) |register| { | 1787 | if (column.register) |register| { |
| 1802 | if (register == cie.return_address_register) { | 1788 | if (register == cie.return_address_register) { |
| 1803 | has_next_ip = column.rule != .undefined; | 1789 | has_return_address = column.rule != .undefined; |
| 1804 | } | 1790 | } |
| 1805 | std.debug.print(" updated {}\n", .{register}); | | |
| 1806 | | 1791 | |
| 1807 | const old_value = try abi.regBytes(context.thread_context, register, context.reg_context); | 1792 | const dest = try abi.regBytes(context.thread_context, register, context.reg_context); |
| 1808 | const new_value = try update_allocator.alloc(u8, old_value.len); | 1793 | const src = try update_allocator.alloc(u8, dest.len); |
| 1809 | | 1794 | |
| 1810 | const prev = update_tail; | 1795 | const prev = update_tail; |
| 1811 | update_tail = try update_allocator.create(RegisterUpdate); | 1796 | update_tail = try update_allocator.create(RegisterUpdate); |
| 1812 | update_tail.?.* = .{ | 1797 | update_tail.?.* = .{ |
| 1813 | .old_value = old_value, | 1798 | .dest = dest, |
| 1814 | .new_value = new_value, | 1799 | .src = src, |
| 1815 | .prev = prev, | 1800 | .prev = prev, |
| 1816 | }; | 1801 | }; |
| 1817 | | 1802 | |
| 1818 | try column.resolveValue( | 1803 | try column.resolveValue( |
| 1819 | context, | 1804 | context, |
| 1820 | expression_context, | 1805 | expression_context, |
| 1821 | new_value, | 1806 | src, |
| 1822 | ); | 1807 | ); |
| 1823 | } | 1808 | } |
| 1824 | } | 1809 | } |
| 1825 | | 1810 | |
| | 1811 | // On all implemented architectures, the CFA is defined as being the previous frame's SP |
| 1826 | (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(context.reg_context), context.reg_context)).* = context.cfa.?; | 1812 | (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(context.reg_context), context.reg_context)).* = context.cfa.?; |
| | 1813 | |
| 1827 | while (update_tail) |tail| { | 1814 | while (update_tail) |tail| { |
| 1828 | @memcpy(tail.old_value, tail.new_value); | 1815 | @memcpy(tail.dest, tail.src); |
| 1829 | update_tail = tail.prev; | 1816 | update_tail = tail.prev; |
| 1830 | } | 1817 | } |
| 1831 | | 1818 | |
| 1832 | if (has_next_ip) { | 1819 | if (has_return_address) { |
| 1833 | context.pc = abi.stripInstructionPtrAuthCode(mem.readIntSliceNative(usize, try abi.regBytes( | 1820 | context.pc = abi.stripInstructionPtrAuthCode(mem.readIntSliceNative(usize, try abi.regBytes( |
| 1834 | context.thread_context, | 1821 | context.thread_context, |
| 1835 | cie.return_address_register, | 1822 | cie.return_address_register, |
| ... | @@ -1838,10 +1825,8 @@ pub const DwarfInfo = struct { | ... | @@ -1838,10 +1825,8 @@ pub const DwarfInfo = struct { |
| 1838 | } else { | 1825 | } else { |
| 1839 | context.pc = 0; | 1826 | context.pc = 0; |
| 1840 | } | 1827 | } |
| 1841 | (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), context.reg_context)).* = context.pc; | | |
| 1842 | std.debug.print(" new context.pc: 0x{x}\n", .{context.pc}); | | |
| 1843 | | 1828 | |
| 1844 | (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(context.reg_context), context.reg_context)).* = context.cfa.?; | 1829 | (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), context.reg_context)).* = context.pc; |
| 1845 | | 1830 | |
| 1846 | // The call instruction will have pushed the address of the instruction that follows the call as the return address | 1831 | // The call instruction will have pushed the address of the instruction that follows the call as the return address |
| 1847 | // However, this return address may be past the end of the function if the caller was `noreturn`. By subtracting one, | 1832 | // However, this return address may be past the end of the function if the caller was `noreturn`. By subtracting one, |