mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 06:13:07 +00:00
macho: don't scan all eh_frame entries, instead follow the offset from the __unwind_info directly
This commit is contained in:
parent
774dc2fdb7
commit
97bda56306
@ -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
|
// __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.
|
// via DWARF before attempting to use the compact unwind info will produce incorrect results.
|
||||||
if (module.unwind_info) |unwind_info| {
|
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;
|
return return_address;
|
||||||
} else |err| {
|
} else |err| {
|
||||||
if (err != error.RequiresDWARFUnwind) return err;
|
if (err != error.RequiresDWARFUnwind) return err;
|
||||||
@ -2026,10 +2026,6 @@ pub const ModuleDebugInfo = switch (native_os) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
try DW.openDwarfDebugInfo(&di, allocator);
|
try DW.openDwarfDebugInfo(&di, allocator);
|
||||||
|
|
||||||
// TODO: Don't actually scan everything, search on demand
|
|
||||||
di.scanAllUnwindInfo(allocator, self.base_address) catch {};
|
|
||||||
|
|
||||||
var info = OFileInfo{
|
var info = OFileInfo{
|
||||||
.di = di,
|
.di = di,
|
||||||
.addr_table = addr_table,
|
.addr_table = addr_table,
|
||||||
|
|||||||
@ -686,7 +686,8 @@ pub const DwarfInfo = struct {
|
|||||||
pub const null_section_array = [_]?Section{null} ** num_sections;
|
pub const null_section_array = [_]?Section{null} ** num_sections;
|
||||||
|
|
||||||
endian: std.builtin.Endian,
|
endian: std.builtin.Endian,
|
||||||
sections: SectionArray,
|
sections: SectionArray = null_section_array,
|
||||||
|
is_macho: bool,
|
||||||
|
|
||||||
// Filled later by the initializer
|
// Filled later by the initializer
|
||||||
abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{},
|
abbrev_table_list: std.ArrayListUnmanaged(AbbrevTableHeader) = .{},
|
||||||
@ -699,8 +700,6 @@ pub const DwarfInfo = struct {
|
|||||||
// Sorted by start_pc
|
// Sorted by start_pc
|
||||||
fde_list: std.ArrayListUnmanaged(FrameDescriptionEntry) = .{},
|
fde_list: std.ArrayListUnmanaged(FrameDescriptionEntry) = .{},
|
||||||
|
|
||||||
is_macho: bool,
|
|
||||||
|
|
||||||
pub fn section(di: DwarfInfo, dwarf_section: DwarfSection) ?[]const u8 {
|
pub fn section(di: DwarfInfo, dwarf_section: DwarfSection) ?[]const u8 {
|
||||||
return if (di.sections[@intFromEnum(dwarf_section)]) |s| s.data else null;
|
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;
|
if (fde_offset >= frame_section.len) return error.MissingFDE;
|
||||||
|
|
||||||
var stream = io.fixedBufferStream(frame_section);
|
var stream = io.fixedBufferStream(frame_section);
|
||||||
|
try stream.seekTo(fde_offset);
|
||||||
|
|
||||||
const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian);
|
const fde_entry_header = try EntryHeader.read(&stream, dwarf_section, di.endian);
|
||||||
if (fde_entry_header.type != .fde) return error.MissingFDE;
|
if (fde_entry_header.type != .fde) return error.MissingFDE;
|
||||||
|
|
||||||
@ -1701,8 +1702,6 @@ pub const DwarfInfo = struct {
|
|||||||
builtin.cpu.arch.endian(),
|
builtin.cpu.arch.endian(),
|
||||||
);
|
);
|
||||||
} else if (di.eh_frame_hdr) |header| {
|
} 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;
|
const eh_frame_len = if (di.section(.eh_frame)) |eh_frame| eh_frame.len else null;
|
||||||
try header.findEntry(
|
try header.findEntry(
|
||||||
context.isValidMemory,
|
context.isValidMemory,
|
||||||
|
|||||||
@ -2142,7 +2142,7 @@ fn dwarfRegNumber(unwind_reg_number: u3) !u8 {
|
|||||||
const dwarf = std.dwarf;
|
const dwarf = std.dwarf;
|
||||||
const abi = dwarf.abi;
|
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(
|
const header = mem.bytesAsValue(
|
||||||
unwind_info_section_header,
|
unwind_info_section_header,
|
||||||
unwind_info[0..@sizeOf(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;
|
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) {
|
.aarch64 => switch (encoding.mode.arm64) {
|
||||||
.OLD => return error.UnimplementedUnwindEncoding,
|
.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;
|
(try abi.regValueNative(usize, context.thread_context, abi.spRegNum(reg_context), reg_context)).* = new_sp;
|
||||||
break :blk new_ip;
|
break :blk new_ip;
|
||||||
},
|
},
|
||||||
.DWARF => return error.RequiresDWARFUnwind,
|
.DWARF => {
|
||||||
.FRAME => {
|
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 fp = (try abi.regValueNative(usize, context.thread_context, abi.fpRegNum(reg_context), reg_context)).*;
|
||||||
const new_sp = fp + 16;
|
const new_sp = fp + 16;
|
||||||
const ip_ptr = fp + @sizeOf(usize);
|
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.fpRegNum(reg_context), reg_context)).* = new_fp;
|
||||||
(try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip;
|
(try abi.regValueNative(usize, context.thread_context, abi.ipRegNum(), reg_context)).* = new_ip;
|
||||||
|
|
||||||
return error.UnimplementedUnwindEncoding;
|
break :blk new_ip;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
else => return error.UnimplementedArch,
|
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;
|
if (context.pc > 0) context.pc -= 1;
|
||||||
return new_ip;
|
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);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user