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) = .{},...@@ -188,9 +188,21 @@ text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},
188/// Pointer to the last allocated text block188/// Pointer to the last allocated text block
189last_text_block: ?*TextBlock = null,189last_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
192blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{},198blocks: 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
194/// A list of all PIE fixups required for this run of the linker.206/// A list of all PIE fixups required for this run of the linker.
195/// Warning, this is currently NOT thread-safe. See the TODO below.207/// Warning, this is currently NOT thread-safe. See the TODO below.
196/// TODO Move this list inside `updateDecl` where it should be allocated208/// TODO Move this list inside `updateDecl` where it should be allocated
...@@ -203,7 +215,7 @@ pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{},...@@ -203,7 +215,7 @@ pie_fixups: std.ArrayListUnmanaged(PIEFixup) = .{},
203const StringIndexContext = struct {215const StringIndexContext = struct {
204 strtab: *std.ArrayListUnmanaged(u8),216 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 {
207 return a == b;219 return a == b;
208 }220 }
209221
...@@ -2224,7 +2236,6 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2224,7 +2236,6 @@ fn resolveSymbols(self: *MachO) !void {
2224 for (self.tentatives.items) |sym| {2236 for (self.tentatives.items) |sym| {
2225 if (symbolIsNull(sym)) continue;2237 if (symbolIsNull(sym)) continue;
22262238
2227 const sym_name = self.getString(sym.n_strx);
2228 const match: MatchingSection = blk: {2239 const match: MatchingSection = blk: {
2229 if (self.common_section_index == null) {2240 if (self.common_section_index == null) {
2230 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2241 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
...@@ -2263,12 +2274,13 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2263,12 +2274,13 @@ fn resolveSymbols(self: *MachO) !void {
2263 .local_sym_index = local_sym_index,2274 .local_sym_index = local_sym_index,
2264 };2275 };
22652276
2266 const block = try self.managed_blocks.addOne(self.base.allocator);2277 const block = try self.base.allocator.create(TextBlock);
2267 block.* = TextBlock.empty;2278 block.* = TextBlock.empty;
2268 block.local_sym_index = local_sym_index;2279 block.local_sym_index = local_sym_index;
2269 block.code = code;2280 block.code = code;
2270 block.size = size;2281 block.size = size;
2271 block.alignment = alignment;2282 block.alignment = alignment;
2283 try self.managed_blocks.append(self.base.allocator, block);
22722284
2273 // Update target section's metadata2285 // Update target section's metadata
2274 // TODO should we update segment's size here too?2286 // TODO should we update segment's size here too?
...@@ -2403,12 +2415,13 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2403,12 +2415,13 @@ fn resolveSymbols(self: *MachO) !void {
2403 // We create an empty atom for this symbol.2415 // We create an empty atom for this symbol.
2404 // TODO perhaps we should special-case special symbols? Create a separate2416 // TODO perhaps we should special-case special symbols? Create a separate
2405 // linked list of atoms?2417 // linked list of atoms?
2406 const block = try self.managed_blocks.addOne(self.base.allocator);2418 const block = try self.base.allocator.create(TextBlock);
2407 block.* = TextBlock.empty;2419 block.* = TextBlock.empty;
2408 block.local_sym_index = local_sym_index;2420 block.local_sym_index = local_sym_index;
2409 block.code = try self.base.allocator.alloc(u8, 0);2421 block.code = try self.base.allocator.alloc(u8, 0);
2410 block.size = 0;2422 block.size = 0;
2411 block.alignment = 0;2423 block.alignment = 0;
2424 try self.managed_blocks.append(self.base.allocator, block);
24122425
2413 if (self.blocks.getPtr(match)) |last| {2426 if (self.blocks.getPtr(match)) |last| {
2414 last.*.next = block;2427 last.*.next = block;
...@@ -3306,12 +3319,18 @@ pub fn deinit(self: *MachO) void {...@@ -3306,12 +3319,18 @@ pub fn deinit(self: *MachO) void {
3306 }3319 }
3307 self.load_commands.deinit(self.base.allocator);3320 self.load_commands.deinit(self.base.allocator);
33083321
3309 for (self.managed_blocks.items) |*block| {3322 for (self.managed_blocks.items) |block| {
3310 block.deinit(self.base.allocator);3323 block.deinit(self.base.allocator);
3324 self.base.allocator.destroy(block);
3311 }3325 }
3312 self.managed_blocks.deinit(self.base.allocator);3326 self.managed_blocks.deinit(self.base.allocator);
3313 self.blocks.deinit(self.base.allocator);3327 self.blocks.deinit(self.base.allocator);
3314 self.text_block_free_list.deinit(self.base.allocator);3328 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);
3315}3334}
33163335
3317pub fn closeFiles(self: MachO) void {3336pub fn closeFiles(self: MachO) void {
...@@ -3325,7 +3344,7 @@ pub fn closeFiles(self: MachO) void {...@@ -3325,7 +3344,7 @@ pub fn closeFiles(self: MachO) void {
33253344
3326fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {3345fn freeTextBlock(self: *MachO, text_block: *TextBlock) void {
3327 log.debug("freeTextBlock {*}", .{text_block});3346 log.debug("freeTextBlock {*}", .{text_block});
3328 // text_block.deinit(self.base.allocator);3347 text_block.deinit(self.base.allocator);
33293348
3330 var already_have_free_list_node = false;3349 var already_have_free_list_node = false;
3331 {3350 {
...@@ -3412,6 +3431,9 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {...@@ -3412,6 +3431,9 @@ pub fn allocateDeclIndexes(self: *MachO, decl: *Module.Decl) !void {
34123431
3413 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);3432 try self.locals.ensureUnusedCapacity(self.base.allocator, 1);
3414 try self.got_entries.ensureUnusedCapacity(self.base.allocator, 1);3433 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
3416 if (self.locals_free_list.popOrNull()) |i| {3438 if (self.locals_free_list.popOrNull()) |i| {
3417 log.debug("reusing symbol index {d} for {s}", .{ i, decl.name });3439 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 {...@@ -3497,7 +3519,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
3497 .externally_managed => |x| break :blk x,3519 .externally_managed => |x| break :blk x,
3498 .appended => {3520 .appended => {
3499 decl.link.macho.code = code_buffer.toOwnedSlice();3521 decl.link.macho.code = code_buffer.toOwnedSlice();
3500 log.warn("WAT", .{});
3501 break :blk decl.link.macho.code;3522 break :blk decl.link.macho.code;
3502 },3523 },
3503 .fail => |em| {3524 .fail => |em| {
src/link/MachO/Object.zig+2-1
...@@ -723,12 +723,13 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {...@@ -723,12 +723,13 @@ pub fn parseTextBlocks(self: *Object, macho_file: *MachO) !void {
723 break :blk block_local_sym_index;723 break :blk block_local_sym_index;
724 };724 };
725725
726 const block = try macho_file.managed_blocks.addOne(macho_file.base.allocator);726 const block = try macho_file.base.allocator.create(TextBlock);
727 block.* = TextBlock.empty;727 block.* = TextBlock.empty;
728 block.local_sym_index = block_local_sym_index;728 block.local_sym_index = block_local_sym_index;
729 block.code = try self.allocator.dupe(u8, code);729 block.code = try self.allocator.dupe(u8, code);
730 block.size = sect.size;730 block.size = sect.size;
731 block.alignment = sect.@"align";731 block.alignment = sect.@"align";
732 try macho_file.managed_blocks.append(macho_file.base.allocator, block);
732733
733 try block.parseRelocsFromObject(self.allocator, relocs, self, .{734 try block.parseRelocsFromObject(self.allocator, relocs, self, .{
734 .base_addr = 0,735 .base_addr = 0,