authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-18 21:55:31+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:41+01:00
loga8629fb8501275d826912085ccd120eb48a53199
treeab66d59c57765b63804c62dd6e14ed5e817cbd78
parent30b7d3e45f25195791f8eba74a2f89d41b325049

macho: fix symbol index dereference in codegen wrt ZigObject

This is incredibly confusing and I really need to simplify it. Elf also possesses this shortcoming so once I get Coff up to speed it should hopefully become clear on how to refactor this.

6 files changed, 76 insertions(+), 26 deletions(-)

src/arch/x86_64/Emit.zig+3-2
...@@ -156,9 +156,10 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -156,9 +156,10 @@ pub fn emitMir(emit: *Emit) Error!void {
156 .Lib => emit.lower.link_mode == .Static,156 .Lib => emit.lower.link_mode == .Static,
157 };157 };
158 const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;158 const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;
159 const sym = macho_file.getSymbol(data.sym_index);159 const sym_index = macho_file.getZigObject().?.symbols.items[data.sym_index];
160 const sym = macho_file.getSymbol(sym_index);
160 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {161 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
161 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);162 _ = try sym.getOrCreateZigGotEntry(sym_index, macho_file);
162 }163 }
163 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)164 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
164 .zig_got_load165 .zig_got_load
src/codegen.zig+1-1
...@@ -993,7 +993,7 @@ fn genDeclRef(...@@ -993,7 +993,7 @@ fn genDeclRef(
993 else993 else
994 null;994 null;
995 const sym_index = try macho_file.getGlobalSymbol(sym_name, lib_name);995 const sym_index = try macho_file.getGlobalSymbol(sym_name, lib_name);
996 macho_file.getSymbol(sym_index).flags.needs_got = true;996 macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;
997 return GenResult.mcv(.{ .load_symbol = sym_index });997 return GenResult.mcv(.{ .load_symbol = sym_index });
998 }998 }
999 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);999 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);
src/link/MachO.zig+20-7
...@@ -542,8 +542,6 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node...@@ -542,8 +542,6 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node
542 self.internal_object = index;542 self.internal_object = index;
543 }543 }
544544
545 state_log.debug("{}", .{self.dumpState()});
546
547 try self.addUndefinedGlobals();545 try self.addUndefinedGlobals();
548 try self.resolveSymbols();546 try self.resolveSymbols();
549 try self.resolveSyntheticSymbols();547 try self.resolveSyntheticSymbols();
...@@ -2389,14 +2387,23 @@ fn initDyldInfoSections(self: *MachO) !void {...@@ -2389,14 +2387,23 @@ fn initDyldInfoSections(self: *MachO) !void {
2389 if (self.la_symbol_ptr_sect_index != null) try self.la_symbol_ptr.addDyldRelocs(self);2387 if (self.la_symbol_ptr_sect_index != null) try self.la_symbol_ptr.addDyldRelocs(self);
2390 try self.initExportTrie();2388 try self.initExportTrie();
23912389
2390 var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1);
2391 defer objects.deinit();
2392 if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index);
2393 objects.appendSliceAssumeCapacity(self.objects.items);
2394
2392 var nrebases: usize = 0;2395 var nrebases: usize = 0;
2393 var nbinds: usize = 0;2396 var nbinds: usize = 0;
2394 var nweak_binds: usize = 0;2397 var nweak_binds: usize = 0;
2395 for (self.objects.items) |index| {2398 for (objects.items) |index| {
2396 const object = self.getFile(index).?.object;2399 const ctx = switch (self.getFile(index).?) {
2397 nrebases += object.num_rebase_relocs;2400 .zig_object => |x| x.dynamic_relocs,
2398 nbinds += object.num_bind_relocs;2401 .object => |x| x.dynamic_relocs,
2399 nweak_binds += object.num_weak_bind_relocs;2402 else => unreachable,
2403 };
2404 nrebases += ctx.rebase_relocs;
2405 nbinds += ctx.bind_relocs;
2406 nweak_binds += ctx.weak_bind_relocs;
2400 }2407 }
2401 try self.rebase.entries.ensureUnusedCapacity(gpa, nrebases);2408 try self.rebase.entries.ensureUnusedCapacity(gpa, nrebases);
2402 try self.bind.entries.ensureUnusedCapacity(gpa, nbinds);2409 try self.bind.entries.ensureUnusedCapacity(gpa, nbinds);
...@@ -3947,6 +3954,12 @@ const HotUpdateState = struct {...@@ -3947,6 +3954,12 @@ const HotUpdateState = struct {
3947 mach_task: ?std.os.darwin.MachTask = null,3954 mach_task: ?std.os.darwin.MachTask = null,
3948};3955};
39493956
3957pub const DynamicRelocs = struct {
3958 rebase_relocs: u32 = 0,
3959 bind_relocs: u32 = 0,
3960 weak_bind_relocs: u32 = 0,
3961};
3962
3950pub const SymtabCtx = struct {3963pub const SymtabCtx = struct {
3951 ilocal: u32 = 0,3964 ilocal: u32 = 0,
3952 istab: u32 = 0,3965 istab: u32 = 0,
src/link/MachO/Atom.zig+23-8
...@@ -402,7 +402,11 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -402,7 +402,11 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
402 defer tracy.end();402 defer tracy.end();
403 assert(self.flags.alive);403 assert(self.flags.alive);
404404
405 const object = self.getFile(macho_file).object;405 const dynrel_ctx = switch (self.getFile(macho_file)) {
406 .zig_object => |x| &x.dynamic_relocs,
407 .object => |x| &x.dynamic_relocs,
408 else => unreachable,
409 };
406 const relocs = self.getRelocs(macho_file);410 const relocs = self.getRelocs(macho_file);
407411
408 for (relocs) |rel| {412 for (relocs) |rel| {
...@@ -437,6 +441,10 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -437,6 +441,10 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
437 }441 }
438 },442 },
439443
444 .zig_got_load => {
445 assert(rel.getTargetSymbol(macho_file).flags.has_zig_got);
446 },
447
440 .got => {448 .got => {
441 rel.getTargetSymbol(macho_file).flags.needs_got = true;449 rel.getTargetSymbol(macho_file).flags.needs_got = true;
442 },450 },
...@@ -448,7 +456,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -448,7 +456,7 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
448 const symbol = rel.getTargetSymbol(macho_file);456 const symbol = rel.getTargetSymbol(macho_file);
449 if (!symbol.flags.tlv) {457 if (!symbol.flags.tlv) {
450 try macho_file.reportParseError2(458 try macho_file.reportParseError2(
451 object.index,459 self.getFile(macho_file).getIndex(),
452 "{s}: illegal thread-local variable reference to regular symbol {s}",460 "{s}: illegal thread-local variable reference to regular symbol {s}",
453 .{ self.getName(macho_file), symbol.getName(macho_file) },461 .{ self.getName(macho_file), symbol.getName(macho_file) },
454 );462 );
...@@ -470,27 +478,34 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -470,27 +478,34 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
470 continue;478 continue;
471 }479 }
472 if (symbol.flags.import) {480 if (symbol.flags.import) {
473 object.num_bind_relocs += 1;481 dynrel_ctx.bind_relocs += 1;
474 if (symbol.flags.weak) {482 if (symbol.flags.weak) {
475 object.num_weak_bind_relocs += 1;483 dynrel_ctx.weak_bind_relocs += 1;
476 macho_file.binds_to_weak = true;484 macho_file.binds_to_weak = true;
477 }485 }
478 continue;486 continue;
479 }487 }
480 if (symbol.flags.@"export") {488 if (symbol.flags.@"export") {
481 if (symbol.flags.weak) {489 if (symbol.flags.weak) {
482 object.num_weak_bind_relocs += 1;490 dynrel_ctx.weak_bind_relocs += 1;
483 macho_file.binds_to_weak = true;491 macho_file.binds_to_weak = true;
484 } else if (symbol.flags.interposable) {492 } else if (symbol.flags.interposable) {
485 object.num_bind_relocs += 1;493 dynrel_ctx.bind_relocs += 1;
486 }494 }
487 }495 }
488 }496 }
489 object.num_rebase_relocs += 1;497 dynrel_ctx.rebase_relocs += 1;
490 }498 }
491 },499 },
492500
493 else => {},501 .signed,
502 .signed1,
503 .signed2,
504 .signed4,
505 .page,
506 .pageoff,
507 .subtractor,
508 => {},
494 }509 }
495 }510 }
496}511}
src/link/MachO/Object.zig+1-3
...@@ -25,10 +25,8 @@ unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record.Index) = .{},...@@ -25,10 +25,8 @@ unwind_records: std.ArrayListUnmanaged(UnwindInfo.Record.Index) = .{},
2525
26alive: bool = true,26alive: bool = true,
27hidden: bool = false,27hidden: bool = false,
28num_rebase_relocs: u32 = 0,
29num_bind_relocs: u32 = 0,
30num_weak_bind_relocs: u32 = 0,
3128
29dynamic_relocs: MachO.DynamicRelocs = .{},
32output_symtab_ctx: MachO.SymtabCtx = .{},30output_symtab_ctx: MachO.SymtabCtx = .{},
3331
34pub fn isObject(path: []const u8) !bool {32pub fn isObject(path: []const u8) !bool {
src/link/MachO/ZigObject.zig+28-5
...@@ -41,6 +41,7 @@ anon_decls: AnonDeclTable = .{},...@@ -41,6 +41,7 @@ anon_decls: AnonDeclTable = .{},
41/// A table of relocations.41/// A table of relocations.
42relocs: RelocationTable = .{},42relocs: RelocationTable = .{},
4343
44dynamic_relocs: MachO.DynamicRelocs = .{},
44output_symtab_ctx: MachO.SymtabCtx = .{},45output_symtab_ctx: MachO.SymtabCtx = .{},
4546
46pub fn init(self: *ZigObject, macho_file: *MachO) !void {47pub fn init(self: *ZigObject, macho_file: *MachO) !void {
...@@ -222,10 +223,31 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {...@@ -222,10 +223,31 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
222}223}
223224
224pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {225pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
225 _ = self;226 for (self.symbols.items, 0..) |index, nlist_idx| {
226 _ = dupes;227 const sym = macho_file.getSymbol(index);
227 _ = macho_file;228 if (sym.visibility != .global) continue;
228 @panic("TODO checkDuplicates");229 const file = sym.getFile(macho_file) orelse continue;
230 if (file.getIndex() == self.index) continue;
231
232 const nlist = self.symtab.items(.nlist)[nlist_idx];
233 if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
234 const gop = try dupes.getOrPut(index);
235 if (!gop.found_existing) {
236 gop.value_ptr.* = .{};
237 }
238 try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
239 }
240 }
241}
242
243pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
244 for (self.atoms.items) |atom_index| {
245 const atom = macho_file.getAtom(atom_index) orelse continue;
246 if (!atom.flags.alive) continue;
247 const sect = atom.getInputSection(macho_file);
248 if (sect.isZerofill()) continue;
249 try atom.scanRelocs(macho_file);
250 }
229}251}
230252
231pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {253pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
...@@ -537,7 +559,8 @@ pub fn updateDecl(...@@ -537,7 +559,8 @@ pub fn updateDecl(
537 const name = mod.intern_pool.stringToSlice(decl.name);559 const name = mod.intern_pool.stringToSlice(decl.name);
538 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);560 const lib_name = mod.intern_pool.stringToSliceUnwrap(variable.lib_name);
539 const index = try self.getGlobalSymbol(macho_file, name, lib_name);561 const index = try self.getGlobalSymbol(macho_file, name, lib_name);
540 macho_file.getSymbol(index).flags.needs_got = true;562 const actual_index = self.symbols.items[index];
563 macho_file.getSymbol(actual_index).flags.needs_got = true;
541 return;564 return;
542 }565 }
543566