Commit c7de5e5111
Changed files (1)
src
link
MachO
src/link/MachO/ZigObject.zig
@@ -296,8 +296,16 @@ pub fn updateDecl(
},
};
const sect_index = try self.getDeclOutputSection(macho_file, decl, code);
- _ = sect_index;
- // const addr = try self.updateDeclCode(decl_index, code);
+ const is_threadlocal = switch (macho_file.sections.items(.header[sect_index].type())) {
+ macho.S_THREAD_LOCAL_ZEROFILL, macho.S_THREAD_LOCAL_REGULAR => true,
+ else => false,
+ };
+ if (is_threadlocal) {
+ // TODO: emit TLV
+ @panic("TODO updateDecl for TLS");
+ } else {
+ try self.updateDeclCode(macho_file, decl_index, sym_index, sect_index, code);
+ }
// if (decl_state) |*ds| {
// try self.d_sym.?.dwarf.commitDeclState(
@@ -314,6 +322,89 @@ pub fn updateDecl(
// try self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index));
}
+fn updateDeclCode(
+ self: *ZigObject,
+ macho_file: *MachO,
+ decl_index: Module.Decl.Index,
+ sym_index: Symbol.Index,
+ sect_index: u8,
+ code: []const u8,
+) !void {
+ const gpa = self.base.comp.gpa;
+ const mod = self.base.comp.module.?;
+ const decl = mod.declPtr(decl_index);
+ const decl_name = mod.intern_pool.stringToSlice(try decl.getFullyQualifiedName(mod));
+
+ log.debug("updateDeclCode {s}{*}", .{ decl_name, decl });
+
+ const required_alignment = decl.getAlignment(mod);
+
+ const sect = &macho_file.sections.items(.header)[sect_index];
+ const sym = macho_file.getSymbol(sym_index);
+ const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
+ const size = &self.symtab.items(.size)[sym.nlist_idx];
+ const atom = sym.getAtom(macho_file).?;
+
+ sym.out_n_sect = sect_index;
+ atom.out_n_sect = sect_index;
+
+ sym.name = try macho_file.strings.insert(gpa, decl_name);
+ atom.flags.alive = true;
+ atom.name = sym.name;
+ nlist.n_strx = sym.name;
+ nlist.n_type = macho.N_SECT;
+ nlist.n_sect = sect_index + 1;
+ size = code.len;
+
+ const old_size = atom.size;
+ const old_vaddr = atom.value;
+ atom.alignment = required_alignment;
+ atom.size = code.len;
+
+ if (old_size > 0) {
+ const capacity = atom.capacity(macho_file);
+ const need_realloc = code.len > capacity or !required_alignment.check(sym.value);
+
+ if (need_realloc) {
+ try atom.grow(macho_file);
+ log.debug("growing {s} from 0x{x} to 0x{x}", .{ decl_name, old_vaddr, atom.value });
+ if (old_vaddr != atom.value) {
+ sym.value = atom.value;
+ nlist.n_value = atom.value;
+
+ if (!macho_file.base.isRelocatable()) {
+ log.debug(" (updating offset table entry)", .{});
+ assert(sym.flags.has_zig_got);
+ const extra = sym.getExtra(macho_file).?;
+ try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
+ }
+ }
+ } else if (code.len < old_size) {
+ atom.shrink(macho_file);
+ } else if (atom.next_index == null) {
+ const needed_size = (sym.value + code.len) - sect.addr;
+ sect.size = needed_size;
+ }
+ } else {
+ try atom.allocate(macho_file);
+ // TODO: freeDeclMetadata in case of error
+
+ sym.value = atom.value;
+ sym.flags.needs_zig_got = true;
+ nlist.n_value = atom.value;
+
+ if (!macho_file.base.isRelocatable()) {
+ const gop = try sym.getOrCreateZigGotEntry(sym_index, macho_file);
+ try macho_file.zig_got.writeOne(macho_file, gop.index);
+ }
+ }
+
+ if (!sect.isZerofill()) {
+ const file_offset = sect.offset + sym.value - sect.addr;
+ try macho_file.base.file.?.pwriteAll(code, file_offset);
+ }
+}
+
fn getDeclOutputSection(
self: *ZigObject,
macho_file: *MachO,