link: fix memory leaks

* Fix linker memory leaks found while running `zig build test-cases`.
 * Add missing target to test manifest.
This commit is contained in:
Jacob Young 2022-12-28 03:20:06 -05:00 committed by Andrew Kelley
parent 70ac9fc7af
commit 74b14edea8
5 changed files with 35 additions and 14 deletions

View File

@ -223,7 +223,9 @@ pub const Options = struct {
pub fn move(self: *Options) Options { pub fn move(self: *Options) Options {
const copied_state = self.*; const copied_state = self.*;
self.frameworks = .{};
self.system_libs = .{}; self.system_libs = .{};
self.force_undefined_symbols = .{};
return copied_state; return copied_state;
} }
}; };
@ -624,7 +626,9 @@ pub const File = struct {
base.releaseLock(); base.releaseLock();
if (base.file) |f| f.close(); if (base.file) |f| f.close();
if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path); if (base.intermediary_basename) |sub_path| base.allocator.free(sub_path);
base.options.frameworks.deinit(base.allocator);
base.options.system_libs.deinit(base.allocator); base.options.system_libs.deinit(base.allocator);
base.options.force_undefined_symbols.deinit(base.allocator);
switch (base.tag) { switch (base.tag) {
.coff => { .coff => {
if (build_options.only_c) unreachable; if (build_options.only_c) unreachable;

View File

@ -289,6 +289,7 @@ pub fn deinit(self: *Coff) void {
self.unresolved.deinit(gpa); self.unresolved.deinit(gpa);
self.locals_free_list.deinit(gpa); self.locals_free_list.deinit(gpa);
self.globals_free_list.deinit(gpa);
self.strtab.deinit(gpa); self.strtab.deinit(gpa);
self.got_entries.deinit(gpa); self.got_entries.deinit(gpa);
self.got_entries_free_list.deinit(gpa); self.got_entries_free_list.deinit(gpa);
@ -1150,8 +1151,10 @@ fn updateDeclCode(self: *Coff, decl_index: Module.Decl.Index, code: []const u8,
} }
fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void { fn freeRelocationsForAtom(self: *Coff, atom: *Atom) void {
_ = self.relocs.remove(atom); var removed_relocs = self.relocs.fetchRemove(atom);
_ = self.base_relocs.remove(atom); if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
var removed_base_relocs = self.base_relocs.fetchRemove(atom);
if (removed_base_relocs) |*base_relocs| base_relocs.value.deinit(self.base.allocator);
} }
fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void { fn freeUnnamedConsts(self: *Coff, decl_index: Module.Decl.Index) void {
@ -1489,9 +1492,8 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8) !u32 {
gop.value_ptr.* = sym_loc; gop.value_ptr.* = sym_loc;
const gpa = self.base.allocator; const gpa = self.base.allocator;
const sym_name = try gpa.dupe(u8, name);
const sym = self.getSymbolPtr(sym_loc); const sym = self.getSymbolPtr(sym_loc);
try self.setSymbolName(sym, sym_name); try self.setSymbolName(sym, name);
sym.storage_class = .EXTERNAL; sym.storage_class = .EXTERNAL;
try self.unresolved.putNoClobber(gpa, global_index, true); try self.unresolved.putNoClobber(gpa, global_index, true);

View File

@ -2576,10 +2576,14 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
} }
fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void { fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {
_ = self.relocs.remove(atom); var removed_relocs = self.relocs.fetchRemove(atom);
_ = self.rebases.remove(atom); if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
_ = self.bindings.remove(atom); var removed_rebases = self.rebases.fetchRemove(atom);
_ = self.lazy_bindings.remove(atom); if (removed_rebases) |*rebases| rebases.value.deinit(self.base.allocator);
var removed_bindings = self.bindings.fetchRemove(atom);
if (removed_bindings) |*bindings| bindings.value.deinit(self.base.allocator);
var removed_lazy_bindings = self.lazy_bindings.fetchRemove(atom);
if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(self.base.allocator);
} }
fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void { fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {

View File

@ -201,7 +201,10 @@ fn putFn(self: *Plan9, decl_index: Module.Decl.Index, out: FnDeclOutput) !void {
const decl = mod.declPtr(decl_index); const decl = mod.declPtr(decl_index);
const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope()); const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope());
if (fn_map_res.found_existing) { if (fn_map_res.found_existing) {
try fn_map_res.value_ptr.functions.put(gpa, decl_index, out); if (try fn_map_res.value_ptr.functions.fetchPut(gpa, decl_index, out)) |old_entry| {
gpa.free(old_entry.value.code);
gpa.free(old_entry.value.lineinfo);
}
} else { } else {
const file = decl.getFileScope(); const file = decl.getFileScope();
const arena = self.path_arena.allocator(); const arena = self.path_arena.allocator();
@ -408,9 +411,11 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
return; return;
}, },
}; };
var duped_code = try self.base.allocator.dupe(u8, code); try self.data_decl_table.ensureUnusedCapacity(self.base.allocator, 1);
errdefer self.base.allocator.free(duped_code); const duped_code = try self.base.allocator.dupe(u8, code);
try self.data_decl_table.put(self.base.allocator, decl_index, duped_code); if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
self.base.allocator.free(old_entry.value);
}
return self.updateFinish(decl); return self.updateFinish(decl);
} }
/// called at the end of update{Decl,Func} /// called at the end of update{Decl,Func}
@ -743,14 +748,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
if (is_fn) { if (is_fn) {
var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?; var symidx_and_submap = self.fn_decl_table.get(decl.getFileScope()).?;
var submap = symidx_and_submap.functions; var submap = symidx_and_submap.functions;
_ = submap.swapRemove(decl_index); if (submap.fetchSwapRemove(decl_index)) |removed_entry| {
self.base.allocator.free(removed_entry.value.code);
self.base.allocator.free(removed_entry.value.lineinfo);
}
if (submap.count() == 0) { if (submap.count() == 0) {
self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol; self.syms.items[symidx_and_submap.sym_index] = aout.Sym.undefined_symbol;
self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {}; self.syms_index_free_list.append(self.base.allocator, symidx_and_submap.sym_index) catch {};
submap.deinit(self.base.allocator); submap.deinit(self.base.allocator);
} }
} else { } else {
_ = self.data_decl_table.swapRemove(decl_index); if (self.data_decl_table.fetchSwapRemove(decl_index)) |removed_entry| {
self.base.allocator.free(removed_entry.value);
}
} }
if (decl.link.plan9.got_index) |i| { if (decl.link.plan9.got_index) |i| {
// TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length

View File

@ -5,6 +5,7 @@ pub fn main() void {
} }
// run // run
// target=x86_64-plan9
// //
// Hello World // Hello World
// //