authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-22 13:58:25+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-24 18:56:48+02:00
log52a9d3f03797f1cd387ec5f2c2a1714e1121cdab
tree1115454e62a9c6afb6d7c6473b0100f05f5cb3a8
parent1ff3ebffa36a6d8f0b2489b7cbb0aceaf9189064

zld: clean up memory management and refactor


3 files changed, 44 insertions(+), 46 deletions(-)

src/link/MachO/Stub.zig+19-43
......@@ -41,6 +41,9 @@ pub fn init(allocator: *Allocator) Stub {
4141}
4242
4343pub fn deinit(self: *Stub) void {
44 for (self.symbols.keys()) |key| {
45 self.allocator.free(key);
46 }
4447 self.symbols.deinit(self.allocator);
4548
4649 if (self.lib_stub) |*lib_stub| {
......@@ -56,6 +59,18 @@ pub fn deinit(self: *Stub) void {
5659 }
5760}
5861
62fn addObjCClassSymbols(self: *Stub, sym_name: []const u8) !void {
63 const expanded = &[_][]const u8{
64 try std.fmt.allocPrint(self.allocator, "_OBJC_CLASS_$_{s}", .{sym_name}),
65 try std.fmt.allocPrint(self.allocator, "_OBJC_METACLASS_$_{s}", .{sym_name}),
66 };
67
68 for (expanded) |sym| {
69 if (self.symbols.contains(sym)) continue;
70 try self.symbols.putNoClobber(self.allocator, sym, .{});
71 }
72}
73
5974pub fn parse(self: *Stub) !void {
6075 const lib_stub = self.lib_stub orelse return error.EmptyStubFile;
6176 if (lib_stub.inner.len == 0) return error.EmptyStubFile;
......@@ -87,32 +102,13 @@ pub fn parse(self: *Stub) !void {
87102 if (exp.symbols) |symbols| {
88103 for (symbols) |sym_name| {
89104 if (self.symbols.contains(sym_name)) continue;
90 try self.symbols.putNoClobber(self.allocator, sym_name, {});
105 try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
91106 }
92107 }
93108
94109 if (exp.objc_classes) |classes| {
95110 for (classes) |sym_name| {
96 log.debug(" | {s}", .{sym_name});
97 {
98 const actual_sym_name = try std.fmt.allocPrint(
99 self.allocator,
100 "_OBJC_CLASS_$_{s}",
101 .{sym_name},
102 );
103 if (self.symbols.contains(actual_sym_name)) continue;
104 try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
105 }
106
107 {
108 const actual_sym_name = try std.fmt.allocPrint(
109 self.allocator,
110 "_OBJC_METACLASS_$_{s}",
111 .{sym_name},
112 );
113 if (self.symbols.contains(actual_sym_name)) continue;
114 try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
115 }
111 try self.addObjCClassSymbols(sym_name);
116112 }
117113 }
118114 }
......@@ -124,34 +120,14 @@ pub fn parse(self: *Stub) !void {
124120
125121 for (reexp.symbols) |sym_name| {
126122 if (self.symbols.contains(sym_name)) continue;
127 try self.symbols.putNoClobber(self.allocator, sym_name, {});
123 try self.symbols.putNoClobber(self.allocator, try self.allocator.dupe(u8, sym_name), {});
128124 }
129125 }
130126 }
131127
132128 if (stub.objc_classes) |classes| {
133 log.debug(" | objc_classes", .{});
134129 for (classes) |sym_name| {
135 log.debug(" | {s}", .{sym_name});
136 {
137 const actual_sym_name = try std.fmt.allocPrint(
138 self.allocator,
139 "_OBJC_CLASS_$_{s}",
140 .{sym_name},
141 );
142 if (self.symbols.contains(actual_sym_name)) continue;
143 try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
144 }
145
146 {
147 const actual_sym_name = try std.fmt.allocPrint(
148 self.allocator,
149 "_OBJC_METACLASS_$_{s}",
150 .{sym_name},
151 );
152 if (self.symbols.contains(actual_sym_name)) continue;
153 try self.symbols.putNoClobber(self.allocator, actual_sym_name, {});
154 }
130 try self.addObjCClassSymbols(sym_name);
155131 }
156132 }
157133 }
src/link/MachO/Symbol.zig+18
......@@ -74,6 +74,8 @@ pub const Regular = struct {
7474 global,
7575 };
7676
77 pub fn deinit(regular: *Regular, allocator: *Allocator) void {}
78
7779 pub fn isTemp(regular: *Regular) bool {
7880 if (regular.linkage == .translation_unit) {
7981 return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
......@@ -85,6 +87,8 @@ pub const Regular = struct {
8587pub const Proxy = struct {
8688 base: Symbol,
8789
90 /// Dynamic binding info - spots within the final
91 /// executable where this proxy is referenced from.
8892 bind_info: std.ArrayListUnmanaged(struct {
8993 segment_id: u16,
9094 address: u64,
......@@ -99,6 +103,10 @@ pub const Proxy = struct {
99103
100104 pub const base_type: Symbol.Type = .proxy;
101105
106 pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {
107 proxy.bind_info.deinit(allocator);
108 }
109
102110 pub fn dylibOrdinal(proxy: *Proxy) u16 {
103111 const file = proxy.file orelse return 0;
104112 return switch (file) {
......@@ -115,6 +123,8 @@ pub const Unresolved = struct {
115123 file: *Object,
116124
117125 pub const base_type: Symbol.Type = .unresolved;
126
127 pub fn deinit(unresolved: *Unresolved, allocator: *Allocator) void {}
118128};
119129
120130pub const Tentative = struct {
......@@ -130,10 +140,18 @@ pub const Tentative = struct {
130140 file: *Object,
131141
132142 pub const base_type: Symbol.Type = .tentative;
143
144 pub fn deinit(tentative: *Tentative, allocator: *Allocator) void {}
133145};
134146
135147pub fn deinit(base: *Symbol, allocator: *Allocator) void {
136148 allocator.free(base.name);
149 switch (base.@"type") {
150 .regular => @fieldParentPtr(Regular, "base", base).deinit(allocator),
151 .proxy => @fieldParentPtr(Proxy, "base", base).deinit(allocator),
152 .unresolved => @fieldParentPtr(Unresolved, "base", base).deinit(allocator),
153 .tentative => @fieldParentPtr(Tentative, "base", base).deinit(allocator),
154 }
137155}
138156
139157pub fn cast(base: *Symbol, comptime T: type) ?*T {
src/link/MachO/Zld.zig+7-3
......@@ -263,7 +263,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8, args: L
263263 self.allocateLinkeditSegment();
264264 try self.allocateSymbols();
265265 try self.allocateTentativeSymbols();
266 try self.allocateProxiesBindAddresses();
266 try self.allocateProxyBindAddresses();
267267 try self.flush();
268268}
269269
......@@ -1347,7 +1347,7 @@ fn allocateTentativeSymbols(self: *Zld) !void {
13471347 }
13481348}
13491349
1350fn allocateProxiesBindAddresses(self: *Zld) !void {
1350fn allocateProxyBindAddresses(self: *Zld) !void {
13511351 for (self.objects.items) |object| {
13521352 for (object.sections.items) |sect| {
13531353 const relocs = sect.relocs orelse continue;
......@@ -1361,6 +1361,7 @@ fn allocateProxiesBindAddresses(self: *Zld) !void {
13611361 const target_map = sect.target_map orelse continue;
13621362 const target_seg = self.load_commands.items[target_map.segment_id].Segment;
13631363 const target_sect = target_seg.sections.items[target_map.section_id];
1364
13641365 try proxy.bind_info.append(self.allocator, .{
13651366 .segment_id = target_map.segment_id,
13661367 .address = target_sect.addr + target_map.offset + rel.offset,
......@@ -2119,7 +2120,10 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
21192120 if (proxy.bind_info.items.len > 0) {
21202121 break :blk 0; // Dynamically bound by dyld.
21212122 }
2122 log.err("expected stubs index or dynamic bind address when relocating symbol '{s}'", .{final.name});
2123 log.err(
2124 "expected stubs index or dynamic bind address when relocating symbol '{s}'",
2125 .{final.name},
2126 );
21232127 log.err("this is an internal linker error", .{});
21242128 return error.FailedToResolveRelocationTarget;
21252129 };