authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-21 15:46:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-21 15:46:57+02:00
log3bfde76cff60a0d9c70d8e660dd633bed17a314f
tree43445d49bcc77b3259e734cbd85f6a266e6c317d
parent5276ce8e638d3d295c443d8bc33e5c51538ae540

macho: fix text block management

For the time being, until we rewrite how atoms are handled across linkers, store two tables in the MachO linker: one for TextBlocks directly created and managed by the linker, and one for TextBlocks that were spawned by Module.Decl. This allows for correct memory clean up after linking is done.

2 files changed, 31 insertions(+), 9 deletions(-)

src/link/MachO.zig+29-8
......@@ -188,9 +188,21 @@ text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},
188188/// Pointer to the last allocated text block
189189last_text_block: ?*TextBlock = null,
190190
191managed_blocks: std.ArrayListUnmanaged(TextBlock) = .{},
191/// List of TextBlocks that are owned directly by the linker.
192/// Currently these are only TextBlocks that are the result of linking
193/// object files. TextBlock which take part in incremental linking are
194/// at present owned by Module.Decl.
195/// TODO consolidate this.
196managed_blocks: std.ArrayListUnmanaged(*TextBlock) = .{},
197
192198blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{},
193199
200/// List of Decls that are currently alive.
201/// We store them here so that we can properly dispose of any allocated
202/// memory within the TextBlock in the incremental linker.
203/// TODO consolidate this.
204decls: std.ArrayListUnmanaged(*Module.Decl) = .{},
205
194206/// A list of all PIE fixups required for this run of the linker.
195207/// Warning, this is currently NOT thread-safe. See the TODO below.
196208/// TODO Move this list inside `updateDecl` where it should be allocated
......@@ -203,7 +215,7 @@ pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{},
203215const StringIndexContext = struct {
204216 strtab: *std.ArrayListUnmanaged(u8),
205217
206 pub fn eql(self: StringIndexContext, a: u32, b: u32) bool {
218 pub fn eql(_: StringIndexContext, a: u32, b: u32) bool {
207219 return a == b;
208220 }
209221
......@@ -2224,7 +2236,6 @@ fn resolveSymbols(self: *MachO) !void {
22242236 for (self.tentatives.items) |sym| {
22252237 if (symbolIsNull(sym)) continue;
22262238
2227 const sym_name = self.getString(sym.n_strx);
22282239 const match: MatchingSection = blk: {
22292240 if (self.common_section_index == null) {
22302241 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
......@@ -2263,12 +2274,13 @@ fn resolveSymbols(self: *MachO) !void {
22632274 .local_sym_index = local_sym_index,
22642275 };
22652276
2266 const block = try self.managed_blocks.addOne(self.base.allocator);
2277 const block = try self.base.allocator.create(TextBlock);
22672278 block.* = TextBlock.empty;
22682279 block.local_sym_index = local_sym_index;
22692280 block.code = code;
22702281 block.size = size;
22712282 block.alignment = alignment;
2283 try self.managed_blocks.append(self.base.allocator, block);
22722284
22732285 // Update target section's metadata
22742286 // TODO should we update segment's size here too?
......@@ -2403,12 +2415,13 @@ fn resolveSymbols(self: *MachO) !void {
24032415 // We create an empty atom for this symbol.
24042416 // TODO perhaps we should special-case special symbols? Create a separate
24052417 // linked list of atoms?
2406 const block = try self.managed_blocks.addOne(self.base.allocator);
2418 const block = try self.base.allocator.create(TextBlock);
24072419 block.* = TextBlock.empty;
24082420 block.local_sym_index = local_sym_index;
24092421 block.code = try self.base.allocator.alloc(u8, 0);
24102422 block.size = 0;
24112423 block.alignment = 0;
2424 try self.managed_blocks.append(self.base.allocator, block);
24122425
24132426 if (self.blocks.getPtr(match)) |last| {
24142427 last.*.next = block;
......@@ -3306,12 +3319,18 @@ pub fn deinit(self: *MachO) void {
33063319 }
33073320 self.load_commands.deinit(self.base.allocator);
33083321
3309 for (self.managed_blocks.items) |*block| {
3322 for (self.managed_blocks.items) |block| {
33103323 block.deinit(self.base.allocator);
3324 self.base.allocator.destroy(block);
33113325 }
33123326 self.managed_blocks.deinit(self.base.allocator);
33133327 self.blocks.deinit(self.base.allocator);
33143328 self.text_block_free_list.deinit(self.base.allocator);
3329
3330 for (self.decls.items) |decl| {
3331 decl.link.macho.deinit(self.base.allocator);
3332 }
3333 self.decls.deinit(self.base.allocator);
33153334}
33163335
33173336pub fn closeFiles(self: MachO) void {
......@@ -3325,7 +3344,7 @@ pub fn closeFiles(self: MachO) void {
33253344
33263345fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
33273346 log.debug("freeTextBlock {*}", .{text_block});
3328 // text_block.deinit(self.base.allocator);
3347 text_block.deinit(self.base.allocator);
33293348
33303349 var already_have_free_list_node = false;
33313350 {
......@@ -3412,6 +3431,9 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
34123431
34133432 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);
34143433 try self.got_entries.ensureUnusedCapacity(self.base.allocator, 1);
3434 try self.decls.ensureUnusedCapacity(self.base.allocator, 1);
3435
3436 self.decls.appendAssumeCapacity(decl);
34153437
34163438 if (self.locals_free_list.popOrNull()) |i| {
34173439 log.debug("reusing symbol index {d} for {s}", .{ i, decl.name });
......@@ -3497,7 +3519,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
34973519 .externally_managed => |x| break :blk x,
34983520 .appended => {
34993521 decl.link.macho.code = code_buffer.toOwnedSlice();
3500 log.warn("WAT", .{});
35013522 break :blk decl.link.macho.code;
35023523 },
35033524 .fail => |em| {
src/link/MachO/Object.zig+2-1
......@@ -723,12 +723,13 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
723723 break :blk block_local_sym_index;
724724 };
725725
726 const block = try macho_file.managed_blocks.addOne(macho_file.base.allocator);
726 const block = try macho_file.base.allocator.create(TextBlock);
727727 block.* = TextBlock.empty;
728728 block.local_sym_index = block_local_sym_index;
729729 block.code = try self.allocator.dupe(u8, code);
730730 block.size = sect.size;
731731 block.alignment = sect.@"align";
732 try macho_file.managed_blocks.append(macho_file.base.allocator, block);
732733
733734 try block.parseRelocsFromObject(self.allocator, relocs, self, .{
734735 .base_addr = 0,