aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2021-07-21 23:38:20 +0200
committerJakub Konka <kubkon@jakubkonka.com>2021-07-21 23:38:20 +0200
commitd0edd37f690c3e6cf3f8a7fc7a27016ba9b010ce (patch)
tree5345caa7297fd77d9c3d1f36fd205d4c0970cfbb
parente05b1e0e07708ca16c1a90e51a668faf51d883f4 (diff)
downloadzig-d0edd37f690c3e6cf3f8a7fc7a27016ba9b010ce.tar.gz
zig-d0edd37f690c3e6cf3f8a7fc7a27016ba9b010ce.zip
macho: fix bug when freeing Decl
Take into account that an already freed Decl will no longer be available as `decl.link.macho` causing a potential "inactive union field" panic.
-rw-r--r--src/link/MachO.zig13
1 files changed, 8 insertions, 5 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 52329e47d1..9bf8ec4a75 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -197,11 +197,11 @@ managed_blocks: std.ArrayListUnmanaged(*TextBlock) = .{},
blocks: std.AutoHashMapUnmanaged(MatchingSection, *TextBlock) = .{},
-/// List of Decls that are currently alive.
+/// Table 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) = .{},
+decls: std.AutoArrayHashMapUnmanaged(*Module.Decl, void) = .{},
/// Currently active Module.Decl.
/// TODO this might not be necessary if we figure out how to pass Module.Decl instance
@@ -3323,7 +3323,7 @@ pub fn deinit(self: *MachO) void {
self.blocks.deinit(self.base.allocator);
self.text_block_free_list.deinit(self.base.allocator);
- for (self.decls.items) |decl| {
+ for (self.decls.keys()) |decl| {
decl.link.macho.deinit(self.base.allocator);
}
self.decls.deinit(self.base.allocator);
@@ -3427,9 +3427,8 @@ 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);
+ try self.decls.putNoClobber(self.base.allocator, decl, {});
if (self.locals_free_list.popOrNull()) |i| {
log.debug("reusing symbol index {d} for {s}", .{ i, decl.name });
@@ -3598,6 +3597,9 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
// Resolve relocations
try decl.link.macho.resolveRelocs(self);
+ // TODO this requires further investigation: should we dispose of resolved relocs, or keep them
+ // so that we can reapply them when moving/growing sections?
+ decl.link.macho.relocs.clearRetainingCapacity();
// Apply pending updates
while (self.pending_updates.popOrNull()) |update| {
@@ -3746,6 +3748,7 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
pub fn freeDecl(self: *MachO, decl: *Module.Decl) void {
log.debug("freeDecl {*}", .{decl});
+ _ = self.decls.swapRemove(decl);
// Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
self.freeTextBlock(&decl.link.macho);
if (decl.link.macho.local_sym_index != 0) {