| author | |
| committer | |
| log | 3dff040ca58effc5aaf1c7313a7baa28ec2ac6dd |
| tree | d8a184dc36e16755633529c7fe4bb88591a91fc7 |
| parent | 24f6c07653eaadb70901ef251d091d3c3c0e010f |
Unlike Apple ld, we will not do any DWARF CFI parsing and simply
output DWARF type unwind records.3 files changed, 155 insertions(+), 117 deletions(-)
src/link/MachO/Object.zig+12-1| ... | @@ -725,7 +725,18 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { | ... | @@ -725,7 +725,18 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void { |
| 725 | } | 725 | } |
| 726 | 726 | ||
| 727 | fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { | 727 | fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void { |
| 728 | const sect = self.unwind_info_sect orelse return; | 728 | const sect = self.unwind_info_sect orelse { |
| 729 | // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`, | ||
| 730 | // we will try fully synthesising unwind info records to somewhat match Apple ld's | ||
| 731 | // approach. However, we will only synthesise DWARF records and nothing more. For this reason, | ||
| 732 | // we still create the output `__TEXT,__unwind_info` section. | ||
| 733 | if (self.eh_frame_sect != null) { | ||
| 734 | if (zld.getSectionByName("__TEXT", "__unwind_info") == null) { | ||
| 735 | _ = try zld.initSection("__TEXT", "__unwind_info", .{}); | ||
| 736 | } | ||
| 737 | } | ||
| 738 | return; | ||
| 739 | }; | ||
| 729 | 740 | ||
| 730 | log.debug("parsing unwind info in {s}", .{self.name}); | 741 | log.debug("parsing unwind info in {s}", .{self.name}); |
| 731 | 742 |
src/link/MachO/UnwindInfo.zig+63-52| ... | @@ -253,37 +253,13 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -253,37 +253,13 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 253 | try records.ensureUnusedCapacity(object.exec_atoms.items.len); | 253 | try records.ensureUnusedCapacity(object.exec_atoms.items.len); |
| 254 | try atom_indexes.ensureUnusedCapacity(object.exec_atoms.items.len); | 254 | try atom_indexes.ensureUnusedCapacity(object.exec_atoms.items.len); |
| 255 | 255 | ||
| 256 | var it = object.getEhFrameRecordsIterator(); | ||
| 257 | |||
| 258 | for (object.exec_atoms.items) |atom_index| { | 256 | for (object.exec_atoms.items) |atom_index| { |
| 259 | var record = if (object.unwind_records_lookup.get(atom_index)) |record_id| blk: { | 257 | var record = if (object.unwind_records_lookup.get(atom_index)) |record_id| blk: { |
| 260 | if (object.unwind_relocs_lookup[record_id].dead) continue; | 258 | if (object.unwind_relocs_lookup[record_id].dead) continue; |
| 261 | var record = unwind_records[record_id]; | 259 | var record = unwind_records[record_id]; |
| 262 | 260 | ||
| 263 | if (UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) { | 261 | if (UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) { |
| 264 | const fde_offset = object.eh_frame_records_lookup.get(atom_index).?; | 262 | try info.collectPersonalityFromDwarf(zld, @intCast(u32, object_id), atom_index, &record); |
| 265 | it.seekTo(fde_offset); | ||
| 266 | const fde = (try it.next()).?; | ||
| 267 | const cie_ptr = fde.getCiePointer(); | ||
| 268 | const cie_offset = fde_offset + 4 - cie_ptr; | ||
| 269 | it.seekTo(cie_offset); | ||
| 270 | const cie = (try it.next()).?; | ||
| 271 | |||
| 272 | if (cie.getPersonalityPointerReloc( | ||
| 273 | zld, | ||
| 274 | @intCast(u32, object_id), | ||
| 275 | cie_offset, | ||
| 276 | )) |target| { | ||
| 277 | const personality_index = info.getPersonalityFunction(target) orelse inner: { | ||
| 278 | const personality_index = info.personalities_count; | ||
| 279 | info.personalities[personality_index] = target; | ||
| 280 | info.personalities_count += 1; | ||
| 281 | break :inner personality_index; | ||
| 282 | }; | ||
| 283 | |||
| 284 | record.personalityFunction = personality_index + 1; | ||
| 285 | UnwindEncoding.setPersonalityIndex(&record.compactUnwindEncoding, personality_index + 1); | ||
| 286 | } | ||
| 287 | } else { | 263 | } else { |
| 288 | if (getPersonalityFunctionReloc( | 264 | if (getPersonalityFunctionReloc( |
| 289 | zld, | 265 | zld, |
| ... | @@ -324,6 +300,21 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -324,6 +300,21 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 324 | const atom = zld.getAtom(atom_index); | 300 | const atom = zld.getAtom(atom_index); |
| 325 | const sym = zld.getSymbol(atom.getSymbolWithLoc()); | 301 | const sym = zld.getSymbol(atom.getSymbolWithLoc()); |
| 326 | if (sym.n_desc == N_DEAD) continue; | 302 | if (sym.n_desc == N_DEAD) continue; |
| 303 | |||
| 304 | if (!object.hasUnwindRecords()) { | ||
| 305 | if (object.eh_frame_records_lookup.get(atom_index)) |fde_offset| { | ||
| 306 | if (object.eh_frame_relocs_lookup.get(fde_offset).?.dead) continue; | ||
| 307 | var record = nullRecord(); | ||
| 308 | try info.collectPersonalityFromDwarf(zld, @intCast(u32, object_id), atom_index, &record); | ||
| 309 | switch (cpu_arch) { | ||
| 310 | .aarch64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_ARM64_MODE.DWARF), | ||
| 311 | .x86_64 => UnwindEncoding.setMode(&record.compactUnwindEncoding, macho.UNWIND_X86_64_MODE.DWARF), | ||
| 312 | else => unreachable, | ||
| 313 | } | ||
| 314 | break :blk record; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 327 | break :blk nullRecord(); | 318 | break :blk nullRecord(); |
| 328 | }; | 319 | }; |
| 329 | 320 | ||
| ... | @@ -499,6 +490,40 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { | ... | @@ -499,6 +490,40 @@ pub fn collect(info: *UnwindInfo, zld: *Zld) !void { |
| 499 | } | 490 | } |
| 500 | } | 491 | } |
| 501 | 492 | ||
| 493 | fn collectPersonalityFromDwarf( | ||
| 494 | info: *UnwindInfo, | ||
| 495 | zld: *Zld, | ||
| 496 | object_id: u32, | ||
| 497 | atom_index: u32, | ||
| 498 | record: *macho.compact_unwind_entry, | ||
| 499 | ) !void { | ||
| 500 | const object = &zld.objects.items[object_id]; | ||
| 501 | var it = object.getEhFrameRecordsIterator(); | ||
| 502 | const fde_offset = object.eh_frame_records_lookup.get(atom_index).?; | ||
| 503 | it.seekTo(fde_offset); | ||
| 504 | const fde = (try it.next()).?; | ||
| 505 | const cie_ptr = fde.getCiePointer(); | ||
| 506 | const cie_offset = fde_offset + 4 - cie_ptr; | ||
| 507 | it.seekTo(cie_offset); | ||
| 508 | const cie = (try it.next()).?; | ||
| 509 | |||
| 510 | if (cie.getPersonalityPointerReloc( | ||
| 511 | zld, | ||
| 512 | @intCast(u32, object_id), | ||
| 513 | cie_offset, | ||
| 514 | )) |target| { | ||
| 515 | const personality_index = info.getPersonalityFunction(target) orelse inner: { | ||
| 516 | const personality_index = info.personalities_count; | ||
| 517 | info.personalities[personality_index] = target; | ||
| 518 | info.personalities_count += 1; | ||
| 519 | break :inner personality_index; | ||
| 520 | }; | ||
| 521 | |||
| 522 | record.personalityFunction = personality_index + 1; | ||
| 523 | UnwindEncoding.setPersonalityIndex(&record.compactUnwindEncoding, personality_index + 1); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | |||
| 502 | pub fn calcSectionSize(info: UnwindInfo, zld: *Zld) !void { | 527 | pub fn calcSectionSize(info: UnwindInfo, zld: *Zld) !void { |
| 503 | const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return; | 528 | const sect_id = zld.getSectionByName("__TEXT", "__unwind_info") orelse return; |
| 504 | const sect = &zld.sections.items(.header)[sect_id]; | 529 | const sect = &zld.sections.items(.header)[sect_id]; |
| ... | @@ -766,40 +791,26 @@ fn getCommonEncoding(info: UnwindInfo, enc: macho.compact_unwind_encoding_t) ?u7 | ... | @@ -766,40 +791,26 @@ fn getCommonEncoding(info: UnwindInfo, enc: macho.compact_unwind_encoding_t) ?u7 |
| 766 | } | 791 | } |
| 767 | 792 | ||
| 768 | pub const UnwindEncoding = struct { | 793 | pub const UnwindEncoding = struct { |
| 769 | pub const UNWIND_X86_64_MODE = enum(u4) { | ||
| 770 | none = 0, | ||
| 771 | ebp_frame = 1, | ||
| 772 | stack_immd = 2, | ||
| 773 | stack_ind = 3, | ||
| 774 | dwarf = 4, | ||
| 775 | }; | ||
| 776 | |||
| 777 | pub const UNWIND_ARM64_MODE = enum(u4) { | ||
| 778 | none = 0, | ||
| 779 | frameless = 2, | ||
| 780 | dwarf = 3, | ||
| 781 | frame = 4, | ||
| 782 | }; | ||
| 783 | |||
| 784 | pub const UNWIND_MODE_MASK: u32 = 0x0F000000; | ||
| 785 | pub const UNWIND_PERSONALITY_INDEX_MASK: u32 = 0x30000000; | ||
| 786 | pub const UNWIND_HAS_LSDA_MASK: u32 = 0x40000000; | ||
| 787 | |||
| 788 | pub fn getMode(enc: macho.compact_unwind_encoding_t) u4 { | 794 | pub fn getMode(enc: macho.compact_unwind_encoding_t) u4 { |
| 789 | const mode = @truncate(u4, (enc & UNWIND_MODE_MASK) >> 24); | 795 | comptime assert(macho.UNWIND_ARM64_MODE_MASK == macho.UNWIND_X86_64_MODE_MASK); |
| 790 | return mode; | 796 | return @truncate(u4, (enc & macho.UNWIND_ARM64_MODE_MASK) >> 24); |
| 791 | } | 797 | } |
| 792 | 798 | ||
| 793 | pub fn isDwarf(enc: macho.compact_unwind_encoding_t, cpu_arch: std.Target.Cpu.Arch) bool { | 799 | pub fn isDwarf(enc: macho.compact_unwind_encoding_t, cpu_arch: std.Target.Cpu.Arch) bool { |
| 794 | switch (cpu_arch) { | 800 | const mode = getMode(enc); |
| 795 | .aarch64 => return @intToEnum(UNWIND_ARM64_MODE, getMode(enc)) == .dwarf, | 801 | return switch (cpu_arch) { |
| 796 | .x86_64 => return @intToEnum(UNWIND_X86_64_MODE, getMode(enc)) == .dwarf, | 802 | .aarch64 => @intToEnum(macho.UNWIND_ARM64_MODE, mode) == .DWARF, |
| 803 | .x86_64 => @intToEnum(macho.UNWIND_X86_64_MODE, mode) == .DWARF, | ||
| 797 | else => unreachable, | 804 | else => unreachable, |
| 798 | } | 805 | }; |
| 806 | } | ||
| 807 | |||
| 808 | pub fn setMode(enc: *macho.compact_unwind_encoding_t, mode: anytype) void { | ||
| 809 | enc.* |= @intCast(u32, @enumToInt(mode)) << 24; | ||
| 799 | } | 810 | } |
| 800 | 811 | ||
| 801 | pub fn hasLsda(enc: macho.compact_unwind_encoding_t) bool { | 812 | pub fn hasLsda(enc: macho.compact_unwind_encoding_t) bool { |
| 802 | const has_lsda = @truncate(u1, (enc & UNWIND_HAS_LSDA_MASK) >> 31); | 813 | const has_lsda = @truncate(u1, (enc & macho.UNWIND_HAS_LSDA) >> 31); |
| 803 | return has_lsda == 1; | 814 | return has_lsda == 1; |
| 804 | } | 815 | } |
| 805 | 816 | ||
| ... | @@ -809,7 +820,7 @@ pub const UnwindEncoding = struct { | ... | @@ -809,7 +820,7 @@ pub const UnwindEncoding = struct { |
| 809 | } | 820 | } |
| 810 | 821 | ||
| 811 | pub fn getPersonalityIndex(enc: macho.compact_unwind_encoding_t) u2 { | 822 | pub fn getPersonalityIndex(enc: macho.compact_unwind_encoding_t) u2 { |
| 812 | const index = @truncate(u2, (enc & UNWIND_PERSONALITY_INDEX_MASK) >> 28); | 823 | const index = @truncate(u2, (enc & macho.UNWIND_PERSONALITY_MASK) >> 28); |
| 813 | return index; | 824 | return index; |
| 814 | } | 825 | } |
| 815 | 826 |
src/link/MachO/dead_strip.zig+80-64| ... | @@ -238,16 +238,10 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable) !void { | ... | @@ -238,16 +238,10 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable) !void { |
| 238 | } | 238 | } |
| 239 | } | 239 | } |
| 240 | 240 | ||
| 241 | for (zld.objects.items) |object, object_id| { | 241 | for (zld.objects.items) |_, object_id| { |
| 242 | // Traverse unwind and eh_frame records noting if the source symbol has been marked, and if so, | 242 | // Traverse unwind and eh_frame records noting if the source symbol has been marked, and if so, |
| 243 | // marking all references as live. | 243 | // marking all references as live. |
| 244 | // TODO I am currently assuming there will always be __unwind_info section emitted which implies | 244 | try markUnwindRecords(zld, @intCast(u32, object_id), alive); |
| 245 | // we will not traverse __eh_frame in isolation. This however is only true for more recent versions | ||
| 246 | // of macOS so if there is a feature request to handle earlier versions of macOS, the following | ||
| 247 | // bit code needs updating as well. | ||
| 248 | if (object.hasUnwindRecords()) { | ||
| 249 | try markUnwindRecords(zld, @intCast(u32, object_id), alive); | ||
| 250 | } | ||
| 251 | } | 245 | } |
| 252 | } | 246 | } |
| 253 | 247 | ||
| ... | @@ -256,9 +250,23 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { | ... | @@ -256,9 +250,23 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 256 | const cpu_arch = zld.options.target.cpu.arch; | 250 | const cpu_arch = zld.options.target.cpu.arch; |
| 257 | 251 | ||
| 258 | const unwind_records = object.getUnwindRecords(); | 252 | const unwind_records = object.getUnwindRecords(); |
| 259 | var it = object.getEhFrameRecordsIterator(); | ||
| 260 | 253 | ||
| 261 | for (object.exec_atoms.items) |atom_index| { | 254 | for (object.exec_atoms.items) |atom_index| { |
| 255 | if (!object.hasUnwindRecords()) { | ||
| 256 | if (object.eh_frame_records_lookup.get(atom_index)) |fde_offset| { | ||
| 257 | const ptr = object.eh_frame_relocs_lookup.getPtr(fde_offset).?; | ||
| 258 | if (ptr.dead) continue; // already marked | ||
| 259 | if (!alive.contains(atom_index)) { | ||
| 260 | // Mark dead and continue. | ||
| 261 | ptr.dead = true; | ||
| 262 | } else { | ||
| 263 | // Mark references live and continue. | ||
| 264 | try markEhFrameRecord(zld, object_id, atom_index, alive); | ||
| 265 | } | ||
| 266 | continue; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 262 | const record_id = object.unwind_records_lookup.get(atom_index) orelse continue; | 270 | const record_id = object.unwind_records_lookup.get(atom_index) orelse continue; |
| 263 | if (object.unwind_relocs_lookup[record_id].dead) continue; // already marked, nothing to do | 271 | if (object.unwind_relocs_lookup[record_id].dead) continue; // already marked, nothing to do |
| 264 | if (!alive.contains(atom_index)) { | 272 | if (!alive.contains(atom_index)) { |
| ... | @@ -272,61 +280,7 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { | ... | @@ -272,61 +280,7 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 272 | 280 | ||
| 273 | const record = unwind_records[record_id]; | 281 | const record = unwind_records[record_id]; |
| 274 | if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) { | 282 | if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) { |
| 275 | const fde_offset = object.eh_frame_records_lookup.get(atom_index).?; | 283 | try markEhFrameRecord(zld, object_id, atom_index, alive); |
| 276 | it.seekTo(fde_offset); | ||
| 277 | const fde = (try it.next()).?; | ||
| 278 | |||
| 279 | const cie_ptr = fde.getCiePointer(); | ||
| 280 | const cie_offset = fde_offset + 4 - cie_ptr; | ||
| 281 | it.seekTo(cie_offset); | ||
| 282 | const cie = (try it.next()).?; | ||
| 283 | |||
| 284 | switch (cpu_arch) { | ||
| 285 | .aarch64 => { | ||
| 286 | // Mark FDE references which should include any referenced LSDA record | ||
| 287 | const relocs = eh_frame.getRelocs(zld, object_id, fde_offset); | ||
| 288 | for (relocs) |rel| { | ||
| 289 | const target = UnwindInfo.parseRelocTarget( | ||
| 290 | zld, | ||
| 291 | object_id, | ||
| 292 | rel, | ||
| 293 | fde.data, | ||
| 294 | @intCast(i32, fde_offset) + 4, | ||
| 295 | ); | ||
| 296 | const target_sym = zld.getSymbol(target); | ||
| 297 | if (!target_sym.undf()) blk: { | ||
| 298 | const target_object = zld.objects.items[target.getFile().?]; | ||
| 299 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index) orelse | ||
| 300 | break :blk; | ||
| 301 | markLive(zld, target_atom_index, alive); | ||
| 302 | } | ||
| 303 | } | ||
| 304 | }, | ||
| 305 | .x86_64 => { | ||
| 306 | const lsda_ptr = try fde.getLsdaPointer(cie, .{ | ||
| 307 | .base_addr = object.eh_frame_sect.?.addr, | ||
| 308 | .base_offset = fde_offset, | ||
| 309 | }); | ||
| 310 | if (lsda_ptr) |lsda_address| { | ||
| 311 | // Mark LSDA record as live | ||
| 312 | const sym_index = object.getSymbolByAddress(lsda_address, null); | ||
| 313 | const target_atom_index = object.getAtomIndexForSymbol(sym_index).?; | ||
| 314 | markLive(zld, target_atom_index, alive); | ||
| 315 | } | ||
| 316 | }, | ||
| 317 | else => unreachable, | ||
| 318 | } | ||
| 319 | |||
| 320 | // Mark CIE references which should include any referenced personalities | ||
| 321 | // that are defined locally. | ||
| 322 | if (cie.getPersonalityPointerReloc(zld, object_id, cie_offset)) |target| { | ||
| 323 | const target_sym = zld.getSymbol(target); | ||
| 324 | if (!target_sym.undf()) { | ||
| 325 | const target_object = zld.objects.items[target.getFile().?]; | ||
| 326 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; | ||
| 327 | markLive(zld, target_atom_index, alive); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | } else { | 284 | } else { |
| 331 | if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| { | 285 | if (UnwindInfo.getPersonalityFunctionReloc(zld, object_id, record_id)) |rel| { |
| 332 | const target = UnwindInfo.parseRelocTarget( | 286 | const target = UnwindInfo.parseRelocTarget( |
| ... | @@ -360,6 +314,68 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { | ... | @@ -360,6 +314,68 @@ fn markUnwindRecords(zld: *Zld, object_id: u32, alive: *AtomTable) !void { |
| 360 | } | 314 | } |
| 361 | } | 315 | } |
| 362 | 316 | ||
| 317 | fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *AtomTable) !void { | ||
| 318 | const cpu_arch = zld.options.target.cpu.arch; | ||
| 319 | const object = &zld.objects.items[object_id]; | ||
| 320 | var it = object.getEhFrameRecordsIterator(); | ||
| 321 | |||
| 322 | const fde_offset = object.eh_frame_records_lookup.get(atom_index).?; | ||
| 323 | it.seekTo(fde_offset); | ||
| 324 | const fde = (try it.next()).?; | ||
| 325 | |||
| 326 | const cie_ptr = fde.getCiePointer(); | ||
| 327 | const cie_offset = fde_offset + 4 - cie_ptr; | ||
| 328 | it.seekTo(cie_offset); | ||
| 329 | const cie = (try it.next()).?; | ||
| 330 | |||
| 331 | switch (cpu_arch) { | ||
| 332 | .aarch64 => { | ||
| 333 | // Mark FDE references which should include any referenced LSDA record | ||
| 334 | const relocs = eh_frame.getRelocs(zld, object_id, fde_offset); | ||
| 335 | for (relocs) |rel| { | ||
| 336 | const target = UnwindInfo.parseRelocTarget( | ||
| 337 | zld, | ||
| 338 | object_id, | ||
| 339 | rel, | ||
| 340 | fde.data, | ||
| 341 | @intCast(i32, fde_offset) + 4, | ||
| 342 | ); | ||
| 343 | const target_sym = zld.getSymbol(target); | ||
| 344 | if (!target_sym.undf()) blk: { | ||
| 345 | const target_object = zld.objects.items[target.getFile().?]; | ||
| 346 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index) orelse | ||
| 347 | break :blk; | ||
| 348 | markLive(zld, target_atom_index, alive); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | }, | ||
| 352 | .x86_64 => { | ||
| 353 | const lsda_ptr = try fde.getLsdaPointer(cie, .{ | ||
| 354 | .base_addr = object.eh_frame_sect.?.addr, | ||
| 355 | .base_offset = fde_offset, | ||
| 356 | }); | ||
| 357 | if (lsda_ptr) |lsda_address| { | ||
| 358 | // Mark LSDA record as live | ||
| 359 | const sym_index = object.getSymbolByAddress(lsda_address, null); | ||
| 360 | const target_atom_index = object.getAtomIndexForSymbol(sym_index).?; | ||
| 361 | markLive(zld, target_atom_index, alive); | ||
| 362 | } | ||
| 363 | }, | ||
| 364 | else => unreachable, | ||
| 365 | } | ||
| 366 | |||
| 367 | // Mark CIE references which should include any referenced personalities | ||
| 368 | // that are defined locally. | ||
| 369 | if (cie.getPersonalityPointerReloc(zld, object_id, cie_offset)) |target| { | ||
| 370 | const target_sym = zld.getSymbol(target); | ||
| 371 | if (!target_sym.undf()) { | ||
| 372 | const target_object = zld.objects.items[target.getFile().?]; | ||
| 373 | const target_atom_index = target_object.getAtomIndexForSymbol(target.sym_index).?; | ||
| 374 | markLive(zld, target_atom_index, alive); | ||
| 375 | } | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 363 | fn prune(zld: *Zld, alive: AtomTable) void { | 379 | fn prune(zld: *Zld, alive: AtomTable) void { |
| 364 | log.debug("pruning dead atoms", .{}); | 380 | log.debug("pruning dead atoms", .{}); |
| 365 | for (zld.objects.items) |*object| { | 381 | for (zld.objects.items) |*object| { |