authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-26 21:41:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:35+02:00
logef0d35e00cd1320b5f0ffde718422a69be54fe80
tree47d7324dd74d0f21881e7d7240e6e0418d10ec2e
parent664b983518f29eed3c60b503cf12bddbb19f3afc

macho: unify allocating special symbols


2 files changed, 111 insertions(+), 81 deletions(-)

src/link/MachO.zig+6-10
...@@ -1389,7 +1389,7 @@ fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {...@@ -1389,7 +1389,7 @@ fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {
1389 }1389 }
1390}1390}
13911391
1392pub fn allocateSpecialSymbols(self: *MachO) !void {1392pub fn allocateSpecialSymbols(self: anytype) !void {
1393 for (&[_][]const u8{1393 for (&[_][]const u8{
1394 "___dso_handle",1394 "___dso_handle",
1395 "__mh_execute_header",1395 "__mh_execute_header",
...@@ -1398,11 +1398,13 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {...@@ -1398,11 +1398,13 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {
1398 if (global.getFile() != null) continue;1398 if (global.getFile() != null) continue;
1399 const sym = self.getSymbolPtr(global);1399 const sym = self.getSymbolPtr(global);
1400 const seg = self.getSegment(self.text_section_index.?);1400 const seg = self.getSegment(self.text_section_index.?);
1401 sym.n_sect = 1;1401 sym.n_sect = self.text_section_index.? + 1;
1402 sym.n_value = seg.vmaddr;1402 sym.n_value = seg.vmaddr;
14031403
1404 log.debug("allocating {s} at the start of {s}", .{1404 log.debug("allocating {s}(@0x{x},sect({d})) at the start of {s}", .{
1405 name,1405 name,
1406 sym.n_value,
1407 sym.n_sect,
1406 seg.segName(),1408 seg.segName(),
1407 });1409 });
1408 }1410 }
...@@ -1479,10 +1481,6 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S...@@ -1479,10 +1481,6 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S
14791481
1480fn createMhExecuteHeaderSymbol(self: *MachO) !void {1482fn createMhExecuteHeaderSymbol(self: *MachO) !void {
1481 if (self.base.options.output_mode != .Exe) return;1483 if (self.base.options.output_mode != .Exe) return;
1482 if (self.getGlobal("__mh_execute_header")) |global| {
1483 const sym = self.getSymbol(global);
1484 if (!sym.undf() and !(sym.pext() or sym.weakDef())) return;
1485 }
14861484
1487 const gpa = self.base.allocator;1485 const gpa = self.base.allocator;
1488 const sym_index = try self.allocateSymbol();1486 const sym_index = try self.allocateSymbol();
...@@ -3748,9 +3746,7 @@ fn addUndefined(self: *MachO, name: []const u8, action: ResolveAction.Kind) !u32...@@ -3748,9 +3746,7 @@ fn addUndefined(self: *MachO, name: []const u8, action: ResolveAction.Kind) !u32
3748 const gop = try self.getOrPutGlobalPtr(name);3746 const gop = try self.getOrPutGlobalPtr(name);
3749 const global_index = self.getGlobalIndex(name).?;3747 const global_index = self.getGlobalIndex(name).?;
37503748
3751 if (gop.found_existing) {3749 if (gop.found_existing) return global_index;
3752 return global_index;
3753 }
37543750
3755 const sym_index = try self.allocateSymbol();3751 const sym_index = try self.allocateSymbol();
3756 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };3752 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
src/link/MachO/zld.zig+105-71
...@@ -78,9 +78,10 @@ pub const Zld = struct {...@@ -78,9 +78,10 @@ pub const Zld = struct {
78 resolver: std.StringHashMapUnmanaged(u32) = .{},78 resolver: std.StringHashMapUnmanaged(u32) = .{},
79 unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},79 unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{},
8080
81 locals_free_list: std.ArrayListUnmanaged(u32) = .{},
82 globals_free_list: std.ArrayListUnmanaged(u32) = .{},
83
81 entry_index: ?u32 = null,84 entry_index: ?u32 = null,
82 mh_execute_header_index: ?u32 = null,
83 dso_handle_index: ?u32 = null,
84 dyld_stub_binder_index: ?u32 = null,85 dyld_stub_binder_index: ?u32 = null,
85 dyld_private_atom_index: ?Atom.Index = null,86 dyld_private_atom_index: ?Atom.Index = null,
8687
...@@ -188,15 +189,23 @@ pub const Zld = struct {...@@ -188,15 +189,23 @@ pub const Zld = struct {
188 }189 }
189 }190 }
190191
191 fn addUndefined(self: *Zld, name: []const u8) !void {192 fn addUndefined(self: *Zld, name: []const u8) !u32 {
193 const gop = try self.getOrPutGlobalPtr(name);
194 const global_index = self.getGlobalIndex(name).?;
195
196 if (gop.found_existing) return global_index;
197
192 const sym_index = try self.allocateSymbol();198 const sym_index = try self.allocateSymbol();
193 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };199 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
200 gop.value_ptr.* = sym_loc;
201
194 const sym = self.getSymbolPtr(sym_loc);202 const sym = self.getSymbolPtr(sym_loc);
195 sym.n_strx = try self.strtab.insert(self.gpa, name);203 sym.n_strx = try self.strtab.insert(self.gpa, name);
196 sym.n_type = macho.N_UNDF;204 sym.n_type = macho.N_UNDF;
197 const global_index = try self.addGlobal(sym_loc);205
198 try self.resolver.putNoClobber(self.gpa, name, global_index);
199 try self.unresolved.putNoClobber(self.gpa, global_index, {});206 try self.unresolved.putNoClobber(self.gpa, global_index, {});
207
208 return global_index;
200 }209 }
201210
202 fn resolveSymbols(self: *Zld) !void {211 fn resolveSymbols(self: *Zld) !void {
...@@ -205,12 +214,12 @@ pub const Zld = struct {...@@ -205,12 +214,12 @@ pub const Zld = struct {
205 // on the linker line.214 // on the linker line.
206 if (self.options.output_mode == .Exe) {215 if (self.options.output_mode == .Exe) {
207 const entry_name = self.options.entry orelse load_commands.default_entry_point;216 const entry_name = self.options.entry orelse load_commands.default_entry_point;
208 try self.addUndefined(entry_name);217 _ = try self.addUndefined(entry_name);
209 }218 }
210219
211 // Force resolution of any symbols requested by the user.220 // Force resolution of any symbols requested by the user.
212 for (self.options.force_undefined_symbols.keys()) |sym_name| {221 for (self.options.force_undefined_symbols.keys()) |sym_name| {
213 try self.addUndefined(sym_name);222 _ = try self.addUndefined(sym_name);
214 }223 }
215224
216 for (self.objects.items, 0..) |_, object_id| {225 for (self.objects.items, 0..) |_, object_id| {
...@@ -222,13 +231,11 @@ pub const Zld = struct {...@@ -222,13 +231,11 @@ pub const Zld = struct {
222 // Finally, force resolution of dyld_stub_binder if there are imports231 // Finally, force resolution of dyld_stub_binder if there are imports
223 // requested.232 // requested.
224 if (self.unresolved.count() > 0) {233 if (self.unresolved.count() > 0) {
225 try self.addUndefined("dyld_stub_binder");234 self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder");
226 }235 }
227236
228 try self.resolveSymbolsInDylibs();237 try self.resolveSymbolsInDylibs();
229238
230 self.dyld_stub_binder_index = self.resolver.get("dyld_stub_binder");
231
232 try self.createMhExecuteHeaderSymbol();239 try self.createMhExecuteHeaderSymbol();
233 try self.createDsoHandleSymbol();240 try self.createDsoHandleSymbol();
234 try self.resolveSymbolsAtLoading();241 try self.resolveSymbolsAtLoading();
...@@ -276,15 +283,16 @@ pub const Zld = struct {...@@ -276,15 +283,16 @@ pub const Zld = struct {
276283
277 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };284 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = object_id + 1 };
278285
279 const global_index = self.resolver.get(sym_name) orelse {286 const gop = try self.getOrPutGlobalPtr(sym_name);
280 const global_index = try self.addGlobal(sym_loc);287 if (!gop.found_existing) {
281 try self.resolver.putNoClobber(self.gpa, sym_name, global_index);288 gop.value_ptr.* = sym_loc;
282 if (sym.undf() and !sym.tentative()) {289 if (sym.undf() and !sym.tentative()) {
283 try self.unresolved.putNoClobber(self.gpa, global_index, {});290 try self.unresolved.putNoClobber(self.gpa, self.getGlobalIndex(sym_name).?, {});
284 }291 }
285 continue;292 continue;
286 };293 }
287 const global = &self.globals.items[global_index];294 const global_index = self.getGlobalIndex(sym_name).?;
295 const global = gop.value_ptr;
288 const global_sym = self.getSymbol(global.*);296 const global_sym = self.getSymbol(global.*);
289297
290 // Cases to consider: sym vs global_sym298 // Cases to consider: sym vs global_sym
...@@ -338,7 +346,7 @@ pub const Zld = struct {...@@ -338,7 +346,7 @@ pub const Zld = struct {
338 const global_object = &self.objects.items[file];346 const global_object = &self.objects.items[file];
339 global_object.globals_lookup[global.sym_index] = global_index;347 global_object.globals_lookup[global.sym_index] = global_index;
340 }348 }
341 _ = self.unresolved.swapRemove(self.resolver.get(sym_name).?);349 _ = self.unresolved.swapRemove(global_index);
342 global.* = sym_loc;350 global.* = sym_loc;
343 } else {351 } else {
344 object.globals_lookup[sym_index] = global_index;352 object.globals_lookup[sym_index] = global_index;
...@@ -448,50 +456,51 @@ pub const Zld = struct {...@@ -448,50 +456,51 @@ pub const Zld = struct {
448456
449 fn createMhExecuteHeaderSymbol(self: *Zld) !void {457 fn createMhExecuteHeaderSymbol(self: *Zld) !void {
450 if (self.options.output_mode != .Exe) return;458 if (self.options.output_mode != .Exe) return;
451 if (self.resolver.get("__mh_execute_header")) |global_index| {
452 const global = self.globals.items[global_index];
453 const sym = self.getSymbol(global);
454 self.mh_execute_header_index = global_index;
455 if (!sym.undf() and !(sym.pext() or sym.weakDef())) return;
456 }
457459
458 const gpa = self.gpa;460 const gpa = self.gpa;
459 const sym_index = try self.allocateSymbol();461 const sym_index = try self.allocateSymbol();
460 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };462 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
461 const sym = self.getSymbolPtr(sym_loc);463 const sym = self.getSymbolPtr(sym_loc);
462 sym.n_strx = try self.strtab.insert(gpa, "__mh_execute_header");464 sym.* = .{
463 sym.n_type = macho.N_SECT | macho.N_EXT;465 .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"),
464 sym.n_desc = macho.REFERENCED_DYNAMICALLY;466 .n_type = macho.N_SECT | macho.N_EXT,
467 .n_sect = 0,
468 .n_desc = macho.REFERENCED_DYNAMICALLY,
469 .n_value = 0,
470 };
465471
466 if (self.resolver.get("__mh_execute_header")) |global_index| {472 const gop = try self.getOrPutGlobalPtr("__mh_execute_header");
467 const global = &self.globals.items[global_index];473 if (gop.found_existing) {
468 const global_object = &self.objects.items[global.getFile().?];474 const global = gop.value_ptr.*;
469 global_object.globals_lookup[global.sym_index] = global_index;475 if (global.getFile()) |file| {
470 global.* = sym_loc;476 const global_object = &self.objects.items[file];
471 self.mh_execute_header_index = global_index;477 global_object.globals_lookup[global.sym_index] = self.getGlobalIndex("__mh_execute_header").?;
472 } else {478 }
473 self.mh_execute_header_index = try self.addGlobal(sym_loc);
474 }479 }
480 gop.value_ptr.* = sym_loc;
475 }481 }
476482
477 fn createDsoHandleSymbol(self: *Zld) !void {483 fn createDsoHandleSymbol(self: *Zld) !void {
478 const global_index = self.resolver.get("___dso_handle") orelse return;484 const global = self.getGlobalPtr("___dso_handle") orelse return;
479 const global = &self.globals.items[global_index];
480 self.dso_handle_index = global_index;
481 if (!self.getSymbol(global.*).undf()) return;485 if (!self.getSymbol(global.*).undf()) return;
482486
483 const gpa = self.gpa;
484 const sym_index = try self.allocateSymbol();487 const sym_index = try self.allocateSymbol();
485 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };488 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
486 const sym = self.getSymbolPtr(sym_loc);489 const sym = self.getSymbolPtr(sym_loc);
487 sym.n_strx = try self.strtab.insert(gpa, "___dso_handle");490 sym.* = .{
488 sym.n_type = macho.N_SECT | macho.N_EXT;491 .n_strx = try self.strtab.insert(self.gpa, "___dso_handle"),
489 sym.n_desc = macho.N_WEAK_DEF;492 .n_type = macho.N_SECT | macho.N_EXT,
490493 .n_sect = 0,
491 const global_object = &self.objects.items[global.getFile().?];494 .n_desc = macho.N_WEAK_DEF,
492 global_object.globals_lookup[global.sym_index] = global_index;495 .n_value = 0,
493 _ = self.unresolved.swapRemove(self.resolver.get("___dso_handle").?);496 };
497 const global_index = self.getGlobalIndex("___dso_handle").?;
498 if (global.getFile()) |file| {
499 const global_object = &self.objects.items[file];
500 global_object.globals_lookup[global.sym_index] = global_index;
501 }
494 global.* = sym_loc;502 global.* = sym_loc;
503 _ = self.unresolved.swapRemove(global_index);
495 }504 }
496505
497 pub fn deinit(self: *Zld) void {506 pub fn deinit(self: *Zld) void {
...@@ -512,6 +521,8 @@ pub const Zld = struct {...@@ -512,6 +521,8 @@ pub const Zld = struct {
512 self.globals.deinit(gpa);521 self.globals.deinit(gpa);
513 self.resolver.deinit(gpa);522 self.resolver.deinit(gpa);
514 self.unresolved.deinit(gpa);523 self.unresolved.deinit(gpa);
524 self.locals_free_list.deinit(gpa);
525 self.globals_free_list.deinit(gpa);
515526
516 for (self.objects.items) |*object| {527 for (self.objects.items) |*object| {
517 object.deinit(gpa);528 object.deinit(gpa);
...@@ -609,10 +620,24 @@ pub const Zld = struct {...@@ -609,10 +620,24 @@ pub const Zld = struct {
609 return index;620 return index;
610 }621 }
611622
612 fn addGlobal(self: *Zld, sym_loc: SymbolWithLoc) !u32 {623 fn allocateGlobal(self: *Zld) !u32 {
613 const global_index = @as(u32, @intCast(self.globals.items.len));624 try self.globals.ensureUnusedCapacity(self.gpa, 1);
614 try self.globals.append(self.gpa, sym_loc);625
615 return global_index;626 const index = blk: {
627 if (self.globals_free_list.popOrNull()) |index| {
628 log.debug(" (reusing global index {d})", .{index});
629 break :blk index;
630 } else {
631 log.debug(" (allocating symbol index {d})", .{self.globals.items.len});
632 const index = @as(u32, @intCast(self.globals.items.len));
633 _ = self.globals.addOneAssumeCapacity();
634 break :blk index;
635 }
636 };
637
638 self.globals.items[index] = .{ .sym_index = 0 };
639
640 return index;
616 }641 }
617642
618 pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void {643 pub fn addGotEntry(self: *Zld, target: SymbolWithLoc) !void {
...@@ -656,27 +681,6 @@ pub const Zld = struct {...@@ -656,27 +681,6 @@ pub const Zld = struct {
656 }681 }
657 }682 }
658683
659 fn allocateSpecialSymbols(self: *Zld) !void {
660 for (&[_]?u32{
661 self.dso_handle_index,
662 self.mh_execute_header_index,
663 }) |maybe_index| {
664 const global_index = maybe_index orelse continue;
665 const global = self.globals.items[global_index];
666 if (global.getFile() != null) continue;
667 const name = self.getSymbolName(global);
668 const sym = self.getSymbolPtr(global);
669 const segment_index = self.getSegmentByName("__TEXT").?;
670 const seg = self.segments.items[segment_index];
671 sym.n_sect = 1;
672 sym.n_value = seg.vmaddr;
673 log.debug("allocating {s} at the start of {s}", .{
674 name,
675 seg.segName(),
676 });
677 }
678 }
679
680 fn writeAtoms(self: *Zld) !void {684 fn writeAtoms(self: *Zld) !void {
681 const gpa = self.gpa;685 const gpa = self.gpa;
682 const slice = self.sections.slice();686 const slice = self.sections.slice();
...@@ -2037,6 +2041,36 @@ pub const Zld = struct {...@@ -2037,6 +2041,36 @@ pub const Zld = struct {
2037 }2041 }
2038 }2042 }
20392043
2044 pub fn getGlobalIndex(self: *const Zld, name: []const u8) ?u32 {
2045 return self.resolver.get(name);
2046 }
2047
2048 pub fn getGlobalPtr(self: *Zld, name: []const u8) ?*SymbolWithLoc {
2049 const global_index = self.resolver.get(name) orelse return null;
2050 return &self.globals.items[global_index];
2051 }
2052
2053 pub fn getGlobal(self: *const Zld, name: []const u8) ?SymbolWithLoc {
2054 const global_index = self.resolver.get(name) orelse return null;
2055 return self.globals.items[global_index];
2056 }
2057
2058 const GetOrPutGlobalPtrResult = struct {
2059 found_existing: bool,
2060 value_ptr: *SymbolWithLoc,
2061 };
2062
2063 pub fn getOrPutGlobalPtr(self: *Zld, name: []const u8) !GetOrPutGlobalPtrResult {
2064 if (self.getGlobalPtr(name)) |ptr| {
2065 return GetOrPutGlobalPtrResult{ .found_existing = true, .value_ptr = ptr };
2066 }
2067 const global_index = try self.allocateGlobal();
2068 const global_name = try self.gpa.dupe(u8, name);
2069 _ = try self.resolver.put(self.gpa, global_name, global_index);
2070 const ptr = &self.globals.items[global_index];
2071 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };
2072 }
2073
2040 pub fn getGotEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 {2074 pub fn getGotEntryAddress(self: *Zld, sym_with_loc: SymbolWithLoc) ?u64 {
2041 const index = self.got_table.lookup.get(sym_with_loc) orelse return null;2075 const index = self.got_table.lookup.get(sym_with_loc) orelse return null;
2042 const header = self.sections.items(.header)[self.got_section_index.?];2076 const header = self.sections.items(.header)[self.got_section_index.?];
...@@ -2934,7 +2968,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -2934,7 +2968,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
2934 try zld.createSegments();2968 try zld.createSegments();
2935 try zld.allocateSegments();2969 try zld.allocateSegments();
29362970
2937 try zld.allocateSpecialSymbols();2971 try MachO.allocateSpecialSymbols(&zld);
29382972
2939 if (build_options.enable_logging) {2973 if (build_options.enable_logging) {
2940 zld.logSymtab();2974 zld.logSymtab();