authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-01 17:25:51+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:46+02:00
log2b3bda43e352152f0150bf2e795419cf1bcfcd90
treef6c550980ea30b8e3ded451b6145ebb203101b22
parent3622fe08dbdcaccb04204b48257e1d5fcbe0d164

zld: abstract Symbol creation logic


6 files changed, 231 insertions(+), 184 deletions(-)

src/link/MachO.zig+1-1
......@@ -724,7 +724,7 @@ fn linkWithZld(self: *MachO, comp: *Compilation) !void {
724724 try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
725725 }
726726 } else {
727 var zld = Zld.init(self.base.allocator);
727 var zld = try Zld.init(self.base.allocator);
728728 defer {
729729 zld.closeFiles();
730730 zld.deinit();
src/link/MachO/Dylib.zig+8-14
......@@ -146,7 +146,12 @@ pub const CreateOpts = struct {
146146 id: ?Id = null,
147147};
148148
149pub fn createAndParseFromPath(allocator: *Allocator, arch: Arch, path: []const u8, opts: CreateOpts) Error!?[]*Dylib {
149pub fn createAndParseFromPath(
150 allocator: *Allocator,
151 arch: Arch,
152 path: []const u8,
153 opts: CreateOpts,
154) Error!?[]*Dylib {
150155 const file = fs.cwd().openFile(path, .{}) catch |err| switch (err) {
151156 error.FileNotFound => return null,
152157 else => |e| return e,
......@@ -505,18 +510,7 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
505510
506511pub fn createProxy(self: *Dylib, sym_name: []const u8) !?*Symbol {
507512 if (!self.symbols.contains(sym_name)) return null;
508
509 const name = try self.allocator.dupe(u8, sym_name);
510 const proxy = try self.allocator.create(Symbol.Proxy);
511 errdefer self.allocator.destroy(proxy);
512
513 proxy.* = .{
514 .base = .{
515 .@"type" = .proxy,
516 .name = name,
517 },
513 return Symbol.Proxy.new(self.allocator, sym_name, .{
518514 .file = self,
519 };
520
521 return &proxy.base;
515 });
522516}
src/link/MachO/Object.zig+7-28
......@@ -9,12 +9,12 @@ const log = std.log.scoped(.object);
99const macho = std.macho;
1010const mem = std.mem;
1111const reloc = @import("reloc.zig");
12const parseName = @import("Zld.zig").parseName;
1213
1314const Allocator = mem.Allocator;
1415const Arch = std.Target.Cpu.Arch;
1516const Relocation = reloc.Relocation;
1617const Symbol = @import("Symbol.zig");
17const parseName = @import("Zld.zig").parseName;
1818
1919usingnamespace @import("commands.zig");
2020
......@@ -437,47 +437,26 @@ pub fn parseSymbols(self: *Object) !void {
437437 if (Symbol.isWeakDef(sym) or Symbol.isPext(sym)) break :linkage .linkage_unit;
438438 break :linkage .global;
439439 };
440 const regular = try self.allocator.create(Symbol.Regular);
441 errdefer self.allocator.destroy(regular);
442 regular.* = .{
443 .base = .{
444 .@"type" = .regular,
445 .name = name,
446 },
440 break :symbol try Symbol.Regular.new(self.allocator, name, .{
447441 .linkage = linkage,
448442 .address = sym.n_value,
449443 .section = sym.n_sect - 1,
450444 .weak_ref = Symbol.isWeakRef(sym),
451445 .file = self,
452 };
453 break :symbol &regular.base;
446 });
454447 }
455448
456449 if (sym.n_value != 0) {
457 const tentative = try self.allocator.create(Symbol.Tentative);
458 errdefer self.allocator.destroy(tentative);
459 tentative.* = .{
460 .base = .{
461 .@"type" = .tentative,
462 .name = name,
463 },
450 break :symbol try Symbol.Tentative.new(self.allocator, name, .{
464451 .size = sym.n_value,
465452 .alignment = (sym.n_desc >> 8) & 0x0f,
466453 .file = self,
467 };
468 break :symbol &tentative.base;
454 });
469455 }
470456
471 const undef = try self.allocator.create(Symbol.Unresolved);
472 errdefer self.allocator.destroy(undef);
473 undef.* = .{
474 .base = .{
475 .@"type" = .unresolved,
476 .name = name,
477 },
457 break :symbol try Symbol.Unresolved.new(self.allocator, name, .{
478458 .file = self,
479 };
480 break :symbol &undef.base;
459 });
481460 };
482461
483462 try self.symbols.append(self.allocator, symbol);
src/link/MachO/StringTable.zig+7-27
......@@ -8,7 +8,6 @@ const Allocator = mem.Allocator;
88
99allocator: *Allocator,
1010buffer: std.ArrayListUnmanaged(u8) = .{},
11used_offsets: std.ArrayListUnmanaged(u32) = .{},
1211cache: std.StringHashMapUnmanaged(u32) = .{},
1312
1413pub const Error = error{OutOfMemory};
......@@ -22,8 +21,13 @@ pub fn init(allocator: *Allocator) Error!StringTable {
2221}
2322
2423pub fn deinit(self: *StringTable) void {
24 {
25 var it = self.cache.keyIterator();
26 while (it.next()) |key| {
27 self.allocator.free(key.*);
28 }
29 }
2530 self.cache.deinit(self.allocator);
26 self.used_offsets.deinit(self.allocator);
2731 self.buffer.deinit(self.allocator);
2832}
2933
......@@ -33,8 +37,6 @@ pub fn getOrPut(self: *StringTable, string: []const u8) Error!u32 {
3337 return off;
3438 }
3539
36 const invalidate_cache = self.needsToGrow(string.len + 1);
37
3840 try self.buffer.ensureUnusedCapacity(self.allocator, string.len + 1);
3941 const new_off = @intCast(u32, self.buffer.items.len);
4042
......@@ -43,25 +45,7 @@ pub fn getOrPut(self: *StringTable, string: []const u8) Error!u32 {
4345 self.buffer.appendSliceAssumeCapacity(string);
4446 self.buffer.appendAssumeCapacity(0);
4547
46 if (invalidate_cache) {
47 log.debug("invalidating cache", .{});
48 // Re-create the cache.
49 self.cache.clearRetainingCapacity();
50 for (self.used_offsets.items) |off| {
51 try self.cache.putNoClobber(self.allocator, self.get(off).?, off);
52 }
53 }
54
55 {
56 log.debug("cache:", .{});
57 var it = self.cache.iterator();
58 while (it.next()) |entry| {
59 log.debug(" | {s} => {}", .{ entry.key_ptr.*, entry.value_ptr.* });
60 }
61 }
62
63 try self.cache.putNoClobber(self.allocator, self.get(new_off).?, new_off);
64 try self.used_offsets.append(self.allocator, new_off);
48 try self.cache.putNoClobber(self.allocator, try self.allocator.dupe(u8, string), new_off);
6549
6650 return new_off;
6751}
......@@ -78,7 +62,3 @@ pub fn asSlice(self: StringTable) []const u8 {
7862pub fn size(self: StringTable) u64 {
7963 return self.buffer.items.len;
8064}
81
82fn needsToGrow(self: StringTable, needed_space: u64) bool {
83 return self.buffer.capacity < needed_space + self.size();
84}
src/link/MachO/Symbol.zig+174-15
......@@ -7,6 +7,7 @@ const mem = std.mem;
77const Allocator = mem.Allocator;
88const Dylib = @import("Dylib.zig");
99const Object = @import("Object.zig");
10const StringTable = @import("StringTable.zig");
1011
1112pub const Type = enum {
1213 regular,
......@@ -19,7 +20,7 @@ pub const Type = enum {
1920@"type": Type,
2021
2122/// Symbol name. Owned slice.
22name: []u8,
23name: []const u8,
2324
2425/// Alias of.
2526alias: ?*Symbol = null,
......@@ -43,23 +44,14 @@ pub const Regular = struct {
4344 section: u8,
4445
4546 /// Whether the symbol is a weak ref.
46 weak_ref: bool,
47 weak_ref: bool = false,
4748
4849 /// Object file where to locate this symbol.
49 file: *Object,
50 /// null means self-reference.
51 file: ?*Object = null,
5052
5153 /// Debug stab if defined.
52 stab: ?struct {
53 /// Stab kind
54 kind: enum {
55 function,
56 global,
57 static,
58 },
59
60 /// Size of the stab.
61 size: u64,
62 } = null,
54 stab: ?Stab = null,
6355
6456 /// True if symbol was already committed into the final
6557 /// symbol table.
......@@ -73,6 +65,68 @@ pub const Regular = struct {
7365 global,
7466 };
7567
68 pub const Stab = struct {
69 /// Stab kind
70 kind: enum {
71 function,
72 global,
73 static,
74 },
75
76 /// Size of the stab.
77 size: u64,
78 };
79
80 const Opts = struct {
81 linkage: Linkage = .translation_unit,
82 address: u64 = 0,
83 section: u8 = 0,
84 weak_ref: bool = false,
85 file: ?*Object = null,
86 stab: ?Stab = null,
87 };
88
89 pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol {
90 const reg = try allocator.create(Regular);
91 errdefer allocator.destroy(reg);
92
93 reg.* = .{
94 .base = .{
95 .@"type" = .regular,
96 .name = try allocator.dupe(u8, name),
97 },
98 .linkage = opts.linkage,
99 .address = opts.address,
100 .section = opts.section,
101 .weak_ref = opts.weak_ref,
102 .file = opts.file,
103 .stab = opts.stab,
104 };
105
106 return &reg.base;
107 }
108
109 pub fn asNlist(regular: *Regular, strtab: *StringTable) !macho.nlist_64 {
110 const n_strx = try strtab.getOrPut(regular.base.name);
111 var nlist = macho.nlist_64{
112 .n_strx = n_strx,
113 .n_type = macho.N_SECT,
114 .n_sect = regular.section,
115 .n_desc = 0,
116 .n_value = regular.address,
117 };
118
119 if (regular.linkage != .translation_unit) {
120 nlist.n_type |= macho.N_EXT;
121 }
122 if (regular.linkage == .linkage_unit) {
123 nlist.n_type |= macho.N_PEXT;
124 nlist.n_desc |= macho.N_WEAK_DEF;
125 }
126
127 return nlist;
128 }
129
76130 pub fn isTemp(regular: *Regular) bool {
77131 if (regular.linkage == .translation_unit) {
78132 return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
......@@ -97,6 +151,36 @@ pub const Proxy = struct {
97151
98152 pub const base_type: Symbol.Type = .proxy;
99153
154 const Opts = struct {
155 file: ?*Dylib = null,
156 };
157
158 pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol {
159 const proxy = try allocator.create(Proxy);
160 errdefer allocator.destroy(proxy);
161
162 proxy.* = .{
163 .base = .{
164 .@"type" = .proxy,
165 .name = try allocator.dupe(u8, name),
166 },
167 .file = opts.file,
168 };
169
170 return &proxy.base;
171 }
172
173 pub fn asNlist(proxy: *Proxy, strtab: *StringTable) !macho.nlist_64 {
174 const n_strx = try strtab.getOrPut(proxy.base.name);
175 return macho.nlist_64{
176 .n_strx = n_strx,
177 .n_type = macho.N_UNDF | macho.N_EXT,
178 .n_sect = 0,
179 .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
180 .n_value = 0,
181 };
182 }
183
100184 pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {
101185 proxy.bind_info.deinit(allocator);
102186 }
......@@ -115,6 +199,36 @@ pub const Unresolved = struct {
115199 file: ?*Object = null,
116200
117201 pub const base_type: Symbol.Type = .unresolved;
202
203 const Opts = struct {
204 file: ?*Object = null,
205 };
206
207 pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol {
208 const undef = try allocator.create(Unresolved);
209 errdefer allocator.destroy(undef);
210
211 undef.* = .{
212 .base = .{
213 .@"type" = .unresolved,
214 .name = try allocator.dupe(u8, name),
215 },
216 .file = opts.file,
217 };
218
219 return &undef.base;
220 }
221
222 pub fn asNlist(undef: *Unresolved, strtab: *StringTable) !macho.nlist_64 {
223 const n_strx = try strtab.getOrPut(undef.base.name);
224 return macho.nlist_64{
225 .n_strx = n_strx,
226 .n_type = macho.N_UNDF,
227 .n_sect = 0,
228 .n_desc = 0,
229 .n_value = 0,
230 };
231 }
118232};
119233
120234pub const Tentative = struct {
......@@ -127,13 +241,49 @@ pub const Tentative = struct {
127241 alignment: u16,
128242
129243 /// File where this symbol was referenced.
130 file: *Object,
244 file: ?*Object = null,
131245
132246 pub const base_type: Symbol.Type = .tentative;
247
248 const Opts = struct {
249 size: u64 = 0,
250 alignment: u16 = 0,
251 file: ?*Object = null,
252 };
253
254 pub fn new(allocator: *Allocator, name: []const u8, opts: Opts) !*Symbol {
255 const tent = try allocator.create(Tentative);
256 errdefer allocator.destroy(tent);
257
258 tent.* = .{
259 .base = .{
260 .@"type" = .tentative,
261 .name = try allocator.dupe(u8, name),
262 },
263 .size = opts.size,
264 .alignment = opts.alignment,
265 .file = opts.file,
266 };
267
268 return &tent.base;
269 }
270
271 pub fn asNlist(tent: *Tentative, strtab: *StringTable) !macho.nlist_64 {
272 // TODO
273 const n_strx = try strtab.getOrPut(tent.base.name);
274 return macho.nlist_64{
275 .n_strx = n_strx,
276 .n_type = macho.N_UNDF,
277 .n_sect = 0,
278 .n_desc = 0,
279 .n_value = 0,
280 };
281 }
133282};
134283
135284pub fn deinit(base: *Symbol, allocator: *Allocator) void {
136285 allocator.free(base.name);
286
137287 switch (base.@"type") {
138288 .proxy => @fieldParentPtr(Proxy, "base", base).deinit(allocator),
139289 else => {},
......@@ -154,6 +304,15 @@ pub fn getTopmostAlias(base: *Symbol) *Symbol {
154304 return base;
155305}
156306
307pub fn asNlist(base: *Symbol, strtab: *StringTable) !macho.nlist_64 {
308 return switch (base.tag) {
309 .regular => @fieldParentPtr(Regular, "base", base).asNlist(strtab),
310 .proxy => @fieldParentPtr(Proxy, "base", base).asNlist(strtab),
311 .unresolved => @fieldParentPtr(Unresolved, "base", base).asNlist(strtab),
312 .tentative => @fieldParentPtr(Tentative, "base", base).asNlist(strtab),
313 };
314}
315
157316pub fn isStab(sym: macho.nlist_64) bool {
158317 return (macho.N_STAB & sym.n_type) != 0;
159318}
src/link/MachO/Zld.zig+34-99
......@@ -17,6 +17,7 @@ const Archive = @import("Archive.zig");
1717const CodeSignature = @import("CodeSignature.zig");
1818const Dylib = @import("Dylib.zig");
1919const Object = @import("Object.zig");
20const StringTable = @import("StringTable.zig");
2021const Symbol = @import("Symbol.zig");
2122const Trie = @import("Trie.zig");
2223
......@@ -24,6 +25,7 @@ usingnamespace @import("commands.zig");
2425usingnamespace @import("bind.zig");
2526
2627allocator: *Allocator,
28strtab: StringTable,
2729
2830target: ?std.Target = null,
2931page_size: ?u16 = null,
......@@ -109,9 +111,6 @@ tentatives: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
109111/// Set if the linker found tentative definitions in any of the objects.
110112tentative_defs_offset: u64 = 0,
111113
112strtab: std.ArrayListUnmanaged(u8) = .{},
113strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
114
115114threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
116115local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
117116stubs: std.ArrayListUnmanaged(*Symbol) = .{},
......@@ -138,8 +137,11 @@ const TlvOffset = struct {
138137/// Default path to dyld
139138const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld";
140139
141pub fn init(allocator: *Allocator) Zld {
142 return .{ .allocator = allocator };
140pub fn init(allocator: *Allocator) !Zld {
141 return Zld{
142 .allocator = allocator,
143 .strtab = try StringTable.init(allocator),
144 };
143145}
144146
145147pub fn deinit(self: *Zld) void {
......@@ -180,15 +182,7 @@ pub fn deinit(self: *Zld) void {
180182 self.tentatives.deinit(self.allocator);
181183 self.globals.deinit(self.allocator);
182184 self.unresolved.deinit(self.allocator);
183 self.strtab.deinit(self.allocator);
184
185 {
186 var it = self.strtab_dir.keyIterator();
187 while (it.next()) |key| {
188 self.allocator.free(key.*);
189 }
190 }
191 self.strtab_dir.deinit(self.allocator);
185 self.strtab.deinit();
192186}
193187
194188pub fn closeFiles(self: Zld) void {
......@@ -1137,16 +1131,7 @@ fn allocateTentativeSymbols(self: *Zld) !void {
11371131 // Convert tentative definitions into regular symbols.
11381132 for (self.tentatives.values()) |sym| {
11391133 const tent = sym.cast(Symbol.Tentative) orelse unreachable;
1140 const reg = try self.allocator.create(Symbol.Regular);
1141 errdefer self.allocator.destroy(reg);
1142
1143 reg.* = .{
1144 .base = .{
1145 .@"type" = .regular,
1146 .name = try self.allocator.dupe(u8, tent.base.name),
1147 .got_index = tent.base.got_index,
1148 .stubs_index = tent.base.stubs_index,
1149 },
1134 const reg = try Symbol.Regular.new(self.allocator, tent.base.name, .{
11501135 .linkage = .global,
11511136 .address = base_address,
11521137 .section = section,
......@@ -1156,16 +1141,18 @@ fn allocateTentativeSymbols(self: *Zld) !void {
11561141 .kind = .global,
11571142 .size = 0,
11581143 },
1159 };
1144 });
1145 reg.got_index = tent.base.got_index;
1146 reg.stubs_index = tent.base.stubs_index;
11601147
1161 try self.globals.putNoClobber(self.allocator, reg.base.name, &reg.base);
1162 tent.base.alias = &reg.base;
1148 try self.globals.putNoClobber(self.allocator, reg.name, reg);
1149 tent.base.alias = reg;
11631150
11641151 if (tent.base.got_index) |idx| {
1165 self.got_entries.items[idx] = &reg.base;
1152 self.got_entries.items[idx] = reg;
11661153 }
11671154 if (tent.base.stubs_index) |idx| {
1168 self.stubs.items[idx] = &reg.base;
1155 self.stubs.items[idx] = reg;
11691156 }
11701157
11711158 const address = mem.alignForwardGeneric(u64, base_address + tent.size, alignment);
......@@ -1615,15 +1602,8 @@ fn resolveSymbols(self: *Zld) !void {
16151602 {
16161603 const name = try self.allocator.dupe(u8, "dyld_stub_binder");
16171604 errdefer self.allocator.free(name);
1618 const undef = try self.allocator.create(Symbol.Unresolved);
1619 errdefer self.allocator.destroy(undef);
1620 undef.* = .{
1621 .base = .{
1622 .@"type" = .unresolved,
1623 .name = name,
1624 },
1625 };
1626 try unresolved.append(&undef.base);
1605 const undef = try Symbol.Unresolved.new(self.allocator, name, .{});
1606 try unresolved.append(undef);
16271607 }
16281608
16291609 var referenced = std.AutoHashMap(*Dylib, void).init(self.allocator);
......@@ -1641,16 +1621,7 @@ fn resolveSymbols(self: *Zld) !void {
16411621 // TODO this is just a temp patch until I work out what to actually
16421622 // do with ___dso_handle and __mh_execute_header symbols which are
16431623 // synthetically created by the linker on macOS.
1644 const name = try self.allocator.dupe(u8, undef.name);
1645 const proxy = try self.allocator.create(Symbol.Proxy);
1646 errdefer self.allocator.destroy(proxy);
1647 proxy.* = .{
1648 .base = .{
1649 .@"type" = .proxy,
1650 .name = name,
1651 },
1652 };
1653 break :inner &proxy.base;
1624 break :inner try Symbol.Proxy.new(self.allocator, undef.name, .{});
16541625 }
16551626
16561627 self.unresolved.putAssumeCapacityNoClobber(undef.name, undef);
......@@ -2126,7 +2097,6 @@ fn populateMetadata(self: *Zld) !void {
21262097 .strsize = 0,
21272098 },
21282099 });
2129 try self.strtab.append(self.allocator, 0);
21302100 }
21312101
21322102 if (self.dysymtab_cmd_index == null) {
......@@ -2752,7 +2722,7 @@ fn writeDebugInfo(self: *Zld) !void {
27522722 const dirname = std.fs.path.dirname(tu_path) orelse "./";
27532723 // Current dir
27542724 try stabs.append(.{
2755 .n_strx = try self.makeString(tu_path[0 .. dirname.len + 1]),
2725 .n_strx = try self.strtab.getOrPut(tu_path[0 .. dirname.len + 1]),
27562726 .n_type = macho.N_SO,
27572727 .n_sect = 0,
27582728 .n_desc = 0,
......@@ -2760,7 +2730,7 @@ fn writeDebugInfo(self: *Zld) !void {
27602730 });
27612731 // Artifact name
27622732 try stabs.append(.{
2763 .n_strx = try self.makeString(tu_path[dirname.len + 1 ..]),
2733 .n_strx = try self.strtab.getOrPut(tu_path[dirname.len + 1 ..]),
27642734 .n_type = macho.N_SO,
27652735 .n_sect = 0,
27662736 .n_desc = 0,
......@@ -2768,7 +2738,7 @@ fn writeDebugInfo(self: *Zld) !void {
27682738 });
27692739 // Path to object file with debug info
27702740 try stabs.append(.{
2771 .n_strx = try self.makeString(object.name.?),
2741 .n_strx = try self.strtab.getOrPut(object.name.?),
27722742 .n_type = macho.N_OSO,
27732743 .n_sect = 0,
27742744 .n_desc = 1,
......@@ -2801,7 +2771,7 @@ fn writeDebugInfo(self: *Zld) !void {
28012771 .n_value = reg.address,
28022772 });
28032773 try stabs.append(.{
2804 .n_strx = try self.makeString(sym.name),
2774 .n_strx = try self.strtab.getOrPut(sym.name),
28052775 .n_type = macho.N_FUN,
28062776 .n_sect = reg.section,
28072777 .n_desc = 0,
......@@ -2824,7 +2794,7 @@ fn writeDebugInfo(self: *Zld) !void {
28242794 },
28252795 .global => {
28262796 try stabs.append(.{
2827 .n_strx = try self.makeString(sym.name),
2797 .n_strx = try self.strtab.getOrPut(sym.name),
28282798 .n_type = macho.N_GSYM,
28292799 .n_sect = 0,
28302800 .n_desc = 0,
......@@ -2833,7 +2803,7 @@ fn writeDebugInfo(self: *Zld) !void {
28332803 },
28342804 .static => {
28352805 try stabs.append(.{
2836 .n_strx = try self.makeString(sym.name),
2806 .n_strx = try self.strtab.getOrPut(sym.name),
28372807 .n_type = macho.N_STSYM,
28382808 .n_sect = reg.section,
28392809 .n_desc = 0,
......@@ -2892,24 +2862,14 @@ fn writeSymbolTable(self: *Zld) !void {
28922862 if (reg.isTemp()) continue;
28932863 if (reg.visited) continue;
28942864
2865 const nlist = try reg.asNlist(&self.strtab);
2866
28952867 switch (reg.linkage) {
28962868 .translation_unit => {
2897 try locals.append(.{
2898 .n_strx = try self.makeString(sym.name),
2899 .n_type = macho.N_SECT,
2900 .n_sect = reg.section,
2901 .n_desc = 0,
2902 .n_value = reg.address,
2903 });
2869 try locals.append(nlist);
29042870 },
29052871 else => {
2906 try exports.append(.{
2907 .n_strx = try self.makeString(sym.name),
2908 .n_type = macho.N_SECT | macho.N_EXT,
2909 .n_sect = reg.section,
2910 .n_desc = 0,
2911 .n_value = reg.address,
2912 });
2872 try exports.append(nlist);
29132873 },
29142874 }
29152875
......@@ -2922,13 +2882,8 @@ fn writeSymbolTable(self: *Zld) !void {
29222882
29232883 for (self.imports.values()) |sym| {
29242884 const proxy = sym.cast(Symbol.Proxy) orelse unreachable;
2925 try undefs.append(.{
2926 .n_strx = try self.makeString(sym.name),
2927 .n_type = macho.N_UNDF | macho.N_EXT,
2928 .n_sect = 0,
2929 .n_desc = (proxy.dylibOrdinal() * macho.N_SYMBOL_RESOLVER) | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY,
2930 .n_value = 0,
2931 });
2885 const nlist = try proxy.asNlist(&self.strtab);
2886 try undefs.append(nlist);
29322887 }
29332888
29342889 const nlocals = locals.items.len;
......@@ -3017,14 +2972,14 @@ fn writeStringTable(self: *Zld) !void {
30172972 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
30182973 const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab;
30192974 symtab.stroff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize);
3020 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.items.len, @alignOf(u64)));
2975 symtab.strsize = @intCast(u32, mem.alignForwardGeneric(u64, self.strtab.size(), @alignOf(u64)));
30212976 seg.inner.filesize += symtab.strsize;
30222977
30232978 log.debug("writing string table from 0x{x} to 0x{x}", .{ symtab.stroff, symtab.stroff + symtab.strsize });
30242979
3025 try self.file.?.pwriteAll(self.strtab.items, symtab.stroff);
2980 try self.file.?.pwriteAll(self.strtab.asSlice(), symtab.stroff);
30262981
3027 if (symtab.strsize > self.strtab.items.len and self.target.?.cpu.arch == .x86_64) {
2982 if (symtab.strsize > self.strtab.size() and self.target.?.cpu.arch == .x86_64) {
30282983 // This is the last section, so we need to pad it out.
30292984 try self.file.?.pwriteAll(&[_]u8{0}, seg.inner.fileoff + seg.inner.filesize - 1);
30302985 }
......@@ -3173,26 +3128,6 @@ fn writeHeader(self: *Zld) !void {
31733128 try self.file.?.pwriteAll(mem.asBytes(&header), 0);
31743129}
31753130
3176fn makeString(self: *Zld, bytes: []const u8) !u32 {
3177 if (self.strtab_dir.get(bytes)) |offset| {
3178 log.debug("reusing '{s}' from string table at offset 0x{x}", .{ bytes, offset });
3179 return offset;
3180 }
3181
3182 try self.strtab.ensureCapacity(self.allocator, self.strtab.items.len + bytes.len + 1);
3183 const offset = @intCast(u32, self.strtab.items.len);
3184 log.debug("writing new string '{s}' into string table at offset 0x{x}", .{ bytes, offset });
3185 self.strtab.appendSliceAssumeCapacity(bytes);
3186 self.strtab.appendAssumeCapacity(0);
3187 try self.strtab_dir.putNoClobber(self.allocator, try self.allocator.dupe(u8, bytes), offset);
3188 return offset;
3189}
3190
3191fn getString(self: *const Zld, str_off: u32) []const u8 {
3192 assert(str_off < self.strtab.items.len);
3193 return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + str_off));
3194}
3195
31963131pub fn parseName(name: *const [16]u8) []const u8 {
31973132 const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
31983133 return name[0..len];