Commit 61b4119a7d

Jakub Konka <kubkon@jakubkonka.com>
2022-07-15 15:04:45
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.
1 parent 35a5a4a
Changed files (2)
src
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,
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 {