authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-30 21:48:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-30 21:48:24+02:00
logebe371b75769dcc5526cdb7650c875764fb536e4
tree4fcd24e1212238b919cf747154fdcefc42a109e8
parentba710ec09dd3df4cd0ee8de9a5299aeaed53a847

macho: report basic __eh_frame problems as errors


7 files changed, 55 insertions(+), 43 deletions(-)

src/link.zig-3
...@@ -693,7 +693,6 @@ pub const File = struct {...@@ -693,7 +693,6 @@ pub const File = struct {
693 /// TODO audit this error set. most of these should be collapsed into one error,693 /// TODO audit this error set. most of these should be collapsed into one error,
694 /// and ErrorFlags should be updated to convey the meaning to the user.694 /// and ErrorFlags should be updated to convey the meaning to the user.
695 pub const FlushError = error{695 pub const FlushError = error{
696 BadDwarfCfi,
697 CacheUnavailable,696 CacheUnavailable,
698 CurrentWorkingDirectoryUnlinked,697 CurrentWorkingDirectoryUnlinked,
699 DivisionByZero,698 DivisionByZero,
...@@ -728,8 +727,6 @@ pub const File = struct {...@@ -728,8 +727,6 @@ pub const File = struct {
728 MissAlignment,727 MissAlignment,
729 MissingEndForBody,728 MissingEndForBody,
730 MissingEndForExpression,729 MissingEndForExpression,
731 /// TODO: this should be removed from the error set in favor of using ErrorFlags
732 MissingSection,
733 MissingSymbol,730 MissingSymbol,
734 MissingTableSymbols,731 MissingTableSymbols,
735 ModuleNameMismatch,732 ModuleNameMismatch,
src/link/MachO.zig+1-1
...@@ -4946,7 +4946,7 @@ fn reportDependencyError(...@@ -4946,7 +4946,7 @@ fn reportDependencyError(
4946 });4946 });
4947}4947}
49484948
4949fn reportParseError(4949pub fn reportParseError(
4950 self: *MachO,4950 self: *MachO,
4951 path: []const u8,4951 path: []const u8,
4952 comptime format: []const u8,4952 comptime format: []const u8,
src/link/MachO/Object.zig+9-6
...@@ -334,7 +334,14 @@ fn sectionLessThanByAddress(ctx: void, lhs: SortedSection, rhs: SortedSection) b...@@ -334,7 +334,14 @@ fn sectionLessThanByAddress(ctx: void, lhs: SortedSection, rhs: SortedSection) b
334 return lhs.header.addr < rhs.header.addr;334 return lhs.header.addr < rhs.header.addr;
335}335}
336336
337pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) !void {337pub const SplitIntoAtomsError = error{
338 OutOfMemory,
339 EndOfStream,
340 MissingEhFrameSection,
341 BadDwarfCfi,
342};
343
344pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) SplitIntoAtomsError!void {
338 log.debug("splitting object({d}, {s}) into atoms", .{ object_id, self.name });345 log.debug("splitting object({d}, {s}) into atoms", .{ object_id, self.name });
339346
340 try self.splitRegularSections(macho_file, object_id);347 try self.splitRegularSections(macho_file, object_id);
...@@ -788,11 +795,7 @@ fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void {...@@ -788,11 +795,7 @@ fn parseUnwindInfo(self: *Object, macho_file: *MachO, object_id: u32) !void {
788 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true;795 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true;
789 } else false;796 } else false;
790797
791 if (needs_eh_frame and !self.hasEhFrameRecords()) {798 if (needs_eh_frame and !self.hasEhFrameRecords()) return error.MissingEhFrameSection;
792 log.err("missing __TEXT,__eh_frame section", .{});
793 log.err(" in object {s}", .{self.name});
794 return error.MissingSection;
795 }
796799
797 try self.parseRelocs(gpa, sect_id);800 try self.parseRelocs(gpa, sect_id);
798 const relocs = self.getRelocs(sect_id);801 const relocs = self.getRelocs(sect_id);
src/link/MachO/UnwindInfo.zig+6-6
...@@ -240,7 +240,7 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -240,7 +240,7 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void {
240 var record = unwind_records[record_id];240 var record = unwind_records[record_id];
241241
242 if (UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {242 if (UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {
243 try info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);243 info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);
244 } else {244 } else {
245 if (getPersonalityFunctionReloc(245 if (getPersonalityFunctionReloc(
246 macho_file,246 macho_file,
...@@ -288,7 +288,7 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -288,7 +288,7 @@ pub fn collect(info: *UnwindInfo, macho_file: *MachO) !void {
288 if (object.eh_frame_records_lookup.get(symbol)) |fde_offset| {288 if (object.eh_frame_records_lookup.get(symbol)) |fde_offset| {
289 if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue;289 if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue;
290 var record = nullRecord();290 var record = nullRecord();
291 try info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);291 info.collectPersonalityFromDwarf(macho_file, @as(u32, @intCast(object_id)), symbol, &record);
292 switch (cpu_arch) {292 switch (cpu_arch) {
293 .aarch64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_ARM64_MODE.DWARF),293 .aarch64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_ARM64_MODE.DWARF),
294 .x86_64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_X86_64_MODE.DWARF),294 .x86_64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_X86_64_MODE.DWARF),
...@@ -500,16 +500,16 @@ fn collectPersonalityFromDwarf(...@@ -500,16 +500,16 @@ fn collectPersonalityFromDwarf(
500 object_id: u32,500 object_id: u32,
501 sym_loc: SymbolWithLoc,501 sym_loc: SymbolWithLoc,
502 record: *macho.compact_unwind_entry,502 record: *macho.compact_unwind_entry,
503) !void {503) void {
504 const object = &macho_file.objects.items[object_id];504 const object = &macho_file.objects.items[object_id];
505 var it = object.getEhFrameRecordsIterator();505 var it = object.getEhFrameRecordsIterator();
506 const fde_offset = object.eh_frame_records_lookup.get(sym_loc).?;506 const fde_offset = object.eh_frame_records_lookup.get(sym_loc).?;
507 it.seekTo(fde_offset);507 it.seekTo(fde_offset);
508 const fde = (try it.next()).?;508 const fde = (it.next() catch return).?; // We don't care about the error since we already handled it
509 const cie_ptr = fde.getCiePointerSource(object_id, macho_file, fde_offset);509 const cie_ptr = fde.getCiePointerSource(object_id, macho_file, fde_offset);
510 const cie_offset = fde_offset + 4 - cie_ptr;510 const cie_offset = fde_offset + 4 - cie_ptr;
511 it.seekTo(cie_offset);511 it.seekTo(cie_offset);
512 const cie = (try it.next()).?;512 const cie = (it.next() catch return).?; // We don't care about the error since we already handled it
513513
514 if (cie.getPersonalityPointerReloc(514 if (cie.getPersonalityPointerReloc(
515 macho_file,515 macho_file,
...@@ -528,7 +528,7 @@ fn collectPersonalityFromDwarf(...@@ -528,7 +528,7 @@ fn collectPersonalityFromDwarf(
528 }528 }
529}529}
530530
531pub fn calcSectionSize(info: UnwindInfo, macho_file: *MachO) !void {531pub fn calcSectionSize(info: UnwindInfo, macho_file: *MachO) void {
532 const sect_id = macho_file.unwind_info_section_index orelse return;532 const sect_id = macho_file.unwind_info_section_index orelse return;
533 const sect = &macho_file.sections.items(.header)[sect_id];533 const sect = &macho_file.sections.items(.header)[sect_id];
534 sect.@"align" = 2;534 sect.@"align" = 2;
src/link/MachO/dead_strip.zig+11-11
...@@ -13,7 +13,7 @@ pub fn gcAtoms(macho_file: *MachO) !void {...@@ -13,7 +13,7 @@ pub fn gcAtoms(macho_file: *MachO) !void {
13 try alive.ensureTotalCapacity(@as(u32, @intCast(macho_file.atoms.items.len)));13 try alive.ensureTotalCapacity(@as(u32, @intCast(macho_file.atoms.items.len)));
1414
15 try collectRoots(macho_file, &roots);15 try collectRoots(macho_file, &roots);
16 try mark(macho_file, roots, &alive);16 mark(macho_file, roots, &alive);
17 prune(macho_file, alive);17 prune(macho_file, alive);
18}18}
1919
...@@ -227,7 +227,7 @@ fn refersLive(macho_file: *MachO, atom_index: Atom.Index, alive: AtomTable) bool...@@ -227,7 +227,7 @@ fn refersLive(macho_file: *MachO, atom_index: Atom.Index, alive: AtomTable) bool
227 return false;227 return false;
228}228}
229229
230fn mark(macho_file: *MachO, roots: AtomTable, alive: *AtomTable) !void {230fn mark(macho_file: *MachO, roots: AtomTable, alive: *AtomTable) void {
231 var it = roots.keyIterator();231 var it = roots.keyIterator();
232 while (it.next()) |root| {232 while (it.next()) |root| {
233 markLive(macho_file, root.*, alive);233 markLive(macho_file, root.*, alive);
...@@ -264,11 +264,11 @@ fn mark(macho_file: *MachO, roots: AtomTable, alive: *AtomTable) !void {...@@ -264,11 +264,11 @@ fn mark(macho_file: *MachO, roots: AtomTable, alive: *AtomTable) !void {
264 for (macho_file.objects.items, 0..) |_, object_id| {264 for (macho_file.objects.items, 0..) |_, object_id| {
265 // Traverse unwind and eh_frame records noting if the source symbol has been marked, and if so,265 // Traverse unwind and eh_frame records noting if the source symbol has been marked, and if so,
266 // marking all references as live.266 // marking all references as live.
267 try markUnwindRecords(macho_file, @as(u32, @intCast(object_id)), alive);267 markUnwindRecords(macho_file, @as(u32, @intCast(object_id)), alive);
268 }268 }
269}269}
270270
271fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !void {271fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) void {
272 const object = &macho_file.objects.items[object_id];272 const object = &macho_file.objects.items[object_id];
273 const cpu_arch = macho_file.base.options.target.cpu.arch;273 const cpu_arch = macho_file.base.options.target.cpu.arch;
274274
...@@ -280,7 +280,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi...@@ -280,7 +280,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi
280 if (!object.hasUnwindRecords()) {280 if (!object.hasUnwindRecords()) {
281 if (alive.contains(atom_index)) {281 if (alive.contains(atom_index)) {
282 // Mark references live and continue.282 // Mark references live and continue.
283 try markEhFrameRecords(macho_file, object_id, atom_index, alive);283 markEhFrameRecords(macho_file, object_id, atom_index, alive);
284 } else {284 } else {
285 while (inner_syms_it.next()) |sym| {285 while (inner_syms_it.next()) |sym| {
286 if (object.eh_frame_records_lookup.get(sym)) |fde_offset| {286 if (object.eh_frame_records_lookup.get(sym)) |fde_offset| {
...@@ -306,7 +306,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi...@@ -306,7 +306,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi
306306
307 const record = unwind_records[record_id];307 const record = unwind_records[record_id];
308 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {308 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) {
309 try markEhFrameRecords(macho_file, object_id, atom_index, alive);309 markEhFrameRecords(macho_file, object_id, atom_index, alive);
310 } else {310 } else {
311 if (UnwindInfo.getPersonalityFunctionReloc(macho_file, object_id, record_id)) |rel| {311 if (UnwindInfo.getPersonalityFunctionReloc(macho_file, object_id, record_id)) |rel| {
312 const target = Atom.parseRelocTarget(macho_file, .{312 const target = Atom.parseRelocTarget(macho_file, .{
...@@ -339,7 +339,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi...@@ -339,7 +339,7 @@ fn markUnwindRecords(macho_file: *MachO, object_id: u32, alive: *AtomTable) !voi
339 }339 }
340}340}
341341
342fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index, alive: *AtomTable) !void {342fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index, alive: *AtomTable) void {
343 const cpu_arch = macho_file.base.options.target.cpu.arch;343 const cpu_arch = macho_file.base.options.target.cpu.arch;
344 const object = &macho_file.objects.items[object_id];344 const object = &macho_file.objects.items[object_id];
345 var it = object.getEhFrameRecordsIterator();345 var it = object.getEhFrameRecordsIterator();
...@@ -348,12 +348,12 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index...@@ -348,12 +348,12 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index
348 while (inner_syms_it.next()) |sym| {348 while (inner_syms_it.next()) |sym| {
349 const fde_offset = object.eh_frame_records_lookup.get(sym) orelse continue; // Continue in case we hit a temp symbol alias349 const fde_offset = object.eh_frame_records_lookup.get(sym) orelse continue; // Continue in case we hit a temp symbol alias
350 it.seekTo(fde_offset);350 it.seekTo(fde_offset);
351 const fde = (try it.next()).?;351 const fde = (it.next() catch continue).?; // We don't care about the error at this point since it was already handled
352352
353 const cie_ptr = fde.getCiePointerSource(object_id, macho_file, fde_offset);353 const cie_ptr = fde.getCiePointerSource(object_id, macho_file, fde_offset);
354 const cie_offset = fde_offset + 4 - cie_ptr;354 const cie_offset = fde_offset + 4 - cie_ptr;
355 it.seekTo(cie_offset);355 it.seekTo(cie_offset);
356 const cie = (try it.next()).?;356 const cie = (it.next() catch continue).?; // We don't care about the error at this point since it was already handled
357357
358 switch (cpu_arch) {358 switch (cpu_arch) {
359 .aarch64 => {359 .aarch64 => {
...@@ -377,10 +377,10 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index...@@ -377,10 +377,10 @@ fn markEhFrameRecords(macho_file: *MachO, object_id: u32, atom_index: Atom.Index
377 },377 },
378 .x86_64 => {378 .x86_64 => {
379 const sect = object.getSourceSection(object.eh_frame_sect_id.?);379 const sect = object.getSourceSection(object.eh_frame_sect_id.?);
380 const lsda_ptr = try fde.getLsdaPointer(cie, .{380 const lsda_ptr = fde.getLsdaPointer(cie, .{
381 .base_addr = sect.addr,381 .base_addr = sect.addr,
382 .base_offset = fde_offset,382 .base_offset = fde_offset,
383 });383 }) catch continue; // We don't care about the error at this point since it was already handled
384 if (lsda_ptr) |lsda_address| {384 if (lsda_ptr) |lsda_address| {
385 // Mark LSDA record as live385 // Mark LSDA record as live
386 const sym_index = object.getSymbolByAddress(lsda_address, null);386 const sym_index = object.getSymbolByAddress(lsda_address, null);
src/link/MachO/eh_frame.zig+14-14
...@@ -13,7 +13,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {...@@ -13,7 +13,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {
13 const fde_offset = object.eh_frame_records_lookup.get(sym) orelse continue;13 const fde_offset = object.eh_frame_records_lookup.get(sym) orelse continue;
14 if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue;14 if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue;
15 it.seekTo(fde_offset);15 it.seekTo(fde_offset);
16 const fde = (try it.next()).?;16 const fde = (it.next() catch continue).?; // We don't care about this error since we already handled it
1717
18 const cie_ptr = fde.getCiePointerSource(@intCast(object_id), macho_file, fde_offset);18 const cie_ptr = fde.getCiePointerSource(@intCast(object_id), macho_file, fde_offset);
19 const cie_offset = fde_offset + 4 - cie_ptr;19 const cie_offset = fde_offset + 4 - cie_ptr;
...@@ -21,7 +21,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {...@@ -21,7 +21,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {
21 if (!cies.contains(cie_offset)) {21 if (!cies.contains(cie_offset)) {
22 try cies.putNoClobber(cie_offset, {});22 try cies.putNoClobber(cie_offset, {});
23 it.seekTo(cie_offset);23 it.seekTo(cie_offset);
24 const cie = (try it.next()).?;24 const cie = (it.next() catch continue).?; // We don't care about this error since we already handled it
25 try cie.scanRelocs(macho_file, @as(u32, @intCast(object_id)), cie_offset);25 try cie.scanRelocs(macho_file, @as(u32, @intCast(object_id)), cie_offset);
26 }26 }
27 }27 }
...@@ -29,7 +29,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {...@@ -29,7 +29,7 @@ pub fn scanRelocs(macho_file: *MachO) !void {
29 }29 }
30}30}
3131
32pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) !void {32pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) error{OutOfMemory}!void {
33 const sect_id = macho_file.eh_frame_section_index orelse return;33 const sect_id = macho_file.eh_frame_section_index orelse return;
34 const sect = &macho_file.sections.items(.header)[sect_id];34 const sect = &macho_file.sections.items(.header)[sect_id];
35 sect.@"align" = 3;35 sect.@"align" = 3;
...@@ -59,7 +59,7 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) !void...@@ -59,7 +59,7 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) !void
59 if (!is_dwarf) continue;59 if (!is_dwarf) continue;
6060
61 eh_it.seekTo(fde_record_offset);61 eh_it.seekTo(fde_record_offset);
62 const source_fde_record = (try eh_it.next()).?;62 const source_fde_record = (eh_it.next() catch continue).?; // We already handled this error
6363
64 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), macho_file, fde_record_offset);64 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), macho_file, fde_record_offset);
65 const cie_offset = fde_record_offset + 4 - cie_ptr;65 const cie_offset = fde_record_offset + 4 - cie_ptr;
...@@ -67,7 +67,7 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) !void...@@ -67,7 +67,7 @@ pub fn calcSectionSize(macho_file: *MachO, unwind_info: *const UnwindInfo) !void
67 const gop = try cies.getOrPut(cie_offset);67 const gop = try cies.getOrPut(cie_offset);
68 if (!gop.found_existing) {68 if (!gop.found_existing) {
69 eh_it.seekTo(cie_offset);69 eh_it.seekTo(cie_offset);
70 const source_cie_record = (try eh_it.next()).?;70 const source_cie_record = (eh_it.next() catch continue).?; // We already handled this error
71 gop.value_ptr.* = size;71 gop.value_ptr.* = size;
72 size += source_cie_record.getSize();72 size += source_cie_record.getSize();
73 }73 }
...@@ -121,7 +121,7 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {...@@ -121,7 +121,7 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {
121 if (!is_dwarf) continue;121 if (!is_dwarf) continue;
122122
123 eh_it.seekTo(fde_record_offset);123 eh_it.seekTo(fde_record_offset);
124 const source_fde_record = (try eh_it.next()).?;124 const source_fde_record = (eh_it.next() catch continue).?; // We already handled this error
125125
126 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), macho_file, fde_record_offset);126 const cie_ptr = source_fde_record.getCiePointerSource(@intCast(object_id), macho_file, fde_record_offset);
127 const cie_offset = fde_record_offset + 4 - cie_ptr;127 const cie_offset = fde_record_offset + 4 - cie_ptr;
...@@ -129,7 +129,7 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {...@@ -129,7 +129,7 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {
129 const gop = try cies.getOrPut(cie_offset);129 const gop = try cies.getOrPut(cie_offset);
130 if (!gop.found_existing) {130 if (!gop.found_existing) {
131 eh_it.seekTo(cie_offset);131 eh_it.seekTo(cie_offset);
132 const source_cie_record = (try eh_it.next()).?;132 const source_cie_record = (eh_it.next() catch continue).?; // We already handled this error
133 var cie_record = try source_cie_record.toOwned(gpa);133 var cie_record = try source_cie_record.toOwned(gpa);
134 try cie_record.relocate(macho_file, @as(u32, @intCast(object_id)), .{134 try cie_record.relocate(macho_file, @as(u32, @intCast(object_id)), .{
135 .source_offset = cie_offset,135 .source_offset = cie_offset,
...@@ -164,17 +164,17 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {...@@ -164,17 +164,17 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {
164 eh_frame_offset + 4 - fde_record.getCiePointer(),164 eh_frame_offset + 4 - fde_record.getCiePointer(),
165 ).?;165 ).?;
166 const eh_frame_sect = object.getSourceSection(object.eh_frame_sect_id.?);166 const eh_frame_sect = object.getSourceSection(object.eh_frame_sect_id.?);
167 const source_lsda_ptr = try fde_record.getLsdaPointer(cie_record, .{167 const source_lsda_ptr = fde_record.getLsdaPointer(cie_record, .{
168 .base_addr = eh_frame_sect.addr,168 .base_addr = eh_frame_sect.addr,
169 .base_offset = fde_record_offset,169 .base_offset = fde_record_offset,
170 });170 }) catch continue; // We already handled this error
171 if (source_lsda_ptr) |ptr| {171 if (source_lsda_ptr) |ptr| {
172 const sym_index = object.getSymbolByAddress(ptr, null);172 const sym_index = object.getSymbolByAddress(ptr, null);
173 const sym = object.symtab[sym_index];173 const sym = object.symtab[sym_index];
174 try fde_record.setLsdaPointer(cie_record, sym.n_value, .{174 fde_record.setLsdaPointer(cie_record, sym.n_value, .{
175 .base_addr = sect.addr,175 .base_addr = sect.addr,
176 .base_offset = eh_frame_offset,176 .base_offset = eh_frame_offset,
177 });177 }) catch continue; // We already handled this error
178 }178 }
179 },179 },
180 else => unreachable,180 else => unreachable,
...@@ -191,10 +191,10 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {...@@ -191,10 +191,10 @@ pub fn write(macho_file: *MachO, unwind_info: *UnwindInfo) !void {
191 const cie_record = eh_records.get(191 const cie_record = eh_records.get(
192 eh_frame_offset + 4 - fde_record.getCiePointer(),192 eh_frame_offset + 4 - fde_record.getCiePointer(),
193 ).?;193 ).?;
194 const lsda_ptr = try fde_record.getLsdaPointer(cie_record, .{194 const lsda_ptr = fde_record.getLsdaPointer(cie_record, .{
195 .base_addr = sect.addr,195 .base_addr = sect.addr,
196 .base_offset = eh_frame_offset,196 .base_offset = eh_frame_offset,
197 });197 }) catch continue; // We already handled this error
198 if (lsda_ptr) |ptr| {198 if (lsda_ptr) |ptr| {
199 record.lsda = ptr - seg.vmaddr;199 record.lsda = ptr - seg.vmaddr;
200 }200 }
...@@ -588,7 +588,7 @@ pub const Iterator = struct {...@@ -588,7 +588,7 @@ pub const Iterator = struct {
588588
589 var size = try reader.readIntLittle(u32);589 var size = try reader.readIntLittle(u32);
590 if (size == 0xFFFFFFFF) {590 if (size == 0xFFFFFFFF) {
591 log.err("MachO doesn't support 64bit DWARF CFI __eh_frame records", .{});591 log.debug("MachO doesn't support 64bit DWARF CFI __eh_frame records", .{});
592 return error.BadDwarfCfi;592 return error.BadDwarfCfi;
593 }593 }
594594
src/link/MachO/zld.zig+14-2
...@@ -388,7 +388,19 @@ pub fn linkWithZld(...@@ -388,7 +388,19 @@ pub fn linkWithZld(
388 }388 }
389389
390 for (macho_file.objects.items, 0..) |*object, object_id| {390 for (macho_file.objects.items, 0..) |*object, object_id| {
391 try object.splitIntoAtoms(macho_file, @as(u32, @intCast(object_id)));391 object.splitIntoAtoms(macho_file, @as(u32, @intCast(object_id))) catch |err| switch (err) {
392 error.MissingEhFrameSection => try macho_file.reportParseError(
393 object.name,
394 "missing section: '__TEXT,__eh_frame' is required but could not be found",
395 .{},
396 ),
397 error.BadDwarfCfi => try macho_file.reportParseError(
398 object.name,
399 "invalid DWARF: failed to parse '__TEXT,__eh_frame' section",
400 .{},
401 ),
402 else => |e| return e,
403 };
392 }404 }
393405
394 if (gc_sections) {406 if (gc_sections) {
...@@ -433,7 +445,7 @@ pub fn linkWithZld(...@@ -433,7 +445,7 @@ pub fn linkWithZld(
433 try unwind_info.collect(macho_file);445 try unwind_info.collect(macho_file);
434446
435 try eh_frame.calcSectionSize(macho_file, &unwind_info);447 try eh_frame.calcSectionSize(macho_file, &unwind_info);
436 try unwind_info.calcSectionSize(macho_file);448 unwind_info.calcSectionSize(macho_file);
437449
438 try pruneAndSortSections(macho_file);450 try pruneAndSortSections(macho_file);
439 try createSegments(macho_file);451 try createSegments(macho_file);