aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-02-06 16:08:42 +0100
committerJakub Konka <kubkon@jakubkonka.com>2023-02-06 16:08:42 +0100
commitf63eda3f6ae4369e12b68bb13e36b23957a9d809 (patch)
tree61e4b190527edcaf3efb3a1124e02c060d5f0a29 /src/link
parentb32f5ee93283f7794c611ebd4a1fbc579b78d8ab (diff)
downloadzig-f63eda3f6ae4369e12b68bb13e36b23957a9d809.tar.gz
zig-f63eda3f6ae4369e12b68bb13e36b23957a9d809.zip
macho: parse and sort data-in-code entries ahead of time
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO/Object.zig37
-rw-r--r--src/link/MachO/zld.zig10
2 files changed, 29 insertions, 18 deletions
diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig
index 771af9b8b3..4d24b2ed6a 100644
--- a/src/link/MachO/Object.zig
+++ b/src/link/MachO/Object.zig
@@ -60,12 +60,16 @@ globals_lookup: []i64 = undefined,
/// Can be undefined as set together with in_symtab.
relocs_lookup: []RelocEntry = undefined,
-/// All relocations sorted and flatened.
+/// All relocations sorted and flatened, sorted by address descending
+/// per section.
relocations: std.ArrayListUnmanaged(macho.relocation_info) = .{},
/// Beginning index to the relocations array for each input section
/// defined within this Object file.
section_relocs_lookup: std.ArrayListUnmanaged(u32) = .{},
+/// Data-in-code records sorted by address.
+data_in_code: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
+
atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
exec_atoms: std.ArrayListUnmanaged(AtomIndex) = .{},
@@ -108,6 +112,7 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
self.unwind_records_lookup.deinit(gpa);
self.relocations.deinit(gpa);
self.section_relocs_lookup.deinit(gpa);
+ self.data_in_code.deinit(gpa);
}
pub 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 {
try self.splitRegularSections(zld, object_id);
try self.parseEhFrameSection(zld, object_id);
try self.parseUnwindInfo(zld, object_id);
+ try self.parseDataInCode(zld.gpa);
}
/// Splits input regular sections into Atoms.
@@ -870,24 +876,27 @@ pub fn getSourceSections(self: Object) []const macho.section_64 {
} else unreachable;
}
-pub fn parseDataInCode(self: Object) ?[]const macho.data_in_code_entry {
+pub fn parseDataInCode(self: *Object, gpa: Allocator) !void {
var it = LoadCommandIterator{
.ncmds = self.header.ncmds,
.buffer = self.contents[@sizeOf(macho.mach_header_64)..][0..self.header.sizeofcmds],
};
- while (it.next()) |cmd| {
+ const cmd = while (it.next()) |cmd| {
switch (cmd.cmd()) {
- .DATA_IN_CODE => {
- const dice = cmd.cast(macho.linkedit_data_command).?;
- const ndice = @divExact(dice.datasize, @sizeOf(macho.data_in_code_entry));
- return @ptrCast(
- [*]const macho.data_in_code_entry,
- @alignCast(@alignOf(macho.data_in_code_entry), &self.contents[dice.dataoff]),
- )[0..ndice];
- },
+ .DATA_IN_CODE => break cmd.cast(macho.linkedit_data_command).?,
else => {},
}
- } else return null;
+ } else return;
+ const ndice = @divExact(cmd.datasize, @sizeOf(macho.data_in_code_entry));
+ const dice = @ptrCast([*]align(1) const macho.data_in_code_entry, self.contents.ptr + cmd.dataoff)[0..ndice];
+ try self.data_in_code.ensureTotalCapacityPrecise(gpa, dice.len);
+ self.data_in_code.appendUnalignedSliceAssumeCapacity(dice);
+ std.sort.sort(macho.data_in_code_entry, self.data_in_code.items, {}, diceLessThan);
+}
+
+fn diceLessThan(ctx: void, lhs: macho.data_in_code_entry, rhs: macho.data_in_code_entry) bool {
+ _ = ctx;
+ return lhs.offset < rhs.offset;
}
fn parseDysymtab(self: Object) ?macho.dysymtab_command {
@@ -1033,3 +1042,7 @@ pub fn getEhFrameRecordsIterator(self: Object) eh_frame.Iterator {
const data = self.getSectionContents(sect);
return .{ .data = data };
}
+
+pub fn hasDataInCode(self: Object) bool {
+ return self.data_in_code.items.len > 0;
+}
diff --git a/src/link/MachO/zld.zig b/src/link/MachO/zld.zig
index 8619163ef2..6a83de0c19 100644
--- a/src/link/MachO/zld.zig
+++ b/src/link/MachO/zld.zig
@@ -2391,16 +2391,14 @@ pub const Zld = struct {
const text_sect_header = self.sections.items(.header)[text_sect_id];
for (self.objects.items) |object| {
- const dice = object.parseDataInCode() orelse continue;
+ if (!object.hasDataInCode()) continue;
+ const dice = object.data_in_code.items;
try out_dice.ensureUnusedCapacity(dice.len);
- for (object.atoms.items) |atom_index| {
+ for (object.exec_atoms.items) |atom_index| {
const atom = self.getAtom(atom_index);
const sym = self.getSymbol(atom.getSymbolWithLoc());
- const sect_id = sym.n_sect - 1;
- if (sect_id != text_sect_id) {
- continue;
- }
+ if (sym.n_desc == N_DEAD) continue;
const source_addr = if (object.getSourceSymbol(atom.sym_index)) |source_sym|
source_sym.n_value