macho: re-implement updateDeclCode

This commit is contained in:
Jakub Konka
2024-01-17 18:59:24 +01:00
parent 0b2133d441
commit c7de5e5111

View File

@@ -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,