authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-19 21:00:54+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-21 22:44:27+02:00
logf9e9974c8f67a7452a08973e963f2c06f85424b3
tree30cb3a7a75c265c0ad4929bc1747c3a03b52d687
parent9530b95afee9964ee88293cf36e0db882ab301e6

macho: skip GOT for TLVs; handle them separately when lowering


3 files changed, 126 insertions(+), 181 deletions(-)

src/arch/x86_64/CodeGen.zig+1-1
...@@ -7578,7 +7578,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7578,7 +7578,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7578 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);7578 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7579 if (self.bin_file.cast(link.File.MachO)) |_| {7579 if (self.bin_file.cast(link.File.MachO)) |_| {
7580 _ = try self.addInst(.{7580 _ = try self.addInst(.{
7581 .tag = .mov_linker,7581 .tag = .lea_linker,
7582 .ops = .tlv_reloc,7582 .ops = .tlv_reloc,
7583 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{7583 .data = .{ .payload = try self.addExtra(Mir.LeaRegisterReloc{
7584 .reg = @enumToInt(Register.rdi),7584 .reg = @enumToInt(Register.rdi),
src/link/MachO.zig+121-174
...@@ -157,7 +157,6 @@ strtab: StringTable(.strtab) = .{},...@@ -157,7 +157,6 @@ strtab: StringTable(.strtab) = .{},
157157
158got_table: TableSection(SymbolWithLoc) = .{},158got_table: TableSection(SymbolWithLoc) = .{},
159stub_table: TableSection(SymbolWithLoc) = .{},159stub_table: TableSection(SymbolWithLoc) = .{},
160tlv_table: SectionTable = .{},
161160
162error_flags: File.ErrorFlags = File.ErrorFlags{},161error_flags: File.ErrorFlags = File.ErrorFlags{},
163162
...@@ -222,6 +221,10 @@ lazy_syms: LazySymbolTable = .{},...@@ -222,6 +221,10 @@ lazy_syms: LazySymbolTable = .{},
222/// Table of tracked Decls.221/// Table of tracked Decls.
223decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},222decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
224223
224/// Table of threadlocal variables descriptors.
225/// They are emitted in the `__thread_vars` section.
226tlv_table: TlvSymbolTable = .{},
227
225/// Hot-code swapping state.228/// Hot-code swapping state.
226hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},229hot_state: if (is_hot_update_compatible) HotUpdateState else struct {} = .{},
227230
...@@ -238,6 +241,8 @@ const LazySymbolMetadata = struct {...@@ -238,6 +241,8 @@ const LazySymbolMetadata = struct {
238 alignment: u32,241 alignment: u32,
239};242};
240243
244const TlvSymbolTable = std.AutoArrayHashMapUnmanaged(SymbolWithLoc, Atom.Index);
245
241const DeclMetadata = struct {246const DeclMetadata = struct {
242 atom: Atom.Index,247 atom: Atom.Index,
243 section: u8,248 section: u8,
...@@ -266,122 +271,6 @@ const DeclMetadata = struct {...@@ -266,122 +271,6 @@ const DeclMetadata = struct {
266 }271 }
267};272};
268273
269const SectionTable = struct {
270 entries: std.ArrayListUnmanaged(Entry) = .{},
271 free_list: std.ArrayListUnmanaged(u32) = .{},
272 lookup: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
273
274 pub fn deinit(st: *ST, allocator: Allocator) void {
275 st.entries.deinit(allocator);
276 st.free_list.deinit(allocator);
277 st.lookup.deinit(allocator);
278 }
279
280 pub fn allocateEntry(st: *ST, allocator: Allocator, target: SymbolWithLoc) !u32 {
281 try st.entries.ensureUnusedCapacity(allocator, 1);
282 const index = blk: {
283 if (st.free_list.popOrNull()) |index| {
284 log.debug(" (reusing entry index {d})", .{index});
285 break :blk index;
286 } else {
287 log.debug(" (allocating entry at index {d})", .{st.entries.items.len});
288 const index = @intCast(u32, st.entries.items.len);
289 _ = st.entries.addOneAssumeCapacity();
290 break :blk index;
291 }
292 };
293 st.entries.items[index] = .{ .target = target, .sym_index = 0 };
294 try st.lookup.putNoClobber(allocator, target, index);
295 return index;
296 }
297
298 pub fn freeEntry(st: *ST, allocator: Allocator, target: SymbolWithLoc) void {
299 const index = st.lookup.get(target) orelse return;
300 st.free_list.append(allocator, index) catch {};
301 st.entries.items[index] = .{
302 .target = .{ .sym_index = 0 },
303 .sym_index = 0,
304 };
305 _ = st.lookup.remove(target);
306 }
307
308 pub fn getAtomIndex(st: *const ST, macho_file: *MachO, target: SymbolWithLoc) ?Atom.Index {
309 const index = st.lookup.get(target) orelse return null;
310 return st.entries.items[index].getAtomIndex(macho_file);
311 }
312
313 const FormatContext = struct {
314 macho_file: *MachO,
315 st: *const ST,
316 };
317
318 fn fmt(
319 ctx: FormatContext,
320 comptime unused_format_string: []const u8,
321 options: std.fmt.FormatOptions,
322 writer: anytype,
323 ) @TypeOf(writer).Error!void {
324 _ = options;
325 comptime assert(unused_format_string.len == 0);
326 try writer.writeAll("SectionTable:\n");
327 for (ctx.st.entries.items, 0..) |entry, i| {
328 const atom_sym = entry.getSymbol(ctx.macho_file);
329 const target_sym = ctx.macho_file.getSymbol(entry.target);
330 try writer.print(" {d}@{x} => ", .{ i, atom_sym.n_value });
331 if (target_sym.undf()) {
332 try writer.print("import('{s}')", .{
333 ctx.macho_file.getSymbolName(entry.target),
334 });
335 } else {
336 try writer.print("local(%{d}) in object({?d})", .{
337 entry.target.sym_index,
338 entry.target.file,
339 });
340 }
341 try writer.writeByte('\n');
342 }
343 }
344
345 fn format(st: *const ST, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
346 _ = st;
347 _ = unused_format_string;
348 _ = options;
349 _ = writer;
350 @compileError("do not format SectionTable directly; use st.fmtDebug()");
351 }
352
353 pub fn fmtDebug(st: *const ST, macho_file: *MachO) std.fmt.Formatter(fmt) {
354 return .{ .data = .{
355 .macho_file = macho_file,
356 .st = st,
357 } };
358 }
359
360 const ST = @This();
361
362 const Entry = struct {
363 target: SymbolWithLoc,
364 // Index into the synthetic symbol table (i.e., file == null).
365 sym_index: u32,
366
367 pub fn getSymbol(entry: Entry, macho_file: *MachO) macho.nlist_64 {
368 return macho_file.getSymbol(.{ .sym_index = entry.sym_index });
369 }
370
371 pub fn getSymbolPtr(entry: Entry, macho_file: *MachO) *macho.nlist_64 {
372 return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index });
373 }
374
375 pub fn getAtomIndex(entry: Entry, macho_file: *MachO) ?Atom.Index {
376 return macho_file.getAtomIndexForSymbol(.{ .sym_index = entry.sym_index });
377 }
378
379 pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {
380 return macho_file.getSymbolName(.{ .sym_index = entry.sym_index });
381 }
382 };
383};
384
385const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));274const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
386const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));275const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
387const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));276const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
...@@ -1520,18 +1409,13 @@ fn createDyldPrivateAtom(self: *MachO) !void {...@@ -1520,18 +1409,13 @@ fn createDyldPrivateAtom(self: *MachO) !void {
1520 try self.writeAtom(atom_index, &buffer);1409 try self.writeAtom(atom_index, &buffer);
1521}1410}
15221411
1523fn createThreadLocalDescriptorAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index {1412fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: SymbolWithLoc) !Atom.Index {
1524 const gpa = self.base.allocator;1413 const gpa = self.base.allocator;
1525 const size = 3 * @sizeOf(u64);1414 const size = 3 * @sizeOf(u64);
1526 const required_alignment: u32 = 1;1415 const required_alignment: u32 = 1;
1527 const atom_index = try self.createAtom();1416 const atom_index = try self.createAtom();
1528 self.getAtomPtr(atom_index).size = size;1417 self.getAtomPtr(atom_index).size = size;
15291418
1530 const target_sym_name = self.getSymbolName(target);
1531 const name_delimiter = mem.indexOf(u8, target_sym_name, "$").?;
1532 const sym_name = try gpa.dupe(u8, target_sym_name[0..name_delimiter]);
1533 defer gpa.free(sym_name);
1534
1535 const sym = self.getAtom(atom_index).getSymbolPtr(self);1419 const sym = self.getAtom(atom_index).getSymbolPtr(self);
1536 sym.n_type = macho.N_SECT;1420 sym.n_type = macho.N_SECT;
1537 sym.n_sect = self.thread_vars_section_index.? + 1;1421 sym.n_sect = self.thread_vars_section_index.? + 1;
...@@ -1706,7 +1590,6 @@ pub fn deinit(self: *MachO) void {...@@ -1706,7 +1590,6 @@ pub fn deinit(self: *MachO) void {
17061590
1707 self.got_table.deinit(gpa);1591 self.got_table.deinit(gpa);
1708 self.stub_table.deinit(gpa);1592 self.stub_table.deinit(gpa);
1709 self.tlv_table.deinit(gpa);
1710 self.strtab.deinit(gpa);1593 self.strtab.deinit(gpa);
17111594
1712 self.locals.deinit(gpa);1595 self.locals.deinit(gpa);
...@@ -1739,14 +1622,12 @@ pub fn deinit(self: *MachO) void {...@@ -1739,14 +1622,12 @@ pub fn deinit(self: *MachO) void {
17391622
1740 self.atoms.deinit(gpa);1623 self.atoms.deinit(gpa);
17411624
1742 if (self.base.options.module) |_| {1625 for (self.decls.values()) |*m| {
1743 for (self.decls.values()) |*m| {1626 m.exports.deinit(gpa);
1744 m.exports.deinit(gpa);
1745 }
1746 self.decls.deinit(gpa);
1747 } else {
1748 assert(self.decls.count() == 0);
1749 }1627 }
1628 self.decls.deinit(gpa);
1629 self.lazy_syms.deinit(gpa);
1630 self.tlv_table.deinit(gpa);
17501631
1751 for (self.unnamed_const_atoms.values()) |*atoms| {1632 for (self.unnamed_const_atoms.values()) |*atoms| {
1752 atoms.deinit(gpa);1633 atoms.deinit(gpa);
...@@ -1926,15 +1807,6 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {...@@ -1926,15 +1807,6 @@ fn addStubEntry(self: *MachO, target: SymbolWithLoc) !void {
1926 self.stub_table_count_dirty = true;1807 self.stub_table_count_dirty = true;
1927}1808}
19281809
1929fn addTlvEntry(self: *MachO, target: SymbolWithLoc) !void {
1930 if (self.tlv_table.lookup.contains(target)) return;
1931 const tlv_index = try self.tlv_table.allocateEntry(self.base.allocator, target);
1932 const tlv_atom_index = try self.createThreadLocalDescriptorAtom(target);
1933 const tlv_atom = self.getAtom(tlv_atom_index);
1934 self.tlv_table.entries.items[tlv_index].sym_index = tlv_atom.getSymbolIndex().?;
1935 self.markRelocsDirtyByTarget(target);
1936}
1937
1938pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {1810pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) !void {
1939 if (build_options.skip_non_native and builtin.object_format != .macho) {1811 if (build_options.skip_non_native and builtin.object_format != .macho) {
1940 @panic("Attempted to compile for object format that was disabled by build configuration");1812 @panic("Attempted to compile for object format that was disabled by build configuration");
...@@ -2081,6 +1953,12 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2081,6 +1953,12 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2081 }1953 }
2082 }1954 }
20831955
1956 const is_threadlocal = if (decl.val.castTag(.variable)) |payload|
1957 payload.data.is_threadlocal and !self.base.options.single_threaded
1958 else
1959 false;
1960 if (is_threadlocal) return self.updateThreadlocalVariable(module, decl_index);
1961
2084 const atom_index = try self.getOrCreateAtomForDecl(decl_index);1962 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2085 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;1963 const sym_index = self.getAtom(atom_index).getSymbolIndex().?;
2086 Atom.freeRelocations(self, atom_index);1964 Atom.freeRelocations(self, atom_index);
...@@ -2229,6 +2107,101 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol, alignmen...@@ -2229,6 +2107,101 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol, alignmen
2229 return atom.*.?;2107 return atom.*.?;
2230}2108}
22312109
2110fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {
2111 // Lowering a TLV on macOS involves two stages:
2112 // 1. first we lower the initializer into appopriate section (__thread_data or __thread_bss)
2113 // 2. next, we create a corresponding threadlocal variable descriptor in __thread_vars
2114
2115 // 1. Lower the initializer value.
2116 const init_atom_index = try self.getOrCreateAtomForDecl(decl_index);
2117 const init_atom = self.getAtomPtr(init_atom_index);
2118 const init_sym_index = init_atom.getSymbolIndex().?;
2119 Atom.freeRelocations(self, init_atom_index);
2120
2121 const gpa = self.base.allocator;
2122
2123 var code_buffer = std.ArrayList(u8).init(gpa);
2124 defer code_buffer.deinit();
2125
2126 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
2127 try d_sym.dwarf.initDeclState(module, decl_index)
2128 else
2129 null;
2130 defer if (decl_state) |*ds| ds.deinit();
2131
2132 const decl = module.declPtr(decl_index);
2133 const decl_metadata = self.decls.get(decl_index).?;
2134 const decl_val = decl.val.castTag(.variable).?.data.init;
2135 const res = if (decl_state) |*ds|
2136 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2137 .ty = decl.ty,
2138 .val = decl_val,
2139 }, &code_buffer, .{
2140 .dwarf = ds,
2141 }, .{
2142 .parent_atom_index = init_sym_index,
2143 })
2144 else
2145 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2146 .ty = decl.ty,
2147 .val = decl_val,
2148 }, &code_buffer, .none, .{
2149 .parent_atom_index = init_sym_index,
2150 });
2151
2152 var code = switch (res) {
2153 .ok => code_buffer.items,
2154 .fail => |em| {
2155 decl.analysis = .codegen_failure;
2156 try module.failed_decls.put(module.gpa, decl_index, em);
2157 return;
2158 },
2159 };
2160
2161 const required_alignment = decl.getAlignment(self.base.options.target);
2162
2163 const decl_name = try decl.getFullyQualifiedName(module);
2164 defer gpa.free(decl_name);
2165
2166 const init_sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{decl_name});
2167 defer gpa.free(init_sym_name);
2168
2169 const sect_id = decl_metadata.section;
2170 const init_sym = init_atom.getSymbolPtr(self);
2171 init_sym.n_strx = try self.strtab.insert(gpa, init_sym_name);
2172 init_sym.n_type = macho.N_SECT;
2173 init_sym.n_sect = sect_id + 1;
2174 init_sym.n_desc = 0;
2175 init_atom.size = code.len;
2176
2177 init_sym.n_value = try self.allocateAtom(init_atom_index, code.len, required_alignment);
2178 errdefer self.freeAtom(init_atom_index);
2179
2180 log.debug("allocated atom for {s} at 0x{x}", .{ init_sym_name, init_sym.n_value });
2181 log.debug(" (required alignment 0x{x})", .{required_alignment});
2182
2183 try self.writeAtom(init_atom_index, code);
2184
2185 if (decl_state) |*ds| {
2186 try self.d_sym.?.dwarf.commitDeclState(
2187 module,
2188 decl_index,
2189 init_sym.n_value,
2190 self.getAtom(init_atom_index).size,
2191 ds,
2192 );
2193 }
2194
2195 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
2196
2197 // 2. Create a TLV descriptor.
2198 const init_atom_sym_loc = init_atom.getSymbolWithLoc();
2199 const gop = try self.tlv_table.getOrPut(gpa, init_atom_sym_loc);
2200 assert(!gop.found_existing);
2201 gop.value_ptr.* = try self.createThreadLocalDescriptorAtom(decl_name, init_atom_sym_loc);
2202 self.markRelocsDirtyByTarget(init_atom_sym_loc);
2203}
2204
2232pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: Module.Decl.Index) !Atom.Index {2205pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: Module.Decl.Index) !Atom.Index {
2233 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);2206 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
2234 if (!gop.found_existing) {2207 if (!gop.found_existing) {
...@@ -2296,21 +2269,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64...@@ -2296,21 +2269,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
2296 const sect_id = decl_metadata.section;2269 const sect_id = decl_metadata.section;
2297 const header = &self.sections.items(.header)[sect_id];2270 const header = &self.sections.items(.header)[sect_id];
2298 const segment = self.getSegment(sect_id);2271 const segment = self.getSegment(sect_id);
2299 const is_threadlocal = if (!self.base.options.single_threaded)
2300 header.flags == macho.S_THREAD_LOCAL_REGULAR or header.flags == macho.S_THREAD_LOCAL_ZEROFILL
2301 else
2302 false;
2303 const code_len = code.len;2272 const code_len = code.len;
23042273
2305 const sym_name = if (is_threadlocal)
2306 try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{decl_name})
2307 else
2308 decl_name;
2309 defer if (is_threadlocal) gpa.free(sym_name);
2310
2311 if (atom.size != 0) {2274 if (atom.size != 0) {
2312 const sym = atom.getSymbolPtr(self);2275 const sym = atom.getSymbolPtr(self);
2313 sym.n_strx = try self.strtab.insert(gpa, sym_name);2276 sym.n_strx = try self.strtab.insert(gpa, decl_name);
2314 sym.n_type = macho.N_SECT;2277 sym.n_type = macho.N_SECT;
2315 sym.n_sect = sect_id + 1;2278 sym.n_sect = sect_id + 1;
2316 sym.n_desc = 0;2279 sym.n_desc = 0;
...@@ -2320,21 +2283,13 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64...@@ -2320,21 +2283,13 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
23202283
2321 if (need_realloc) {2284 if (need_realloc) {
2322 const vaddr = try self.growAtom(atom_index, code_len, required_alignment);2285 const vaddr = try self.growAtom(atom_index, code_len, required_alignment);
2323 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, sym.n_value, vaddr });2286 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ decl_name, sym.n_value, vaddr });
2324 log.debug(" (required alignment 0x{x})", .{required_alignment});2287 log.debug(" (required alignment 0x{x})", .{required_alignment});
23252288
2326 if (vaddr != sym.n_value) {2289 if (vaddr != sym.n_value) {
2327 sym.n_value = vaddr;2290 sym.n_value = vaddr;
2328 // TODO: I think we should update the offset to the initializer here too.
2329 const target: SymbolWithLoc = if (is_threadlocal) blk: {
2330 const tlv_atom_index = self.tlv_table.getAtomIndex(self, .{
2331 .sym_index = sym_index,
2332 }).?;
2333 const tlv_atom = self.getAtom(tlv_atom_index);
2334 break :blk tlv_atom.getSymbolWithLoc();
2335 } else .{ .sym_index = sym_index };
2336 log.debug(" (updating GOT entry)", .{});2291 log.debug(" (updating GOT entry)", .{});
2337 const got_atom_index = self.got_table.lookup.get(target).?;2292 const got_atom_index = self.got_table.lookup.get(.{ .sym_index = sym_index }).?;
2338 try self.writeOffsetTableEntry(got_atom_index);2293 try self.writeOffsetTableEntry(got_atom_index);
2339 }2294 }
2340 } else if (code_len < atom.size) {2295 } else if (code_len < atom.size) {
...@@ -2346,7 +2301,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64...@@ -2346,7 +2301,7 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
2346 self.getAtomPtr(atom_index).size = code_len;2301 self.getAtomPtr(atom_index).size = code_len;
2347 } else {2302 } else {
2348 const sym = atom.getSymbolPtr(self);2303 const sym = atom.getSymbolPtr(self);
2349 sym.n_strx = try self.strtab.insert(gpa, sym_name);2304 sym.n_strx = try self.strtab.insert(gpa, decl_name);
2350 sym.n_type = macho.N_SECT;2305 sym.n_type = macho.N_SECT;
2351 sym.n_sect = sect_id + 1;2306 sym.n_sect = sect_id + 1;
2352 sym.n_desc = 0;2307 sym.n_desc = 0;
...@@ -2354,21 +2309,13 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64...@@ -2354,21 +2309,13 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []u8) !u64
2354 const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);2309 const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);
2355 errdefer self.freeAtom(atom_index);2310 errdefer self.freeAtom(atom_index);
23562311
2357 log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, vaddr });2312 log.debug("allocated atom for {s} at 0x{x}", .{ decl_name, vaddr });
2358 log.debug(" (required alignment 0x{x})", .{required_alignment});2313 log.debug(" (required alignment 0x{x})", .{required_alignment});
23592314
2360 self.getAtomPtr(atom_index).size = code_len;2315 self.getAtomPtr(atom_index).size = code_len;
2361 sym.n_value = vaddr;2316 sym.n_value = vaddr;
23622317
2363 if (is_threadlocal) {2318 try self.addGotEntry(.{ .sym_index = sym_index });
2364 try self.addTlvEntry(.{ .sym_index = sym_index });
2365 }
2366 const target: SymbolWithLoc = if (is_threadlocal) blk: {
2367 const tlv_atom_index = self.tlv_table.getAtomIndex(self, .{ .sym_index = sym_index }).?;
2368 const tlv_atom = self.getAtom(tlv_atom_index);
2369 break :blk tlv_atom.getSymbolWithLoc();
2370 } else .{ .sym_index = sym_index };
2371 try self.addGotEntry(target);
2372 }2319 }
23732320
2374 try self.writeAtom(atom_index, code);2321 try self.writeAtom(atom_index, code);
...@@ -4169,8 +4116,8 @@ pub fn logSymtab(self: *MachO) void {...@@ -4169,8 +4116,8 @@ pub fn logSymtab(self: *MachO) void {
4169 log.debug("stubs entries:", .{});4116 log.debug("stubs entries:", .{});
4170 log.debug("{}", .{self.stub_table});4117 log.debug("{}", .{self.stub_table});
41714118
4172 log.debug("threadlocal entries:", .{});4119 // log.debug("threadlocal entries:", .{});
4173 log.debug("{}", .{self.tlv_table.fmtDebug(self)});4120 // log.debug("{}", .{self.tlv_table});
4174}4121}
41754122
4176pub fn logAtoms(self: *MachO) void {4123pub fn logAtoms(self: *MachO) void {
src/link/MachO/Relocation.zig+4-6
...@@ -15,7 +15,7 @@ pub const Type = enum {...@@ -15,7 +15,7 @@ pub const Type = enum {
15 got,15 got,
16 /// RIP-relative displacement16 /// RIP-relative displacement
17 signed,17 signed,
18 /// RIP-relative displacement to GOT pointer to TLV thunk18 /// RIP-relative displacement to a TLV thunk
19 tlv,19 tlv,
2020
21 // aarch6421 // aarch64
...@@ -52,11 +52,9 @@ pub fn getTargetBaseAddress(self: Relocation, macho_file: *MachO) ?u64 {...@@ -52,11 +52,9 @@ pub fn getTargetBaseAddress(self: Relocation, macho_file: *MachO) ?u64 {
52 return header.addr + got_index * @sizeOf(u64);52 return header.addr + got_index * @sizeOf(u64);
53 },53 },
54 .tlv => {54 .tlv => {
55 const thunk_atom_index = macho_file.tlv_table.getAtomIndex(macho_file, self.target) orelse return null;55 const atom_index = macho_file.tlv_table.get(self.target) orelse return null;
56 const thunk_atom = macho_file.getAtom(thunk_atom_index);56 const atom = macho_file.getAtom(atom_index);
57 const got_index = macho_file.got_table.lookup.get(thunk_atom.getSymbolWithLoc()) orelse return null;57 return atom.getSymbol(macho_file).n_value;
58 const header = macho_file.sections.items(.header)[macho_file.got_section_index.?];
59 return header.addr + got_index * @sizeOf(u64);
60 },58 },
61 .branch => {59 .branch => {
62 if (macho_file.stub_table.lookup.get(self.target)) |index| {60 if (macho_file.stub_table.lookup.get(self.target)) |index| {