authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-17 10:22:01-04:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-07-20 22:58:16-04:00
log97bda56306622784b2f2e4f036d817bbe5f2025e
treeecec2a45ed278bf105155049695526d9d32b4006
parent774dc2fdb75dc7f6b7e0bd2cfe947fffb9829ba1

macho: don't scan all eh_frame entries, instead follow the offset from the __unwind_info directly


3 files changed, 29 insertions(+), 15 deletions(-)

lib/std/debug.zig+1-5
...@@ -642,7 +642,7 @@ pub const StackIterator = struct {...@@ -642,7 +642,7 @@ pub const StackIterator = struct {
642 // __unwind_info is a requirement for unwinding on Darwin. It may fall back to DWARF, but unwinding642 // __unwind_info is a requirement for unwinding on Darwin. It may fall back to DWARF, but unwinding
643 // via DWARF before attempting to use the compact unwind info will produce incorrect results.643 // via DWARF before attempting to use the compact unwind info will produce incorrect results.
644 if (module.unwind_info) |unwind_info| {644 if (module.unwind_info) |unwind_info| {
645 if (macho.unwindFrame(&unwind_state.dwarf_context, unwind_info, module.base_address)) |return_address| {645 if (macho.unwindFrame(&unwind_state.dwarf_context, unwind_info, module.eh_frame, module.base_address)) |return_address| {
646 return return_address;646 return return_address;
647 } else |err| {647 } else |err| {
648 if (err != error.RequiresDWARFUnwind) return err;648 if (err != error.RequiresDWARFUnwind) return err;
...@@ -2026,10 +2026,6 @@ pub const ModuleDebugInfo = switch (native_os) {...@@ -2026,10 +2026,6 @@ pub const ModuleDebugInfo = switch (native_os) {
2026 };2026 };
20272027
2028 try DW.openDwarfDebugInfo(&di, allocator);2028 try DW.openDwarfDebugInfo(&di, allocator);
2029
2030 // TODO: Don't actually scan everything, search on demand
2031 di.scanAllUnwindInfo(allocator, self.base_address) catch {};
2032
2033 var info = OFileInfo{2029 var info = OFileInfo{
2034 .di = di,2030 .di = di,
2035 .addr_table = addr_table,2031 .addr_table = addr_table,
lib/std/dwarf.zig+4-5
...@@ -686,7 +686,8 @@ pub const DwarfInfo = struct {...@@ -686,7 +686,8 @@ pub const DwarfInfo = struct {
686 pub const null_section_array = [_]?Section{null} ** num_sections;686 pub const null_section_array = [_]?Section{null} ** num_sections;
687687
688 endian: std.builtin.Endian,688 endian: std.builtin.Endian,
689 sections: SectionArray,689 sections: SectionArray = null_section_array,
690 is_macho: bool,
690691
691 // Filled later by the initializer692 // Filled later by the initializer
692 abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{},693 abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{},
...@@ -699,8 +700,6 @@ pub const DwarfInfo = struct {...@@ -699,8 +700,6 @@ pub const DwarfInfo = struct {
699 // Sorted by start_pc700 // Sorted by start_pc
700 fde_list: std.ArrayListUnmanaged(FrameDescriptionEntry) = .{},701 fde_list: std.ArrayListUnmanaged(FrameDescriptionEntry) = .{},
701702
702 is_macho: bool,
703
704 pub fn section(di: DwarfInfo, dwarf_section: DwarfSection) ?[]const u8 {703 pub fn section(di: DwarfInfo, dwarf_section: DwarfSection) ?[]const u8 {
705 return if (di.sections[@intFromEnum(dwarf_section)]) |s| s.data else null;704 return if (di.sections[@intFromEnum(dwarf_section)]) |s| s.data else null;
706 }705 }
...@@ -1672,6 +1671,8 @@ pub const DwarfInfo = struct {...@@ -1672,6 +1671,8 @@ pub const DwarfInfo = struct {
1672 if (fde_offset >= frame_section.len) return error.MissingFDE;1671 if (fde_offset >= frame_section.len) return error.MissingFDE;
16731672
1674 var stream = io.fixedBufferStream(frame_section);1673 var stream = io.fixedBufferStream(frame_section);
1674 try stream.seekTo(fde_offset);
1675
1675 const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian);1676 const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian);
1676 if (fde_entry_header.type != .fde) return error.MissingFDE;1677 if (fde_entry_header.type != .fde) return error.MissingFDE;
16771678
...@@ -1701,8 +1702,6 @@ pub const DwarfInfo = struct {...@@ -1701,8 +1702,6 @@ pub const DwarfInfo = struct {
1701 builtin.cpu.arch.endian(),1702 builtin.cpu.arch.endian(),
1702 );1703 );
1703 } else if (di.eh_frame_hdr) |header| {1704 } else if (di.eh_frame_hdr) |header| {
1704 std.debug.print("EH_FRAME_HDR\n", .{});
1705
1706 const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null;1705 const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null;
1707 try header.findEntry(1706 try header.findEntry(
1708 context.isValidMemory,1707 context.isValidMemory,
lib/std/macho.zig+24-5
...@@ -2142,7 +2142,7 @@ fn dwarfRegNumber(unwind_reg_number: u3) !u8 {...@@ -2142,7 +2142,7 @@ fn dwarfRegNumber(unwind_reg_number: u3) !u8 {
2142const dwarf = std.dwarf;2142const dwarf = std.dwarf;
2143const abi = dwarf.abi;2143const abi = dwarf.abi;
21442144
2145pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, module_base_address: usize) !usize {2145pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, eh_frame: ?[]const u8, module_base_address: usize) !usize {
2146 const header = mem.bytesAsValue(2146 const header = mem.bytesAsValue(
2147 unwind_info_section_header,2147 unwind_info_section_header,
2148 unwind_info[0..@sizeOf(unwind_info_section_header)],2148 unwind_info[0..@sizeOf(unwind_info_section_header)],
...@@ -2396,7 +2396,9 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul...@@ -2396,7 +2396,9 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul
23962396
2397 break :blk new_ip;2397 break :blk new_ip;
2398 },2398 },
2399 .DWARF => return error.RequiresDWARFUnwind,2399 .DWARF => {
2400 return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.x86_64.dwarf));
2401 },
2400 },2402 },
2401 .aarch64 => switch (encoding.mode.arm64) {2403 .aarch64 => switch (encoding.mode.arm64) {
2402 .OLD => return error.UnimplementedUnwindEncoding,2404 .OLD => return error.UnimplementedUnwindEncoding,
...@@ -2408,8 +2410,10 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul...@@ -2408,8 +2410,10 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul
2408 (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(reg_context), reg_context)).* = new_sp;2410 (try abi.regValueNative(usize, context.thread_context, abi.spRegNum(reg_context), reg_context)).* = new_sp;
2409 break :blk new_ip;2411 break :blk new_ip;
2410 },2412 },
2411 .DWARF => return error.RequiresDWARFUnwind,2413 .DWARF => {
2412 .FRAME => {2414 return unwindFrameDwarf(context, eh_frame orelse return error.MissingEhFrame, @intCast(encoding.value.arm64.dwarf));
2415 },
2416 .FRAME => blk: {
2413 const fp = (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).*;2417 const fp = (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).*;
2414 const new_sp = fp + 16;2418 const new_sp = fp + 16;
2415 const ip_ptr = fp + @sizeOf(usize);2419 const ip_ptr = fp + @sizeOf(usize);
...@@ -2453,7 +2457,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul...@@ -2453,7 +2457,7 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul
2453 (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).* = new_fp;2457 (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).* = new_fp;
2454 (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip;2458 (try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip;
24552459
2456 return error.UnimplementedUnwindEncoding;2460 break :blk new_ip;
2457 },2461 },
2458 },2462 },
2459 else => return error.UnimplementedArch,2463 else => return error.UnimplementedArch,
...@@ -2463,3 +2467,18 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul...@@ -2463,3 +2467,18 @@ pub fn unwindFrame(context: *dwarf.UnwindContext, unwind_info: []const u8, modul
2463 if (context.pc > 0) context.pc -= 1;2467 if (context.pc > 0) context.pc -= 1;
2464 return new_ip;2468 return new_ip;
2465}2469}
2470
2471fn unwindFrameDwarf(context: *dwarf.UnwindContext, eh_frame: []const u8, fde_offset: usize) !usize {
2472 var di = dwarf.DwarfInfo{
2473 .endian = builtin.cpu.arch.endian(),
2474 .is_macho = true,
2475 };
2476 defer di.deinit(context.allocator);
2477
2478 di.sections[@intFromEnum(dwarf.DwarfSection.eh_frame)] = .{
2479 .data = eh_frame,
2480 .owned = false,
2481 };
2482
2483 return di.unwindFrame(context, fde_offset);
2484}