macho: unify creating atoms

This commit is contained in:
Jakub Konka 2023-08-26 22:05:42 +02:00
parent ef0d35e00c
commit 7f74b3562d
5 changed files with 55 additions and 48 deletions

View File

@ -1410,30 +1410,29 @@ pub fn allocateSpecialSymbols(self: anytype) !void {
}
}
pub fn createAtom(self: *MachO) !Atom.Index {
const CreateAtomOpts = struct {
size: u64 = 0,
alignment: u32 = 0,
};
pub fn createAtom(self: *MachO, sym_index: u32, opts: CreateAtomOpts) !Atom.Index {
const gpa = self.base.allocator;
const atom_index = @as(Atom.Index, @intCast(self.atoms.items.len));
const index = @as(Atom.Index, @intCast(self.atoms.items.len));
const atom = try self.atoms.addOne(gpa);
const sym_index = try self.allocateSymbol();
try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
atom.* = .{
.sym_index = sym_index,
.inner_sym_index = 0,
.inner_nsyms_trailing = 0,
.file = 0,
.size = 0,
.alignment = 0,
.prev_index = null,
.next_index = null,
};
log.debug("creating ATOM(%{d}) at index {d}", .{ sym_index, atom_index });
return atom_index;
atom.* = .{};
atom.sym_index = sym_index;
atom.size = opts.size;
atom.alignment = opts.alignment;
log.debug("creating ATOM(%{d}) at index {d}", .{ sym_index, index });
return index;
}
fn createDyldPrivateAtom(self: *MachO) !void {
if (self.dyld_private_atom_index != null) return;
const atom_index = try self.createAtom();
const sym_index = try self.allocateSymbol();
const atom_index = try self.createAtom(sym_index, .{});
try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index);
const atom = self.getAtomPtr(atom_index);
atom.size = @sizeOf(u64);
@ -1452,7 +1451,9 @@ fn createThreadLocalDescriptorAtom(self: *MachO, sym_name: []const u8, target: S
const gpa = self.base.allocator;
const size = 3 * @sizeOf(u64);
const required_alignment: u32 = 1;
const atom_index = try self.createAtom();
const sym_index = try self.allocateSymbol();
const atom_index = try self.createAtom(sym_index, .{});
try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
self.getAtomPtr(atom_index).size = size;
const sym = self.getAtom(atom_index).getSymbolPtr(self);
@ -1936,7 +1937,9 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
log.debug("allocating symbol indexes for {s}", .{name});
const atom_index = try self.createAtom();
const sym_index = try self.allocateSymbol();
const atom_index = try self.createAtom(sym_index, .{});
try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), typed_value, &code_buffer, .none, .{
.parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?,
@ -2138,7 +2141,11 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
},
};
switch (metadata.state.*) {
.unused => metadata.atom.* = try self.createAtom(),
.unused => {
const sym_index = try self.allocateSymbol();
metadata.atom.* = try self.createAtom(sym_index, .{});
try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, metadata.atom.*);
},
.pending_flush => return metadata.atom.*,
.flushed => {},
}
@ -2250,8 +2257,11 @@ fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.D
pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: Module.Decl.Index) !Atom.Index {
const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
if (!gop.found_existing) {
const sym_index = try self.allocateSymbol();
const atom_index = try self.createAtom(sym_index, .{});
try self.atom_by_index_table.putNoClobber(self.base.allocator, sym_index, atom_index);
gop.value_ptr.* = .{
.atom = try self.createAtom(),
.atom = atom_index,
.section = self.getDeclOutputSection(decl_index),
.exports = .{},
};

View File

@ -4,13 +4,13 @@
/// a stub trampoline, it can be found in the linkers `locals` arraylist.
/// If this field is 0 and file is 0, it means the codegen size = 0 and there is no symbol or
/// offset table entry.
sym_index: u32,
sym_index: u32 = 0,
/// 0 means an Atom is a synthetic Atom such as a GOT cell defined by the linker.
/// Otherwise, it is the index into appropriate object file (indexing from 1).
/// Prefer using `getFile()` helper to get the file index out rather than using
/// the field directly.
file: u32,
file: u32 = 0,
/// If this Atom is not a synthetic Atom, i.e., references a subsection in an
/// Object file, `inner_sym_index` and `inner_nsyms_trailing` tell where and if
@ -18,22 +18,22 @@ file: u32,
/// address range. These could for example be an alias symbol which can be used
/// internally by the relocation records, or if the Object file couldn't be split
/// into subsections, this Atom may encompass an entire input section.
inner_sym_index: u32,
inner_nsyms_trailing: u32,
inner_sym_index: u32 = 0,
inner_nsyms_trailing: u32 = 0,
/// Size and alignment of this atom
/// Unlike in Elf, we need to store the size of this symbol as part of
/// the atom since macho.nlist_64 lacks this information.
size: u64,
size: u64 = 0,
/// Alignment of this atom as a power of 2.
/// For instance, aligmment of 0 should be read as 2^0 = 1 byte aligned.
alignment: u32,
alignment: u32 = 0,
/// Points to the previous and next neighbours
/// TODO use the same trick as with symbols: reserve index 0 as null atom
next_index: ?Index,
prev_index: ?Index,
next_index: ?Index = null,
prev_index: ?Index = null,
pub const Index = u32;

View File

@ -573,7 +573,7 @@ fn createAtomFromSubsection(
out_sect_id: u8,
) !Atom.Index {
const gpa = zld.gpa;
const atom_index = try zld.createEmptyAtom(sym_index, size, alignment);
const atom_index = try zld.createAtom(sym_index, .{ .size = size, .alignment = alignment });
const atom = zld.getAtomPtr(atom_index);
atom.inner_sym_index = inner_sym_index;
atom.inner_nsyms_trailing = inner_nsyms_trailing;

View File

@ -342,7 +342,7 @@ fn isReachable(
fn createThunkAtom(zld: *Zld) !Atom.Index {
const sym_index = try zld.allocateSymbol();
const atom_index = try zld.createEmptyAtom(sym_index, @sizeOf(u32) * 3, 2);
const atom_index = try zld.createAtom(sym_index, .{ .size = @sizeOf(u32) * 3, .alignment = 2 });
const sym = zld.getSymbolPtr(.{ .sym_index = sym_index });
sym.n_type = macho.N_SECT;
sym.n_sect = zld.text_section_index.? + 1;

View File

@ -112,32 +112,26 @@ pub const Zld = struct {
self.sections.set(sym.n_sect - 1, section);
}
pub fn createEmptyAtom(self: *Zld, sym_index: u32, size: u64, alignment: u32) !Atom.Index {
const CreateAtomOpts = struct {
size: u64 = 0,
alignment: u32 = 0,
};
pub fn createAtom(self: *Zld, sym_index: u32, opts: CreateAtomOpts) !Atom.Index {
const gpa = self.gpa;
const index = @as(Atom.Index, @intCast(self.atoms.items.len));
const atom = try self.atoms.addOne(gpa);
atom.* = .{
.sym_index = 0,
.inner_sym_index = 0,
.inner_nsyms_trailing = 0,
.file = 0,
.size = 0,
.alignment = 0,
.prev_index = null,
.next_index = null,
};
atom.* = .{};
atom.sym_index = sym_index;
atom.size = size;
atom.alignment = alignment;
atom.size = opts.size;
atom.alignment = opts.alignment;
log.debug("creating ATOM(%{d}) at index {d}", .{ sym_index, index });
return index;
}
fn createDyldPrivateAtom(self: *Zld) !void {
const sym_index = try self.allocateSymbol();
const atom_index = try self.createEmptyAtom(sym_index, @sizeOf(u64), 3);
const atom_index = try self.createAtom(sym_index, .{ .size = @sizeOf(u64), .alignment = 3 });
const sym = self.getSymbolPtr(.{ .sym_index = sym_index });
sym.n_type = macho.N_SECT;
@ -176,7 +170,10 @@ pub const Zld = struct {
.n_value = 0,
};
const atom_index = try self.createEmptyAtom(global.sym_index, size, alignment);
const atom_index = try self.createAtom(global.sym_index, .{
.size = size,
.alignment = alignment,
});
const atom = self.getAtomPtr(atom_index);
atom.file = global.file;