authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-06 16:08:42+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-06 16:08:42+01:00
logf63eda3f6ae4369e12b68bb13e36b23957a9d809
tree61e4b190527edcaf3efb3a1124e02c060d5f0a29
parentb32f5ee93283f7794c611ebd4a1fbc579b78d8ab

macho: parse and sort data-in-code entries ahead of time


2 files changed, 29 insertions(+), 18 deletions(-)

src/link/MachO/Object.zig+25-12
......@@ -60,12 +60,16 @@ globals_lookup: []i64 = undefined,
6060/// Can be undefined as set together with in_symtab.
6161relocs_lookup: []RelocEntry = undefined,
6262
63/// All relocations sorted and flatened.
63/// All relocations sorted and flatened, sorted by address descending
64/// per section.
6465relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{},
6566/// Beginning index to the relocations array for each input section
6667/// defined within this Object file.
6768section_relocs_lookup: std.ArrayListUnmanaged(u32) = .{},
6869
70/// Data-in-code records sorted by address.
71data_in_code: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
72
6973atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
7074exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
7175
......@@ -108,6 +112,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
108112 self.unwind_records_lookup.deinit(gpa);
109113 self.relocations.deinit(gpa);
110114 self.section_relocs_lookup.deinit(gpa);
115 self.data_in_code.deinit(gpa);
111116}
112117
113118pub fn parse(self: *Object, allocator: Allocator, cpu_arch: std.Target.Cpu.Arch) !void {
......@@ -365,6 +370,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u32) !void {
365370 try self.splitRegularSections(zld, object_id);
366371 try self.parseEhFrameSection(zld, object_id);
367372 try self.parseUnwindInfo(zld, object_id);
373 try self.parseDataInCode(zld.gpa);
368374}
369375
370376/// Splits input regular sections into Atoms.
......@@ -870,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {
870876 } else unreachable;
871877}
872878
873pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
879pub fn parseDataInCode(self: *Object, gpa: Allocator) !void {
874880 var it = LoadCommandIterator{
875881 .ncmds = self.header.ncmds,
876882 .buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],
877883 };
878 while (it.next()) |cmd| {
884 const cmd = while (it.next()) |cmd| {
879885 switch (cmd.cmd()) {
880 .DATA_IN_CODE => {
881 const dice = cmd.cast(macho.linkedit_data_command).?;
882 const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
883 return @ptrCast(
884 [*]const macho.data_in_code_entry,
885 @alignCast(@alignOf(macho.data_in_code_entry), &self.contents[dice.dataoff]),
886 )[0..ndice];
887 },
886 .DATA_IN_CODE => break cmd.cast(macho.linkedit_data_command).?,
888887 else => {},
889888 }
890 } 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;
891900}
892901
893902fn parseDysymtab(self: Object) ?macho.dysymtab_command {
......@@ -1033,3 +1042,7 @@ pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {
10331042 const data = self.getSectionContents(sect);
10341043 return .{ .data = data };
10351044}
1045
1046pub fn hasDataInCode(self: Object) bool {
1047 return self.data_in_code.items.len > 0;
1048}
src/link/MachO/zld.zig+4-6
......@@ -2391,16 +2391,14 @@ pub const Zld = struct {
23912391 const text_sect_header = self.sections.items(.header)[text_sect_id];
23922392
23932393 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;
23952396 try out_dice.ensureUnusedCapacity(dice.len);
23962397
2397 for (object.atoms.items) |atom_index| {
2398 for (object.exec_atoms.items) |atom_index| {
23982399 const atom = self.getAtom(atom_index);
23992400 const sym = self.getSymbol(atom.getSymbolWithLoc());
2400 const sect_id = sym.n_sect - 1;
2401 if (sect_id != text_sect_id) {
2402 continue;
2403 }
2401 if (sym.n_desc == N_DEAD) continue;
24042402
24052403 const source_addr = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
24062404 source_sym.n_value