diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-05 00:19:45 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2021-09-05 00:19:45 +0200 |
| commit | d92b5416e86f2b6bf0cf530c8f98da572bf9efde (patch) | |
| tree | 40445f7051dadc283b3b336fd120fb9c8270eee8 /src | |
| parent | 7e87f93e068af192a3c39bdeebfe8e9b612311b0 (diff) | |
| download | zig-d92b5416e86f2b6bf0cf530c8f98da572bf9efde.tar.gz zig-d92b5416e86f2b6bf0cf530c8f98da572bf9efde.zip | |
macho: add a small routine to update section ordinals at the end
The actual ordinals may change when adding new sections to the segments.
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 4ee81e7c43..ce6fe49d35 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -162,6 +162,7 @@ stubs_map: std.AutoArrayHashMapUnmanaged(u32, *TextBlock) = .{}, error_flags: File.ErrorFlags = File.ErrorFlags{}, load_commands_dirty: bool = false, +sections_order_dirty: bool = false, has_dices: bool = false, has_stabs: bool = false, @@ -806,6 +807,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { defer tracy.end(); try self.setEntryPoint(); + try self.updateSectionOrdinals(); try self.writeLinkeditSegment(); if (self.d_sym) |*ds| { @@ -3817,6 +3819,7 @@ fn allocateSection( try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); self.load_commands_dirty = true; + self.sections_order_dirty = true; return index; } @@ -3998,6 +4001,44 @@ fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { }; } +fn updateSectionOrdinals(self: *MachO) !void { + if (!self.sections_order_dirty) return; + + const tracy = trace(@src()); + defer tracy.end(); + + var ordinal_remap = std.AutoHashMap(u8, u8).init(self.base.allocator); + defer ordinal_remap.deinit(); + var ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}; + + var new_ordinal: u8 = 0; + for (self.load_commands.items) |lc, lc_id| { + if (lc != .Segment) break; + + for (lc.Segment.sections.items) |_, sect_id| { + const match = MatchingSection{ + .seg = @intCast(u16, lc_id), + .sect = @intCast(u16, sect_id), + }; + const old_ordinal = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); + new_ordinal += 1; + try ordinal_remap.putNoClobber(old_ordinal, new_ordinal); + try ordinals.putNoClobber(self.base.allocator, match, {}); + } + } + + for (self.locals.items) |*sym| { + if (sym.n_sect == 0) continue; + sym.n_sect = ordinal_remap.get(sym.n_sect).?; + } + for (self.globals.items) |*sym| { + sym.n_sect = ordinal_remap.get(sym.n_sect).?; + } + + self.section_ordinals.deinit(self.base.allocator); + self.section_ordinals = ordinals; +} + fn writeDyldInfoData(self: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); |
