aboutsummaryrefslogtreecommitdiff
path: root/lib/std/macho.zig
diff options
context:
space:
mode:
authorkcbanner <kcbanner@gmail.com>2023-07-17 10:22:01 -0400
committerkcbanner <kcbanner@gmail.com>2023-07-20 22:58:16 -0400
commit97bda56306622784b2f2e4f036d817bbe5f2025e (patch)
treeecec2a45ed278bf105155049695526d9d32b4006 /lib/std/macho.zig
parent774dc2fdb75dc7f6b7e0bd2cfe947fffb9829ba1 (diff)
downloadzig-97bda56306622784b2f2e4f036d817bbe5f2025e.tar.gz
zig-97bda56306622784b2f2e4f036d817bbe5f2025e.zip
macho: don't scan all eh_frame entries, instead follow the offset from the __unwind_info directly
Diffstat (limited to 'lib/std/macho.zig')
-rw-r--r--lib/std/macho.zig29
1 files changed, 24 insertions, 5 deletions
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);
+}