Commit 52a9d3f037

Jakub Konka <kubkon@jakubkonka.com>
2021-06-22 13:58:25
zld: clean up memory management and refactor
1 parent 1ff3ebf
Changed files (3)
src/link/MachO/Stub.zig
@@ -41,6 +41,9 @@ pub fn init(allocator: *Allocator) Stub {
 }
 
 pub fn deinit(self: *Stub) void {
+    for (self.symbols.keys()) |key| {
+        self.allocator.free(key);
+    }
     self.symbols.deinit(self.allocator);
 
     if (self.lib_stub) |*lib_stub| {
@@ -56,6 +59,18 @@ pub fn deinit(self: *Stub) void {
     }
 }
 
+fn addObjCClassSymbols(self: *Stub, sym_name: []const u8) !void {
+    const expanded = &[_][]const u8{
+        try std.fmt.allocPrint(self.allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
+        try std.fmt.allocPrint(self.allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
+    };
+
+    for (expanded) |sym| {
+        if (self.symbols.contains(sym)) continue;
+        try self.symbols.putNoClobber(self.allocator, sym, .{});
+    }
+}
+
 pub fn parse(self: *Stub) !void {
     const lib_stub = self.lib_stub orelse return error.EmptyStubFile;
     if (lib_stub.inner.len == 0) return error.EmptyStubFile;
@@ -87,32 +102,13 @@ pub fn parse(self: *Stub) !void {
                 if (exp.symbols) |symbols| {
                     for (symbols) |sym_name| {
                         if (self.symbols.contains(sym_name)) continue;
-                        try self.symbols.putNoClobber(self.allocator, sym_name, {});
+                        try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
                     }
                 }
 
                 if (exp.objc_classes) |classes| {
                     for (classes) |sym_name| {
-                        log.debug("    | {s}", .{sym_name});
-                        {
-                            const actual_sym_name = try std.fmt.allocPrint(
-                                self.allocator,
-                                "_OBJC_CLASS_$_{s}",
-                                .{sym_name},
-                            );
-                            if (self.symbols.contains(actual_sym_name)) continue;
-                            try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
-                        }
-
-                        {
-                            const actual_sym_name = try std.fmt.allocPrint(
-                                self.allocator,
-                                "_OBJC_METACLASS_$_{s}",
-                                .{sym_name},
-                            );
-                            if (self.symbols.contains(actual_sym_name)) continue;
-                            try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
-                        }
+                        try self.addObjCClassSymbols(sym_name);
                     }
                 }
             }
@@ -124,34 +120,14 @@ pub fn parse(self: *Stub) !void {
 
                 for (reexp.symbols) |sym_name| {
                     if (self.symbols.contains(sym_name)) continue;
-                    try self.symbols.putNoClobber(self.allocator, sym_name, {});
+                    try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
                 }
             }
         }
 
         if (stub.objc_classes) |classes| {
-            log.debug("  | objc_classes", .{});
             for (classes) |sym_name| {
-                log.debug("    | {s}", .{sym_name});
-                {
-                    const actual_sym_name = try std.fmt.allocPrint(
-                        self.allocator,
-                        "_OBJC_CLASS_$_{s}",
-                        .{sym_name},
-                    );
-                    if (self.symbols.contains(actual_sym_name)) continue;
-                    try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
-                }
-
-                {
-                    const actual_sym_name = try std.fmt.allocPrint(
-                        self.allocator,
-                        "_OBJC_METACLASS_$_{s}",
-                        .{sym_name},
-                    );
-                    if (self.symbols.contains(actual_sym_name)) continue;
-                    try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
-                }
+                try self.addObjCClassSymbols(sym_name);
             }
         }
     }
src/link/MachO/Symbol.zig
@@ -74,6 +74,8 @@ pub const Regular = struct {
         global,
     };
 
+    pub fn deinit(regular: *Regular, allocator: *Allocator) void {}
+
     pub fn isTemp(regular: *Regular) bool {
         if (regular.linkage == .translation_unit) {
             return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
@@ -85,6 +87,8 @@ pub const Regular = struct {
 pub const Proxy = struct {
     base: Symbol,
 
+    /// Dynamic binding info - spots within the final
+    /// executable where this proxy is referenced from.
     bind_info: std.ArrayListUnmanaged(struct {
         segment_id: u16,
         address: u64,
@@ -99,6 +103,10 @@ pub const Proxy = struct {
 
     pub const base_type: Symbol.Type = .proxy;
 
+    pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {
+        proxy.bind_info.deinit(allocator);
+    }
+
     pub fn dylibOrdinal(proxy: *Proxy) u16 {
         const file = proxy.file orelse return 0;
         return switch (file) {
@@ -115,6 +123,8 @@ pub const Unresolved = struct {
     file: *Object,
 
     pub const base_type: Symbol.Type = .unresolved;
+
+    pub fn deinit(unresolved: *Unresolved, allocator: *Allocator) void {}
 };
 
 pub const Tentative = struct {
@@ -130,10 +140,18 @@ pub const Tentative = struct {
     file: *Object,
 
     pub const base_type: Symbol.Type = .tentative;
+
+    pub fn deinit(tentative: *Tentative, allocator: *Allocator) void {}
 };
 
 pub fn deinit(base: *Symbol, allocator: *Allocator) void {
     allocator.free(base.name);
+    switch (base.@"type") {
+        .regular => @fieldParentPtr(Regular, "base", base).deinit(allocator),
+        .proxy => @fieldParentPtr(Proxy, "base", base).deinit(allocator),
+        .unresolved => @fieldParentPtr(Unresolved, "base", base).deinit(allocator),
+        .tentative => @fieldParentPtr(Tentative, "base", base).deinit(allocator),
+    }
 }
 
 pub fn cast(base: *Symbol, comptime T: type) ?*T {
src/link/MachO/Zld.zig
@@ -263,7 +263,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L
     self.allocateLinkeditSegment();
     try self.allocateSymbols();
     try self.allocateTentativeSymbols();
-    try self.allocateProxiesBindAddresses();
+    try self.allocateProxyBindAddresses();
     try self.flush();
 }
 
@@ -1347,7 +1347,7 @@ fn allocateTentativeSymbols(self: *Zld) !void {
     }
 }
 
-fn allocateProxiesBindAddresses(self: *Zld) !void {
+fn allocateProxyBindAddresses(self: *Zld) !void {
     for (self.objects.items) |object| {
         for (object.sections.items) |sect| {
             const relocs = sect.relocs orelse continue;
@@ -1361,6 +1361,7 @@ fn allocateProxiesBindAddresses(self: *Zld) !void {
                     const target_map = sect.target_map orelse continue;
                     const target_seg = self.load_commands.items[target_map.segment_id].Segment;
                     const target_sect = target_seg.sections.items[target_map.section_id];
+
                     try proxy.bind_info.append(self.allocator, .{
                         .segment_id = target_map.segment_id,
                         .address = target_sect.addr + target_map.offset + rel.offset,
@@ -2119,7 +2120,10 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
                         if (proxy.bind_info.items.len > 0) {
                             break :blk 0; // Dynamically bound by dyld.
                         }
-                        log.err("expected stubs index or dynamic bind address when relocating symbol '{s}'", .{final.name});
+                        log.err(
+                            "expected stubs index or dynamic bind address when relocating symbol '{s}'",
+                            .{final.name},
+                        );
                         log.err("this is an internal linker error", .{});
                         return error.FailedToResolveRelocationTarget;
                     };