diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 410f5db380..d2fc5b1338 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -642,7 +642,7 @@ pub const StackIterator = struct { // __unwind_info is a requirement for unwinding on Darwin. It may fall back to DWARF, but unwinding // via DWARF before attempting to use the compact unwind info will produce incorrect results. if (module.unwind_info) |unwind_info| { - if (macho.unwindFrame(&unwind_state.dwarf_context, unwind_info, module.base_address)) |return_address| { + if (macho.unwindFrame(&unwind_state.dwarf_context, unwind_info, module.eh_frame, module.base_address)) |return_address| { return return_address; } else |err| { if (err != error.RequiresDWARFUnwind) return err; @@ -2026,10 +2026,6 @@ pub const ModuleDebugInfo = switch (native_os) { }; try DW.openDwarfDebugInfo(&di, allocator); - - // TODO: Don't actually scan everything, search on demand - di.scanAllUnwindInfo(allocator, self.base_address) catch {}; - var info = OFileInfo{ .di = di, .addr_table = addr_table, diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index d4b7d6ba33..1721cc2d88 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -686,7 +686,8 @@ pub const DwarfInfo = struct { pub const null_section_array = [_]?Section{null} ** num_sections; endian: std.builtin.Endian, - sections: SectionArray, + sections: SectionArray = null_section_array, + is_macho: bool, // Filled later by the initializer abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{}, @@ -699,8 +700,6 @@ pub const DwarfInfo = struct { // Sorted by start_pc fde_list: std.ArrayListUnmanaged(FrameDescriptionEntry) = .{}, - is_macho: bool, - pub fn section(di: DwarfInfo, dwarf_section: DwarfSection) ?[]const u8 { return if (di.sections[@intFromEnum(dwarf_section)]) |s| s.data else null; } @@ -1672,6 +1671,8 @@ pub const DwarfInfo = struct { if (fde_offset >= frame_section.len) return error.MissingFDE; var stream = io.fixedBufferStream(frame_section); + try stream.seekTo(fde_offset); + const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian); if (fde_entry_header.type != .fde) return error.MissingFDE; @@ -1701,8 +1702,6 @@ pub const DwarfInfo = struct { builtin.cpu.arch.endian(), ); } else if (di.eh_frame_hdr) |header| { - std.debug.print("EH_FRAME_HDR\n", .{}); - const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null; try header.findEntry( context.isValidMemory, diff --git a/lib/std/macho.zig b/lib/std/macho.zig index dbf49b5f3d..3c18e1f23c 100644 --- a/lib/std/macho.zig +++ b/lib/std/macho.zig @@ -2142,7 +2142,7 @@ fn dwarfRegNumber(unwind_reg_number: u3) !u8 { const dwarf = std.dwarf; const abi = dwarf.abi; -pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, module_base_address: usize) !usize { +pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, eh_frame: ?[]const u8, module_base_address: usize) !usize { const header = mem.bytesAsValue( unwind_info_section_header, unwind_info[0..@sizeOf(unwind_info_section_header)], @@ -2396,7 +2396,9 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul break :blk new_ip; }, - .DWARF => return error.RequiresDWARFUnwind, + .DWARF => { + return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf)); + }, }, .aarch64 => switch (encoding.mode.arm64) { .OLD => return error.UnimplementedUnwindEncoding, @@ -2408,8 +2410,10 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(reg_context), reg_context)).* = new_sp; break :blk new_ip; }, - .DWARF => return error.RequiresDWARFUnwind, - .FRAME => { + .DWARF => { + return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf)); + }, + .FRAME => blk: { const fp = (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).*; const new_sp = fp + 16; const ip_ptr = fp + @sizeOf(usize); @@ -2453,7 +2457,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).* = new_fp; (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip; - return error.UnimplementedUnwindEncoding; + break :blk new_ip; }, }, else => return error.UnimplementedArch, @@ -2463,3 +2467,18 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul if (context.pc > 0) context.pc -= 1; return new_ip; } + +fn unwindFrameDwarf(context: *dwarf.UnwindContext, eh_frame: []const u8, fde_offset: usize) !usize { + var di = dwarf.DwarfInfo{ + .endian = builtin.cpu.arch.endian(), + .is_macho = true, + }; + defer di.deinit(context.allocator); + + di.sections[@intFromEnum(dwarf.DwarfSection.eh_frame)] = .{ + .data = eh_frame, + .owned = false, + }; + + return di.unwindFrame(context, fde_offset); +}