authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-12-28 03:20:06-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-12-28 14:24:27-05:00
log74b14edea8b7d8ae7816feda2ee37a4ca016bc03
tree2e5beb75cf5f179d947021a981ddc6210d0c9630
parent70ac9fc7afe672d39cdcc2f1fa4df00d34f5a775

link: fix memory leaks

* Fix linker memory leaks found while running `zig build test-cases`. * Add missing target to test manifest.

5 files changed, 35 insertions(+), 14 deletions(-)

src/link.zig+4
...@@ -223,7 +223,9 @@ pub const Options = struct {...@@ -223,7 +223,9 @@ pub const Options = struct {
223223
224 pub fn move(self: *Options) Options {224 pub fn move(self: *Options) Options {
225 const copied_state = self.*;225 const copied_state = self.*;
226 self.frameworks = .{};
226 self.system_libs = .{};227 self.system_libs = .{};
228 self.force_undefined_symbols = .{};
227 return copied_state;229 return copied_state;
228 }230 }
229};231};
...@@ -624,7 +626,9 @@ pub const File = struct {...@@ -624,7 +626,9 @@ pub const File = struct {
624 base.releaseLock();626 base.releaseLock();
625 if (base.file) |f| f.close();627 if (base.file) |f| f.close();
626 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);628 if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
629 base.options.frameworks.deinit(base.allocator);
627 base.options.system_libs.deinit(base.allocator);630 base.options.system_libs.deinit(base.allocator);
631 base.options.force_undefined_symbols.deinit(base.allocator);
628 switch (base.tag) {632 switch (base.tag) {
629 .coff => {633 .coff => {
630 if (build_options.only_c) unreachable;634 if (build_options.only_c) unreachable;
src/link/Coff.zig+6-4
...@@ -289,6 +289,7 @@ pub fn deinit(self: *Coff) void {...@@ -289,6 +289,7 @@ pub fn deinit(self: *Coff) void {
289289
290 self.unresolved.deinit(gpa);290 self.unresolved.deinit(gpa);
291 self.locals_free_list.deinit(gpa);291 self.locals_free_list.deinit(gpa);
292 self.globals_free_list.deinit(gpa);
292 self.strtab.deinit(gpa);293 self.strtab.deinit(gpa);
293 self.got_entries.deinit(gpa);294 self.got_entries.deinit(gpa);
294 self.got_entries_free_list.deinit(gpa);295 self.got_entries_free_list.deinit(gpa);
...@@ -1150,8 +1151,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,...@@ -1150,8 +1151,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
1150}1151}
11511152
1152fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void {1153fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void {
1153 _ = self.relocs.remove(atom);1154 var removed_relocs = self.relocs.fetchRemove(atom);
1154 _ = self.base_relocs.remove(atom);1155 if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
1156 var removed_base_relocs = self.base_relocs.fetchRemove(atom);
1157 if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(self.base.allocator);
1155}1158}
11561159
1157fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void {1160fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void {
...@@ -1489,9 +1492,8 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {...@@ -1489,9 +1492,8 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {
1489 gop.value_ptr.* = sym_loc;1492 gop.value_ptr.* = sym_loc;
14901493
1491 const gpa = self.base.allocator;1494 const gpa = self.base.allocator;
1492 const sym_name = try gpa.dupe(u8, name);
1493 const sym = self.getSymbolPtr(sym_loc);1495 const sym = self.getSymbolPtr(sym_loc);
1494 try self.setSymbolName(sym, sym_name);1496 try self.setSymbolName(sym, name);
1495 sym.storage_class = .EXTERNAL;1497 sym.storage_class = .EXTERNAL;
14961498
1497 try self.unresolved.putNoClobber(gpa, global_index, true);1499 try self.unresolved.putNoClobber(gpa, global_index, true);
src/link/MachO.zig+8-4
...@@ -2576,10 +2576,14 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -2576,10 +2576,14 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
2576}2576}
25772577
2578fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {2578fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {
2579 _ = self.relocs.remove(atom);2579 var removed_relocs = self.relocs.fetchRemove(atom);
2580 _ = self.rebases.remove(atom);2580 if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
2581 _ = self.bindings.remove(atom);2581 var removed_rebases = self.rebases.fetchRemove(atom);
2582 _ = self.lazy_bindings.remove(atom);2582 if (removed_rebases) |*rebases| rebases.value.deinit(self.base.allocator);
2583 var removed_bindings = self.bindings.fetchRemove(atom);
2584 if (removed_bindings) |*bindings| bindings.value.deinit(self.base.allocator);
2585 var removed_lazy_bindings = self.lazy_bindings.fetchRemove(atom);
2586 if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(self.base.allocator);
2583}2587}
25842588
2585fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {2589fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
src/link/Plan9.zig+16-6
...@@ -201,7 +201,10 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {...@@ -201,7 +201,10 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {
201 const decl = mod.declPtr(decl_index);201 const decl = mod.declPtr(decl_index);
202 const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope());202 const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope());
203 if (fn_map_res.found_existing) {203 if (fn_map_res.found_existing) {
204 try fn_map_res.value_ptr.functions.put(gpa, decl_index, out);204 if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {
205 gpa.free(old_entry.value.code);
206 gpa.free(old_entry.value.lineinfo);
207 }
205 } else {208 } else {
206 const file = decl.getFileScope();209 const file = decl.getFileScope();
207 const arena = self.path_arena.allocator();210 const arena = self.path_arena.allocator();
...@@ -408,9 +411,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)...@@ -408,9 +411,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
408 return;411 return;
409 },412 },
410 };413 };
411 var duped_code = try self.base.allocator.dupe(u8, code);414 try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1);
412 errdefer self.base.allocator.free(duped_code);415 const duped_code = try self.base.allocator.dupe(u8, code);
413 try self.data_decl_table.put(self.base.allocator, decl_index, duped_code);416 if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
417 self.base.allocator.free(old_entry.value);
418 }
414 return self.updateFinish(decl);419 return self.updateFinish(decl);
415}420}
416/// called at the end of update{Decl,Func}421/// called at the end of update{Decl,Func}
...@@ -743,14 +748,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {...@@ -743,14 +748,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
743 if (is_fn) {748 if (is_fn) {
744 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?;749 var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?;
745 var submap = symidx_and_submap.functions;750 var submap = symidx_and_submap.functions;
746 _ = submap.swapRemove(decl_index);751 if (submap.fetchSwapRemove(decl_index)) |removed_entry| {
752 self.base.allocator.free(removed_entry.value.code);
753 self.base.allocator.free(removed_entry.value.lineinfo);
754 }
747 if (submap.count() == 0) {755 if (submap.count() == 0) {
748 self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol;756 self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol;
749 self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {};757 self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {};
750 submap.deinit(self.base.allocator);758 submap.deinit(self.base.allocator);
751 }759 }
752 } else {760 } else {
753 _ = self.data_decl_table.swapRemove(decl_index);761 if (self.data_decl_table.fetchSwapRemove(decl_index)) |removed_entry| {
762 self.base.allocator.free(removed_entry.value);
763 }
754 }764 }
755 if (decl.link.plan9.got_index) |i| {765 if (decl.link.plan9.got_index) |i| {
756 // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length766 // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length
test/cases/plan9/hello_world_with_updates.1.zig+1
...@@ -5,6 +5,7 @@ pub fn main() void {...@@ -5,6 +5,7 @@ pub fn main() void {
5}5}
66
7// run7// run
8// target=x86_64-plan9
8//9//
9// Hello World10// Hello World
10//11//