| author | |
| committer | |
| log | f77e1b86225cd49c2d04dfa6ca4a7ede315dc0b1 |
| tree | c30cddc29ae1f1162f3ec38fcaf89b94ecb4e6dd |
| parent | d916954bee0f477bcada0693d4aa952197cf1eef |
| parent | 180db2bf23f05a02876d4567cac3b04842c11acb |
| signature |
tests: enable stack trace tests for x86_64-selfhosted13 files changed, 200 insertions(+), 125 deletions(-)
lib/std/debug.zig+10-2| ... | @@ -732,11 +732,12 @@ pub const StackIterator = struct { | ... | @@ -732,11 +732,12 @@ pub const StackIterator = struct { |
| 732 | // via DWARF before attempting to use the compact unwind info will produce incorrect results. | 732 | // via DWARF before attempting to use the compact unwind info will produce incorrect results. |
| 733 | if (module.unwind_info) |unwind_info| { | 733 | if (module.unwind_info) |unwind_info| { |
| 734 | if (SelfInfo.unwindFrameMachO( | 734 | if (SelfInfo.unwindFrameMachO( |
| 735 | unwind_state.debug_info.allocator, | ||
| 736 | module.base_address, | ||
| 735 | &unwind_state.dwarf_context, | 737 | &unwind_state.dwarf_context, |
| 736 | &it.ma, | 738 | &it.ma, |
| 737 | unwind_info, | 739 | unwind_info, |
| 738 | module.eh_frame, | 740 | module.eh_frame, |
| 739 | module.base_address, | ||
| 740 | )) |return_address| { | 741 | )) |return_address| { |
| 741 | return return_address; | 742 | return return_address; |
| 742 | } else |err| { | 743 | } else |err| { |
| ... | @@ -748,7 +749,14 @@ pub const StackIterator = struct { | ... | @@ -748,7 +749,14 @@ pub const StackIterator = struct { |
| 748 | } | 749 | } |
| 749 | 750 | ||
| 750 | if (try module.getDwarfInfoForAddress(unwind_state.debug_info.allocator, unwind_state.dwarf_context.pc)) |di| { | 751 | if (try module.getDwarfInfoForAddress(unwind_state.debug_info.allocator, unwind_state.dwarf_context.pc)) |di| { |
| 751 | return SelfInfo.unwindFrameDwarf(di, &unwind_state.dwarf_context, &it.ma, null); | 752 | return SelfInfo.unwindFrameDwarf( |
| 753 | unwind_state.debug_info.allocator, | ||
| 754 | di, | ||
| 755 | module.base_address, | ||
| 756 | &unwind_state.dwarf_context, | ||
| 757 | &it.ma, | ||
| 758 | null, | ||
| 759 | ); | ||
| 752 | } else return error.MissingDebugInfo; | 760 | } else return error.MissingDebugInfo; |
| 753 | } | 761 | } |
| 754 | 762 |
lib/std/debug/Dwarf.zig+14-4| ... | @@ -48,6 +48,8 @@ compile_unit_list: std.ArrayListUnmanaged(CompileUnit) = .empty, | ... | @@ -48,6 +48,8 @@ compile_unit_list: std.ArrayListUnmanaged(CompileUnit) = .empty, |
| 48 | /// Filled later by the initializer | 48 | /// Filled later by the initializer |
| 49 | func_list: std.ArrayListUnmanaged(Func) = .empty, | 49 | func_list: std.ArrayListUnmanaged(Func) = .empty, |
| 50 | 50 | ||
| 51 | /// Starts out non-`null` if the `.eh_frame_hdr` section is present. May become `null` later if we | ||
| 52 | /// find that `.eh_frame_hdr` is incomplete. | ||
| 51 | eh_frame_hdr: ?ExceptionFrameHeader = null, | 53 | eh_frame_hdr: ?ExceptionFrameHeader = null, |
| 52 | /// These lookup tables are only used if `eh_frame_hdr` is null | 54 | /// These lookup tables are only used if `eh_frame_hdr` is null |
| 53 | cie_map: std.AutoArrayHashMapUnmanaged(u64, CommonInformationEntry) = .empty, | 55 | cie_map: std.AutoArrayHashMapUnmanaged(u64, CommonInformationEntry) = .empty, |
| ... | @@ -1754,10 +1756,12 @@ fn readDebugAddr(di: Dwarf, compile_unit: CompileUnit, index: u64) !u64 { | ... | @@ -1754,10 +1756,12 @@ fn readDebugAddr(di: Dwarf, compile_unit: CompileUnit, index: u64) !u64 { |
| 1754 | }; | 1756 | }; |
| 1755 | } | 1757 | } |
| 1756 | 1758 | ||
| 1757 | /// If .eh_frame_hdr is present, then only the header needs to be parsed. | 1759 | /// If `.eh_frame_hdr` is present, then only the header needs to be parsed. Otherwise, `.eh_frame` |
| 1760 | /// and `.debug_frame` are scanned and a sorted list of FDEs is built for binary searching during | ||
| 1761 | /// unwinding. Even if `.eh_frame_hdr` is used, we may find during unwinding that it's incomplete, | ||
| 1762 | /// in which case we build the sorted list of FDEs at that point. | ||
| 1758 | /// | 1763 | /// |
| 1759 | /// Otherwise, .eh_frame and .debug_frame are scanned and a sorted list | 1764 | /// See also `scanCieFdeInfo`. |
| 1760 | /// of FDEs is built for binary searching during unwinding. | ||
| 1761 | pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void { | 1765 | pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void { |
| 1762 | if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: { | 1766 | if (di.section(.eh_frame_hdr)) |eh_frame_hdr| blk: { |
| 1763 | var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian }; | 1767 | var fbr: FixedBufferReader = .{ .buf = eh_frame_hdr, .endian = native_endian }; |
| ... | @@ -1797,6 +1801,12 @@ pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) | ... | @@ -1797,6 +1801,12 @@ pub fn scanAllUnwindInfo(di: *Dwarf, allocator: Allocator, base_address: usize) |
| 1797 | return; | 1801 | return; |
| 1798 | } | 1802 | } |
| 1799 | 1803 | ||
| 1804 | try di.scanCieFdeInfo(allocator, base_address); | ||
| 1805 | } | ||
| 1806 | |||
| 1807 | /// Scan `.eh_frame` and `.debug_frame` and build a sorted list of FDEs for binary searching during | ||
| 1808 | /// unwinding. | ||
| 1809 | pub fn scanCieFdeInfo(di: *Dwarf, allocator: Allocator, base_address: usize) !void { | ||
| 1800 | const frame_sections = [2]Section.Id{ .eh_frame, .debug_frame }; | 1810 | const frame_sections = [2]Section.Id{ .eh_frame, .debug_frame }; |
| 1801 | for (frame_sections) |frame_section| { | 1811 | for (frame_sections) |frame_section| { |
| 1802 | if (di.section(frame_section)) |section_data| { | 1812 | if (di.section(frame_section)) |section_data| { |
| ... | @@ -2125,7 +2135,7 @@ pub const ElfModule = struct { | ... | @@ -2125,7 +2135,7 @@ pub const ElfModule = struct { |
| 2125 | return self.dwarf.getSymbol(allocator, relocated_address); | 2135 | return self.dwarf.getSymbol(allocator, relocated_address); |
| 2126 | } | 2136 | } |
| 2127 | 2137 | ||
| 2128 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*const Dwarf { | 2138 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*Dwarf { |
| 2129 | _ = allocator; | 2139 | _ = allocator; |
| 2130 | _ = address; | 2140 | _ = address; |
| 2131 | return &self.dwarf; | 2141 | return &self.dwarf; |
lib/std/debug/SelfInfo.zig+64-33| ... | @@ -707,7 +707,7 @@ pub const Module = switch (native_os) { | ... | @@ -707,7 +707,7 @@ pub const Module = switch (native_os) { |
| 707 | } | 707 | } |
| 708 | } | 708 | } |
| 709 | 709 | ||
| 710 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*const Dwarf { | 710 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*Dwarf { |
| 711 | return if ((try self.getOFileInfoForAddress(allocator, address)).o_file_info) |o_file_info| &o_file_info.di else null; | 711 | return if ((try self.getOFileInfoForAddress(allocator, address)).o_file_info) |o_file_info| &o_file_info.di else null; |
| 712 | } | 712 | } |
| 713 | }, | 713 | }, |
| ... | @@ -784,7 +784,7 @@ pub const Module = switch (native_os) { | ... | @@ -784,7 +784,7 @@ pub const Module = switch (native_os) { |
| 784 | return .{}; | 784 | return .{}; |
| 785 | } | 785 | } |
| 786 | 786 | ||
| 787 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*const Dwarf { | 787 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*Dwarf { |
| 788 | _ = allocator; | 788 | _ = allocator; |
| 789 | _ = address; | 789 | _ = address; |
| 790 | 790 | ||
| ... | @@ -808,7 +808,7 @@ pub const Module = switch (native_os) { | ... | @@ -808,7 +808,7 @@ pub const Module = switch (native_os) { |
| 808 | return .{}; | 808 | return .{}; |
| 809 | } | 809 | } |
| 810 | 810 | ||
| 811 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*const Dwarf { | 811 | pub fn getDwarfInfoForAddress(self: *@This(), allocator: Allocator, address: usize) !?*Dwarf { |
| 812 | _ = self; | 812 | _ = self; |
| 813 | _ = allocator; | 813 | _ = allocator; |
| 814 | _ = address; | 814 | _ = address; |
| ... | @@ -1156,11 +1156,12 @@ test machoSearchSymbols { | ... | @@ -1156,11 +1156,12 @@ test machoSearchSymbols { |
| 1156 | /// If the compact encoding can't encode a way to unwind a frame, it will | 1156 | /// If the compact encoding can't encode a way to unwind a frame, it will |
| 1157 | /// defer unwinding to DWARF, in which case `.eh_frame` will be used if available. | 1157 | /// defer unwinding to DWARF, in which case `.eh_frame` will be used if available. |
| 1158 | pub fn unwindFrameMachO( | 1158 | pub fn unwindFrameMachO( |
| 1159 | allocator: Allocator, | ||
| 1160 | base_address: usize, | ||
| 1159 | context: *UnwindContext, | 1161 | context: *UnwindContext, |
| 1160 | ma: *std.debug.MemoryAccessor, | 1162 | ma: *std.debug.MemoryAccessor, |
| 1161 | unwind_info: []const u8, | 1163 | unwind_info: []const u8, |
| 1162 | eh_frame: ?[]const u8, | 1164 | eh_frame: ?[]const u8, |
| 1163 | module_base_address: usize, | ||
| 1164 | ) !usize { | 1165 | ) !usize { |
| 1165 | const header = std.mem.bytesAsValue( | 1166 | const header = std.mem.bytesAsValue( |
| 1166 | macho.unwind_info_section_header, | 1167 | macho.unwind_info_section_header, |
| ... | @@ -1172,7 +1173,7 @@ pub fn unwindFrameMachO( | ... | @@ -1172,7 +1173,7 @@ pub fn unwindFrameMachO( |
| 1172 | ); | 1173 | ); |
| 1173 | if (indices.len == 0) return error.MissingUnwindInfo; | 1174 | if (indices.len == 0) return error.MissingUnwindInfo; |
| 1174 | 1175 | ||
| 1175 | const mapped_pc = context.pc - module_base_address; | 1176 | const mapped_pc = context.pc - base_address; |
| 1176 | const second_level_index = blk: { | 1177 | const second_level_index = blk: { |
| 1177 | var left: usize = 0; | 1178 | var left: usize = 0; |
| 1178 | var len: usize = indices.len; | 1179 | var len: usize = indices.len; |
| ... | @@ -1351,7 +1352,7 @@ pub fn unwindFrameMachO( | ... | @@ -1351,7 +1352,7 @@ pub fn unwindFrameMachO( |
| 1351 | else stack_size: { | 1352 | else stack_size: { |
| 1352 | // In .STACK_IND, the stack size is inferred from the subq instruction at the beginning of the function. | 1353 | // In .STACK_IND, the stack size is inferred from the subq instruction at the beginning of the function. |
| 1353 | const sub_offset_addr = | 1354 | const sub_offset_addr = |
| 1354 | module_base_address + | 1355 | base_address + |
| 1355 | entry.function_offset + | 1356 | entry.function_offset + |
| 1356 | encoding.value.x86_64.frameless.stack.indirect.sub_offset; | 1357 | encoding.value.x86_64.frameless.stack.indirect.sub_offset; |
| 1357 | if (ma.load(usize, sub_offset_addr) == null) return error.InvalidUnwindInfo; | 1358 | if (ma.load(usize, sub_offset_addr) == null) return error.InvalidUnwindInfo; |
| ... | @@ -1416,7 +1417,7 @@ pub fn unwindFrameMachO( | ... | @@ -1416,7 +1417,7 @@ pub fn unwindFrameMachO( |
| 1416 | break :blk new_ip; | 1417 | break :blk new_ip; |
| 1417 | }, | 1418 | }, |
| 1418 | .DWARF => { | 1419 | .DWARF => { |
| 1419 | return unwindFrameMachODwarf(context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); | 1420 | return unwindFrameMachODwarf(allocator, base_address, context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); |
| 1420 | }, | 1421 | }, |
| 1421 | }, | 1422 | }, |
| 1422 | .aarch64, .aarch64_be => switch (encoding.mode.arm64) { | 1423 | .aarch64, .aarch64_be => switch (encoding.mode.arm64) { |
| ... | @@ -1430,7 +1431,7 @@ pub fn unwindFrameMachO( | ... | @@ -1430,7 +1431,7 @@ pub fn unwindFrameMachO( |
| 1430 | break :blk new_ip; | 1431 | break :blk new_ip; |
| 1431 | }, | 1432 | }, |
| 1432 | .DWARF => { | 1433 | .DWARF => { |
| 1433 | return unwindFrameMachODwarf(context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); | 1434 | return unwindFrameMachODwarf(allocator, base_address, context, ma, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); |
| 1434 | }, | 1435 | }, |
| 1435 | .FRAME => blk: { | 1436 | .FRAME => blk: { |
| 1436 | const fp = (try regValueNative(context.thread_context, fpRegNum(reg_context), reg_context)).*; | 1437 | const fp = (try regValueNative(context.thread_context, fpRegNum(reg_context), reg_context)).*; |
| ... | @@ -1555,13 +1556,16 @@ pub inline fn stripInstructionPtrAuthCode(ptr: usize) usize { | ... | @@ -1555,13 +1556,16 @@ pub inline fn stripInstructionPtrAuthCode(ptr: usize) usize { |
| 1555 | 1556 | ||
| 1556 | /// Unwind a stack frame using DWARF unwinding info, updating the register context. | 1557 | /// Unwind a stack frame using DWARF unwinding info, updating the register context. |
| 1557 | /// | 1558 | /// |
| 1558 | /// If `.eh_frame_hdr` is available, it will be used to binary search for the FDE. | 1559 | /// If `.eh_frame_hdr` is available and complete, it will be used to binary search for the FDE. |
| 1559 | /// Otherwise, a linear scan of `.eh_frame` and `.debug_frame` is done to find the FDE. | 1560 | /// Otherwise, a linear scan of `.eh_frame` and `.debug_frame` is done to find the FDE. The latter |
| 1561 | /// may require lazily loading the data in those sections. | ||
| 1560 | /// | 1562 | /// |
| 1561 | /// `explicit_fde_offset` is for cases where the FDE offset is known, such as when __unwind_info | 1563 | /// `explicit_fde_offset` is for cases where the FDE offset is known, such as when __unwind_info |
| 1562 | /// defers unwinding to DWARF. This is an offset into the `.eh_frame` section. | 1564 | /// defers unwinding to DWARF. This is an offset into the `.eh_frame` section. |
| 1563 | pub fn unwindFrameDwarf( | 1565 | pub fn unwindFrameDwarf( |
| 1564 | di: *const Dwarf, | 1566 | allocator: Allocator, |
| 1567 | di: *Dwarf, | ||
| 1568 | base_address: usize, | ||
| 1565 | context: *UnwindContext, | 1569 | context: *UnwindContext, |
| 1566 | ma: *std.debug.MemoryAccessor, | 1570 | ma: *std.debug.MemoryAccessor, |
| 1567 | explicit_fde_offset: ?usize, | 1571 | explicit_fde_offset: ?usize, |
| ... | @@ -1570,10 +1574,7 @@ pub fn unwindFrameDwarf( | ... | @@ -1570,10 +1574,7 @@ pub fn unwindFrameDwarf( |
| 1570 | if (context.pc == 0) return 0; | 1574 | if (context.pc == 0) return 0; |
| 1571 | 1575 | ||
| 1572 | // Find the FDE and CIE | 1576 | // Find the FDE and CIE |
| 1573 | var cie: Dwarf.CommonInformationEntry = undefined; | 1577 | const cie, const fde = if (explicit_fde_offset) |fde_offset| blk: { |
| 1574 | var fde: Dwarf.FrameDescriptionEntry = undefined; | ||
| 1575 | |||
| 1576 | if (explicit_fde_offset) |fde_offset| { | ||
| 1577 | const dwarf_section: Dwarf.Section.Id = .eh_frame; | 1578 | const dwarf_section: Dwarf.Section.Id = .eh_frame; |
| 1578 | const frame_section = di.section(dwarf_section) orelse return error.MissingFDE; | 1579 | const frame_section = di.section(dwarf_section) orelse return error.MissingFDE; |
| 1579 | if (fde_offset >= frame_section.len) return error.MissingFDE; | 1580 | if (fde_offset >= frame_section.len) return error.MissingFDE; |
| ... | @@ -1594,7 +1595,7 @@ pub fn unwindFrameDwarf( | ... | @@ -1594,7 +1595,7 @@ pub fn unwindFrameDwarf( |
| 1594 | const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, null, dwarf_section); | 1595 | const cie_entry_header = try Dwarf.EntryHeader.read(&fbr, null, dwarf_section); |
| 1595 | if (cie_entry_header.type != .cie) return Dwarf.bad(); | 1596 | if (cie_entry_header.type != .cie) return Dwarf.bad(); |
| 1596 | 1597 | ||
| 1597 | cie = try Dwarf.CommonInformationEntry.parse( | 1598 | const cie = try Dwarf.CommonInformationEntry.parse( |
| 1598 | cie_entry_header.entry_bytes, | 1599 | cie_entry_header.entry_bytes, |
| 1599 | 0, | 1600 | 0, |
| 1600 | true, | 1601 | true, |
| ... | @@ -1604,8 +1605,7 @@ pub fn unwindFrameDwarf( | ... | @@ -1604,8 +1605,7 @@ pub fn unwindFrameDwarf( |
| 1604 | @sizeOf(usize), | 1605 | @sizeOf(usize), |
| 1605 | native_endian, | 1606 | native_endian, |
| 1606 | ); | 1607 | ); |
| 1607 | 1608 | const fde = try Dwarf.FrameDescriptionEntry.parse( | |
| 1608 | fde = try Dwarf.FrameDescriptionEntry.parse( | ||
| 1609 | fde_entry_header.entry_bytes, | 1609 | fde_entry_header.entry_bytes, |
| 1610 | 0, | 1610 | 0, |
| 1611 | true, | 1611 | true, |
| ... | @@ -1613,17 +1613,44 @@ pub fn unwindFrameDwarf( | ... | @@ -1613,17 +1613,44 @@ pub fn unwindFrameDwarf( |
| 1613 | @sizeOf(usize), | 1613 | @sizeOf(usize), |
| 1614 | native_endian, | 1614 | native_endian, |
| 1615 | ); | 1615 | ); |
| 1616 | } else if (di.eh_frame_hdr) |header| { | 1616 | |
| 1617 | const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null; | 1617 | break :blk .{ cie, fde }; |
| 1618 | try header.findEntry( | 1618 | } else blk: { |
| 1619 | ma, | 1619 | // `.eh_frame_hdr` may be incomplete. We'll try it first, but if the lookup fails, we fall |
| 1620 | eh_frame_len, | 1620 | // back to loading `.eh_frame`/`.debug_frame` and using those from that point on. |
| 1621 | @intFromPtr(di.section(.eh_frame_hdr).?.ptr), | 1621 | |
| 1622 | context.pc, | 1622 | if (di.eh_frame_hdr) |header| hdr: { |
| 1623 | &cie, | 1623 | const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null; |
| 1624 | &fde, | 1624 | |
| 1625 | ); | 1625 | var cie: Dwarf.CommonInformationEntry = undefined; |
| 1626 | } else { | 1626 | var fde: Dwarf.FrameDescriptionEntry = undefined; |
| 1627 | |||
| 1628 | header.findEntry( | ||
| 1629 | ma, | ||
| 1630 | eh_frame_len, | ||
| 1631 | @intFromPtr(di.section(.eh_frame_hdr).?.ptr), | ||
| 1632 | context.pc, | ||
| 1633 | &cie, | ||
| 1634 | &fde, | ||
| 1635 | ) catch |err| switch (err) { | ||
| 1636 | error.InvalidDebugInfo => { | ||
| 1637 | // `.eh_frame_hdr` appears to be incomplete, so go ahead and populate `cie_map` | ||
| 1638 | // and `fde_list`, and fall back to the binary search logic below. | ||
| 1639 | try di.scanCieFdeInfo(allocator, base_address); | ||
| 1640 | |||
| 1641 | // Since `.eh_frame_hdr` is incomplete, we're very likely to get more lookup | ||
| 1642 | // failures using it, and we've just built a complete, sorted list of FDEs | ||
| 1643 | // anyway, so just stop using `.eh_frame_hdr` altogether. | ||
| 1644 | di.eh_frame_hdr = null; | ||
| 1645 | |||
| 1646 | break :hdr; | ||
| 1647 | }, | ||
| 1648 | else => return err, | ||
| 1649 | }; | ||
| 1650 | |||
| 1651 | break :blk .{ cie, fde }; | ||
| 1652 | } | ||
| 1653 | |||
| 1627 | const index = std.sort.binarySearch(Dwarf.FrameDescriptionEntry, di.fde_list.items, context.pc, struct { | 1654 | const index = std.sort.binarySearch(Dwarf.FrameDescriptionEntry, di.fde_list.items, context.pc, struct { |
| 1628 | pub fn compareFn(pc: usize, item: Dwarf.FrameDescriptionEntry) std.math.Order { | 1655 | pub fn compareFn(pc: usize, item: Dwarf.FrameDescriptionEntry) std.math.Order { |
| 1629 | if (pc < item.pc_begin) return .lt; | 1656 | if (pc < item.pc_begin) return .lt; |
| ... | @@ -1635,9 +1662,11 @@ pub fn unwindFrameDwarf( | ... | @@ -1635,9 +1662,11 @@ pub fn unwindFrameDwarf( |
| 1635 | } | 1662 | } |
| 1636 | }.compareFn); | 1663 | }.compareFn); |
| 1637 | 1664 | ||
| 1638 | fde = if (index) |i| di.fde_list.items[i] else return error.MissingFDE; | 1665 | const fde = if (index) |i| di.fde_list.items[i] else return error.MissingFDE; |
| 1639 | cie = di.cie_map.get(fde.cie_length_offset) orelse return error.MissingCIE; | 1666 | const cie = di.cie_map.get(fde.cie_length_offset) orelse return error.MissingCIE; |
| 1640 | } | 1667 | |
| 1668 | break :blk .{ cie, fde }; | ||
| 1669 | }; | ||
| 1641 | 1670 | ||
| 1642 | var expression_context: Dwarf.expression.Context = .{ | 1671 | var expression_context: Dwarf.expression.Context = .{ |
| 1643 | .format = cie.format, | 1672 | .format = cie.format, |
| ... | @@ -1802,6 +1831,8 @@ pub fn supportsUnwinding(target: std.Target) bool { | ... | @@ -1802,6 +1831,8 @@ pub fn supportsUnwinding(target: std.Target) bool { |
| 1802 | } | 1831 | } |
| 1803 | 1832 | ||
| 1804 | fn unwindFrameMachODwarf( | 1833 | fn unwindFrameMachODwarf( |
| 1834 | allocator: Allocator, | ||
| 1835 | base_address: usize, | ||
| 1805 | context: *UnwindContext, | 1836 | context: *UnwindContext, |
| 1806 | ma: *std.debug.MemoryAccessor, | 1837 | ma: *std.debug.MemoryAccessor, |
| 1807 | eh_frame: []const u8, | 1838 | eh_frame: []const u8, |
| ... | @@ -1818,7 +1849,7 @@ fn unwindFrameMachODwarf( | ... | @@ -1818,7 +1849,7 @@ fn unwindFrameMachODwarf( |
| 1818 | .owned = false, | 1849 | .owned = false, |
| 1819 | }; | 1850 | }; |
| 1820 | 1851 | ||
| 1821 | return unwindFrameDwarf(&di, context, ma, fde_offset); | 1852 | return unwindFrameDwarf(allocator, &di, base_address, context, ma, fde_offset); |
| 1822 | } | 1853 | } |
| 1823 | 1854 | ||
| 1824 | /// This is a virtual machine that runs DWARF call frame instructions. | 1855 | /// This is a virtual machine that runs DWARF call frame instructions. |
src/Compilation.zig+4-5| ... | @@ -1274,15 +1274,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil | ... | @@ -1274,15 +1274,12 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil |
| 1274 | // The "any" values provided by resolved config only account for | 1274 | // The "any" values provided by resolved config only account for |
| 1275 | // explicitly-provided settings. We now make them additionally account | 1275 | // explicitly-provided settings. We now make them additionally account |
| 1276 | // for default setting resolution. | 1276 | // for default setting resolution. |
| 1277 | const any_unwind_tables = switch (options.config.any_unwind_tables) { | 1277 | const any_unwind_tables = options.config.any_unwind_tables or options.root_mod.unwind_tables != .none; |
| 1278 | .none => options.root_mod.unwind_tables, | ||
| 1279 | .sync, .@"async" => |uwt| uwt, | ||
| 1280 | }; | ||
| 1281 | const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded; | 1278 | const any_non_single_threaded = options.config.any_non_single_threaded or !options.root_mod.single_threaded; |
| 1282 | const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread; | 1279 | const any_sanitize_thread = options.config.any_sanitize_thread or options.root_mod.sanitize_thread; |
| 1283 | const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz; | 1280 | const any_fuzz = options.config.any_fuzz or options.root_mod.fuzz; |
| 1284 | 1281 | ||
| 1285 | const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables != .none; | 1282 | const link_eh_frame_hdr = options.link_eh_frame_hdr or any_unwind_tables; |
| 1286 | const build_id = options.build_id orelse .none; | 1283 | const build_id = options.build_id orelse .none; |
| 1287 | 1284 | ||
| 1288 | const link_libc = options.config.link_libc; | 1285 | const link_libc = options.config.link_libc; |
| ... | @@ -6459,6 +6456,7 @@ fn buildOutputFromZig( | ... | @@ -6459,6 +6456,7 @@ fn buildOutputFromZig( |
| 6459 | .root_optimize_mode = optimize_mode, | 6456 | .root_optimize_mode = optimize_mode, |
| 6460 | .root_strip = strip, | 6457 | .root_strip = strip, |
| 6461 | .link_libc = comp.config.link_libc, | 6458 | .link_libc = comp.config.link_libc, |
| 6459 | .any_unwind_tables = comp.root_mod.unwind_tables != .none, | ||
| 6462 | }); | 6460 | }); |
| 6463 | 6461 | ||
| 6464 | const root_mod = try Package.Module.create(arena, .{ | 6462 | const root_mod = try Package.Module.create(arena, .{ |
| ... | @@ -6595,6 +6593,7 @@ pub fn build_crt_file( | ... | @@ -6595,6 +6593,7 @@ pub fn build_crt_file( |
| 6595 | .root_optimize_mode = comp.compilerRtOptMode(), | 6593 | .root_optimize_mode = comp.compilerRtOptMode(), |
| 6596 | .root_strip = comp.compilerRtStrip(), | 6594 | .root_strip = comp.compilerRtStrip(), |
| 6597 | .link_libc = false, | 6595 | .link_libc = false, |
| 6596 | .any_unwind_tables = options.unwind_tables != .none, | ||
| 6598 | .lto = switch (output_mode) { | 6597 | .lto = switch (output_mode) { |
| 6599 | .Lib => comp.config.lto, | 6598 | .Lib => comp.config.lto, |
| 6600 | .Obj, .Exe => .none, | 6599 | .Obj, .Exe => .none, |
src/Compilation/Config.zig+8-13| ... | @@ -12,14 +12,13 @@ link_libunwind: bool, | ... | @@ -12,14 +12,13 @@ link_libunwind: bool, |
| 12 | /// True if and only if the c_source_files field will have nonzero length when | 12 | /// True if and only if the c_source_files field will have nonzero length when |
| 13 | /// calling Compilation.create. | 13 | /// calling Compilation.create. |
| 14 | any_c_source_files: bool, | 14 | any_c_source_files: bool, |
| 15 | /// This is not `.none` if any `Module` has `unwind_tables` set explicitly to a | 15 | /// This is `true` if any `Module` has `unwind_tables` set explicitly to a |
| 16 | /// value other than `.none`. Until `Compilation.create()` is called, it is | 16 | /// value other than `.none`. Until `Compilation.create()` is called, it is |
| 17 | /// possible for this to be `.none` while in fact all `Module` instances have | 17 | /// possible for this to be `false` while in fact all `Module` instances have |
| 18 | /// `unwind_tables != .none` due to the default. After `Compilation.create()` is | 18 | /// `unwind_tables != .none` due to the default. After `Compilation.create()` is |
| 19 | /// called, this will also take into account the default setting, making this | 19 | /// called, this will also take into account the default setting, making this |
| 20 | /// value `.sync` or `.@"async"` if and only if any `Module` has | 20 | /// value `true` if and only if any `Module` has `unwind_tables != .none`. |
| 21 | /// `unwind_tables != .none`. | 21 | any_unwind_tables: bool, |
| 22 | any_unwind_tables: std.builtin.UnwindTables, | ||
| 23 | /// This is true if any Module has single_threaded set explicitly to false. Until | 22 | /// This is true if any Module has single_threaded set explicitly to false. Until |
| 24 | /// Compilation.create is called, it is possible for this to be false while in | 23 | /// Compilation.create is called, it is possible for this to be false while in |
| 25 | /// fact all Module instances have single_threaded=false due to the default | 24 | /// fact all Module instances have single_threaded=false due to the default |
| ... | @@ -57,6 +56,7 @@ export_memory: bool, | ... | @@ -57,6 +56,7 @@ export_memory: bool, |
| 57 | shared_memory: bool, | 56 | shared_memory: bool, |
| 58 | is_test: bool, | 57 | is_test: bool, |
| 59 | debug_format: DebugFormat, | 58 | debug_format: DebugFormat, |
| 59 | root_optimize_mode: std.builtin.OptimizeMode, | ||
| 60 | root_strip: bool, | 60 | root_strip: bool, |
| 61 | root_error_tracing: bool, | 61 | root_error_tracing: bool, |
| 62 | dll_export_fns: bool, | 62 | dll_export_fns: bool, |
| ... | @@ -88,7 +88,7 @@ pub const Options = struct { | ... | @@ -88,7 +88,7 @@ pub const Options = struct { |
| 88 | any_non_single_threaded: bool = false, | 88 | any_non_single_threaded: bool = false, |
| 89 | any_sanitize_thread: bool = false, | 89 | any_sanitize_thread: bool = false, |
| 90 | any_fuzz: bool = false, | 90 | any_fuzz: bool = false, |
| 91 | any_unwind_tables: std.builtin.UnwindTables = .none, | 91 | any_unwind_tables: bool = false, |
| 92 | any_dyn_libs: bool = false, | 92 | any_dyn_libs: bool = false, |
| 93 | any_c_source_files: bool = false, | 93 | any_c_source_files: bool = false, |
| 94 | any_non_stripped: bool = false, | 94 | any_non_stripped: bool = false, |
| ... | @@ -359,12 +359,6 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -359,12 +359,6 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 359 | break :b false; | 359 | break :b false; |
| 360 | }; | 360 | }; |
| 361 | 361 | ||
| 362 | const any_unwind_tables = b: { | ||
| 363 | if (options.any_unwind_tables != .none) break :b options.any_unwind_tables; | ||
| 364 | |||
| 365 | break :b target_util.needUnwindTables(target, link_libunwind, options.any_sanitize_thread); | ||
| 366 | }; | ||
| 367 | |||
| 368 | const link_mode = b: { | 362 | const link_mode = b: { |
| 369 | const explicitly_exe_or_dyn_lib = switch (options.output_mode) { | 363 | const explicitly_exe_or_dyn_lib = switch (options.output_mode) { |
| 370 | .Obj => false, | 364 | .Obj => false, |
| ... | @@ -496,7 +490,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -496,7 +490,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 496 | .link_libc = link_libc, | 490 | .link_libc = link_libc, |
| 497 | .link_libcpp = link_libcpp, | 491 | .link_libcpp = link_libcpp, |
| 498 | .link_libunwind = link_libunwind, | 492 | .link_libunwind = link_libunwind, |
| 499 | .any_unwind_tables = any_unwind_tables, | 493 | .any_unwind_tables = options.any_unwind_tables, |
| 500 | .any_c_source_files = options.any_c_source_files, | 494 | .any_c_source_files = options.any_c_source_files, |
| 501 | .any_non_single_threaded = options.any_non_single_threaded, | 495 | .any_non_single_threaded = options.any_non_single_threaded, |
| 502 | .any_error_tracing = any_error_tracing, | 496 | .any_error_tracing = any_error_tracing, |
| ... | @@ -515,6 +509,7 @@ pub fn resolve(options: Options) ResolveError!Config { | ... | @@ -515,6 +509,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 515 | .use_lld = use_lld, | 509 | .use_lld = use_lld, |
| 516 | .wasi_exec_model = wasi_exec_model, | 510 | .wasi_exec_model = wasi_exec_model, |
| 517 | .debug_format = debug_format, | 511 | .debug_format = debug_format, |
| 512 | .root_optimize_mode = root_optimize_mode, | ||
| 518 | .root_strip = root_strip, | 513 | .root_strip = root_strip, |
| 519 | .dll_export_fns = dll_export_fns, | 514 | .dll_export_fns = dll_export_fns, |
| 520 | .rdynamic = rdynamic, | 515 | .rdynamic = rdynamic, |
src/Package/Module.zig+13-5| ... | @@ -112,17 +112,14 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { | ... | @@ -112,17 +112,14 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 112 | if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread); | 112 | if (options.inherited.sanitize_thread == true) assert(options.global.any_sanitize_thread); |
| 113 | if (options.inherited.fuzz == true) assert(options.global.any_fuzz); | 113 | if (options.inherited.fuzz == true) assert(options.global.any_fuzz); |
| 114 | if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded); | 114 | if (options.inherited.single_threaded == false) assert(options.global.any_non_single_threaded); |
| 115 | if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables != .none); | 115 | if (options.inherited.unwind_tables) |uwt| if (uwt != .none) assert(options.global.any_unwind_tables); |
| 116 | if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing); | 116 | if (options.inherited.error_tracing == true) assert(options.global.any_error_tracing); |
| 117 | 117 | ||
| 118 | const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target; | 118 | const resolved_target = options.inherited.resolved_target orelse options.parent.?.resolved_target; |
| 119 | const target = resolved_target.result; | 119 | const target = resolved_target.result; |
| 120 | 120 | ||
| 121 | const optimize_mode = options.inherited.optimize_mode orelse | 121 | const optimize_mode = options.inherited.optimize_mode orelse |
| 122 | if (options.parent) |p| p.optimize_mode else .Debug; | 122 | if (options.parent) |p| p.optimize_mode else options.global.root_optimize_mode; |
| 123 | |||
| 124 | const unwind_tables = options.inherited.unwind_tables orelse | ||
| 125 | if (options.parent) |p| p.unwind_tables else options.global.any_unwind_tables; | ||
| 126 | 123 | ||
| 127 | const strip = b: { | 124 | const strip = b: { |
| 128 | if (options.inherited.strip) |x| break :b x; | 125 | if (options.inherited.strip) |x| break :b x; |
| ... | @@ -220,6 +217,17 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { | ... | @@ -220,6 +217,17 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 220 | break :b false; | 217 | break :b false; |
| 221 | }; | 218 | }; |
| 222 | 219 | ||
| 220 | const unwind_tables = b: { | ||
| 221 | if (options.inherited.unwind_tables) |x| break :b x; | ||
| 222 | if (options.parent) |p| break :b p.unwind_tables; | ||
| 223 | |||
| 224 | break :b target_util.defaultUnwindTables( | ||
| 225 | target, | ||
| 226 | options.global.link_libunwind, | ||
| 227 | sanitize_thread or options.global.any_sanitize_thread, | ||
| 228 | ); | ||
| 229 | }; | ||
| 230 | |||
| 223 | const fuzz = b: { | 231 | const fuzz = b: { |
| 224 | if (options.inherited.fuzz) |x| break :b x; | 232 | if (options.inherited.fuzz) |x| break :b x; |
| 225 | if (options.parent) |p| break :b p.fuzz; | 233 | if (options.parent) |p| break :b p.fuzz; |
src/libcxx.zig+6-6| ... | @@ -397,6 +397,10 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -397,6 +397,10 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 397 | 397 | ||
| 398 | const optimize_mode = comp.compilerRtOptMode(); | 398 | const optimize_mode = comp.compilerRtOptMode(); |
| 399 | const strip = comp.compilerRtStrip(); | 399 | const strip = comp.compilerRtStrip(); |
| 400 | // See the `-fno-exceptions` logic for WASI. | ||
| 401 | // The old 32-bit x86 variant of SEH doesn't use tables. | ||
| 402 | const unwind_tables: std.builtin.UnwindTables = | ||
| 403 | if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows)) .none else .@"async"; | ||
| 400 | 404 | ||
| 401 | const config = Compilation.Config.resolve(.{ | 405 | const config = Compilation.Config.resolve(.{ |
| 402 | .output_mode = output_mode, | 406 | .output_mode = output_mode, |
| ... | @@ -408,6 +412,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -408,6 +412,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 408 | .root_optimize_mode = optimize_mode, | 412 | .root_optimize_mode = optimize_mode, |
| 409 | .root_strip = strip, | 413 | .root_strip = strip, |
| 410 | .link_libc = true, | 414 | .link_libc = true, |
| 415 | .any_unwind_tables = unwind_tables != .none, | ||
| 411 | .lto = comp.config.lto, | 416 | .lto = comp.config.lto, |
| 412 | .any_sanitize_thread = comp.config.any_sanitize_thread, | 417 | .any_sanitize_thread = comp.config.any_sanitize_thread, |
| 413 | }) catch |err| { | 418 | }) catch |err| { |
| ... | @@ -438,12 +443,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -438,12 +443,7 @@ pub fn buildLibCxxAbi(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 438 | .valgrind = false, | 443 | .valgrind = false, |
| 439 | .optimize_mode = optimize_mode, | 444 | .optimize_mode = optimize_mode, |
| 440 | .structured_cfg = comp.root_mod.structured_cfg, | 445 | .structured_cfg = comp.root_mod.structured_cfg, |
| 441 | // See the `-fno-exceptions` logic for WASI. | 446 | .unwind_tables = unwind_tables, |
| 442 | // The old 32-bit x86 variant of SEH doesn't use tables. | ||
| 443 | .unwind_tables = if (target.os.tag == .wasi or (target.cpu.arch == .x86 and target.os.tag == .windows)) | ||
| 444 | .none | ||
| 445 | else | ||
| 446 | .@"async", | ||
| 447 | .pic = comp.root_mod.pic, | 447 | .pic = comp.root_mod.pic, |
| 448 | }, | 448 | }, |
| 449 | .global = config, | 449 | .global = config, |
src/libunwind.zig+5-2| ... | @@ -27,6 +27,9 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -27,6 +27,9 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 27 | const arena = arena_allocator.allocator(); | 27 | const arena = arena_allocator.allocator(); |
| 28 | 28 | ||
| 29 | const output_mode = .Lib; | 29 | const output_mode = .Lib; |
| 30 | const target = comp.root_mod.resolved_target.result; | ||
| 31 | const unwind_tables: std.builtin.UnwindTables = | ||
| 32 | if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async"; | ||
| 30 | const config = Compilation.Config.resolve(.{ | 33 | const config = Compilation.Config.resolve(.{ |
| 31 | .output_mode = .Lib, | 34 | .output_mode = .Lib, |
| 32 | .resolved_target = comp.root_mod.resolved_target, | 35 | .resolved_target = comp.root_mod.resolved_target, |
| ... | @@ -36,6 +39,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -36,6 +39,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 36 | .root_optimize_mode = comp.compilerRtOptMode(), | 39 | .root_optimize_mode = comp.compilerRtOptMode(), |
| 37 | .root_strip = comp.compilerRtStrip(), | 40 | .root_strip = comp.compilerRtStrip(), |
| 38 | .link_libc = true, | 41 | .link_libc = true, |
| 42 | .any_unwind_tables = unwind_tables != .none, | ||
| 39 | .lto = comp.config.lto, | 43 | .lto = comp.config.lto, |
| 40 | }) catch |err| { | 44 | }) catch |err| { |
| 41 | comp.setMiscFailure( | 45 | comp.setMiscFailure( |
| ... | @@ -45,7 +49,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -45,7 +49,6 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 45 | ); | 49 | ); |
| 46 | return error.SubCompilationFailed; | 50 | return error.SubCompilationFailed; |
| 47 | }; | 51 | }; |
| 48 | const target = comp.root_mod.resolved_target.result; | ||
| 49 | const root_mod = Module.create(arena, .{ | 52 | const root_mod = Module.create(arena, .{ |
| 50 | .global_cache_directory = comp.global_cache_directory, | 53 | .global_cache_directory = comp.global_cache_directory, |
| 51 | .paths = .{ | 54 | .paths = .{ |
| ... | @@ -65,7 +68,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr | ... | @@ -65,7 +68,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr |
| 65 | .sanitize_thread = false, | 68 | .sanitize_thread = false, |
| 66 | // necessary so that libunwind can unwind through its own stack frames | 69 | // necessary so that libunwind can unwind through its own stack frames |
| 67 | // The old 32-bit x86 variant of SEH doesn't use tables. | 70 | // The old 32-bit x86 variant of SEH doesn't use tables. |
| 68 | .unwind_tables = if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async", | 71 | .unwind_tables = unwind_tables, |
| 69 | .pic = if (target_util.supports_fpic(target)) true else null, | 72 | .pic = if (target_util.supports_fpic(target)) true else null, |
| 70 | .optimize_mode = comp.compilerRtOptMode(), | 73 | .optimize_mode = comp.compilerRtOptMode(), |
| 71 | }, | 74 | }, |
src/main.zig+5-12| ... | @@ -575,6 +575,7 @@ const usage_build_generic = | ... | @@ -575,6 +575,7 @@ const usage_build_generic = |
| 575 | \\ 0x[hexstring] Maximum 32 bytes | 575 | \\ 0x[hexstring] Maximum 32 bytes |
| 576 | \\ none (default) Disable build-id | 576 | \\ none (default) Disable build-id |
| 577 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker | 577 | \\ --eh-frame-hdr Enable C++ exception handling by passing --eh-frame-hdr to linker |
| 578 | \\ --no-eh-frame-hdr Disable C++ exception handling by passing --no-eh-frame-hdr to linker | ||
| 578 | \\ --emit-relocs Enable output of relocation sections for post build tools | 579 | \\ --emit-relocs Enable output of relocation sections for post build tools |
| 579 | \\ -z [arg] Set linker extension flags | 580 | \\ -z [arg] Set linker extension flags |
| 580 | \\ nodelete Indicate that the object cannot be deleted from a process | 581 | \\ nodelete Indicate that the object cannot be deleted from a process |
| ... | @@ -1582,6 +1583,8 @@ fn buildOutputType( | ... | @@ -1582,6 +1583,8 @@ fn buildOutputType( |
| 1582 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); | 1583 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); |
| 1583 | } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { | 1584 | } else if (mem.eql(u8, arg, "--eh-frame-hdr")) { |
| 1584 | link_eh_frame_hdr = true; | 1585 | link_eh_frame_hdr = true; |
| 1586 | } else if (mem.eql(u8, arg, "--no-eh-frame-hdr")) { | ||
| 1587 | link_eh_frame_hdr = false; | ||
| 1585 | } else if (mem.eql(u8, arg, "--dynamicbase")) { | 1588 | } else if (mem.eql(u8, arg, "--dynamicbase")) { |
| 1586 | linker_dynamicbase = true; | 1589 | linker_dynamicbase = true; |
| 1587 | } else if (mem.eql(u8, arg, "--no-dynamicbase")) { | 1590 | } else if (mem.eql(u8, arg, "--no-dynamicbase")) { |
| ... | @@ -2846,12 +2849,7 @@ fn buildOutputType( | ... | @@ -2846,12 +2849,7 @@ fn buildOutputType( |
| 2846 | create_module.opts.any_fuzz = true; | 2849 | create_module.opts.any_fuzz = true; |
| 2847 | if (mod_opts.unwind_tables) |uwt| switch (uwt) { | 2850 | if (mod_opts.unwind_tables) |uwt| switch (uwt) { |
| 2848 | .none => {}, | 2851 | .none => {}, |
| 2849 | .sync => if (create_module.opts.any_unwind_tables == .none) { | 2852 | .sync, .@"async" => create_module.opts.any_unwind_tables = true, |
| 2850 | create_module.opts.any_unwind_tables = .sync; | ||
| 2851 | }, | ||
| 2852 | .@"async" => { | ||
| 2853 | create_module.opts.any_unwind_tables = .@"async"; | ||
| 2854 | }, | ||
| 2855 | }; | 2853 | }; |
| 2856 | if (mod_opts.strip == false) | 2854 | if (mod_opts.strip == false) |
| 2857 | create_module.opts.any_non_stripped = true; | 2855 | create_module.opts.any_non_stripped = true; |
| ... | @@ -7563,12 +7561,7 @@ fn handleModArg( | ... | @@ -7563,12 +7561,7 @@ fn handleModArg( |
| 7563 | create_module.opts.any_fuzz = true; | 7561 | create_module.opts.any_fuzz = true; |
| 7564 | if (mod_opts.unwind_tables) |uwt| switch (uwt) { | 7562 | if (mod_opts.unwind_tables) |uwt| switch (uwt) { |
| 7565 | .none => {}, | 7563 | .none => {}, |
| 7566 | .sync => if (create_module.opts.any_unwind_tables == .none) { | 7564 | .sync, .@"async" => create_module.opts.any_unwind_tables = true, |
| 7567 | create_module.opts.any_unwind_tables = .sync; | ||
| 7568 | }, | ||
| 7569 | .@"async" => { | ||
| 7570 | create_module.opts.any_unwind_tables = .@"async"; | ||
| 7571 | }, | ||
| 7572 | }; | 7565 | }; |
| 7573 | if (mod_opts.strip == false) | 7566 | if (mod_opts.strip == false) |
| 7574 | create_module.opts.any_non_stripped = true; | 7567 | create_module.opts.any_non_stripped = true; |
src/target.zig+1-1| ... | @@ -407,7 +407,7 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool { | ... | @@ -407,7 +407,7 @@ pub fn clangSupportsNoImplicitFloatArg(target: std.Target) bool { |
| 407 | }; | 407 | }; |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | pub fn needUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables { | 410 | pub fn defaultUnwindTables(target: std.Target, libunwind: bool, libtsan: bool) std.builtin.UnwindTables { |
| 411 | if (target.os.tag == .windows) { | 411 | if (target.os.tag == .windows) { |
| 412 | // The old 32-bit x86 variant of SEH doesn't use tables. | 412 | // The old 32-bit x86 variant of SEH doesn't use tables. |
| 413 | return if (target.cpu.arch != .x86) .@"async" else .none; | 413 | return if (target.cpu.arch != .x86) .@"async" else .none; |
test/src/StackTrace.zig+25-6| ... | @@ -21,17 +21,34 @@ const Config = struct { | ... | @@ -21,17 +21,34 @@ const Config = struct { |
| 21 | }; | 21 | }; |
| 22 | 22 | ||
| 23 | pub fn addCase(self: *StackTrace, config: Config) void { | 23 | pub fn addCase(self: *StackTrace, config: Config) void { |
| 24 | self.addCaseInner(config, true); | ||
| 25 | if (shouldTestNonLlvm(self.b.graph.host.result)) { | ||
| 26 | self.addCaseInner(config, false); | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | fn addCaseInner(self: *StackTrace, config: Config, use_llvm: bool) void { | ||
| 24 | if (config.Debug) |per_mode| | 31 | if (config.Debug) |per_mode| |
| 25 | self.addExpect(config.name, config.source, .Debug, per_mode); | 32 | self.addExpect(config.name, config.source, .Debug, use_llvm, per_mode); |
| 26 | 33 | ||
| 27 | if (config.ReleaseSmall) |per_mode| | 34 | if (config.ReleaseSmall) |per_mode| |
| 28 | self.addExpect(config.name, config.source, .ReleaseSmall, per_mode); | 35 | self.addExpect(config.name, config.source, .ReleaseSmall, use_llvm, per_mode); |
| 29 | 36 | ||
| 30 | if (config.ReleaseFast) |per_mode| | 37 | if (config.ReleaseFast) |per_mode| |
| 31 | self.addExpect(config.name, config.source, .ReleaseFast, per_mode); | 38 | self.addExpect(config.name, config.source, .ReleaseFast, use_llvm, per_mode); |
| 32 | 39 | ||
| 33 | if (config.ReleaseSafe) |per_mode| | 40 | if (config.ReleaseSafe) |per_mode| |
| 34 | self.addExpect(config.name, config.source, .ReleaseSafe, per_mode); | 41 | self.addExpect(config.name, config.source, .ReleaseSafe, use_llvm, per_mode); |
| 42 | } | ||
| 43 | |||
| 44 | fn shouldTestNonLlvm(target: std.Target) bool { | ||
| 45 | return switch (target.cpu.arch) { | ||
| 46 | .x86_64 => switch (target.ofmt) { | ||
| 47 | .elf => true, | ||
| 48 | else => false, | ||
| 49 | }, | ||
| 50 | else => false, | ||
| 51 | }; | ||
| 35 | } | 52 | } |
| 36 | 53 | ||
| 37 | fn addExpect( | 54 | fn addExpect( |
| ... | @@ -39,13 +56,14 @@ fn addExpect( | ... | @@ -39,13 +56,14 @@ fn addExpect( |
| 39 | name: []const u8, | 56 | name: []const u8, |
| 40 | source: []const u8, | 57 | source: []const u8, |
| 41 | optimize_mode: OptimizeMode, | 58 | optimize_mode: OptimizeMode, |
| 59 | use_llvm: bool, | ||
| 42 | mode_config: Config.PerMode, | 60 | mode_config: Config.PerMode, |
| 43 | ) void { | 61 | ) void { |
| 44 | for (mode_config.exclude_os) |tag| if (tag == builtin.os.tag) return; | 62 | for (mode_config.exclude_os) |tag| if (tag == builtin.os.tag) return; |
| 45 | 63 | ||
| 46 | const b = self.b; | 64 | const b = self.b; |
| 47 | const annotated_case_name = b.fmt("check {s} ({s})", .{ | 65 | const annotated_case_name = b.fmt("check {s} ({s} {s})", .{ |
| 48 | name, @tagName(optimize_mode), | 66 | name, @tagName(optimize_mode), if (use_llvm) "llvm" else "selfhosted", |
| 49 | }); | 67 | }); |
| 50 | for (self.test_filters) |test_filter| { | 68 | for (self.test_filters) |test_filter| { |
| 51 | if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; | 69 | if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break; |
| ... | @@ -61,6 +79,7 @@ fn addExpect( | ... | @@ -61,6 +79,7 @@ fn addExpect( |
| 61 | .target = b.graph.host, | 79 | .target = b.graph.host, |
| 62 | .error_tracing = mode_config.error_tracing, | 80 | .error_tracing = mode_config.error_tracing, |
| 63 | }), | 81 | }), |
| 82 | .use_llvm = use_llvm, | ||
| 64 | }); | 83 | }); |
| 65 | 84 | ||
| 66 | const run = b.addRunArtifact(exe); | 85 | const run = b.addRunArtifact(exe); |
test/src/check-stack-trace.zig+15-6| ... | @@ -58,14 +58,23 @@ pub fn main() !void { | ... | @@ -58,14 +58,23 @@ pub fn main() !void { |
| 58 | try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]); | 58 | try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]); |
| 59 | try buf.appendSlice(" [address]"); | 59 | try buf.appendSlice(" [address]"); |
| 60 | if (optimize_mode == .Debug) { | 60 | if (optimize_mode == .Debug) { |
| 61 | // On certain platforms (windows) or possibly depending on how we choose to link main | 61 | try buf.appendSlice(line[marks[3] .. marks[4] + delims[4].len]); |
| 62 | // the object file extension may be present so we simply strip any extension. | 62 | |
| 63 | if (mem.indexOfScalar(u8, line[marks[4]..marks[5]], '.')) |idot| { | 63 | const file_name = line[marks[4] + delims[4].len .. marks[5]]; |
| 64 | try buf.appendSlice(line[marks[3] .. marks[4] + idot]); | 64 | // The LLVM backend currently uses the object file name in the debug info here. |
| 65 | try buf.appendSlice(line[marks[5]..]); | 65 | // This actually violates the DWARF specification (DWARF5 § 3.1.1, lines 24-27). |
| 66 | // The self-hosted backend uses the root Zig source file of the module (in compilance with the spec). | ||
| 67 | if (std.mem.eql(u8, file_name, "test") or | ||
| 68 | std.mem.eql(u8, file_name, "test.exe.obj") or | ||
| 69 | std.mem.endsWith(u8, file_name, ".zig")) | ||
| 70 | { | ||
| 71 | try buf.appendSlice("[main_file]"); | ||
| 66 | } else { | 72 | } else { |
| 67 | try buf.appendSlice(line[marks[3]..]); | 73 | // Something unexpected; include it verbatim. |
| 74 | try buf.appendSlice(file_name); | ||
| 68 | } | 75 | } |
| 76 | |||
| 77 | try buf.appendSlice(line[marks[5]..]); | ||
| 69 | } else { | 78 | } else { |
| 70 | try buf.appendSlice(line[marks[3] .. marks[3] + delims[3].len]); | 79 | try buf.appendSlice(line[marks[3] .. marks[3] + delims[3].len]); |
| 71 | try buf.appendSlice("[function]"); | 80 | try buf.appendSlice("[function]"); |
test/stack_traces.zig+30-30| ... | @@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 13 | .Debug = .{ | 13 | .Debug = .{ |
| 14 | .expect = | 14 | .expect = |
| 15 | \\error: TheSkyIsFalling | 15 | \\error: TheSkyIsFalling |
| 16 | \\source.zig:2:5: [address] in main (test) | 16 | \\source.zig:2:5: [address] in main ([main_file]) |
| 17 | \\ return error.TheSkyIsFalling; | 17 | \\ return error.TheSkyIsFalling; |
| 18 | \\ ^ | 18 | \\ ^ |
| 19 | \\ | 19 | \\ |
| ... | @@ -61,10 +61,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -61,10 +61,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 61 | .Debug = .{ | 61 | .Debug = .{ |
| 62 | .expect = | 62 | .expect = |
| 63 | \\error: TheSkyIsFalling | 63 | \\error: TheSkyIsFalling |
| 64 | \\source.zig:2:5: [address] in foo (test) | 64 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 65 | \\ return error.TheSkyIsFalling; | 65 | \\ return error.TheSkyIsFalling; |
| 66 | \\ ^ | 66 | \\ ^ |
| 67 | \\source.zig:6:5: [address] in main (test) | 67 | \\source.zig:6:5: [address] in main ([main_file]) |
| 68 | \\ try foo(); | 68 | \\ try foo(); |
| 69 | \\ ^ | 69 | \\ ^ |
| 70 | \\ | 70 | \\ |
| ... | @@ -120,7 +120,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -120,7 +120,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 120 | .Debug = .{ | 120 | .Debug = .{ |
| 121 | .expect = | 121 | .expect = |
| 122 | \\error: UnrelatedError | 122 | \\error: UnrelatedError |
| 123 | \\source.zig:13:5: [address] in main (test) | 123 | \\source.zig:13:5: [address] in main ([main_file]) |
| 124 | \\ return error.UnrelatedError; | 124 | \\ return error.UnrelatedError; |
| 125 | \\ ^ | 125 | \\ ^ |
| 126 | \\ | 126 | \\ |
| ... | @@ -172,7 +172,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -172,7 +172,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 172 | .Debug = .{ | 172 | .Debug = .{ |
| 173 | .expect = | 173 | .expect = |
| 174 | \\error: UnrelatedError | 174 | \\error: UnrelatedError |
| 175 | \\source.zig:10:5: [address] in main (test) | 175 | \\source.zig:10:5: [address] in main ([main_file]) |
| 176 | \\ return error.UnrelatedError; | 176 | \\ return error.UnrelatedError; |
| 177 | \\ ^ | 177 | \\ ^ |
| 178 | \\ | 178 | \\ |
| ... | @@ -224,10 +224,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -224,10 +224,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 224 | .Debug = .{ | 224 | .Debug = .{ |
| 225 | .expect = | 225 | .expect = |
| 226 | \\error: TheSkyIsFalling | 226 | \\error: TheSkyIsFalling |
| 227 | \\source.zig:2:5: [address] in foo (test) | 227 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 228 | \\ return error.TheSkyIsFalling; | 228 | \\ return error.TheSkyIsFalling; |
| 229 | \\ ^ | 229 | \\ ^ |
| 230 | \\source.zig:10:5: [address] in main (test) | 230 | \\source.zig:10:5: [address] in main ([main_file]) |
| 231 | \\ try foo(); | 231 | \\ try foo(); |
| 232 | \\ ^ | 232 | \\ ^ |
| 233 | \\ | 233 | \\ |
| ... | @@ -284,7 +284,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -284,7 +284,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 284 | .Debug = .{ | 284 | .Debug = .{ |
| 285 | .expect = | 285 | .expect = |
| 286 | \\error: BadTime | 286 | \\error: BadTime |
| 287 | \\source.zig:12:5: [address] in main (test) | 287 | \\source.zig:12:5: [address] in main ([main_file]) |
| 288 | \\ return error.BadTime; | 288 | \\ return error.BadTime; |
| 289 | \\ ^ | 289 | \\ ^ |
| 290 | \\ | 290 | \\ |
| ... | @@ -332,10 +332,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -332,10 +332,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 332 | .Debug = .{ | 332 | .Debug = .{ |
| 333 | .expect = | 333 | .expect = |
| 334 | \\error: AndMyCarIsOutOfGas | 334 | \\error: AndMyCarIsOutOfGas |
| 335 | \\source.zig:2:5: [address] in foo (test) | 335 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 336 | \\ return error.TheSkyIsFalling; | 336 | \\ return error.TheSkyIsFalling; |
| 337 | \\ ^ | 337 | \\ ^ |
| 338 | \\source.zig:6:5: [address] in main (test) | 338 | \\source.zig:6:5: [address] in main ([main_file]) |
| 339 | \\ return foo() catch error.AndMyCarIsOutOfGas; | 339 | \\ return foo() catch error.AndMyCarIsOutOfGas; |
| 340 | \\ ^ | 340 | \\ ^ |
| 341 | \\ | 341 | \\ |
| ... | @@ -391,7 +391,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -391,7 +391,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 391 | .Debug = .{ | 391 | .Debug = .{ |
| 392 | .expect = | 392 | .expect = |
| 393 | \\error: SomethingUnrelatedWentWrong | 393 | \\error: SomethingUnrelatedWentWrong |
| 394 | \\source.zig:11:5: [address] in main (test) | 394 | \\source.zig:11:5: [address] in main ([main_file]) |
| 395 | \\ return error.SomethingUnrelatedWentWrong; | 395 | \\ return error.SomethingUnrelatedWentWrong; |
| 396 | \\ ^ | 396 | \\ ^ |
| 397 | \\ | 397 | \\ |
| ... | @@ -456,13 +456,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -456,13 +456,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 456 | .Debug = .{ | 456 | .Debug = .{ |
| 457 | .expect = | 457 | .expect = |
| 458 | \\error: StillUnresolved | 458 | \\error: StillUnresolved |
| 459 | \\source.zig:1:18: [address] in foo (test) | 459 | \\source.zig:1:18: [address] in foo ([main_file]) |
| 460 | \\fn foo() !void { return error.TheSkyIsFalling; } | 460 | \\fn foo() !void { return error.TheSkyIsFalling; } |
| 461 | \\ ^ | 461 | \\ ^ |
| 462 | \\source.zig:2:18: [address] in bar (test) | 462 | \\source.zig:2:18: [address] in bar ([main_file]) |
| 463 | \\fn bar() !void { return error.InternalError; } | 463 | \\fn bar() !void { return error.InternalError; } |
| 464 | \\ ^ | 464 | \\ ^ |
| 465 | \\source.zig:23:5: [address] in main (test) | 465 | \\source.zig:23:5: [address] in main ([main_file]) |
| 466 | \\ return error.StillUnresolved; | 466 | \\ return error.StillUnresolved; |
| 467 | \\ ^ | 467 | \\ ^ |
| 468 | \\ | 468 | \\ |
| ... | @@ -527,13 +527,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -527,13 +527,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 527 | .Debug = .{ | 527 | .Debug = .{ |
| 528 | .expect = | 528 | .expect = |
| 529 | \\error: TestExpectedError | 529 | \\error: TestExpectedError |
| 530 | \\source.zig:9:18: [address] in foo (test) | 530 | \\source.zig:9:18: [address] in foo ([main_file]) |
| 531 | \\fn foo() !void { return error.Foo; } | 531 | \\fn foo() !void { return error.Foo; } |
| 532 | \\ ^ | 532 | \\ ^ |
| 533 | \\source.zig:5:5: [address] in expectError (test) | 533 | \\source.zig:5:5: [address] in expectError ([main_file]) |
| 534 | \\ return error.TestExpectedError; | 534 | \\ return error.TestExpectedError; |
| 535 | \\ ^ | 535 | \\ ^ |
| 536 | \\source.zig:17:5: [address] in main (test) | 536 | \\source.zig:17:5: [address] in main ([main_file]) |
| 537 | \\ try expectError(error.Bar, foo()); | 537 | \\ try expectError(error.Bar, foo()); |
| 538 | \\ ^ | 538 | \\ ^ |
| 539 | \\ | 539 | \\ |
| ... | @@ -592,13 +592,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -592,13 +592,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 592 | .Debug = .{ | 592 | .Debug = .{ |
| 593 | .expect = | 593 | .expect = |
| 594 | \\error: AndMyCarIsOutOfGas | 594 | \\error: AndMyCarIsOutOfGas |
| 595 | \\source.zig:2:5: [address] in foo (test) | 595 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 596 | \\ return error.TheSkyIsFalling; | 596 | \\ return error.TheSkyIsFalling; |
| 597 | \\ ^ | 597 | \\ ^ |
| 598 | \\source.zig:6:5: [address] in bar (test) | 598 | \\source.zig:6:5: [address] in bar ([main_file]) |
| 599 | \\ return error.AndMyCarIsOutOfGas; | 599 | \\ return error.AndMyCarIsOutOfGas; |
| 600 | \\ ^ | 600 | \\ ^ |
| 601 | \\source.zig:11:9: [address] in main (test) | 601 | \\source.zig:11:9: [address] in main ([main_file]) |
| 602 | \\ try bar(); | 602 | \\ try bar(); |
| 603 | \\ ^ | 603 | \\ ^ |
| 604 | \\ | 604 | \\ |
| ... | @@ -657,13 +657,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -657,13 +657,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 657 | .Debug = .{ | 657 | .Debug = .{ |
| 658 | .expect = | 658 | .expect = |
| 659 | \\error: AndMyCarIsOutOfGas | 659 | \\error: AndMyCarIsOutOfGas |
| 660 | \\source.zig:2:5: [address] in foo (test) | 660 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 661 | \\ return error.TheSkyIsFalling; | 661 | \\ return error.TheSkyIsFalling; |
| 662 | \\ ^ | 662 | \\ ^ |
| 663 | \\source.zig:6:5: [address] in bar (test) | 663 | \\source.zig:6:5: [address] in bar ([main_file]) |
| 664 | \\ return error.AndMyCarIsOutOfGas; | 664 | \\ return error.AndMyCarIsOutOfGas; |
| 665 | \\ ^ | 665 | \\ ^ |
| 666 | \\source.zig:11:9: [address] in main (test) | 666 | \\source.zig:11:9: [address] in main ([main_file]) |
| 667 | \\ try bar(); | 667 | \\ try bar(); |
| 668 | \\ ^ | 668 | \\ ^ |
| 669 | \\ | 669 | \\ |
| ... | @@ -724,16 +724,16 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -724,16 +724,16 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 724 | .Debug = .{ | 724 | .Debug = .{ |
| 725 | .expect = | 725 | .expect = |
| 726 | \\error: TheSkyIsFalling | 726 | \\error: TheSkyIsFalling |
| 727 | \\source.zig:10:5: [address] in make_error (test) | 727 | \\source.zig:10:5: [address] in make_error ([main_file]) |
| 728 | \\ return error.TheSkyIsFalling; | 728 | \\ return error.TheSkyIsFalling; |
| 729 | \\ ^ | 729 | \\ ^ |
| 730 | \\source.zig:6:5: [address] in bar (test) | 730 | \\source.zig:6:5: [address] in bar ([main_file]) |
| 731 | \\ return make_error(); | 731 | \\ return make_error(); |
| 732 | \\ ^ | 732 | \\ ^ |
| 733 | \\source.zig:2:5: [address] in foo (test) | 733 | \\source.zig:2:5: [address] in foo ([main_file]) |
| 734 | \\ try bar(); | 734 | \\ try bar(); |
| 735 | \\ ^ | 735 | \\ ^ |
| 736 | \\source.zig:14:5: [address] in main (test) | 736 | \\source.zig:14:5: [address] in main ([main_file]) |
| 737 | \\ try foo(); | 737 | \\ try foo(); |
| 738 | \\ ^ | 738 | \\ ^ |
| 739 | \\ | 739 | \\ |
| ... | @@ -797,10 +797,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -797,10 +797,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 797 | .windows, // TODO intermittent failures | 797 | .windows, // TODO intermittent failures |
| 798 | }, | 798 | }, |
| 799 | .expect = | 799 | .expect = |
| 800 | \\source.zig:7:8: [address] in foo (test) | 800 | \\source.zig:7:8: [address] in foo ([main_file]) |
| 801 | \\ bar(); | 801 | \\ bar(); |
| 802 | \\ ^ | 802 | \\ ^ |
| 803 | \\source.zig:10:8: [address] in main (test) | 803 | \\source.zig:10:8: [address] in main ([main_file]) |
| 804 | \\ foo(); | 804 | \\ foo(); |
| 805 | \\ ^ | 805 | \\ ^ |
| 806 | \\ | 806 | \\ |
| ... | @@ -829,7 +829,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -829,7 +829,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 829 | .Debug = .{ | 829 | .Debug = .{ |
| 830 | .expect = | 830 | .expect = |
| 831 | \\error: TheSkyIsFalling | 831 | \\error: TheSkyIsFalling |
| 832 | \\source.zig:3:5: [address] in main (test) | 832 | \\source.zig:3:5: [address] in main ([main_file]) |
| 833 | \\ return error.TheSkyIsFalling; | 833 | \\ return error.TheSkyIsFalling; |
| 834 | \\ ^ | 834 | \\ ^ |
| 835 | \\ | 835 | \\ |