authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-07 15:20:56+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-07 15:20:56+01:00
log9ccd8ed0ad4cc9e68c2a2e0c9b1e32d50259357e
treeb44064a12274e2b7adcfaea3adbca93ba8ce1af2
parenta5b34a61ab61882bf55d87e4cbc8186215ecf320
parent4b1a883d35565766d30f587d2cb2ccfe8c065c8b
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14575 from ziglang/fix-14459

macho+zld: fix misc alignment issues when parsing object files in archives

7 files changed, 137 insertions(+), 95 deletions(-)

src/link/MachO/Dylib.zig+2
...@@ -166,6 +166,8 @@ pub fn parseFromBinary(...@@ -166,6 +166,8 @@ pub fn parseFromBinary(
166 const symtab_cmd = cmd.cast(macho.symtab_command).?;166 const symtab_cmd = cmd.cast(macho.symtab_command).?;
167 const symtab = @ptrCast(167 const symtab = @ptrCast(
168 [*]const macho.nlist_64,168 [*]const macho.nlist_64,
169 // Alignment is guaranteed as a dylib is a final linked image and has to have sections
170 // properly aligned in order to be correctly loaded by the loader.
169 @alignCast(@alignOf(macho.nlist_64), &data[symtab_cmd.symoff]),171 @alignCast(@alignOf(macho.nlist_64), &data[symtab_cmd.symoff]),
170 )[0..symtab_cmd.nsyms];172 )[0..symtab_cmd.nsyms];
171 const strtab = data[symtab_cmd.stroff..][0..symtab_cmd.strsize];173 const strtab = data[symtab_cmd.stroff..][0..symtab_cmd.strsize];
src/link/MachO/Object.zig+103-52
...@@ -60,14 +60,24 @@ globals_lookup: []i64 = undefined,...@@ -60,14 +60,24 @@ globals_lookup: []i64 = undefined,
60/// Can be undefined as set together with in_symtab.60/// Can be undefined as set together with in_symtab.
61relocs_lookup: []RelocEntry = undefined,61relocs_lookup: []RelocEntry = undefined,
6262
63/// All relocations sorted and flatened, sorted by address descending
64/// per section.
65relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{},
66/// Beginning index to the relocations array for each input section
67/// defined within this Object file.
68section_relocs_lookup: std.ArrayListUnmanaged(u32) = .{},
69
70/// Data-in-code records sorted by address.
71data_in_code: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
72
63atoms: std.ArrayListUnmanaged(AtomIndex) = .{},73atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
64exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},74exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
6575
66eh_frame_sect: ?macho.section_64 = null,76eh_frame_sect_id: ?u8 = null,
67eh_frame_relocs_lookup: std.AutoArrayHashMapUnmanaged(u32, Record) = .{},77eh_frame_relocs_lookup: std.AutoArrayHashMapUnmanaged(u32, Record) = .{},
68eh_frame_records_lookup: std.AutoArrayHashMapUnmanaged(AtomIndex, u32) = .{},78eh_frame_records_lookup: std.AutoArrayHashMapUnmanaged(AtomIndex, u32) = .{},
6979
70unwind_info_sect: ?macho.section_64 = null,80unwind_info_sect_id: ?u8 = null,
71unwind_relocs_lookup: []Record = undefined,81unwind_relocs_lookup: []Record = undefined,
72unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{},82unwind_records_lookup: std.AutoHashMapUnmanaged(AtomIndex, u32) = .{},
7383
...@@ -100,6 +110,9 @@ pub fn deinit(self: *Object, gpa: Allocator) void {...@@ -100,6 +110,9 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
100 gpa.free(self.unwind_relocs_lookup);110 gpa.free(self.unwind_relocs_lookup);
101 }111 }
102 self.unwind_records_lookup.deinit(gpa);112 self.unwind_records_lookup.deinit(gpa);
113 self.relocations.deinit(gpa);
114 self.section_relocs_lookup.deinit(gpa);
115 self.data_in_code.deinit(gpa);
103}116}
104117
105pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void {118pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void {
...@@ -137,15 +150,18 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)...@@ -137,15 +150,18 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
137 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],150 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],
138 };151 };
139 const nsects = self.getSourceSections().len;152 const nsects = self.getSourceSections().len;
153
154 // Prepopulate relocations per section lookup table.
155 try self.section_relocs_lookup.resize(allocator, nsects);
156 mem.set(u32, self.section_relocs_lookup.items, 0);
157
158 // Parse symtab.
140 const symtab = while (it.next()) |cmd| switch (cmd.cmd()) {159 const symtab = while (it.next()) |cmd| switch (cmd.cmd()) {
141 .SYMTAB => break cmd.cast(macho.symtab_command).?,160 .SYMTAB => break cmd.cast(macho.symtab_command).?,
142 else => {},161 else => {},
143 } else return;162 } else return;
144163
145 self.in_symtab = @ptrCast(164 self.in_symtab = @ptrCast([*]align(1) const macho.nlist_64, self.contents.ptr + symtab.symoff)[0..symtab.nsyms];
146 [*]const macho.nlist_64,
147 @alignCast(@alignOf(macho.nlist_64), &self.contents[symtab.symoff]),
148 )[0..symtab.nsyms];
149 self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];165 self.in_strtab = self.contents[symtab.stroff..][0..symtab.strsize];
150166
151 self.symtab = try allocator.alloc(macho.nlist_64, self.in_symtab.?.len + nsects);167 self.symtab = try allocator.alloc(macho.nlist_64, self.in_symtab.?.len + nsects);
...@@ -212,10 +228,10 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)...@@ -212,10 +228,10 @@ pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch)
212 }228 }
213229
214 // Parse __TEXT,__eh_frame header if one exists230 // Parse __TEXT,__eh_frame header if one exists
215 self.eh_frame_sect = self.getSourceSectionByName("__TEXT", "__eh_frame");231 self.eh_frame_sect_id = self.getSourceSectionIndexByName("__TEXT", "__eh_frame");
216232
217 // Parse __LD,__compact_unwind header if one exists233 // Parse __LD,__compact_unwind header if one exists
218 self.unwind_info_sect = self.getSourceSectionByName("__LD", "__compact_unwind");234 self.unwind_info_sect_id = self.getSourceSectionIndexByName("__LD", "__compact_unwind");
219 if (self.hasUnwindRecords()) {235 if (self.hasUnwindRecords()) {
220 self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len);236 self.unwind_relocs_lookup = try allocator.alloc(Record, self.getUnwindRecords().len);
221 mem.set(Record, self.unwind_relocs_lookup, .{237 mem.set(Record, self.unwind_relocs_lookup, .{
...@@ -354,6 +370,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -354,6 +370,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u32) !void {
354 try self.splitRegularSections(zld, object_id);370 try self.splitRegularSections(zld, object_id);
355 try self.parseEhFrameSection(zld, object_id);371 try self.parseEhFrameSection(zld, object_id);
356 try self.parseUnwindInfo(zld, object_id);372 try self.parseUnwindInfo(zld, object_id);
373 try self.parseDataInCode(zld.gpa);
357}374}
358375
359/// Splits input regular sections into Atoms.376/// Splits input regular sections into Atoms.
...@@ -452,6 +469,8 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -452,6 +469,8 @@ pub fn splitRegularSections(self: *Object, zld: *Zld, object_id: u32) !void {
452 zld.sections.items(.header)[out_sect_id].sectName(),469 zld.sections.items(.header)[out_sect_id].sectName(),
453 });470 });
454471
472 try self.parseRelocs(gpa, section.id);
473
455 const cpu_arch = zld.options.target.cpu.arch;474 const cpu_arch = zld.options.target.cpu.arch;
456 const sect_loc = filterSymbolsBySection(symtab[sect_sym_index..], sect_id + 1);475 const sect_loc = filterSymbolsBySection(symtab[sect_sym_index..], sect_id + 1);
457 const sect_start_index = sect_sym_index + sect_loc.index;476 const sect_start_index = sect_sym_index + sect_loc.index;
...@@ -623,25 +642,36 @@ fn filterRelocs(...@@ -623,25 +642,36 @@ fn filterRelocs(
623 return .{ .start = @intCast(u32, start), .len = @intCast(u32, len) };642 return .{ .start = @intCast(u32, start), .len = @intCast(u32, len) };
624}643}
625644
645/// Parse all relocs for the input section, and sort in descending order.
646/// Previously, I have wrongly assumed the compilers output relocations for each
647/// section in a sorted manner which is simply not true.
648fn parseRelocs(self: *Object, gpa: Allocator, sect_id: u8) !void {
649 const section = self.getSourceSection(sect_id);
650 const start = @intCast(u32, self.relocations.items.len);
651 if (self.getSourceRelocs(section)) |relocs| {
652 try self.relocations.ensureUnusedCapacity(gpa, relocs.len);
653 self.relocations.appendUnalignedSliceAssumeCapacity(relocs);
654 std.sort.sort(macho.relocation_info, self.relocations.items[start..], {}, relocGreaterThan);
655 }
656 self.section_relocs_lookup.items[sect_id] = start;
657}
658
626fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void {659fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void {
627 const atom = zld.getAtom(atom_index);660 const atom = zld.getAtom(atom_index);
628661
629 const source_sect = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: {662 const source_sect_id = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: {
630 const source_sect = self.getSourceSection(source_sym.n_sect - 1);663 break :blk source_sym.n_sect - 1;
631 assert(!source_sect.isZerofill());
632 break :blk source_sect;
633 } else blk: {664 } else blk: {
634 // If there was no matching symbol present in the source symtab, this means665 // If there was no matching symbol present in the source symtab, this means
635 // we are dealing with either an entire section, or part of it, but also666 // we are dealing with either an entire section, or part of it, but also
636 // starting at the beginning.667 // starting at the beginning.
637 const nbase = @intCast(u32, self.in_symtab.?.len);668 const nbase = @intCast(u32, self.in_symtab.?.len);
638 const sect_id = @intCast(u16, atom.sym_index - nbase);669 const sect_id = @intCast(u8, atom.sym_index - nbase);
639 const source_sect = self.getSourceSection(sect_id);670 break :blk sect_id;
640 assert(!source_sect.isZerofill());
641 break :blk source_sect;
642 };671 };
643672 const source_sect = self.getSourceSection(source_sect_id);
644 const relocs = self.getRelocs(source_sect);673 assert(!source_sect.isZerofill());
674 const relocs = self.getRelocs(source_sect_id);
645675
646 self.relocs_lookup[atom.sym_index] = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: {676 self.relocs_lookup[atom.sym_index] = if (self.getSourceSymbol(atom.sym_index)) |source_sym| blk: {
647 const offset = source_sym.n_value - source_sect.addr;677 const offset = source_sym.n_value - source_sect.addr;
...@@ -649,8 +679,14 @@ fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void {...@@ -649,8 +679,14 @@ fn cacheRelocs(self: *Object, zld: *Zld, atom_index: AtomIndex) !void {
649 } else filterRelocs(relocs, 0, atom.size);679 } else filterRelocs(relocs, 0, atom.size);
650}680}
651681
682fn relocGreaterThan(ctx: void, lhs: macho.relocation_info, rhs: macho.relocation_info) bool {
683 _ = ctx;
684 return lhs.r_address > rhs.r_address;
685}
686
652fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {687fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
653 const sect = self.eh_frame_sect orelse return;688 const sect_id = self.eh_frame_sect_id orelse return;
689 const sect = self.getSourceSection(sect_id);
654690
655 log.debug("parsing __TEXT,__eh_frame section", .{});691 log.debug("parsing __TEXT,__eh_frame section", .{});
656692
...@@ -660,7 +696,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -660,7 +696,8 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
660696
661 const gpa = zld.gpa;697 const gpa = zld.gpa;
662 const cpu_arch = zld.options.target.cpu.arch;698 const cpu_arch = zld.options.target.cpu.arch;
663 const relocs = self.getRelocs(sect);699 try self.parseRelocs(gpa, sect_id);
700 const relocs = self.getRelocs(sect_id);
664701
665 var it = self.getEhFrameRecordsIterator();702 var it = self.getEhFrameRecordsIterator();
666 var record_count: u32 = 0;703 var record_count: u32 = 0;
...@@ -728,12 +765,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -728,12 +765,12 @@ fn parseEhFrameSection(self: *Object, zld: *Zld, object_id: u32) !void {
728}765}
729766
730fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {767fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
731 const sect = self.unwind_info_sect orelse {768 const sect_id = self.unwind_info_sect_id orelse {
732 // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`,769 // If it so happens that the object had `__eh_frame` section defined but no `__compact_unwind`,
733 // we will try fully synthesising unwind info records to somewhat match Apple ld's770 // we will try fully synthesising unwind info records to somewhat match Apple ld's
734 // approach. However, we will only synthesise DWARF records and nothing more. For this reason,771 // approach. However, we will only synthesise DWARF records and nothing more. For this reason,
735 // we still create the output `__TEXT,__unwind_info` section.772 // we still create the output `__TEXT,__unwind_info` section.
736 if (self.eh_frame_sect != null) {773 if (self.hasEhFrameRecords()) {
737 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {774 if (zld.getSectionByName("__TEXT", "__unwind_info") == null) {
738 _ = try zld.initSection("__TEXT", "__unwind_info", .{});775 _ = try zld.initSection("__TEXT", "__unwind_info", .{});
739 }776 }
...@@ -758,15 +795,15 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -758,15 +795,15 @@ fn parseUnwindInfo(self: *Object, zld: *Zld, object_id: u32) !void {
758 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true;795 if (UnwindInfo.UnwindEncoding.isDwarf(record.compactUnwindEncoding, cpu_arch)) break true;
759 } else false;796 } else false;
760797
761 if (needs_eh_frame) {798 if (needs_eh_frame and !self.hasEhFrameRecords()) {
762 if (self.eh_frame_sect == null) {799 log.err("missing __TEXT,__eh_frame section", .{});
763 log.err("missing __TEXT,__eh_frame section", .{});800 log.err(" in object {s}", .{self.name});
764 log.err(" in object {s}", .{self.name});801 return error.MissingSection;
765 return error.MissingSection;
766 }
767 }802 }
768803
769 const relocs = self.getRelocs(sect);804 try self.parseRelocs(gpa, sect_id);
805 const relocs = self.getRelocs(sect_id);
806
770 for (unwind_records) |record, record_id| {807 for (unwind_records) |record, record_id| {
771 const offset = record_id * @sizeOf(macho.compact_unwind_entry);808 const offset = record_id * @sizeOf(macho.compact_unwind_entry);
772 const rel_pos = filterRelocs(809 const rel_pos = filterRelocs(
...@@ -806,25 +843,23 @@ pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 {...@@ -806,25 +843,23 @@ pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 {
806 return symtab[mapped_index];843 return symtab[mapped_index];
807}844}
808845
809pub fn getSourceSection(self: Object, index: u16) macho.section_64 {846pub fn getSourceSection(self: Object, index: u8) macho.section_64 {
810 const sections = self.getSourceSections();847 const sections = self.getSourceSections();
811 assert(index < sections.len);848 assert(index < sections.len);
812 return sections[index];849 return sections[index];
813}850}
814851
815pub fn getSourceSectionByName(self: Object, segname: []const u8, sectname: []const u8) ?macho.section_64 {852pub fn getSourceSectionByName(self: Object, segname: []const u8, sectname: []const u8) ?macho.section_64 {
853 const index = self.getSourceSectionIndexByName(segname, sectname) orelse return null;
816 const sections = self.getSourceSections();854 const sections = self.getSourceSections();
817 for (sections) |sect| {855 return sections[index];
818 if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName()))
819 return sect;
820 } else return null;
821}856}
822857
823pub fn getSourceSectionIndexByName(self: Object, segname: []const u8, sectname: []const u8) ?u8 {858pub fn getSourceSectionIndexByName(self: Object, segname: []const u8, sectname: []const u8) ?u8 {
824 const sections = self.getSourceSections();859 const sections = self.getSourceSections();
825 for (sections) |sect, i| {860 for (sections) |sect, i| {
826 if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName()))861 if (mem.eql(u8, segname, sect.segName()) and mem.eql(u8, sectname, sect.sectName()))
827 return @intCast(u8, i + 1);862 return @intCast(u8, i);
828 } else return null;863 } else return null;
829}864}
830865
...@@ -841,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {...@@ -841,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {
841 } else unreachable;876 } else unreachable;
842}877}
843878
844pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {879pub fn parseDataInCode(self: *Object, gpa: Allocator) !void {
845 var it = LoadCommandIterator{880 var it = LoadCommandIterator{
846 .ncmds = self.header.ncmds,881 .ncmds = self.header.ncmds,
847 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],882 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],
848 };883 };
849 while (it.next()) |cmd| {884 const cmd = while (it.next()) |cmd| {
850 switch (cmd.cmd()) {885 switch (cmd.cmd()) {
851 .DATA_IN_CODE => {886 .DATA_IN_CODE => break cmd.cast(macho.linkedit_data_command).?,
852 const dice = cmd.cast(macho.linkedit_data_command).?;
853 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
854 return @ptrCast(
855 [*]const macho.data_in_code_entry,
856 @alignCast(@alignOf(macho.data_in_code_entry), &self.contents[dice.dataoff]),
857 )[0..ndice];
858 },
859 else => {},887 else => {},
860 }888 }
861 } else return null;889 } else return;
890 const ndice = @divExact(cmd.datasize, @sizeOf(macho.data_in_code_entry));
891 const dice = @ptrCast([*]align(1) const macho.data_in_code_entry, self.contents.ptr + cmd.dataoff)[0..ndice];
892 try self.data_in_code.ensureTotalCapacityPrecise(gpa, dice.len);
893 self.data_in_code.appendUnalignedSliceAssumeCapacity(dice);
894 std.sort.sort(macho.data_in_code_entry, self.data_in_code.items, {}, diceLessThan);
895}
896
897fn diceLessThan(ctx: void, lhs: macho.data_in_code_entry, rhs: macho.data_in_code_entry) bool {
898 _ = ctx;
899 return lhs.offset < rhs.offset;
862}900}
863901
864fn parseDysymtab(self: Object) ?macho.dysymtab_command {902fn parseDysymtab(self: Object) ?macho.dysymtab_command {
...@@ -914,11 +952,18 @@ pub fn getSectionAliasSymbolPtr(self: *Object, sect_id: u8) *macho.nlist_64 {...@@ -914,11 +952,18 @@ pub fn getSectionAliasSymbolPtr(self: *Object, sect_id: u8) *macho.nlist_64 {
914 return &self.symtab[self.getSectionAliasSymbolIndex(sect_id)];952 return &self.symtab[self.getSectionAliasSymbolIndex(sect_id)];
915}953}
916954
917pub fn getRelocs(self: Object, sect: macho.section_64) []align(1) const macho.relocation_info {955fn getSourceRelocs(self: Object, sect: macho.section_64) ?[]align(1) const macho.relocation_info {
918 if (sect.nreloc == 0) return &[0]macho.relocation_info{};956 if (sect.nreloc == 0) return null;
919 return @ptrCast([*]align(1) const macho.relocation_info, self.contents.ptr + sect.reloff)[0..sect.nreloc];957 return @ptrCast([*]align(1) const macho.relocation_info, self.contents.ptr + sect.reloff)[0..sect.nreloc];
920}958}
921959
960pub fn getRelocs(self: Object, sect_id: u8) []const macho.relocation_info {
961 const sect = self.getSourceSection(sect_id);
962 const start = self.section_relocs_lookup.items[sect_id];
963 const len = sect.nreloc;
964 return self.relocations.items[start..][0..len];
965}
966
922pub fn getSymbolName(self: Object, index: u32) []const u8 {967pub fn getSymbolName(self: Object, index: u32) []const u8 {
923 const strtab = self.in_strtab.?;968 const strtab = self.in_strtab.?;
924 const sym = self.symtab[index];969 const sym = self.symtab[index];
...@@ -976,22 +1021,28 @@ pub fn getAtomIndexForSymbol(self: Object, sym_index: u32) ?AtomIndex {...@@ -976,22 +1021,28 @@ pub fn getAtomIndexForSymbol(self: Object, sym_index: u32) ?AtomIndex {
976}1021}
9771022
978pub fn hasUnwindRecords(self: Object) bool {1023pub fn hasUnwindRecords(self: Object) bool {
979 return self.unwind_info_sect != null;1024 return self.unwind_info_sect_id != null;
980}1025}
9811026
982pub fn getUnwindRecords(self: Object) []align(1) const macho.compact_unwind_entry {1027pub fn getUnwindRecords(self: Object) []align(1) const macho.compact_unwind_entry {
983 const sect = self.unwind_info_sect orelse return &[0]macho.compact_unwind_entry{};1028 const sect_id = self.unwind_info_sect_id orelse return &[0]macho.compact_unwind_entry{};
1029 const sect = self.getSourceSection(sect_id);
984 const data = self.getSectionContents(sect);1030 const data = self.getSectionContents(sect);
985 const num_entries = @divExact(data.len, @sizeOf(macho.compact_unwind_entry));1031 const num_entries = @divExact(data.len, @sizeOf(macho.compact_unwind_entry));
986 return @ptrCast([*]align(1) const macho.compact_unwind_entry, data)[0..num_entries];1032 return @ptrCast([*]align(1) const macho.compact_unwind_entry, data)[0..num_entries];
987}1033}
9881034
989pub fn hasEhFrameRecords(self: Object) bool {1035pub fn hasEhFrameRecords(self: Object) bool {
990 return self.eh_frame_sect != null;1036 return self.eh_frame_sect_id != null;
991}1037}
9921038
993pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {1039pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {
994 const sect = self.eh_frame_sect orelse return .{ .data = &[0]u8{} };1040 const sect_id = self.eh_frame_sect_id orelse return .{ .data = &[0]u8{} };
1041 const sect = self.getSourceSection(sect_id);
995 const data = self.getSectionContents(sect);1042 const data = self.getSectionContents(sect);
996 return .{ .data = data };1043 return .{ .data = data };
997}1044}
1045
1046pub fn hasDataInCode(self: Object) bool {
1047 return self.data_in_code.items.len > 0;
1048}
src/link/MachO/UnwindInfo.zig+2-6
...@@ -703,15 +703,11 @@ pub fn parseRelocTarget(...@@ -703,15 +703,11 @@ pub fn parseRelocTarget(
703 } else return sym_loc;703 } else return sym_loc;
704}704}
705705
706fn getRelocs(706fn getRelocs(zld: *Zld, object_id: u32, record_id: usize) []const macho.relocation_info {
707 zld: *Zld,
708 object_id: u32,
709 record_id: usize,
710) []align(1) const macho.relocation_info {
711 const object = &zld.objects.items[object_id];707 const object = &zld.objects.items[object_id];
712 assert(object.hasUnwindRecords());708 assert(object.hasUnwindRecords());
713 const rel_pos = object.unwind_relocs_lookup[record_id].reloc;709 const rel_pos = object.unwind_relocs_lookup[record_id].reloc;
714 const relocs = object.getRelocs(object.unwind_info_sect.?);710 const relocs = object.getRelocs(object.unwind_info_sect_id.?);
715 return relocs[rel_pos.start..][0..rel_pos.len];711 return relocs[rel_pos.start..][0..rel_pos.len];
716}712}
717713
src/link/MachO/ZldAtom.zig+14-17
...@@ -143,7 +143,7 @@ pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u...@@ -143,7 +143,7 @@ pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u
143 sym.n_value143 sym.n_value
144 else blk: {144 else blk: {
145 const nbase = @intCast(u32, object.in_symtab.?.len);145 const nbase = @intCast(u32, object.in_symtab.?.len);
146 const sect_id = @intCast(u16, atom.sym_index - nbase);146 const sect_id = @intCast(u8, atom.sym_index - nbase);
147 const source_sect = object.getSourceSection(sect_id);147 const source_sect = object.getSourceSection(sect_id);
148 break :blk source_sect.addr;148 break :blk source_sect.addr;
149 };149 };
...@@ -180,7 +180,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext {...@@ -180,7 +180,7 @@ pub fn getRelocContext(zld: *Zld, atom_index: AtomIndex) RelocContext {
180 };180 };
181 }181 }
182 const nbase = @intCast(u32, object.in_symtab.?.len);182 const nbase = @intCast(u32, object.in_symtab.?.len);
183 const sect_id = @intCast(u16, atom.sym_index - nbase);183 const sect_id = @intCast(u8, atom.sym_index - nbase);
184 const source_sect = object.getSourceSection(sect_id);184 const source_sect = object.getSourceSection(sect_id);
185 return .{185 return .{
186 .base_addr = source_sect.addr,186 .base_addr = source_sect.addr,
...@@ -724,7 +724,7 @@ fn resolveRelocsArm64(...@@ -724,7 +724,7 @@ fn resolveRelocsArm64(
724724
725 if (rel.r_extern == 0) {725 if (rel.r_extern == 0) {
726 const base_addr = if (target.sym_index > object.source_address_lookup.len)726 const base_addr = if (target.sym_index > object.source_address_lookup.len)
727 @intCast(i64, object.getSourceSection(@intCast(u16, rel.r_symbolnum - 1)).addr)727 @intCast(i64, object.getSourceSection(@intCast(u8, rel.r_symbolnum - 1)).addr)
728 else728 else
729 object.source_address_lookup[target.sym_index];729 object.source_address_lookup[target.sym_index];
730 ptr_addend -= base_addr;730 ptr_addend -= base_addr;
...@@ -861,7 +861,7 @@ fn resolveRelocsX86(...@@ -861,7 +861,7 @@ fn resolveRelocsX86(
861861
862 if (rel.r_extern == 0) {862 if (rel.r_extern == 0) {
863 const base_addr = if (target.sym_index > object.source_address_lookup.len)863 const base_addr = if (target.sym_index > object.source_address_lookup.len)
864 @intCast(i64, object.getSourceSection(@intCast(u16, rel.r_symbolnum - 1)).addr)864 @intCast(i64, object.getSourceSection(@intCast(u8, rel.r_symbolnum - 1)).addr)
865 else865 else
866 object.source_address_lookup[target.sym_index];866 object.source_address_lookup[target.sym_index];
867 addend += @intCast(i32, @intCast(i64, context.base_addr) + rel.r_address + 4 -867 addend += @intCast(i32, @intCast(i64, context.base_addr) + rel.r_address + 4 -
...@@ -884,7 +884,7 @@ fn resolveRelocsX86(...@@ -884,7 +884,7 @@ fn resolveRelocsX86(
884884
885 if (rel.r_extern == 0) {885 if (rel.r_extern == 0) {
886 const base_addr = if (target.sym_index > object.source_address_lookup.len)886 const base_addr = if (target.sym_index > object.source_address_lookup.len)
887 @intCast(i64, object.getSourceSection(@intCast(u16, rel.r_symbolnum - 1)).addr)887 @intCast(i64, object.getSourceSection(@intCast(u8, rel.r_symbolnum - 1)).addr)
888 else888 else
889 object.source_address_lookup[target.sym_index];889 object.source_address_lookup[target.sym_index];
890 addend -= base_addr;890 addend -= base_addr;
...@@ -928,7 +928,7 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {...@@ -928,7 +928,7 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {
928 // we are dealing with either an entire section, or part of it, but also928 // we are dealing with either an entire section, or part of it, but also
929 // starting at the beginning.929 // starting at the beginning.
930 const nbase = @intCast(u32, object.in_symtab.?.len);930 const nbase = @intCast(u32, object.in_symtab.?.len);
931 const sect_id = @intCast(u16, atom.sym_index - nbase);931 const sect_id = @intCast(u8, atom.sym_index - nbase);
932 const source_sect = object.getSourceSection(sect_id);932 const source_sect = object.getSourceSection(sect_id);
933 assert(!source_sect.isZerofill());933 assert(!source_sect.isZerofill());
934 const code = object.getSectionContents(source_sect);934 const code = object.getSectionContents(source_sect);
...@@ -943,28 +943,25 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {...@@ -943,28 +943,25 @@ pub fn getAtomCode(zld: *Zld, atom_index: AtomIndex) []const u8 {
943 return code[offset..][0..code_len];943 return code[offset..][0..code_len];
944}944}
945945
946pub fn getAtomRelocs(zld: *Zld, atom_index: AtomIndex) []align(1) const macho.relocation_info {946pub fn getAtomRelocs(zld: *Zld, atom_index: AtomIndex) []const macho.relocation_info {
947 const atom = zld.getAtom(atom_index);947 const atom = zld.getAtom(atom_index);
948 assert(atom.getFile() != null); // Synthetic atom shouldn't need to unique for relocs.948 assert(atom.getFile() != null); // Synthetic atom shouldn't need to unique for relocs.
949 const object = zld.objects.items[atom.getFile().?];949 const object = zld.objects.items[atom.getFile().?];
950 const cache = object.relocs_lookup[atom.sym_index];950 const cache = object.relocs_lookup[atom.sym_index];
951951
952 const source_sect = if (object.getSourceSymbol(atom.sym_index)) |source_sym| blk: {952 const source_sect_id = if (object.getSourceSymbol(atom.sym_index)) |source_sym| blk: {
953 const source_sect = object.getSourceSection(source_sym.n_sect - 1);953 break :blk source_sym.n_sect - 1;
954 assert(!source_sect.isZerofill());
955 break :blk source_sect;
956 } else blk: {954 } else blk: {
957 // If there was no matching symbol present in the source symtab, this means955 // If there was no matching symbol present in the source symtab, this means
958 // we are dealing with either an entire section, or part of it, but also956 // we are dealing with either an entire section, or part of it, but also
959 // starting at the beginning.957 // starting at the beginning.
960 const nbase = @intCast(u32, object.in_symtab.?.len);958 const nbase = @intCast(u32, object.in_symtab.?.len);
961 const sect_id = @intCast(u16, atom.sym_index - nbase);959 const sect_id = @intCast(u8, atom.sym_index - nbase);
962 const source_sect = object.getSourceSection(sect_id);960 break :blk sect_id;
963 assert(!source_sect.isZerofill());
964 break :blk source_sect;
965 };961 };
966962 const source_sect = object.getSourceSection(source_sect_id);
967 const relocs = object.getRelocs(source_sect);963 assert(!source_sect.isZerofill());
964 const relocs = object.getRelocs(source_sect_id);
968 return relocs[cache.start..][0..cache.len];965 return relocs[cache.start..][0..cache.len];
969}966}
970967
src/link/MachO/dead_strip.zig+4-3
...@@ -88,7 +88,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {...@@ -88,7 +88,7 @@ fn collectRoots(zld: *Zld, roots: *AtomTable) !void {
88 source_sym.n_sect - 188 source_sym.n_sect - 1
89 else sect_id: {89 else sect_id: {
90 const nbase = @intCast(u32, object.in_symtab.?.len);90 const nbase = @intCast(u32, object.in_symtab.?.len);
91 const sect_id = @intCast(u16, atom.sym_index - nbase);91 const sect_id = @intCast(u8, atom.sym_index - nbase);
92 break :sect_id sect_id;92 break :sect_id sect_id;
93 };93 };
94 const source_sect = object.getSourceSection(sect_id);94 const source_sect = object.getSourceSection(sect_id);
...@@ -223,7 +223,7 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable) !void {...@@ -223,7 +223,7 @@ fn mark(zld: *Zld, roots: AtomTable, alive: *AtomTable) !void {
223 source_sym.n_sect - 1223 source_sym.n_sect - 1
224 else blk: {224 else blk: {
225 const nbase = @intCast(u32, object.in_symtab.?.len);225 const nbase = @intCast(u32, object.in_symtab.?.len);
226 const sect_id = @intCast(u16, atom.sym_index - nbase);226 const sect_id = @intCast(u8, atom.sym_index - nbase);
227 break :blk sect_id;227 break :blk sect_id;
228 };228 };
229 const source_sect = object.getSourceSection(sect_id);229 const source_sect = object.getSourceSection(sect_id);
...@@ -350,8 +350,9 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A...@@ -350,8 +350,9 @@ fn markEhFrameRecord(zld: *Zld, object_id: u32, atom_index: AtomIndex, alive: *A
350 }350 }
351 },351 },
352 .x86_64 => {352 .x86_64 => {
353 const sect = object.getSourceSection(object.eh_frame_sect_id.?);
353 const lsda_ptr = try fde.getLsdaPointer(cie, .{354 const lsda_ptr = try fde.getLsdaPointer(cie, .{
354 .base_addr = object.eh_frame_sect.?.addr,355 .base_addr = sect.addr,
355 .base_offset = fde_offset,356 .base_offset = fde_offset,
356 });357 });
357 if (lsda_ptr) |lsda_address| {358 if (lsda_ptr) |lsda_address| {
src/link/MachO/eh_frame.zig+4-7
...@@ -171,8 +171,9 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {...@@ -171,8 +171,9 @@ pub fn write(zld: *Zld, unwind_info: *UnwindInfo) !void {
171 const cie_record = eh_records.get(171 const cie_record = eh_records.get(
172 eh_frame_offset + 4 - fde_record.getCiePointer(),172 eh_frame_offset + 4 - fde_record.getCiePointer(),
173 ).?;173 ).?;
174 const eh_frame_sect = object.getSourceSection(object.eh_frame_sect_id.?);
174 const source_lsda_ptr = try fde_record.getLsdaPointer(cie_record, .{175 const source_lsda_ptr = try fde_record.getLsdaPointer(cie_record, .{
175 .base_addr = object.eh_frame_sect.?.addr,176 .base_addr = eh_frame_sect.addr,
176 .base_offset = fde_record_offset,177 .base_offset = fde_record_offset,
177 });178 });
178 if (source_lsda_ptr) |ptr| {179 if (source_lsda_ptr) |ptr| {
...@@ -552,16 +553,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {...@@ -552,16 +553,12 @@ pub fn EhFrameRecord(comptime is_mutable: bool) type {
552 };553 };
553}554}
554555
555pub fn getRelocs(556pub fn getRelocs(zld: *Zld, object_id: u32, source_offset: u32) []const macho.relocation_info {
556 zld: *Zld,
557 object_id: u32,
558 source_offset: u32,
559) []align(1) const macho.relocation_info {
560 const object = &zld.objects.items[object_id];557 const object = &zld.objects.items[object_id];
561 assert(object.hasEhFrameRecords());558 assert(object.hasEhFrameRecords());
562 const urel = object.eh_frame_relocs_lookup.get(source_offset) orelse559 const urel = object.eh_frame_relocs_lookup.get(source_offset) orelse
563 return &[0]macho.relocation_info{};560 return &[0]macho.relocation_info{};
564 const all_relocs = object.getRelocs(object.eh_frame_sect.?);561 const all_relocs = object.getRelocs(object.eh_frame_sect_id.?);
565 return all_relocs[urel.reloc.start..][0..urel.reloc.len];562 return all_relocs[urel.reloc.start..][0..urel.reloc.len];
566}563}
567564
src/link/MachO/zld.zig+8-10
...@@ -2391,22 +2391,20 @@ pub const Zld = struct {...@@ -2391,22 +2391,20 @@ pub const Zld = struct {
2391 const text_sect_header = self.sections.items(.header)[text_sect_id];2391 const text_sect_header = self.sections.items(.header)[text_sect_id];
23922392
2393 for (self.objects.items) |object| {2393 for (self.objects.items) |object| {
2394 const dice = object.parseDataInCode() orelse continue;2394 if (!object.hasDataInCode()) continue;
2395 const dice = object.data_in_code.items;
2395 try out_dice.ensureUnusedCapacity(dice.len);2396 try out_dice.ensureUnusedCapacity(dice.len);
23962397
2397 for (object.atoms.items) |atom_index| {2398 for (object.exec_atoms.items) |atom_index| {
2398 const atom = self.getAtom(atom_index);2399 const atom = self.getAtom(atom_index);
2399 const sym = self.getSymbol(atom.getSymbolWithLoc());2400 const sym = self.getSymbol(atom.getSymbolWithLoc());
2400 const sect_id = sym.n_sect - 1;2401 if (sym.n_desc == N_DEAD) continue;
2401 if (sect_id != text_sect_id) {
2402 continue;
2403 }
24042402
2405 const source_addr = if (object.getSourceSymbol(atom.sym_index)) |source_sym|2403 const source_addr = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
2406 source_sym.n_value2404 source_sym.n_value
2407 else blk: {2405 else blk: {
2408 const nbase = @intCast(u32, object.in_symtab.?.len);2406 const nbase = @intCast(u32, object.in_symtab.?.len);
2409 const source_sect_id = @intCast(u16, atom.sym_index - nbase);2407 const source_sect_id = @intCast(u8, atom.sym_index - nbase);
2410 break :blk object.getSourceSection(source_sect_id).addr;2408 break :blk object.getSourceSection(source_sect_id).addr;
2411 };2409 };
2412 const filtered_dice = filterDataInCode(dice, source_addr, source_addr + atom.size);2410 const filtered_dice = filterDataInCode(dice, source_addr, source_addr + atom.size);
...@@ -2699,12 +2697,12 @@ pub const Zld = struct {...@@ -2699,12 +2697,12 @@ pub const Zld = struct {
2699 // Exclude region comprising all symbol stabs.2697 // Exclude region comprising all symbol stabs.
2700 const nlocals = self.dysymtab_cmd.nlocalsym;2698 const nlocals = self.dysymtab_cmd.nlocalsym;
27012699
2702 const locals_buf = try self.gpa.alloc(u8, nlocals * @sizeOf(macho.nlist_64));2700 const locals = try self.gpa.alloc(macho.nlist_64, nlocals);
2703 defer self.gpa.free(locals_buf);2701 defer self.gpa.free(locals);
27042702
2703 const locals_buf = @ptrCast([*]u8, locals.ptr)[0 .. @sizeOf(macho.nlist_64) * nlocals];
2705 const amt = try self.file.preadAll(locals_buf, self.symtab_cmd.symoff);2704 const amt = try self.file.preadAll(locals_buf, self.symtab_cmd.symoff);
2706 if (amt != locals_buf.len) return error.InputOutput;2705 if (amt != locals_buf.len) return error.InputOutput;
2707 const locals = @ptrCast([*]macho.nlist_64, @alignCast(@alignOf(macho.nlist_64), locals_buf))[0..nlocals];
27082706
2709 const istab: usize = for (locals) |local, i| {2707 const istab: usize = for (locals) |local, i| {
2710 if (local.stab()) break i;2708 if (local.stab()) break i;