aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-09-09 00:25:55 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-09-09 00:25:55 +0200
commit9fb44e8e1fa4f07e44e2d354e09db9d953861e71 (patch)
treeff2e06aee633e5f81a2306c1cb9701f4598f6b58 /src
parente00b9d6192a09305c4160ccbeeb761a1f1af855a (diff)
downloadzig-9fb44e8e1fa4f07e44e2d354e09db9d953861e71.tar.gz
zig-9fb44e8e1fa4f07e44e2d354e09db9d953861e71.zip
macho: precompute total required size when parsing objects
This way, we can preallocate the necessary sizes for segments and sections upfront rather than doing it per parsed atom.
Diffstat (limited to 'src')
-rw-r--r--src/link/MachO.zig41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 927334f880..808d96b767 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -2589,6 +2589,47 @@ fn resolveDyldStubBinder(self: *MachO) !void {
}
fn parseTextBlocks(self: *MachO) !void {
+ var section_metadata = std.AutoHashMap(MatchingSection, struct {
+ size: u64,
+ alignment: u32,
+ }).init(self.base.allocator);
+ defer section_metadata.deinit();
+
+ for (self.objects.items) |object| {
+ const seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
+ for (seg.sections.items) |sect| {
+ const match = (try self.getMatchingSection(sect)) orelse {
+ log.debug("unhandled section", .{});
+ continue;
+ };
+ const res = try section_metadata.getOrPut(match);
+ if (!res.found_existing) {
+ res.value_ptr.* = .{
+ .size = 0,
+ .alignment = 0,
+ };
+ }
+ const alignment = try math.powi(u32, 2, sect.@"align");
+ res.value_ptr.size += mem.alignForwardGeneric(u64, sect.size, alignment);
+ res.value_ptr.alignment = math.max(res.value_ptr.alignment, sect.@"align");
+ }
+ }
+
+ var it = section_metadata.iterator();
+ while (it.next()) |entry| {
+ const match = entry.key_ptr.*;
+ const metadata = entry.value_ptr.*;
+ const seg = self.load_commands.items[match.seg].Segment;
+ const sect = seg.sections.items[match.sect];
+ log.debug("{s},{s} => size: 0x{x}, alignment: 0x{x}", .{
+ commands.segmentName(sect),
+ commands.sectionName(sect),
+ metadata.size,
+ metadata.alignment,
+ });
+ try self.growSection(match, @intCast(u32, metadata.size));
+ }
+
for (self.objects.items) |*object, object_id| {
try object.parseTextBlocks(self.base.allocator, @intCast(u16, object_id), self);
}