authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-09 19:30:58+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
logf86a38564f5d8eb903b940ddf9b9f5685a3ca932
tree0681926bedfcbe95136ba485da7eab960943dbac
parent2e87883be85956b2a5be682423256e9ba700c13f

macho: migrate synthetic sections


2 files changed, 136 insertions(+), 67 deletions(-)

src/link/MachO.zig+3
......@@ -68,6 +68,7 @@ weak_bind: WeakBind = .{},
6868lazy_bind: LazyBind = .{},
6969export_trie: ExportTrie = .{},
7070unwind_info: UnwindInfo = .{},
71data_in_code: DataInCode = .{},
7172
7273/// Tracked loadable segments during incremental linking.
7374zig_text_seg_index: ?u8 = null,
......@@ -316,6 +317,7 @@ pub fn deinit(self: *MachO) void {
316317 self.lazy_bind.deinit(gpa);
317318 self.export_trie.deinit(gpa);
318319 self.unwind_info.deinit(gpa);
320 self.data_in_code.deinit(gpa);
319321
320322 self.thunks.deinit(gpa);
321323}
......@@ -4524,6 +4526,7 @@ const Bind = bind.Bind;
45244526const Cache = std.Build.Cache;
45254527const CodeSignature = @import("MachO/CodeSignature.zig");
45264528const Compilation = @import("../Compilation.zig");
4529const DataInCode = synthetic.DataInCode;
45274530pub const DebugSymbols = @import("MachO/DebugSymbols.zig");
45284531const Dylib = @import("MachO/Dylib.zig");
45294532const ExportTrie = @import("MachO/dyld_info/Trie.zig");
src/link/MachO/synthetic.zig+133-67
......@@ -18,15 +18,15 @@ pub const ZigGotSection = struct {
1818 }
1919
2020 pub fn addSymbol(zig_got: *ZigGotSection, sym_index: Symbol.Index, macho_file: *MachO) !Index {
21 const comp = macho_file.base.comp;
22 const gpa = comp.gpa;
21 const gpa = macho_file.base.comp.gpa;
22 const zo = macho_file.getZigObject().?;
2323 const index = try zig_got.allocateEntry(gpa);
2424 const entry = &zig_got.entries.items[index];
2525 entry.* = sym_index;
26 const symbol = macho_file.getSymbol(sym_index);
26 const symbol = zo.getSymbol(sym_index);
2727 assert(symbol.flags.needs_zig_got);
2828 symbol.flags.has_zig_got = true;
29 try symbol.addExtra(.{ .zig_got = index }, macho_file);
29 symbol.addExtra(.{ .zig_got = index }, macho_file);
3030 return index;
3131 }
3232
......@@ -53,9 +53,10 @@ pub const ZigGotSection = struct {
5353 try macho_file.growSection(macho_file.zig_got_sect_index.?, needed_size);
5454 zig_got.dirty = false;
5555 }
56 const zo = macho_file.getZigObject().?;
5657 const off = zig_got.entryOffset(index, macho_file);
5758 const entry = zig_got.entries.items[index];
58 const value = macho_file.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file);
59 const value = zo.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file);
5960
6061 var buf: [8]u8 = undefined;
6162 std.mem.writeInt(u64, &buf, value, .little);
......@@ -63,8 +64,9 @@ pub const ZigGotSection = struct {
6364 }
6465
6566 pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void {
67 const zo = macho_file.getZigObject().?;
6668 for (zig_got.entries.items) |entry| {
67 const symbol = macho_file.getSymbol(entry);
69 const symbol = zo.getSymbol(entry);
6870 const value = symbol.address(.{ .stubs = false }, macho_file);
6971 try writer.writeInt(u64, value, .little);
7072 }
......@@ -87,22 +89,25 @@ pub const ZigGotSection = struct {
8789 ) !void {
8890 _ = options;
8991 _ = unused_fmt_string;
92 const zig_got = ctx.zig_got;
93 const macho_file = ctx.macho_file;
94 const zo = macho_file.getZigObject().?;
9095 try writer.writeAll("__zig_got\n");
91 for (ctx.zig_got.entries.items, 0..) |entry, index| {
92 const symbol = ctx.macho_file.getSymbol(entry);
96 for (zig_got.entries.items, 0..) |entry, index| {
97 const symbol = zo.getSymbol(entry);
9398 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
9499 index,
95 ctx.zig_got.entryAddress(@intCast(index), ctx.macho_file),
100 zig_got.entryAddress(@intCast(index), macho_file),
96101 entry,
97 symbol.getAddress(.{}, ctx.macho_file),
98 symbol.getName(ctx.macho_file),
102 symbol.getAddress(.{}, macho_file),
103 symbol.getName(macho_file),
99104 });
100105 }
101106 }
102107};
103108
104109pub const GotSection = struct {
105 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
110 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
106111
107112 pub const Index = u32;
108113
......@@ -110,14 +115,14 @@ pub const GotSection = struct {
110115 got.symbols.deinit(allocator);
111116 }
112117
113 pub fn addSymbol(got: *GotSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
118 pub fn addSymbol(got: *GotSection, ref: MachO.Ref, macho_file: *MachO) !void {
114119 const gpa = macho_file.base.comp.gpa;
115120 const index = @as(Index, @intCast(got.symbols.items.len));
116121 const entry = try got.symbols.addOne(gpa);
117 entry.* = sym_index;
118 const symbol = macho_file.getSymbol(sym_index);
122 entry.* = ref;
123 const symbol = ref.getSymbol(macho_file).?;
119124 symbol.flags.has_got = true;
120 try symbol.addExtra(.{ .got = index }, macho_file);
125 symbol.addExtra(.{ .got = index }, macho_file);
121126 }
122127
123128 pub fn getAddress(got: GotSection, index: Index, macho_file: *MachO) u64 {
......@@ -133,8 +138,8 @@ pub const GotSection = struct {
133138 pub fn write(got: GotSection, macho_file: *MachO, writer: anytype) !void {
134139 const tracy = trace(@src());
135140 defer tracy.end();
136 for (got.symbols.items) |sym_index| {
137 const sym = macho_file.getSymbol(sym_index);
141 for (got.symbols.items) |ref| {
142 const sym = ref.getSymbol(macho_file).?;
138143 const value = if (sym.flags.import) @as(u64, 0) else sym.getAddress(.{}, macho_file);
139144 try writer.writeInt(u64, value, .little);
140145 }
......@@ -157,12 +162,12 @@ pub const GotSection = struct {
157162 ) !void {
158163 _ = options;
159164 _ = unused_fmt_string;
160 for (ctx.got.symbols.items, 0..) |entry, i| {
161 const symbol = ctx.macho_file.getSymbol(entry);
165 for (ctx.got.symbols.items, 0..) |ref, i| {
166 const symbol = ref.getSymbol(ctx.macho_file).?;
162167 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
163168 i,
164169 symbol.getGotAddress(ctx.macho_file),
165 entry,
170 ref,
166171 symbol.getAddress(.{}, ctx.macho_file),
167172 symbol.getName(ctx.macho_file),
168173 });
......@@ -171,7 +176,7 @@ pub const GotSection = struct {
171176};
172177
173178pub const StubsSection = struct {
174 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
179 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
175180
176181 pub const Index = u32;
177182
......@@ -179,13 +184,13 @@ pub const StubsSection = struct {
179184 stubs.symbols.deinit(allocator);
180185 }
181186
182 pub fn addSymbol(stubs: *StubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
187 pub fn addSymbol(stubs: *StubsSection, ref: MachO.Ref, macho_file: *MachO) !void {
183188 const gpa = macho_file.base.comp.gpa;
184189 const index = @as(Index, @intCast(stubs.symbols.items.len));
185190 const entry = try stubs.symbols.addOne(gpa);
186 entry.* = sym_index;
187 const symbol = macho_file.getSymbol(sym_index);
188 try symbol.addExtra(.{ .stubs = index }, macho_file);
191 entry.* = ref;
192 const symbol = ref.getSymbol(macho_file).?;
193 symbol.addExtra(.{ .stubs = index }, macho_file);
189194 }
190195
191196 pub fn getAddress(stubs: StubsSection, index: Index, macho_file: *MachO) u64 {
......@@ -205,8 +210,8 @@ pub const StubsSection = struct {
205210 const cpu_arch = macho_file.getTarget().cpu.arch;
206211 const laptr_sect = macho_file.sections.items(.header)[macho_file.la_symbol_ptr_sect_index.?];
207212
208 for (stubs.symbols.items, 0..) |sym_index, idx| {
209 const sym = macho_file.getSymbol(sym_index);
213 for (stubs.symbols.items, 0..) |ref, idx| {
214 const sym = ref.getSymbol(macho_file).?;
210215 const source = sym.getAddress(.{ .stubs = true }, macho_file);
211216 const target = laptr_sect.addr + idx * @sizeOf(u64);
212217 switch (cpu_arch) {
......@@ -248,12 +253,12 @@ pub const StubsSection = struct {
248253 ) !void {
249254 _ = options;
250255 _ = unused_fmt_string;
251 for (ctx.stubs.symbols.items, 0..) |entry, i| {
252 const symbol = ctx.macho_file.getSymbol(entry);
256 for (ctx.stubs.symbols.items, 0..) |ref, i| {
257 const symbol = ref.getSymbol(ctx.macho_file).?;
253258 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
254259 i,
255260 symbol.getStubsAddress(ctx.macho_file),
256 entry,
261 ref,
257262 symbol.getAddress(.{}, ctx.macho_file),
258263 symbol.getName(ctx.macho_file),
259264 });
......@@ -284,8 +289,8 @@ pub const StubsHelperSection = struct {
284289 _ = stubs_helper;
285290 const cpu_arch = macho_file.getTarget().cpu.arch;
286291 var s: usize = preambleSize(cpu_arch);
287 for (macho_file.stubs.symbols.items) |sym_index| {
288 const sym = macho_file.getSymbol(sym_index);
292 for (macho_file.stubs.symbols.items) |ref| {
293 const sym = ref.getSymbol(macho_file).?;
289294 if (sym.flags.weak) continue;
290295 s += entrySize(cpu_arch);
291296 }
......@@ -304,8 +309,8 @@ pub const StubsHelperSection = struct {
304309 const entry_size = entrySize(cpu_arch);
305310
306311 var idx: usize = 0;
307 for (macho_file.stubs.symbols.items) |sym_index| {
308 const sym = macho_file.getSymbol(sym_index);
312 for (macho_file.stubs.symbols.items) |ref| {
313 const sym = ref.getSymbol(macho_file).?;
309314 if (sym.flags.weak) continue;
310315 const offset = macho_file.lazy_bind.offsets.items[idx];
311316 const source: i64 = @intCast(sect.addr + preamble_size + entry_size * idx);
......@@ -339,14 +344,15 @@ pub const StubsHelperSection = struct {
339344
340345 fn writePreamble(stubs_helper: StubsHelperSection, macho_file: *MachO, writer: anytype) !void {
341346 _ = stubs_helper;
347 const obj = macho_file.getInternalObject().?;
342348 const cpu_arch = macho_file.getTarget().cpu.arch;
343349 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
344350 const dyld_private_addr = target: {
345 const sym = macho_file.getSymbol(macho_file.dyld_private_index.?);
351 const sym = obj.getDyldPrivateRef(macho_file).?.getSymbol(macho_file).?;
346352 break :target sym.getAddress(.{}, macho_file);
347353 };
348354 const dyld_stub_binder_addr = target: {
349 const sym = macho_file.getSymbol(macho_file.dyld_stub_binder_index.?);
355 const sym = obj.getDyldStubBinderRef(macho_file).?.getSymbol(macho_file).?;
350356 break :target sym.getGotAddress(macho_file);
351357 };
352358 switch (cpu_arch) {
......@@ -402,8 +408,8 @@ pub const LaSymbolPtrSection = struct {
402408 const cpu_arch = macho_file.getTarget().cpu.arch;
403409 const sect = macho_file.sections.items(.header)[macho_file.stubs_helper_sect_index.?];
404410 var stub_helper_idx: u32 = 0;
405 for (macho_file.stubs.symbols.items) |sym_index| {
406 const sym = macho_file.getSymbol(sym_index);
411 for (macho_file.stubs.symbols.items) |ref| {
412 const sym = ref.getSymbol(macho_file).?;
407413 if (sym.flags.weak) {
408414 const value = sym.getAddress(.{ .stubs = false }, macho_file);
409415 try writer.writeInt(u64, @intCast(value), .little);
......@@ -418,7 +424,7 @@ pub const LaSymbolPtrSection = struct {
418424};
419425
420426pub const TlvPtrSection = struct {
421 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
427 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
422428
423429 pub const Index = u32;
424430
......@@ -426,13 +432,13 @@ pub const TlvPtrSection = struct {
426432 tlv.symbols.deinit(allocator);
427433 }
428434
429 pub fn addSymbol(tlv: *TlvPtrSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
435 pub fn addSymbol(tlv: *TlvPtrSection, ref: MachO.Ref, macho_file: *MachO) !void {
430436 const gpa = macho_file.base.comp.gpa;
431437 const index = @as(Index, @intCast(tlv.symbols.items.len));
432438 const entry = try tlv.symbols.addOne(gpa);
433 entry.* = sym_index;
434 const symbol = macho_file.getSymbol(sym_index);
435 try symbol.addExtra(.{ .tlv_ptr = index }, macho_file);
439 entry.* = ref;
440 const symbol = ref.getSymbol(macho_file).?;
441 symbol.addExtra(.{ .tlv_ptr = index }, macho_file);
436442 }
437443
438444 pub fn getAddress(tlv: TlvPtrSection, index: Index, macho_file: *MachO) u64 {
......@@ -449,8 +455,8 @@ pub const TlvPtrSection = struct {
449455 const tracy = trace(@src());
450456 defer tracy.end();
451457
452 for (tlv.symbols.items) |sym_index| {
453 const sym = macho_file.getSymbol(sym_index);
458 for (tlv.symbols.items) |ref| {
459 const sym = ref.getSymbol(macho_file).?;
454460 if (sym.flags.import) {
455461 try writer.writeInt(u64, 0, .little);
456462 } else {
......@@ -476,12 +482,12 @@ pub const TlvPtrSection = struct {
476482 ) !void {
477483 _ = options;
478484 _ = unused_fmt_string;
479 for (ctx.tlv.symbols.items, 0..) |entry, i| {
480 const symbol = ctx.macho_file.getSymbol(entry);
485 for (ctx.tlv.symbols.items, 0..) |ref, i| {
486 const symbol = ref.getSymbol(ctx.macho_file).?;
481487 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
482488 i,
483489 symbol.getTlvPtrAddress(ctx.macho_file),
484 entry,
490 ref,
485491 symbol.getAddress(.{}, ctx.macho_file),
486492 symbol.getName(ctx.macho_file),
487493 });
......@@ -490,7 +496,7 @@ pub const TlvPtrSection = struct {
490496};
491497
492498pub const ObjcStubsSection = struct {
493 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
499 symbols: std.ArrayListUnmanaged(MachO.Ref) = .{},
494500
495501 pub fn deinit(objc: *ObjcStubsSection, allocator: Allocator) void {
496502 objc.symbols.deinit(allocator);
......@@ -504,13 +510,13 @@ pub const ObjcStubsSection = struct {
504510 };
505511 }
506512
507 pub fn addSymbol(objc: *ObjcStubsSection, sym_index: Symbol.Index, macho_file: *MachO) !void {
513 pub fn addSymbol(objc: *ObjcStubsSection, ref: MachO.Ref, macho_file: *MachO) !void {
508514 const gpa = macho_file.base.comp.gpa;
509515 const index = @as(Index, @intCast(objc.symbols.items.len));
510516 const entry = try objc.symbols.addOne(gpa);
511 entry.* = sym_index;
512 const symbol = macho_file.getSymbol(sym_index);
513 try symbol.addExtra(.{ .objc_stubs = index }, macho_file);
517 entry.* = ref;
518 const symbol = ref.getSymbol(macho_file).?;
519 symbol.addExtra(.{ .objc_stubs = index }, macho_file);
514520 }
515521
516522 pub fn getAddress(objc: ObjcStubsSection, index: Index, macho_file: *MachO) u64 {
......@@ -527,8 +533,10 @@ pub const ObjcStubsSection = struct {
527533 const tracy = trace(@src());
528534 defer tracy.end();
529535
530 for (objc.symbols.items, 0..) |sym_index, idx| {
531 const sym = macho_file.getSymbol(sym_index);
536 const obj = macho_file.getInternalObject().?;
537
538 for (objc.symbols.items, 0..) |ref, idx| {
539 const sym = ref.getSymbol(macho_file).?;
532540 const addr = objc.getAddress(@intCast(idx), macho_file);
533541 switch (macho_file.getTarget().cpu.arch) {
534542 .x86_64 => {
......@@ -540,7 +548,7 @@ pub const ObjcStubsSection = struct {
540548 }
541549 try writer.writeAll(&.{ 0xff, 0x25 });
542550 {
543 const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?);
551 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
544552 const target = target_sym.getGotAddress(macho_file);
545553 const source = addr + 7;
546554 try writer.writeInt(i32, @intCast(target - source - 2 - 4), .little);
......@@ -560,7 +568,7 @@ pub const ObjcStubsSection = struct {
560568 );
561569 }
562570 {
563 const target_sym = macho_file.getSymbol(macho_file.objc_msg_send_index.?);
571 const target_sym = obj.getObjcMsgSendRef(macho_file).?.getSymbol(macho_file).?;
564572 const target = target_sym.getGotAddress(macho_file);
565573 const source = addr + 2 * @sizeOf(u32);
566574 const pages = try aarch64.calcNumberOfPages(@intCast(source), @intCast(target));
......@@ -599,12 +607,12 @@ pub const ObjcStubsSection = struct {
599607 ) !void {
600608 _ = options;
601609 _ = unused_fmt_string;
602 for (ctx.objc.symbols.items, 0..) |entry, i| {
603 const symbol = ctx.macho_file.getSymbol(entry);
610 for (ctx.objc.symbols.items, 0..) |ref, i| {
611 const symbol = ref.getSymbol(ctx.macho_file).?;
604612 try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{
605613 i,
606614 symbol.getObjcStubsAddress(ctx.macho_file),
607 entry,
615 ref,
608616 symbol.getAddress(.{}, ctx.macho_file),
609617 symbol.getName(ctx.macho_file),
610618 });
......@@ -620,31 +628,89 @@ pub const Indsymtab = struct {
620628 return @intCast(macho_file.stubs.symbols.items.len * 2 + macho_file.got.symbols.items.len);
621629 }
622630
631 pub fn updateSize(ind: *Indsymtab, macho_file: *MachO) !void {
632 macho_file.dysymtab_cmd.nindirectsyms = ind.nsyms(macho_file);
633 }
634
623635 pub fn write(ind: Indsymtab, macho_file: *MachO, writer: anytype) !void {
624636 const tracy = trace(@src());
625637 defer tracy.end();
626638
627639 _ = ind;
628640
629 for (macho_file.stubs.symbols.items) |sym_index| {
630 const sym = macho_file.getSymbol(sym_index);
641 for (macho_file.stubs.symbols.items) |ref| {
642 const sym = ref.getSymbol(macho_file).?;
631643 try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
632644 }
633645
634 for (macho_file.got.symbols.items) |sym_index| {
635 const sym = macho_file.getSymbol(sym_index);
646 for (macho_file.got.symbols.items) |ref| {
647 const sym = ref.getSymbol(macho_file).?;
636648 try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
637649 }
638650
639 for (macho_file.stubs.symbols.items) |sym_index| {
640 const sym = macho_file.getSymbol(sym_index);
651 for (macho_file.stubs.symbols.items) |ref| {
652 const sym = ref.getSymbol(macho_file).?;
641653 try writer.writeInt(u32, sym.getOutputSymtabIndex(macho_file).?, .little);
642654 }
643655 }
644656};
645657
658pub const DataInCode = struct {
659 entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
660
661 pub fn deinit(dice: *DataInCode, allocator: Allocator) void {
662 dice.entries.deinit(allocator);
663 }
664
665 pub fn size(dice: DataInCode) usize {
666 return dice.entries.items.len * @sizeOf(macho.data_in_code_entry);
667 }
668
669 pub fn updateSize(dice: *DataInCode, macho_file: *MachO) !void {
670 const gpa = macho_file.base.comp.gpa;
671 const base_address = if (!macho_file.base.isRelocatable())
672 macho_file.getTextSegment().vmaddr
673 else
674 0;
675
676 for (macho_file.objects.items) |index| {
677 const object = macho_file.getFile(index).?.object;
678 const dices = object.getDataInCode();
679
680 try dice.entries.ensureUnusedCapacity(gpa, dices.len);
681
682 var next_dice: usize = 0;
683 for (object.getAtoms()) |atom_index| {
684 if (next_dice >= dices.len) break;
685 const atom = object.getAtom(atom_index) orelse continue;
686 if (!atom.flags.alive) continue;
687 const start_off = atom.getInputAddress(macho_file);
688 const end_off = start_off + atom.size;
689 const start_dice = next_dice;
690
691 if (end_off < dices[next_dice].offset) continue;
692
693 while (next_dice < dices.len and
694 dices[next_dice].offset < end_off) : (next_dice += 1)
695 {}
696
697 if (atom.alive.load(.seq_cst)) for (dices[start_dice..next_dice]) |d| {
698 dice.entries.appendAssumeCapacity(.{
699 .offset = @intCast(atom.getAddress(macho_file) + d.offset - start_off - base_address),
700 .length = d.length,
701 .kind = d.kind,
702 });
703 };
704 }
705 }
706
707 macho_file.data_in_code_cmd.datasize = math.cast(u32, dice.size()) orelse return error.Overflow;
708 }
709};
710
646711const aarch64 = @import("../aarch64.zig");
647712const assert = std.debug.assert;
713const macho = std.macho;
648714const math = std.math;
649715const std = @import("std");
650716const trace = @import("../../tracy.zig").trace;