diff --git a/src/link/MachO.zig b/src/link/MachO.zig index f271e00950..6fc5989a1d 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -188,9 +188,21 @@ text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{}, /// Pointer to the last allocated text block last_text_block: ?*TextBlock = null, -managed_blocks: std.ArrayListUnmanaged(TextBlock) = .{}, +/// List of TextBlocks that are owned directly by the linker. +/// Currently these are only TextBlocks that are the result of linking +/// object files. TextBlock which take part in incremental linking are +/// at present owned by Module.Decl. +/// TODO consolidate this. +managed_blocks: std.ArrayListUnmanaged(*TextBlock) = .{}, + blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{}, +/// List of Decls that are currently alive. +/// We store them here so that we can properly dispose of any allocated +/// memory within the TextBlock in the incremental linker. +/// TODO consolidate this. +decls: std.ArrayListUnmanaged(*Module.Decl) = .{}, + /// A list of all PIE fixups required for this run of the linker. /// Warning, this is currently NOT thread-safe. See the TODO below. /// TODO Move this list inside `updateDecl` where it should be allocated @@ -203,7 +215,7 @@ pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{}, const StringIndexContext = struct { strtab: *std.ArrayListUnmanaged(u8), - pub fn eql(self: StringIndexContext, a: u32, b: u32) bool { + pub fn eql(_: StringIndexContext, a: u32, b: u32) bool { return a == b; } @@ -2224,7 +2236,6 @@ fn resolveSymbols(self: *MachO) !void { for (self.tentatives.items) |sym| { if (symbolIsNull(sym)) continue; - const sym_name = self.getString(sym.n_strx); const match: MatchingSection = blk: { if (self.common_section_index == null) { const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; @@ -2263,12 +2274,13 @@ fn resolveSymbols(self: *MachO) !void { .local_sym_index = local_sym_index, }; - const block = try self.managed_blocks.addOne(self.base.allocator); + const block = try self.base.allocator.create(TextBlock); block.* = TextBlock.empty; block.local_sym_index = local_sym_index; block.code = code; block.size = size; block.alignment = alignment; + try self.managed_blocks.append(self.base.allocator, block); // Update target section's metadata // TODO should we update segment's size here too? @@ -2403,12 +2415,13 @@ fn resolveSymbols(self: *MachO) !void { // We create an empty atom for this symbol. // TODO perhaps we should special-case special symbols? Create a separate // linked list of atoms? - const block = try self.managed_blocks.addOne(self.base.allocator); + const block = try self.base.allocator.create(TextBlock); block.* = TextBlock.empty; block.local_sym_index = local_sym_index; block.code = try self.base.allocator.alloc(u8, 0); block.size = 0; block.alignment = 0; + try self.managed_blocks.append(self.base.allocator, block); if (self.blocks.getPtr(match)) |last| { last.*.next = block; @@ -3306,12 +3319,18 @@ pub fn deinit(self: *MachO) void { } self.load_commands.deinit(self.base.allocator); - for (self.managed_blocks.items) |*block| { + for (self.managed_blocks.items) |block| { block.deinit(self.base.allocator); + self.base.allocator.destroy(block); } self.managed_blocks.deinit(self.base.allocator); self.blocks.deinit(self.base.allocator); self.text_block_free_list.deinit(self.base.allocator); + + for (self.decls.items) |decl| { + decl.link.macho.deinit(self.base.allocator); + } + self.decls.deinit(self.base.allocator); } pub fn closeFiles(self: MachO) void { @@ -3325,7 +3344,7 @@ pub fn closeFiles(self: MachO) void { fn freeTextBlock(self: *MachO, text_block: *TextBlock) void { log.debug("freeTextBlock {*}", .{text_block}); - // text_block.deinit(self.base.allocator); + text_block.deinit(self.base.allocator); var already_have_free_list_node = false; { @@ -3412,6 +3431,9 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void { try self.locals.ensureUnusedCapacity(self.base.allocator, 1); try self.got_entries.ensureUnusedCapacity(self.base.allocator, 1); + try self.decls.ensureUnusedCapacity(self.base.allocator, 1); + + self.decls.appendAssumeCapacity(decl); if (self.locals_free_list.popOrNull()) |i| { 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 { .externally_managed => |x| break :blk x, .appended => { decl.link.macho.code = code_buffer.toOwnedSlice(); - log.warn("WAT", .{}); break :blk decl.link.macho.code; }, .fail => |em| { diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 407918456b..7291e0929c 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -723,12 +723,13 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void { break :blk block_local_sym_index; }; - const block = try macho_file.managed_blocks.addOne(macho_file.base.allocator); + const block = try macho_file.base.allocator.create(TextBlock); block.* = TextBlock.empty; block.local_sym_index = block_local_sym_index; block.code = try self.allocator.dupe(u8, code); block.size = sect.size; block.alignment = sect.@"align"; + try macho_file.managed_blocks.append(macho_file.base.allocator, block); try block.parseRelocsFromObject(self.allocator, relocs, self, .{ .base_addr = 0,