From 61b4119a7d5862f58fc4a34024456e3feca292a5 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 15 Jul 2022 15:04:45 +0200 Subject: [PATCH] macho: link atom starting section by orig section id In x86_64 relocs, it can so happen that the compiler refers to the same atom by both the actual assigned symbol and the start of the section. In this case, we need to link the two together so add an alias. --- src/link/MachO/Atom.zig | 11 ++++------- src/link/MachO/Object.zig | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index d58e898848..ecf2f10149 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -659,13 +659,10 @@ pub fn resolveRelocs(self: *Atom, macho_file: *MachO) !void { // If there is no atom for target, we still need to check for special, atom-less // symbols such as `___dso_handle`. const target_name = macho_file.getSymbolName(rel.target); - if (macho_file.globals.contains(target_name)) { - const atomless_sym = macho_file.getSymbol(rel.target); - log.debug(" | atomless target '{s}'", .{target_name}); - break :blk atomless_sym.n_value; - } - log.debug(" | undef target '{s}'", .{target_name}); - break :blk 0; + assert(macho_file.globals.contains(target_name)); + const atomless_sym = macho_file.getSymbol(rel.target); + log.debug(" | atomless target '{s}'", .{target_name}); + break :blk atomless_sym.n_value; }; log.debug(" | target ATOM(%{d}, '{s}') in object({d})", .{ target_atom.sym_index, diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index 91e2169b7d..2737b5e164 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -425,6 +425,7 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) macho_file.getSection(match).sectName(), }); + const arch = macho_file.base.options.target.cpu.arch; const is_zerofill = blk: { const section_type = sect.type_(); break :blk section_type == macho.S_ZEROFILL or section_type == macho.S_THREAD_LOCAL_ZEROFILL; @@ -538,6 +539,31 @@ pub fn splitIntoAtomsOneShot(self: *Object, macho_file: *MachO, object_id: u32) match, sect, ); + + if (arch == .x86_64 and addr == sect.addr) { + // In x86_64 relocs, it can so happen that the compiler refers to the same + // atom by both the actual assigned symbol and the start of the section. In this + // case, we need to link the two together so add an alias. + const alias = self.sections_as_symbols.get(sect_id) orelse blk: { + const alias = @intCast(u32, self.symtab.items.len); + try self.symtab.append(gpa, .{ + .n_strx = 0, + .n_type = macho.N_SECT, + .n_sect = macho_file.getSectionOrdinal(match), + .n_desc = 0, + .n_value = addr, + }); + try self.sections_as_symbols.putNoClobber(gpa, sect_id, alias); + break :blk alias; + }; + try atom.contained.append(gpa, .{ + .sym_index = alias, + .offset = 0, + .stab = null, + }); + try self.atom_by_index_table.put(gpa, alias, atom); + } + try macho_file.addAtomToSection(atom, match); } } else {