| ... | @@ -1676,7 +1676,7 @@ pub const DwarfInfo = struct { | ... | @@ -1676,7 +1676,7 @@ pub const DwarfInfo = struct { |
| 1676 | var expression_context = .{ | 1676 | var expression_context = .{ |
| 1677 | .isValidMemory = context.isValidMemory, | 1677 | .isValidMemory = context.isValidMemory, |
| 1678 | .compile_unit = di.findCompileUnit(fde.pc_begin) catch null, | 1678 | .compile_unit = di.findCompileUnit(fde.pc_begin) catch null, |
| 1679 | .thread_context = &context.thread_context, | 1679 | .thread_context = context.thread_context, |
| 1680 | .reg_context = context.reg_context, | 1680 | .reg_context = context.reg_context, |
| 1681 | .cfa = context.cfa, | 1681 | .cfa = context.cfa, |
| 1682 | }; | 1682 | }; |
| ... | @@ -1690,7 +1690,7 @@ pub const DwarfInfo = struct { | ... | @@ -1690,7 +1690,7 @@ pub const DwarfInfo = struct { |
| 1690 | context.cfa = switch (row.cfa.rule) { | 1690 | context.cfa = switch (row.cfa.rule) { |
| 1691 | .val_offset => |offset| blk: { | 1691 | .val_offset => |offset| blk: { |
| 1692 | const register = row.cfa.register orelse return error.InvalidCFARule; | 1692 | const register = row.cfa.register orelse return error.InvalidCFARule; |
| 1693 | const value = mem.readIntSliceNative(usize, try abi.regBytes(&context.thread_context, register, context.reg_context)); | 1693 | const value = mem.readIntSliceNative(usize, try abi.regBytes(context.thread_context, register, context.reg_context)); |
| 1694 | break :blk try call_frame.applyOffset(value, offset); | 1694 | break :blk try call_frame.applyOffset(value, offset); |
| 1695 | }, | 1695 | }, |
| 1696 | .expression => |expression| blk: { | 1696 | .expression => |expression| blk: { |
| ... | @@ -1733,7 +1733,7 @@ pub const DwarfInfo = struct { | ... | @@ -1733,7 +1733,7 @@ pub const DwarfInfo = struct { |
| 1733 | has_next_ip = column.rule != .undefined; | 1733 | has_next_ip = column.rule != .undefined; |
| 1734 | } | 1734 | } |
| 1735 | | 1735 | |
| 1736 | const old_value = try abi.regBytes(&context.thread_context, register, context.reg_context); | 1736 | const old_value = try abi.regBytes(context.thread_context, register, context.reg_context); |
| 1737 | const new_value = try update_allocator.alloc(u8, old_value.len); | 1737 | const new_value = try update_allocator.alloc(u8, old_value.len); |
| 1738 | | 1738 | |
| 1739 | const prev = update_tail; | 1739 | const prev = update_tail; |
| ... | @@ -1758,12 +1758,12 @@ pub const DwarfInfo = struct { | ... | @@ -1758,12 +1758,12 @@ pub const DwarfInfo = struct { |
| 1758 | } | 1758 | } |
| 1759 | | 1759 | |
| 1760 | if (has_next_ip) { | 1760 | if (has_next_ip) { |
| 1761 | context.pc = mem.readIntSliceNative(usize, try abi.regBytes(&context.thread_context, comptime abi.ipRegNum(), context.reg_context)); | 1761 | context.pc = mem.readIntSliceNative(usize, try abi.regBytes(context.thread_context, comptime abi.ipRegNum(), context.reg_context)); |
| 1762 | } else { | 1762 | } else { |
| 1763 | context.pc = 0; | 1763 | context.pc = 0; |
| 1764 | } | 1764 | } |
| 1765 | | 1765 | |
| 1766 | mem.writeIntSliceNative(usize, try abi.regBytes(&context.thread_context, abi.spRegNum(context.reg_context), context.reg_context), context.cfa.?); | 1766 | mem.writeIntSliceNative(usize, try abi.regBytes(context.thread_context, abi.spRegNum(context.reg_context), context.reg_context), context.cfa.?); |
| 1767 | | 1767 | |
| 1768 | // The call instruction will have pushed the address of the instruction that follows the call as the return address | 1768 | // The call instruction will have pushed the address of the instruction that follows the call as the return address |
| 1769 | // However, this return address may be past the end of the function if the caller was `noreturn`. | 1769 | // However, this return address may be past the end of the function if the caller was `noreturn`. |
| ... | @@ -1779,7 +1779,7 @@ pub const UnwindContext = struct { | ... | @@ -1779,7 +1779,7 @@ pub const UnwindContext = struct { |
| 1779 | allocator: mem.Allocator, | 1779 | allocator: mem.Allocator, |
| 1780 | cfa: ?usize, | 1780 | cfa: ?usize, |
| 1781 | pc: usize, | 1781 | pc: usize, |
| 1782 | thread_context: debug.ThreadContext, | 1782 | thread_context: *debug.ThreadContext, |
| 1783 | reg_context: abi.RegisterContext, | 1783 | reg_context: abi.RegisterContext, |
| 1784 | isValidMemory: *const fn (address: usize) bool, | 1784 | isValidMemory: *const fn (address: usize) bool, |
| 1785 | vm: call_frame.VirtualMachine = .{}, | 1785 | vm: call_frame.VirtualMachine = .{}, |
| ... | @@ -1788,14 +1788,14 @@ pub const UnwindContext = struct { | ... | @@ -1788,14 +1788,14 @@ pub const UnwindContext = struct { |
| 1788 | pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext { | 1788 | pub fn init(allocator: mem.Allocator, thread_context: *const debug.ThreadContext, isValidMemory: *const fn (address: usize) bool) !UnwindContext { |
| 1789 | const pc = mem.readIntSliceNative(usize, try abi.regBytes(thread_context, abi.ipRegNum(), null)); | 1789 | const pc = mem.readIntSliceNative(usize, try abi.regBytes(thread_context, abi.ipRegNum(), null)); |
| 1790 | | 1790 | |
| 1791 | if (builtin.os.tag == .macos) @compileError("Fix below TODO"); | 1791 | const context_copy = try allocator.create(debug.ThreadContext); |
| | 1792 | debug.dupeContext(thread_context, context_copy); |
| 1792 | | 1793 | |
| 1793 | return .{ | 1794 | return .{ |
| 1794 | .allocator = allocator, | 1795 | .allocator = allocator, |
| 1795 | .cfa = null, | 1796 | .cfa = null, |
| 1796 | .pc = pc, | 1797 | .pc = pc, |
| 1797 | // TODO: This is broken on macos, need a function that knows how to copy the OSs mcontext properly | 1798 | .thread_context = context_copy, |
| 1798 | .thread_context = thread_context.*, | | |
| 1799 | .reg_context = undefined, | 1799 | .reg_context = undefined, |
| 1800 | .isValidMemory = isValidMemory, | 1800 | .isValidMemory = isValidMemory, |
| 1801 | }; | 1801 | }; |
| ... | @@ -1804,10 +1804,11 @@ pub const UnwindContext = struct { | ... | @@ -1804,10 +1804,11 @@ pub const UnwindContext = struct { |
| 1804 | pub fn deinit(self: *UnwindContext) void { | 1804 | pub fn deinit(self: *UnwindContext) void { |
| 1805 | self.vm.deinit(self.allocator); | 1805 | self.vm.deinit(self.allocator); |
| 1806 | self.stack_machine.deinit(self.allocator); | 1806 | self.stack_machine.deinit(self.allocator); |
| | 1807 | self.allocator.destroy(self.thread_context); |
| 1807 | } | 1808 | } |
| 1808 | | 1809 | |
| 1809 | pub fn getFp(self: *const UnwindContext) !usize { | 1810 | pub fn getFp(self: *const UnwindContext) !usize { |
| 1810 | return mem.readIntSliceNative(usize, try abi.regBytes(&self.thread_context, abi.fpRegNum(self.reg_context), self.reg_context)); | 1811 | return mem.readIntSliceNative(usize, try abi.regBytes(self.thread_context, abi.fpRegNum(self.reg_context), self.reg_context)); |
| 1811 | } | 1812 | } |
| 1812 | }; | 1813 | }; |
| 1813 | | 1814 | |