diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-09 00:25:55 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-09 00:25:55 +0200 |
| commit | 9fb44e8e1fa4f07e44e2d354e09db9d953861e71 (patch) | |
| tree | ff2e06aee633e5f81a2306c1cb9701f4598f6b58 /src | |
| parent | e00b9d6192a09305c4160ccbeeb761a1f1af855a (diff) | |
| download | zig-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.zig | 41 |
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); } |
