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,...@@ -60,12 +60,16 @@ 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.63/// All relocations sorted and flatened, sorted by address descending
64/// per section.
64relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{},65relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{},
65/// Beginning index to the relocations array for each input section66/// Beginning index to the relocations array for each input section
66/// defined within this Object file.67/// defined within this Object file.
67section_relocs_lookup: std.ArrayListUnmanaged(u32) = .{},68section_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
69atoms: std.ArrayListUnmanaged(AtomIndex) = .{},73atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
70exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},74exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
7175
...@@ -108,6 +112,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {...@@ -108,6 +112,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
108 self.unwind_records_lookup.deinit(gpa);112 self.unwind_records_lookup.deinit(gpa);
109 self.relocations.deinit(gpa);113 self.relocations.deinit(gpa);
110 self.section_relocs_lookup.deinit(gpa);114 self.section_relocs_lookup.deinit(gpa);
115 self.data_in_code.deinit(gpa);
111}116}
112117
113pub 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 {
...@@ -365,6 +370,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u32) !void {...@@ -365,6 +370,7 @@ pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u32) !void {
365 try self.splitRegularSections(zld, object_id);370 try self.splitRegularSections(zld, object_id);
366 try self.parseEhFrameSection(zld, object_id);371 try self.parseEhFrameSection(zld, object_id);
367 try self.parseUnwindInfo(zld, object_id);372 try self.parseUnwindInfo(zld, object_id);
373 try self.parseDataInCode(zld.gpa);
368}374}
369375
370/// Splits input regular sections into Atoms.376/// Splits input regular sections into Atoms.
...@@ -870,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {...@@ -870,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {
870 } else unreachable;876 } else unreachable;
871}877}
872878
873pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {879pub fn parseDataInCode(self: *Object, gpa: Allocator) !void {
874 var it = LoadCommandIterator{880 var it = LoadCommandIterator{
875 .ncmds = self.header.ncmds,881 .ncmds = self.header.ncmds,
876 .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],
877 };883 };
878 while (it.next()) |cmd| {884 const cmd = while (it.next()) |cmd| {
879 switch (cmd.cmd()) {885 switch (cmd.cmd()) {
880 .DATA_IN_CODE => {886 .DATA_IN_CODE => break cmd.cast(macho.linkedit_data_command).?,
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 },
888 else => {},887 else => {},
889 }888 }
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;
891}900}
892901
893fn parseDysymtab(self: Object) ?macho.dysymtab_command {902fn parseDysymtab(self: Object) ?macho.dysymtab_command {
...@@ -1033,3 +1042,7 @@ pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {...@@ -1033,3 +1042,7 @@ pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {
1033 const data = self.getSectionContents(sect);1042 const data = self.getSectionContents(sect);
1034 return .{ .data = data };1043 return .{ .data = data };
1035}1044}
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 {...@@ -2391,16 +2391,14 @@ 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