mirror of
https://github.com/ziglang/zig.git
synced 2026-02-15 05:48:31 +00:00
elf: move ownership of atoms into objects
This commit is contained in:
parent
f1fedb3a51
commit
669f285943
138
src/link/Elf.zig
138
src/link/Elf.zig
@ -54,7 +54,7 @@ phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{},
|
||||
shdr_table_offset: ?u64 = null,
|
||||
/// Table of lists of atoms per output section.
|
||||
/// This table is not used to track incrementally generated atoms.
|
||||
output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{},
|
||||
output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Ref)) = .{},
|
||||
output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{},
|
||||
|
||||
/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
|
||||
@ -203,10 +203,6 @@ resolver: std.AutoArrayHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
has_text_reloc: bool = false,
|
||||
num_ifunc_dynrelocs: usize = 0,
|
||||
|
||||
/// List of atoms that are owned directly by the linker.
|
||||
atoms: std.ArrayListUnmanaged(Atom) = .{},
|
||||
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
/// List of range extension thunks.
|
||||
thunks: std.ArrayListUnmanaged(Thunk) = .{},
|
||||
|
||||
@ -375,9 +371,6 @@ pub fn createEmpty(
|
||||
try self.symbols.append(gpa, .{});
|
||||
// Index 0 is always a null symbol.
|
||||
try self.symbols_extra.append(gpa, 0);
|
||||
// Allocate atom index 0 to null atom
|
||||
try self.atoms.append(gpa, .{});
|
||||
try self.atoms_extra.append(gpa, 0);
|
||||
// Append null file at index 0
|
||||
try self.files.append(gpa, .null);
|
||||
// Append null byte to string tables
|
||||
@ -499,8 +492,6 @@ pub fn deinit(self: *Elf) void {
|
||||
self.resolver.deinit(gpa);
|
||||
self.start_stop_indexes.deinit(gpa);
|
||||
|
||||
self.atoms.deinit(gpa);
|
||||
self.atoms_extra.deinit(gpa);
|
||||
for (self.thunks.items) |*th| {
|
||||
th.deinit(gpa);
|
||||
}
|
||||
@ -1305,6 +1296,8 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
|
||||
self.files.set(index, .{ .linker_defined = .{ .index = index } });
|
||||
self.linker_defined_index = index;
|
||||
const object = self.file(index).?.linker_defined;
|
||||
try object.init(gpa);
|
||||
}
|
||||
|
||||
// Now, we are ready to resolve the symbols across all input files.
|
||||
@ -1379,15 +1372,15 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
|
||||
|
||||
// Beyond this point, everything has been allocated a virtual address and we can resolve
|
||||
// the relocations, and commit objects to file.
|
||||
if (self.zigObjectPtr()) |zig_object| {
|
||||
if (self.zigObjectPtr()) |zo| {
|
||||
var has_reloc_errors = false;
|
||||
for (zig_object.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
for (zo.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = zo.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const out_shndx = atom_ptr.outputShndx() orelse continue;
|
||||
const shdr = &self.shdrs.items[out_shndx];
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
const code = try zig_object.codeAlloc(self, atom_index);
|
||||
const code = try zo.codeAlloc(self, atom_index);
|
||||
defer gpa.free(code);
|
||||
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
|
||||
atom_ptr.resolveRelocsAlloc(self, code) catch |err| switch (err) {
|
||||
@ -2012,8 +2005,8 @@ pub fn resolveSymbols(self: *Elf) void {
|
||||
const cg_owner = self.comdatGroupOwner(cg.owner);
|
||||
if (cg_owner.file != index) {
|
||||
for (cg.comdatGroupMembers(self)) |shndx| {
|
||||
const atom_index = object.atoms.items[shndx];
|
||||
if (self.atom(atom_index)) |atom_ptr| {
|
||||
const atom_index = object.atoms_indexes.items[shndx];
|
||||
if (object.atom(atom_index)) |atom_ptr| {
|
||||
atom_ptr.flags.alive = false;
|
||||
atom_ptr.markFdesDead(self);
|
||||
}
|
||||
@ -2117,7 +2110,7 @@ fn claimUnresolved(self: *Elf) void {
|
||||
fn scanRelocs(self: *Elf) !void {
|
||||
const gpa = self.base.comp.gpa;
|
||||
|
||||
var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);
|
||||
var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
|
||||
defer {
|
||||
var it = undefs.iterator();
|
||||
while (it.next()) |entry| {
|
||||
@ -3721,11 +3714,11 @@ fn sortInitFini(self: *Elf) !void {
|
||||
|
||||
const Entry = struct {
|
||||
priority: i32,
|
||||
atom_index: Atom.Index,
|
||||
atom_ref: Ref,
|
||||
|
||||
pub fn lessThan(ctx: *Elf, lhs: @This(), rhs: @This()) bool {
|
||||
if (lhs.priority == rhs.priority) {
|
||||
return ctx.atom(lhs.atom_index).?.priority(ctx) < ctx.atom(rhs.atom_index).?.priority(ctx);
|
||||
return ctx.atom(lhs.atom_ref).?.priority(ctx) < ctx.atom(rhs.atom_ref).?.priority(ctx);
|
||||
}
|
||||
return lhs.priority < rhs.priority;
|
||||
}
|
||||
@ -3756,8 +3749,8 @@ fn sortInitFini(self: *Elf) !void {
|
||||
try entries.ensureTotalCapacityPrecise(atom_list.items.len);
|
||||
defer entries.deinit();
|
||||
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
for (atom_list.items) |ref| {
|
||||
const atom_ptr = self.atom(ref).?;
|
||||
const object = atom_ptr.file(self).?.object;
|
||||
const priority = blk: {
|
||||
if (is_ctor_dtor) {
|
||||
@ -3770,14 +3763,14 @@ fn sortInitFini(self: *Elf) !void {
|
||||
const priority = std.fmt.parseUnsigned(u16, it.first(), 10) catch default;
|
||||
break :blk priority;
|
||||
};
|
||||
entries.appendAssumeCapacity(.{ .priority = priority, .atom_index = atom_index });
|
||||
entries.appendAssumeCapacity(.{ .priority = priority, .atom_ref = ref });
|
||||
}
|
||||
|
||||
mem.sort(Entry, entries.items, self, Entry.lessThan);
|
||||
|
||||
atom_list.clearRetainingCapacity();
|
||||
for (entries.items) |entry| {
|
||||
atom_list.appendAssumeCapacity(entry.atom_index);
|
||||
atom_list.appendAssumeCapacity(entry.atom_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4143,23 +4136,23 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
|
||||
}
|
||||
}
|
||||
|
||||
if (self.zigObjectPtr()) |zig_object| {
|
||||
for (zig_object.atoms.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (self.zigObjectPtr()) |zo| {
|
||||
for (zo.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = zo.atom(atom_index) orelse continue;
|
||||
atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
|
||||
}
|
||||
|
||||
for (zig_object.locals()) |local_index| {
|
||||
for (zo.locals()) |local_index| {
|
||||
const local = self.symbol(local_index);
|
||||
local.output_section_index = backlinks[local.output_section_index];
|
||||
}
|
||||
|
||||
for (zig_object.globals()) |global_index| {
|
||||
for (zo.globals()) |global_index| {
|
||||
const global = self.symbol(global_index);
|
||||
const atom_ptr = global.atom(self) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
// TODO claim unresolved for objects
|
||||
if (global.file(self).?.index() != zig_object.index) continue;
|
||||
if (global.file(self).?.index() != zo.index) continue;
|
||||
const out_shndx = global.outputShndx() orelse continue;
|
||||
global.output_section_index = backlinks[out_shndx];
|
||||
}
|
||||
@ -4182,8 +4175,8 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
const shdr = &self.shdrs.items[shndx];
|
||||
if (atom_list.items.len == 0) continue;
|
||||
if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
for (atom_list.items) |ref| {
|
||||
const atom_ptr = self.atom(ref) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const offset = atom_ptr.alignment.forward(shdr.sh_size);
|
||||
const padding = offset - shdr.sh_size;
|
||||
@ -4618,7 +4611,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
|
||||
fn writeAtoms(self: *Elf) !void {
|
||||
const gpa = self.base.comp.gpa;
|
||||
|
||||
var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Atom.Index)).init(gpa);
|
||||
var undefs = std.AutoHashMap(Symbol.Index, std.ArrayList(Ref)).init(gpa);
|
||||
defer {
|
||||
var it = undefs.iterator();
|
||||
while (it.next()) |entry| {
|
||||
@ -4666,21 +4659,21 @@ fn writeAtoms(self: *Elf) !void {
|
||||
0;
|
||||
@memset(buffer, padding_byte);
|
||||
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
for (atom_list.items) |ref| {
|
||||
const atom_ptr = self.atom(ref).?;
|
||||
assert(atom_ptr.flags.alive);
|
||||
|
||||
const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(base_offset))) orelse
|
||||
return error.Overflow;
|
||||
const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
|
||||
|
||||
log.debug("writing atom({d}) at 0x{x}", .{ atom_index, sh_offset + offset });
|
||||
log.debug("writing atom({}) at 0x{x}", .{ ref, sh_offset + offset });
|
||||
|
||||
// TODO decompress directly into provided buffer
|
||||
const out_code = buffer[offset..][0..size];
|
||||
const in_code = switch (atom_ptr.file(self).?) {
|
||||
.object => |x| try x.codeDecompressAlloc(self, atom_index),
|
||||
.zig_object => |x| try x.codeAlloc(self, atom_index),
|
||||
.object => |x| try x.codeDecompressAlloc(self, ref.index),
|
||||
.zig_object => |x| try x.codeAlloc(self, ref.index),
|
||||
else => unreachable,
|
||||
};
|
||||
defer gpa.free(in_code);
|
||||
@ -5598,64 +5591,6 @@ fn getStartStopBasename(self: *Elf, shdr: elf.Elf64_Shdr) ?[]const u8 {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn atom(self: *Elf, atom_index: Atom.Index) ?*Atom {
|
||||
if (atom_index == 0) return null;
|
||||
assert(atom_index < self.atoms.items.len);
|
||||
return &self.atoms.items[atom_index];
|
||||
}
|
||||
|
||||
pub fn addAtom(self: *Elf) !Atom.Index {
|
||||
const gpa = self.base.comp.gpa;
|
||||
const index = @as(Atom.Index, @intCast(self.atoms.items.len));
|
||||
const atom_ptr = try self.atoms.addOne(gpa);
|
||||
atom_ptr.* = .{ .atom_index = index };
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn addAtomExtra(self: *Elf, extra: Atom.Extra) !u32 {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
try self.atoms_extra.ensureUnusedCapacity(self.base.comp.gpa, fields.len);
|
||||
return self.addAtomExtraAssumeCapacity(extra);
|
||||
}
|
||||
|
||||
pub fn addAtomExtraAssumeCapacity(self: *Elf, extra: Atom.Extra) u32 {
|
||||
const index = @as(u32, @intCast(self.atoms_extra.items.len));
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields) |field| {
|
||||
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn atomExtra(self: *Elf, index: u32) ?Atom.Extra {
|
||||
if (index == 0) return null;
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
var i: usize = index;
|
||||
var result: Atom.Extra = undefined;
|
||||
inline for (fields) |field| {
|
||||
@field(result, field.name) = switch (field.type) {
|
||||
u32 => self.atoms_extra.items[i],
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn setAtomExtra(self: *Elf, index: u32, extra: Atom.Extra) void {
|
||||
assert(index > 0);
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields, 0..) |field, i| {
|
||||
self.atoms_extra.items[index + i] = switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addThunk(self: *Elf) !Thunk.Index {
|
||||
const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
|
||||
const th = try self.thunks.addOne(self.base.comp.gpa);
|
||||
@ -5692,6 +5627,11 @@ pub fn fileHandle(self: Elf, index: File.HandleIndex) File.Handle {
|
||||
return self.file_handles.items[index];
|
||||
}
|
||||
|
||||
pub fn atom(self: *Elf, ref: Ref) ?*Atom {
|
||||
const file_ptr = self.file(ref.file) orelse return null;
|
||||
return file_ptr.atom(ref.index);
|
||||
}
|
||||
|
||||
/// Returns pointer-to-symbol described at sym_index.
|
||||
pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol {
|
||||
return &self.symbols.items[sym_index];
|
||||
@ -5938,9 +5878,9 @@ fn reportUndefinedSymbols(self: *Elf, undefs: anytype) !void {
|
||||
var err = try self.base.addErrorWithNotesAssumeCapacity(nnotes);
|
||||
try err.addMsg("undefined symbol: {s}", .{self.symbol(undef_index).name(self)});
|
||||
|
||||
for (atoms[0..natoms]) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const file_ptr = self.file(atom_ptr.file_index).?;
|
||||
for (atoms[0..natoms]) |ref| {
|
||||
const atom_ptr = self.atom(ref).?;
|
||||
const file_ptr = self.file(ref.file).?;
|
||||
try err.addNote("referenced by {s}:{s}", .{ file_ptr.fmtPath(), atom_ptr.name(self) });
|
||||
}
|
||||
|
||||
@ -6401,7 +6341,7 @@ const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndF
|
||||
|
||||
const RelaSection = struct {
|
||||
shndx: u32,
|
||||
atom_list: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
atom_list: std.ArrayListUnmanaged(Ref) = .{},
|
||||
};
|
||||
const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection);
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
|
||||
|
||||
pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
|
||||
assert(self.flags.thunk);
|
||||
const extras = self.extra(elf_file).?;
|
||||
const extras = self.extra(elf_file);
|
||||
return elf_file.thunk(extras.thunk);
|
||||
}
|
||||
|
||||
@ -99,7 +99,8 @@ pub fn priority(self: Atom, elf_file: *Elf) u64 {
|
||||
/// File offset relocation happens transparently, so it is not included in
|
||||
/// this calculation.
|
||||
pub fn capacity(self: Atom, elf_file: *Elf) u64 {
|
||||
const next_addr = if (elf_file.atom(self.next_index)) |next|
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const next_addr = if (zo.atom(self.next_index)) |next|
|
||||
next.address(elf_file)
|
||||
else
|
||||
std.math.maxInt(u32);
|
||||
@ -107,8 +108,9 @@ pub fn capacity(self: Atom, elf_file: *Elf) u64 {
|
||||
}
|
||||
|
||||
pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
// No need to keep a free list node for the last block.
|
||||
const next = elf_file.atom(self.next_index) orelse return false;
|
||||
const next = zo.atom(self.next_index) orelse return false;
|
||||
const cap: u64 = @intCast(next.address(elf_file) - self.address(elf_file));
|
||||
const ideal_cap = Elf.padToIdeal(self.size);
|
||||
if (cap <= ideal_cap) return false;
|
||||
@ -117,6 +119,7 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
|
||||
}
|
||||
|
||||
pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const shdr = &elf_file.shdrs.items[self.outputShndx().?];
|
||||
const meta = elf_file.last_atom_and_free_list_table.getPtr(self.outputShndx().?).?;
|
||||
const free_list = &meta.free_list;
|
||||
@ -137,7 +140,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
var i: usize = if (elf_file.base.child_pid == null) 0 else free_list.items.len;
|
||||
while (i < free_list.items.len) {
|
||||
const big_atom_index = free_list.items[i];
|
||||
const big_atom = elf_file.atom(big_atom_index).?;
|
||||
const big_atom = zo.atom(big_atom_index).?;
|
||||
// We now have a pointer to a live atom that has too much capacity.
|
||||
// Is it enough that we could fit this new atom?
|
||||
const cap = big_atom.capacity(elf_file);
|
||||
@ -169,7 +172,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
free_list_removal = i;
|
||||
}
|
||||
break :blk @intCast(new_start_vaddr);
|
||||
} else if (elf_file.atom(last_atom_index.*)) |last| {
|
||||
} else if (zo.atom(last_atom_index.*)) |last| {
|
||||
const ideal_capacity = Elf.padToIdeal(last.size);
|
||||
const ideal_capacity_end_vaddr = @as(u64, @intCast(last.value)) + ideal_capacity;
|
||||
const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr);
|
||||
@ -189,7 +192,7 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
});
|
||||
|
||||
const expand_section = if (atom_placement) |placement_index|
|
||||
elf_file.atom(placement_index).?.next_index == 0
|
||||
zo.atom(placement_index).?.next_index == 0
|
||||
else
|
||||
true;
|
||||
if (expand_section) {
|
||||
@ -214,15 +217,15 @@ pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
// This function can also reallocate an atom.
|
||||
// In this case we need to "unplug" it from its previous location before
|
||||
// plugging it in to its new location.
|
||||
if (elf_file.atom(self.prev_index)) |prev| {
|
||||
if (zo.atom(self.prev_index)) |prev| {
|
||||
prev.next_index = self.next_index;
|
||||
}
|
||||
if (elf_file.atom(self.next_index)) |next| {
|
||||
if (zo.atom(self.next_index)) |next| {
|
||||
next.prev_index = self.prev_index;
|
||||
}
|
||||
|
||||
if (atom_placement) |big_atom_index| {
|
||||
const big_atom = elf_file.atom(big_atom_index).?;
|
||||
const big_atom = zo.atom(big_atom_index).?;
|
||||
self.prev_index = big_atom_index;
|
||||
self.next_index = big_atom.next_index;
|
||||
big_atom.next_index = self.atom_index;
|
||||
@ -250,6 +253,7 @@ pub fn grow(self: *Atom, elf_file: *Elf) !void {
|
||||
pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
log.debug("freeAtom {d} ({s})", .{ self.atom_index, self.name(elf_file) });
|
||||
|
||||
const zo = elf_file.zigObjectPtr().?;
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const shndx = self.outputShndx().?;
|
||||
@ -272,9 +276,9 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_file.atom(last_atom_index.*)) |last_atom| {
|
||||
if (zo.atom(last_atom_index.*)) |last_atom| {
|
||||
if (last_atom.atom_index == self.atom_index) {
|
||||
if (elf_file.atom(self.prev_index)) |_| {
|
||||
if (zo.atom(self.prev_index)) |_| {
|
||||
// TODO shrink the section size here
|
||||
last_atom_index.* = self.prev_index;
|
||||
} else {
|
||||
@ -283,7 +287,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
if (elf_file.atom(self.prev_index)) |prev| {
|
||||
if (zo.atom(self.prev_index)) |prev| {
|
||||
prev.next_index = self.next_index;
|
||||
if (!already_have_free_list_node and prev.*.freeListEligible(elf_file)) {
|
||||
// The free list is heuristics, it doesn't have to be perfect, so we can
|
||||
@ -294,7 +298,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
self.prev_index = 0;
|
||||
}
|
||||
|
||||
if (elf_file.atom(self.next_index)) |next| {
|
||||
if (zo.atom(self.next_index)) |next| {
|
||||
next.prev_index = self.prev_index;
|
||||
} else {
|
||||
self.next_index = 0;
|
||||
@ -313,7 +317,7 @@ pub fn relocs(self: Atom, elf_file: *Elf) []const elf.Elf64_Rela {
|
||||
switch (self.file(elf_file).?) {
|
||||
.zig_object => |x| return x.relocs.items[shndx].items,
|
||||
.object => |x| {
|
||||
const extras = self.extra(elf_file).?;
|
||||
const extras = self.extra(elf_file);
|
||||
return x.relocs.items[extras.rel_index..][0..extras.rel_count];
|
||||
},
|
||||
else => unreachable,
|
||||
@ -367,7 +371,7 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
|
||||
|
||||
pub fn fdes(self: Atom, elf_file: *Elf) []Fde {
|
||||
if (!self.flags.fde) return &[0]Fde{};
|
||||
const extras = self.extra(elf_file).?;
|
||||
const extras = self.extra(elf_file);
|
||||
const object = self.file(elf_file).?.object;
|
||||
return object.fdes.items[extras.fde_start..][0..extras.fde_count];
|
||||
}
|
||||
@ -712,9 +716,9 @@ fn reportUndefined(
|
||||
{
|
||||
const gop = try undefs.getOrPut(sym_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = std.ArrayList(Atom.Index).init(gpa);
|
||||
gop.value_ptr.* = std.ArrayList(Elf.Ref).init(gpa);
|
||||
}
|
||||
try gop.value_ptr.append(self.atom_index);
|
||||
try gop.value_ptr.append(.{ .index = self.atom_index, .file = self.file_index });
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1001,25 +1005,23 @@ const AddExtraOpts = struct {
|
||||
rel_count: ?u32 = null,
|
||||
};
|
||||
|
||||
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) !void {
|
||||
if (atom.extra(elf_file) == null) {
|
||||
atom.extra_index = try elf_file.addAtomExtra(.{});
|
||||
}
|
||||
var extras = atom.extra(elf_file).?;
|
||||
pub fn addExtra(atom: *Atom, opts: AddExtraOpts, elf_file: *Elf) void {
|
||||
const file_ptr = atom.file(elf_file).?;
|
||||
var extras = file_ptr.atomExtra(atom.extra_index);
|
||||
inline for (@typeInfo(@TypeOf(opts)).Struct.fields) |field| {
|
||||
if (@field(opts, field.name)) |x| {
|
||||
@field(extras, field.name) = x;
|
||||
}
|
||||
}
|
||||
atom.setExtra(extras, elf_file);
|
||||
file_ptr.setAtomExtra(atom.extra_index, extras);
|
||||
}
|
||||
|
||||
pub inline fn extra(atom: Atom, elf_file: *Elf) ?Extra {
|
||||
return elf_file.atomExtra(atom.extra_index);
|
||||
pub inline fn extra(atom: Atom, elf_file: *Elf) Extra {
|
||||
return atom.file(elf_file).?.atomExtra(atom.extra_index);
|
||||
}
|
||||
|
||||
pub inline fn setExtra(atom: Atom, extras: Extra, elf_file: *Elf) void {
|
||||
elf_file.setAtomExtra(atom.extra_index, extras);
|
||||
atom.file(elf_file).?.setAtomExtra(atom.extra_index, extras);
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
@ -1063,7 +1065,7 @@ fn format2(
|
||||
});
|
||||
if (atom.flags.fde) {
|
||||
try writer.writeAll(" : fdes{ ");
|
||||
const extras = atom.extra(elf_file).?;
|
||||
const extras = atom.extra(elf_file);
|
||||
for (atom.fdes(elf_file), extras.fde_start..) |fde, i| {
|
||||
try writer.print("{d}", .{i});
|
||||
if (!fde.alive) try writer.writeAll("([*])");
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
index: File.Index,
|
||||
|
||||
symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
strtab: std.ArrayListUnmanaged(u8) = .{},
|
||||
symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
@ -11,6 +12,11 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
|
||||
self.symbols.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
|
||||
// Null byte in strtab
|
||||
try self.strtab.append(allocator, 0);
|
||||
}
|
||||
|
||||
pub fn addGlobal(self: *LinkerDefined, name: [:0]const u8, elf_file: *Elf) !u32 {
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
@ -41,7 +47,7 @@ pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {
|
||||
const global = elf_file.symbol(index);
|
||||
if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
|
||||
global.value = 0;
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.file_index = self.index;
|
||||
global.esym_index = sym_idx;
|
||||
global.version_index = elf_file.default_sym_version;
|
||||
@ -127,6 +133,7 @@ const mem = std.mem;
|
||||
const std = @import("std");
|
||||
|
||||
const Allocator = mem.Allocator;
|
||||
const Atom = @import("Atom.zig");
|
||||
const Elf = @import("../Elf.zig");
|
||||
const File = @import("file.zig").File;
|
||||
const LinkerDefined = @This();
|
||||
|
||||
@ -10,9 +10,12 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
strtab: std.ArrayListUnmanaged(u8) = .{},
|
||||
first_global: ?Symbol.Index = null,
|
||||
symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
relocs: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
|
||||
|
||||
atoms: std.ArrayListUnmanaged(Atom) = .{},
|
||||
atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .{},
|
||||
comdat_group_data: std.ArrayListUnmanaged(u32) = .{},
|
||||
|
||||
@ -49,6 +52,8 @@ pub fn deinit(self: *Object, allocator: Allocator) void {
|
||||
self.strtab.deinit(allocator);
|
||||
self.symbols.deinit(allocator);
|
||||
self.atoms.deinit(allocator);
|
||||
self.atoms_indexes.deinit(allocator);
|
||||
self.atoms_extra.deinit(allocator);
|
||||
self.comdat_groups.deinit(allocator);
|
||||
self.comdat_group_data.deinit(allocator);
|
||||
self.relocs.deinit(allocator);
|
||||
@ -71,15 +76,17 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
|
||||
|
||||
// Append null input merge section
|
||||
try self.input_merge_sections.append(gpa, .{});
|
||||
// Allocate atom index 0 to null atom
|
||||
try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) });
|
||||
|
||||
try self.initAtoms(gpa, handle, elf_file);
|
||||
try self.initSymtab(gpa, elf_file);
|
||||
|
||||
for (self.shdrs.items, 0..) |shdr, i| {
|
||||
const atom = elf_file.atom(self.atoms.items[i]) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const atom_ptr = self.atom(self.atoms_indexes.items[i]) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
if ((cpu_arch == .x86_64 and shdr.sh_type == elf.SHT_X86_64_UNWIND) or
|
||||
mem.eql(u8, atom.name(elf_file), ".eh_frame"))
|
||||
mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame"))
|
||||
{
|
||||
try self.parseEhFrame(gpa, handle, @as(u32, @intCast(i)), elf_file);
|
||||
}
|
||||
@ -179,8 +186,11 @@ fn parseCommon(self: *Object, allocator: Allocator, handle: std.fs.File, elf_fil
|
||||
|
||||
fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: *Elf) !void {
|
||||
const shdrs = self.shdrs.items;
|
||||
try self.atoms.resize(allocator, shdrs.len);
|
||||
@memset(self.atoms.items, 0);
|
||||
try self.atoms.ensureTotalCapacityPrecise(allocator, shdrs.len);
|
||||
try self.atoms_extra.ensureTotalCapacityPrecise(allocator, shdrs.len * @sizeOf(Atom.Extra));
|
||||
try self.atoms_indexes.ensureTotalCapacityPrecise(allocator, shdrs.len);
|
||||
try self.atoms_indexes.resize(allocator, shdrs.len);
|
||||
@memset(self.atoms_indexes.items, 0);
|
||||
|
||||
for (shdrs, 0..) |shdr, i| {
|
||||
if (shdr.sh_flags & elf.SHF_EXCLUDE != 0 and
|
||||
@ -242,7 +252,19 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
|
||||
else => {
|
||||
const shndx = @as(u32, @intCast(i));
|
||||
if (self.skipShdr(shndx, elf_file)) continue;
|
||||
try self.addAtom(allocator, handle, shdr, shndx, elf_file);
|
||||
const size, const alignment = if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) blk: {
|
||||
const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
|
||||
defer allocator.free(data);
|
||||
const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
|
||||
break :blk .{ chdr.ch_size, Alignment.fromNonzeroByteUnits(chdr.ch_addralign) };
|
||||
} else .{ shdr.sh_size, Alignment.fromNonzeroByteUnits(shdr.sh_addralign) };
|
||||
const atom_index = self.addAtomAssumeCapacity(.{
|
||||
.name = shdr.sh_name,
|
||||
.shndx = shndx,
|
||||
.size = size,
|
||||
.alignment = alignment,
|
||||
});
|
||||
self.atoms_indexes.items[shndx] = atom_index;
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -250,14 +272,14 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
|
||||
// Parse relocs sections if any.
|
||||
for (shdrs, 0..) |shdr, i| switch (shdr.sh_type) {
|
||||
elf.SHT_REL, elf.SHT_RELA => {
|
||||
const atom_index = self.atoms.items[shdr.sh_info];
|
||||
if (elf_file.atom(atom_index)) |atom| {
|
||||
const atom_index = self.atoms_indexes.items[shdr.sh_info];
|
||||
if (self.atom(atom_index)) |atom_ptr| {
|
||||
const relocs = try self.preadRelocsAlloc(allocator, handle, @intCast(i));
|
||||
defer allocator.free(relocs);
|
||||
atom.relocs_section_index = @intCast(i);
|
||||
atom_ptr.relocs_section_index = @intCast(i);
|
||||
const rel_index: u32 = @intCast(self.relocs.items.len);
|
||||
const rel_count: u32 = @intCast(relocs.len);
|
||||
try atom.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file);
|
||||
atom_ptr.addExtra(.{ .rel_index = rel_index, .rel_count = rel_count }, elf_file);
|
||||
try self.relocs.appendUnalignedSlice(allocator, relocs);
|
||||
if (elf_file.getTarget().cpu.arch == .riscv64) {
|
||||
sortRelocs(self.relocs.items[rel_index..][0..rel_count]);
|
||||
@ -268,27 +290,6 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file:
|
||||
};
|
||||
}
|
||||
|
||||
fn addAtom(self: *Object, allocator: Allocator, handle: std.fs.File, shdr: elf.Elf64_Shdr, shndx: u32, elf_file: *Elf) !void {
|
||||
const atom_index = try elf_file.addAtom();
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
atom.atom_index = atom_index;
|
||||
atom.name_offset = shdr.sh_name;
|
||||
atom.file_index = self.index;
|
||||
atom.input_section_index = shndx;
|
||||
self.atoms.items[shndx] = atom_index;
|
||||
|
||||
if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
|
||||
const data = try self.preadShdrContentsAlloc(allocator, handle, shndx);
|
||||
defer allocator.free(data);
|
||||
const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
|
||||
atom.size = chdr.ch_size;
|
||||
atom.alignment = Alignment.fromNonzeroByteUnits(chdr.ch_addralign);
|
||||
} else {
|
||||
atom.size = shdr.sh_size;
|
||||
atom.alignment = Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
|
||||
}
|
||||
}
|
||||
|
||||
fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u32 {
|
||||
const name = blk: {
|
||||
const name = self.getString(shdr.sh_name);
|
||||
@ -368,8 +369,10 @@ fn initSymtab(self: *Object, allocator: Allocator, elf_file: *Elf) !void {
|
||||
sym_ptr.value = @intCast(sym.st_value);
|
||||
sym_ptr.name_offset = sym.st_name;
|
||||
sym_ptr.esym_index = @as(u32, @intCast(i));
|
||||
sym_ptr.atom_index = if (sym.st_shndx == elf.SHN_ABS) 0 else self.atoms.items[sym.st_shndx];
|
||||
sym_ptr.file_index = self.index;
|
||||
if (sym.st_shndx != elf.SHN_ABS) {
|
||||
sym_ptr.atom_ref = .{ .index = self.atoms_indexes.items[sym.st_shndx], .file = self.index };
|
||||
}
|
||||
}
|
||||
|
||||
for (self.symtab.items[first_global..]) |sym| {
|
||||
@ -456,15 +459,15 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
|
||||
var i: u32 = @as(u32, @intCast(fdes_start));
|
||||
while (i < self.fdes.items.len) {
|
||||
const fde = self.fdes.items[i];
|
||||
const atom = fde.atom(elf_file);
|
||||
const atom_ptr = fde.atom(elf_file);
|
||||
const start = i;
|
||||
i += 1;
|
||||
while (i < self.fdes.items.len) : (i += 1) {
|
||||
const next_fde = self.fdes.items[i];
|
||||
if (atom.atom_index != next_fde.atom(elf_file).atom_index) break;
|
||||
if (atom_ptr.atom_index != next_fde.atom(elf_file).atom_index) break;
|
||||
}
|
||||
try atom.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file);
|
||||
atom.flags.fde = true;
|
||||
atom_ptr.addExtra(.{ .fde_start = start, .fde_count = i - start }, elf_file);
|
||||
atom_ptr.flags.fde = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,19 +510,19 @@ fn filterRelocs(
|
||||
pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
if (atom.scanRelocsRequiresCode(elf_file)) {
|
||||
if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
|
||||
// TODO ideally, we don't have to decompress at this stage (should already be done)
|
||||
// and we just fetch the code slice.
|
||||
const code = try self.codeDecompressAlloc(elf_file, atom_index);
|
||||
defer gpa.free(code);
|
||||
try atom.scanRelocs(elf_file, code, undefs);
|
||||
} else try atom.scanRelocs(elf_file, null, undefs);
|
||||
try atom_ptr.scanRelocs(elf_file, code, undefs);
|
||||
} else try atom_ptr.scanRelocs(elf_file, null, undefs);
|
||||
}
|
||||
|
||||
for (self.cies.items) |cie| {
|
||||
@ -547,19 +550,21 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) void {
|
||||
if (esym.st_shndx == elf.SHN_UNDEF) continue;
|
||||
|
||||
if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
|
||||
const atom_index = self.atoms.items[esym.st_shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const atom_index = self.atoms_indexes.items[esym.st_shndx];
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
}
|
||||
|
||||
const global = elf_file.symbol(index);
|
||||
if (self.asFile().symbolRank(esym, !self.alive) < global.symbolRank(elf_file)) {
|
||||
const atom_index = switch (esym.st_shndx) {
|
||||
elf.SHN_ABS, elf.SHN_COMMON => 0,
|
||||
else => self.atoms.items[esym.st_shndx],
|
||||
};
|
||||
switch (esym.st_shndx) {
|
||||
elf.SHN_ABS, elf.SHN_COMMON => {},
|
||||
else => global.atom_ref = .{
|
||||
.index = self.atoms_indexes.items[esym.st_shndx],
|
||||
.file = self.index,
|
||||
},
|
||||
}
|
||||
global.value = @intCast(esym.st_value);
|
||||
global.atom_index = atom_index;
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
global.version_index = elf_file.default_sym_version;
|
||||
@ -588,7 +593,7 @@ pub fn claimUnresolved(self: *Object, elf_file: *Elf) void {
|
||||
};
|
||||
|
||||
global.value = 0;
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
|
||||
@ -609,7 +614,7 @@ pub fn claimUnresolvedObject(self: *Object, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
global.value = 0;
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
}
|
||||
@ -633,13 +638,13 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markEhFrameAtomsDead(self: Object, elf_file: *Elf) void {
|
||||
pub fn markEhFrameAtomsDead(self: *Object, elf_file: *Elf) void {
|
||||
const cpu_arch = elf_file.getTarget().cpu.arch;
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
const is_eh_frame = (cpu_arch == .x86_64 and atom.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or
|
||||
mem.eql(u8, atom.name(elf_file), ".eh_frame");
|
||||
if (atom.flags.alive and is_eh_frame) atom.flags.alive = false;
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
const is_eh_frame = (cpu_arch == .x86_64 and atom_ptr.inputShdr(elf_file).sh_type == elf.SHT_X86_64_UNWIND) or
|
||||
mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame");
|
||||
if (atom_ptr.flags.alive and is_eh_frame) atom_ptr.flags.alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -657,9 +662,9 @@ pub fn checkDuplicates(self: *Object, dupes: anytype, elf_file: *Elf) error{OutO
|
||||
sym.st_shndx == elf.SHN_COMMON) continue;
|
||||
|
||||
if (sym.st_shndx != elf.SHN_ABS) {
|
||||
const atom_index = self.atoms.items[sym.st_shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const atom_index = self.atoms_indexes.items[sym.st_shndx];
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
}
|
||||
|
||||
const gop = try dupes.getOrPut(index);
|
||||
@ -680,8 +685,8 @@ pub fn initMergeSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.shdrs.items, 0..) |shdr, shndx| {
|
||||
if (shdr.sh_flags & elf.SHF_MERGE == 0) continue;
|
||||
|
||||
const atom_index = self.atoms.items[shndx];
|
||||
const atom_ptr = elf_file.atom(atom_index) orelse continue;
|
||||
const atom_index = self.atoms_indexes.items[shndx];
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
if (atom_ptr.relocs(elf_file).len > 0) continue;
|
||||
|
||||
@ -755,7 +760,7 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
|
||||
const imsec = self.inputMergeSection(index) orelse continue;
|
||||
if (imsec.offsets.items.len == 0) continue;
|
||||
const msec = elf_file.mergeSection(imsec.merge_section_index);
|
||||
const atom_ptr = elf_file.atom(imsec.atom_index).?;
|
||||
const atom_ptr = self.atom(imsec.atom_index).?;
|
||||
const isec = atom_ptr.inputShdr(elf_file);
|
||||
|
||||
try imsec.subsections.resize(gpa, imsec.strings.items.len);
|
||||
@ -802,10 +807,10 @@ pub fn resolveMergeSubsections(self: *Object, elf_file: *Elf) !void {
|
||||
sym.value = offset;
|
||||
}
|
||||
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom_ptr = elf_file.atom(atom_index) orelse continue;
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const extras = atom_ptr.extra(elf_file) orelse continue;
|
||||
const extras = atom_ptr.extra(elf_file);
|
||||
const relocs = self.relocs.items[extras.rel_index..][0..extras.rel_count];
|
||||
for (relocs) |*rel| {
|
||||
const esym = self.symtab.items[rel.r_sym()];
|
||||
@ -867,21 +872,10 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
const atom_index = try elf_file.addAtom();
|
||||
try self.atoms.append(gpa, atom_index);
|
||||
|
||||
const is_tls = global.type(elf_file) == elf.STT_TLS;
|
||||
const name = if (is_tls) ".tls_common" else ".common";
|
||||
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
const name_offset = @as(u32, @intCast(self.strtab.items.len));
|
||||
try self.strtab.writer(gpa).print("{s}\x00", .{name});
|
||||
atom.atom_index = atom_index;
|
||||
atom.name_offset = name_offset;
|
||||
atom.file_index = self.index;
|
||||
atom.size = this_sym.st_size;
|
||||
const alignment = this_sym.st_value;
|
||||
atom.alignment = Alignment.fromNonzeroByteUnits(alignment);
|
||||
|
||||
var sh_flags: u32 = elf.SHF_ALLOC | elf.SHF_WRITE;
|
||||
if (is_tls) sh_flags |= elf.SHF_TLS;
|
||||
@ -897,38 +891,45 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
|
||||
.sh_size = sh_size,
|
||||
.sh_link = 0,
|
||||
.sh_info = 0,
|
||||
.sh_addralign = alignment,
|
||||
.sh_addralign = this_sym.st_value,
|
||||
.sh_entsize = 0,
|
||||
};
|
||||
atom.input_section_index = shndx;
|
||||
|
||||
const atom_index = try self.addAtom(gpa, .{
|
||||
.name = name_offset,
|
||||
.shndx = shndx,
|
||||
.size = this_sym.st_size,
|
||||
.alignment = Alignment.fromNonzeroByteUnits(this_sym.st_value),
|
||||
});
|
||||
try self.atoms_indexes.append(gpa, atom_index);
|
||||
|
||||
global.value = 0;
|
||||
global.atom_index = atom_index;
|
||||
global.atom_ref = .{ .index = atom_index, .file = self.index };
|
||||
global.flags.weak = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initOutputSections(self: Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
pub fn initOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
_ = try self.initOutputSection(elf_file, shdr);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
atom.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
atom_ptr.output_section_index = self.initOutputSection(elf_file, shdr) catch unreachable;
|
||||
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const gop = try elf_file.output_sections.getOrPut(gpa, atom.output_section_index);
|
||||
const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(gpa, atom_index);
|
||||
try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index });
|
||||
}
|
||||
|
||||
for (self.locals()) |local_index| {
|
||||
@ -938,9 +939,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
local.output_section_index = msub.mergeSection(elf_file).output_section_index;
|
||||
continue;
|
||||
}
|
||||
const atom = local.atom(elf_file) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
local.output_section_index = atom.output_section_index;
|
||||
const atom_ptr = local.atom(elf_file) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
local.output_section_index = atom_ptr.output_section_index;
|
||||
}
|
||||
|
||||
for (self.globals()) |global_index| {
|
||||
@ -951,9 +952,9 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
global.output_section_index = msub.mergeSection(elf_file).output_section_index;
|
||||
continue;
|
||||
}
|
||||
const atom = global.atom(elf_file) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
global.output_section_index = atom.output_section_index;
|
||||
const atom_ptr = global.atom(elf_file) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
global.output_section_index = atom_ptr.output_section_index;
|
||||
}
|
||||
|
||||
for (self.symbols.items[self.symtab.items.len..]) |local_index| {
|
||||
@ -964,11 +965,11 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shndx = atom.relocsShndx() orelse continue;
|
||||
pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shndx = atom_ptr.relocsShndx() orelse continue;
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
const out_shndx = try self.initOutputSection(elf_file, shdr);
|
||||
const out_shdr = &elf_file.shdrs.items[out_shndx];
|
||||
@ -978,24 +979,24 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shndx = blk: {
|
||||
const shndx = atom.relocsShndx() orelse continue;
|
||||
const shndx = atom_ptr.relocsShndx() orelse continue;
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
break :blk self.initOutputSection(elf_file, shdr) catch unreachable;
|
||||
};
|
||||
const shdr = &elf_file.shdrs.items[shndx];
|
||||
shdr.sh_info = atom.outputShndx().?;
|
||||
shdr.sh_info = atom_ptr.outputShndx().?;
|
||||
shdr.sh_link = elf_file.symtab_section_index.?;
|
||||
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom.outputShndx().?);
|
||||
const gop = try elf_file.output_rela_sections.getOrPut(gpa, atom_ptr.outputShndx().?);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{ .shndx = shndx };
|
||||
try gop.value_ptr.atom_list.append(gpa, atom_index);
|
||||
try gop.value_ptr.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1129,11 +1130,10 @@ pub fn globals(self: Object) []const Symbol.Index {
|
||||
|
||||
/// Returns atom's code and optionally uncompresses data if required (for compressed sections).
|
||||
/// Caller owns the memory.
|
||||
pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
|
||||
pub fn codeDecompressAlloc(self: *Object, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
const atom_ptr = elf_file.atom(atom_index).?;
|
||||
assert(atom_ptr.file_index == self.index);
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
const handle = elf_file.fileHandle(self.file_handle);
|
||||
const data = try self.preadShdrContentsAlloc(gpa, handle, atom_ptr.input_section_index);
|
||||
@ -1194,6 +1194,82 @@ fn preadRelocsAlloc(self: Object, allocator: Allocator, handle: std.fs.File, shn
|
||||
return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];
|
||||
}
|
||||
|
||||
const AddAtomArgs = struct {
|
||||
name: u32,
|
||||
shndx: u32,
|
||||
size: u64,
|
||||
alignment: Alignment,
|
||||
};
|
||||
|
||||
fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index {
|
||||
try self.atoms.ensureUnusedCapacity(allocator, 1);
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
|
||||
return self.addAtomAssumeCapacity(args);
|
||||
}
|
||||
|
||||
fn addAtomAssumeCapacity(self: *Object, args: AddAtomArgs) Atom.Index {
|
||||
const atom_index: Atom.Index = @intCast(self.atoms.items.len);
|
||||
const atom_ptr = self.atoms.addOneAssumeCapacity();
|
||||
atom_ptr.* = .{
|
||||
.atom_index = atom_index,
|
||||
.name_offset = args.name,
|
||||
.file_index = self.index,
|
||||
.input_section_index = args.shndx,
|
||||
.extra_index = self.addAtomExtraAssumeCapacity(.{}),
|
||||
.size = args.size,
|
||||
.alignment = args.alignment,
|
||||
};
|
||||
return atom_index;
|
||||
}
|
||||
|
||||
pub fn atom(self: *Object, atom_index: Atom.Index) ?*Atom {
|
||||
if (atom_index == 0) return null;
|
||||
assert(atom_index < self.atoms.items.len);
|
||||
return &self.atoms.items[atom_index];
|
||||
}
|
||||
|
||||
pub fn addAtomExtra(self: *Object, allocator: Allocator, extra: Atom.Extra) !u32 {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
|
||||
return self.addAtomExtraAssumeCapacity(extra);
|
||||
}
|
||||
|
||||
pub fn addAtomExtraAssumeCapacity(self: *Object, extra: Atom.Extra) u32 {
|
||||
const index = @as(u32, @intCast(self.atoms_extra.items.len));
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields) |field| {
|
||||
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn atomExtra(self: *Object, index: u32) Atom.Extra {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
var i: usize = index;
|
||||
var result: Atom.Extra = undefined;
|
||||
inline for (fields) |field| {
|
||||
@field(result, field.name) = switch (field.type) {
|
||||
u32 => self.atoms_extra.items[i],
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn setAtomExtra(self: *Object, index: u32, extra: Atom.Extra) void {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields, 0..) |field, i| {
|
||||
self.atoms_extra.items[index + i] = switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {
|
||||
const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);
|
||||
const msec = try self.input_merge_sections.addOne(allocator);
|
||||
@ -1280,9 +1356,9 @@ fn formatAtoms(
|
||||
_ = options;
|
||||
const object = ctx.object;
|
||||
try writer.writeAll(" atoms\n");
|
||||
for (object.atoms.items) |atom_index| {
|
||||
const atom = ctx.elf_file.atom(atom_index) orelse continue;
|
||||
try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});
|
||||
for (object.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = object.atom(atom_index) orelse continue;
|
||||
try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -1354,9 +1430,9 @@ fn formatComdatGroups(
|
||||
try writer.print(" COMDAT({d})\n", .{cg_index});
|
||||
const cg_members = cg.comdatGroupMembers(elf_file);
|
||||
for (cg_members) |shndx| {
|
||||
const atom_index = object.atoms.items[shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });
|
||||
const atom_index = object.atoms_indexes.items[shndx];
|
||||
const atom_ptr = object.atom(atom_index) orelse continue;
|
||||
try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +232,7 @@ pub fn resolveSymbols(self: *SharedObject, elf_file: *Elf) void {
|
||||
const global = elf_file.symbol(index);
|
||||
if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {
|
||||
global.value = @intCast(this_sym.st_value);
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.version_index = self.versyms.items[esym_index];
|
||||
global.file_index = self.index;
|
||||
|
||||
@ -9,10 +9,9 @@ name_offset: u32 = 0,
|
||||
/// Index of file where this symbol is defined.
|
||||
file_index: File.Index = 0,
|
||||
|
||||
/// Index of atom containing this symbol.
|
||||
/// Index of 0 means there is no associated atom with this symbol.
|
||||
/// Reference to Atom containing this symbol if any.
|
||||
/// Use `atom` to get the pointer to the atom.
|
||||
atom_index: Atom.Index = 0,
|
||||
atom_ref: Elf.Ref = .{ .index = 0, .file = 0 },
|
||||
|
||||
/// Assigned output section index for this symbol.
|
||||
output_section_index: u32 = 0,
|
||||
@ -68,7 +67,8 @@ pub fn name(symbol: Symbol, elf_file: *Elf) [:0]const u8 {
|
||||
}
|
||||
|
||||
pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
|
||||
return elf_file.atom(symbol.atom_index);
|
||||
const file_ptr = elf_file.file(symbol.atom_ref.file) orelse return null;
|
||||
return file_ptr.atom(symbol.atom_ref.index);
|
||||
}
|
||||
|
||||
pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {
|
||||
|
||||
@ -15,7 +15,9 @@ local_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
global_symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
|
||||
globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
|
||||
|
||||
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
atoms: std.ArrayListUnmanaged(Atom) = .{},
|
||||
atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
atoms_extra: std.ArrayListUnmanaged(u32) = .{},
|
||||
relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
|
||||
|
||||
num_dynrelocs: u32 = 0,
|
||||
@ -80,7 +82,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf) !void {
|
||||
const comp = elf_file.base.comp;
|
||||
const gpa = comp.gpa;
|
||||
|
||||
try self.atoms.append(gpa, 0); // null input section
|
||||
try self.atoms.append(gpa, .{ .extra_index = try self.addAtomExtra(gpa, .{}) }); // null input section
|
||||
try self.relocs.append(gpa, .{}); // null relocs section
|
||||
try self.strtab.buffer.append(gpa, 0);
|
||||
|
||||
@ -117,6 +119,8 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
|
||||
self.global_symbols.deinit(allocator);
|
||||
self.globals_lookup.deinit(allocator);
|
||||
self.atoms.deinit(allocator);
|
||||
self.atoms_indexes.deinit(allocator);
|
||||
self.atoms_extra.deinit(allocator);
|
||||
for (self.relocs.items) |*list| {
|
||||
list.deinit(allocator);
|
||||
}
|
||||
@ -276,24 +280,20 @@ pub fn addGlobalEsym(self: *ZigObject, allocator: Allocator) !Symbol.Index {
|
||||
return index | global_symbol_bit;
|
||||
}
|
||||
|
||||
pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
|
||||
pub fn newAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
const atom_index = try elf_file.addAtom();
|
||||
const atom_index = try self.addAtom(gpa);
|
||||
const symbol_index = try elf_file.addSymbol();
|
||||
const esym_index = try self.addLocalEsym(gpa);
|
||||
|
||||
const shndx = @as(u32, @intCast(self.atoms.items.len));
|
||||
try self.atoms.append(gpa, atom_index);
|
||||
try self.atoms_indexes.append(gpa, atom_index);
|
||||
try self.local_symbols.append(gpa, symbol_index);
|
||||
|
||||
const atom_ptr = elf_file.atom(atom_index).?;
|
||||
atom_ptr.file_index = self.index;
|
||||
|
||||
const symbol_ptr = elf_file.symbol(symbol_index);
|
||||
symbol_ptr.file_index = self.index;
|
||||
symbol_ptr.atom_index = atom_index;
|
||||
symbol_ptr.atom_ref = .{ .index = atom_index, .file = self.index };
|
||||
|
||||
self.local_esyms.items(.shndx)[esym_index] = shndx;
|
||||
self.local_esyms.items(.shndx)[esym_index] = atom_index;
|
||||
self.local_esyms.items(.elf_sym)[esym_index].st_shndx = SHN_ATOM;
|
||||
symbol_ptr.esym_index = esym_index;
|
||||
|
||||
@ -301,21 +301,22 @@ pub fn addAtom(self: *ZigObject, elf_file: *Elf) !Symbol.Index {
|
||||
const relocs_index = @as(u32, @intCast(self.relocs.items.len));
|
||||
const relocs = try self.relocs.addOne(gpa);
|
||||
relocs.* = .{};
|
||||
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
atom_ptr.relocs_section_index = relocs_index;
|
||||
|
||||
return symbol_index;
|
||||
}
|
||||
|
||||
/// TODO actually create fake input shdrs and return that instead.
|
||||
pub fn inputShdr(self: ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {
|
||||
_ = self;
|
||||
const atom = elf_file.atom(atom_index) orelse return Elf.null_shdr;
|
||||
const shndx = atom.outputShndx() orelse return Elf.null_shdr;
|
||||
pub fn inputShdr(self: *ZigObject, atom_index: Atom.Index, elf_file: *Elf) elf.Elf64_Shdr {
|
||||
const atom_ptr = self.atom(atom_index) orelse return Elf.null_shdr;
|
||||
const shndx = atom_ptr.outputShndx() orelse return Elf.null_shdr;
|
||||
var shdr = elf_file.shdrs.items[shndx];
|
||||
shdr.sh_addr = 0;
|
||||
shdr.sh_offset = 0;
|
||||
shdr.sh_size = atom.size;
|
||||
shdr.sh_addralign = atom.alignment.toByteUnits() orelse 1;
|
||||
shdr.sh_size = atom_ptr.size;
|
||||
shdr.sh_addralign = atom_ptr.alignment.toByteUnits() orelse 1;
|
||||
return shdr;
|
||||
}
|
||||
|
||||
@ -329,24 +330,23 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
|
||||
|
||||
if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) {
|
||||
assert(esym.st_shndx == SHN_ATOM);
|
||||
const atom_index = self.atoms.items[shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const atom_ptr = self.atom(shndx) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
}
|
||||
|
||||
const global = elf_file.symbol(index);
|
||||
if (self.asFile().symbolRank(esym, false) < global.symbolRank(elf_file)) {
|
||||
const atom_index = switch (esym.st_shndx) {
|
||||
elf.SHN_ABS, elf.SHN_COMMON => 0,
|
||||
SHN_ATOM => self.atoms.items[shndx],
|
||||
SHN_ATOM => shndx,
|
||||
else => unreachable,
|
||||
};
|
||||
const output_section_index = if (elf_file.atom(atom_index)) |atom|
|
||||
atom.outputShndx().?
|
||||
const output_section_index = if (self.atom(atom_index)) |atom_ptr|
|
||||
atom_ptr.outputShndx().?
|
||||
else
|
||||
elf.SHN_UNDEF;
|
||||
global.value = @intCast(esym.st_value);
|
||||
global.atom_index = atom_index;
|
||||
global.atom_ref = .{ .index = atom_index, .file = self.index };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
global.output_section_index = output_section_index;
|
||||
@ -376,7 +376,7 @@ pub fn claimUnresolved(self: ZigObject, elf_file: *Elf) void {
|
||||
};
|
||||
|
||||
global.value = 0;
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
global.version_index = if (is_import) elf.VER_NDX_LOCAL else elf_file.default_sym_version;
|
||||
@ -397,7 +397,7 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
|
||||
}
|
||||
|
||||
global.value = 0;
|
||||
global.atom_index = 0;
|
||||
global.atom_ref = .{ .index = 0, .file = 0 };
|
||||
global.esym_index = esym_index;
|
||||
global.file_index = self.index;
|
||||
}
|
||||
@ -405,19 +405,19 @@ pub fn claimUnresolvedObject(self: ZigObject, elf_file: *Elf) void {
|
||||
|
||||
pub fn scanRelocs(self: *ZigObject, elf_file: *Elf, undefs: anytype) !void {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
if (atom.scanRelocsRequiresCode(elf_file)) {
|
||||
if (atom_ptr.scanRelocsRequiresCode(elf_file)) {
|
||||
// TODO ideally we don't have to fetch the code here.
|
||||
// Perhaps it would make sense to save the code until flushModule where we
|
||||
// would free all of generated code?
|
||||
const code = try self.codeAlloc(elf_file, atom_index);
|
||||
defer gpa.free(code);
|
||||
try atom.scanRelocs(elf_file, code, undefs);
|
||||
} else try atom.scanRelocs(elf_file, null, undefs);
|
||||
try atom_ptr.scanRelocs(elf_file, code, undefs);
|
||||
} else try atom_ptr.scanRelocs(elf_file, null, undefs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,9 +450,8 @@ pub fn checkDuplicates(self: *ZigObject, dupes: anytype, elf_file: *Elf) error{O
|
||||
esym.st_shndx == elf.SHN_COMMON) continue;
|
||||
|
||||
if (esym.st_shndx == SHN_ATOM) {
|
||||
const atom_index = self.atoms.items[shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const atom_ptr = self.atom(shndx) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
}
|
||||
|
||||
const gop = try dupes.getOrPut(index);
|
||||
@ -517,20 +516,20 @@ pub fn writeAr(self: ZigObject, writer: anytype) !void {
|
||||
try writer.writeAll(self.data.items);
|
||||
}
|
||||
|
||||
pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
const rela_shndx = atom.relocsShndx() orelse continue;
|
||||
pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
|
||||
for (self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = self.atom(atom_index) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const rela_shndx = atom_ptr.relocsShndx() orelse continue;
|
||||
// TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
|
||||
if (self.relocs.items[rela_shndx].items.len == 0) continue;
|
||||
const out_shndx = atom.outputShndx().?;
|
||||
const out_shndx = atom_ptr.outputShndx().?;
|
||||
const out_shdr = elf_file.shdrs.items[out_shndx];
|
||||
if (out_shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
const sec = elf_file.output_rela_sections.getPtr(out_shndx).?;
|
||||
try sec.atom_list.append(gpa, atom_index);
|
||||
try sec.atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
|
||||
}
|
||||
}
|
||||
|
||||
@ -561,7 +560,7 @@ pub fn globals(self: ZigObject) []const Symbol.Index {
|
||||
pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
|
||||
for (self.locals()) |local_index| {
|
||||
const local = elf_file.symbol(local_index);
|
||||
if (local.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
|
||||
if (local.atom(elf_file)) |atom_ptr| if (!atom_ptr.flags.alive) continue;
|
||||
const esym = local.elfSym(elf_file);
|
||||
switch (esym.st_type()) {
|
||||
elf.STT_SECTION, elf.STT_NOTYPE => continue,
|
||||
@ -577,7 +576,7 @@ pub fn updateSymtabSize(self: *ZigObject, elf_file: *Elf) !void {
|
||||
const global = elf_file.symbol(global_index);
|
||||
const file_ptr = global.file(elf_file) orelse continue;
|
||||
if (file_ptr.index() != self.index) continue;
|
||||
if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
|
||||
if (global.atom(elf_file)) |atom_ptr| if (!atom_ptr.flags.alive) continue;
|
||||
global.flags.output_symtab = true;
|
||||
if (global.isLocal(elf_file)) {
|
||||
try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
|
||||
@ -621,11 +620,10 @@ pub fn asFile(self: *ZigObject) File {
|
||||
|
||||
/// Returns atom's code.
|
||||
/// Caller owns the memory.
|
||||
pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
|
||||
pub fn codeAlloc(self: *ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8 {
|
||||
const gpa = elf_file.base.comp.gpa;
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
assert(atom.file_index == self.index);
|
||||
const shdr = &elf_file.shdrs.items[atom.outputShndx().?];
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const shdr = &elf_file.shdrs.items[atom_ptr.outputShndx().?];
|
||||
|
||||
if (shdr.sh_flags & elf.SHF_TLS != 0) {
|
||||
const tlv = self.tls_variables.get(atom_index).?;
|
||||
@ -633,13 +631,13 @@ pub fn codeAlloc(self: ZigObject, elf_file: *Elf, atom_index: Atom.Index) ![]u8
|
||||
return code;
|
||||
}
|
||||
|
||||
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom.value));
|
||||
const size = std.math.cast(usize, atom.size) orelse return error.Overflow;
|
||||
const file_offset = shdr.sh_offset + @as(u64, @intCast(atom_ptr.value));
|
||||
const size = std.math.cast(usize, atom_ptr.size) orelse return error.Overflow;
|
||||
const code = try gpa.alloc(u8, size);
|
||||
errdefer gpa.free(code);
|
||||
const amt = try elf_file.base.file.?.preadAll(code, file_offset);
|
||||
if (amt != code.len) {
|
||||
log.err("fetching code for {s} failed", .{atom.name(elf_file)});
|
||||
log.err("fetching code for {s} failed", .{atom_ptr.name(elf_file)});
|
||||
return error.InputOutput;
|
||||
}
|
||||
return code;
|
||||
@ -760,7 +758,7 @@ pub fn getOrCreateMetadataForLazySymbol(
|
||||
};
|
||||
switch (metadata.state.*) {
|
||||
.unused => {
|
||||
const symbol_index = try self.addAtom(elf_file);
|
||||
const symbol_index = try self.newAtom(elf_file);
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
sym.flags.needs_zig_got = true;
|
||||
metadata.symbol_index.* = symbol_index;
|
||||
@ -824,7 +822,7 @@ pub fn getOrCreateMetadataForDecl(
|
||||
const gop = try self.decls.getOrPut(gpa, decl_index);
|
||||
if (!gop.found_existing) {
|
||||
const any_non_single_threaded = elf_file.base.comp.config.any_non_single_threaded;
|
||||
const symbol_index = try self.addAtom(elf_file);
|
||||
const symbol_index = try self.newAtom(elf_file);
|
||||
const mod = elf_file.base.comp.module.?;
|
||||
const decl = mod.declPtr(decl_index);
|
||||
const sym = elf_file.symbol(symbol_index);
|
||||
@ -1048,7 +1046,7 @@ fn updateTlv(
|
||||
{
|
||||
const gop = try elf_file.output_sections.getOrPut(gpa, atom_ptr.output_section_index);
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
try gop.value_ptr.append(gpa, atom_ptr.atom_index);
|
||||
try gop.value_ptr.append(gpa, .{ .index = atom_ptr.atom_index, .file = self.index });
|
||||
}
|
||||
}
|
||||
|
||||
@ -1307,8 +1305,7 @@ pub fn lowerUnnamedConst(
|
||||
return error.CodegenFail;
|
||||
},
|
||||
};
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
try unnamed_consts.append(gpa, sym.atom_index);
|
||||
try unnamed_consts.append(gpa, sym_index);
|
||||
return sym_index;
|
||||
}
|
||||
|
||||
@ -1332,7 +1329,7 @@ fn lowerConst(
|
||||
var code_buffer = std.ArrayList(u8).init(gpa);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
const sym_index = try self.addAtom(elf_file);
|
||||
const sym_index = try self.newAtom(elf_file);
|
||||
|
||||
const res = try codegen.generateSymbol(
|
||||
&elf_file.base,
|
||||
@ -1530,6 +1527,72 @@ pub fn getString(self: ZigObject, off: u32) [:0]const u8 {
|
||||
return self.strtab.getAssumeExists(off);
|
||||
}
|
||||
|
||||
fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
|
||||
try self.atoms.ensureUnusedCapacity(allocator, 1);
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
|
||||
return self.addAtomAssumeCapacity();
|
||||
}
|
||||
|
||||
fn addAtomAssumeCapacity(self: *ZigObject) Atom.Index {
|
||||
const atom_index: Atom.Index = @intCast(self.atoms.items.len);
|
||||
const atom_ptr = self.atoms.addOneAssumeCapacity();
|
||||
atom_ptr.* = .{
|
||||
.file_index = self.index,
|
||||
.atom_index = atom_index,
|
||||
.extra_index = self.addAtomExtraAssumeCapacity(.{}),
|
||||
};
|
||||
return atom_index;
|
||||
}
|
||||
|
||||
pub fn atom(self: *ZigObject, atom_index: Atom.Index) ?*Atom {
|
||||
if (atom_index == 0) return null;
|
||||
assert(atom_index < self.atoms.items.len);
|
||||
return &self.atoms.items[atom_index];
|
||||
}
|
||||
|
||||
fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
|
||||
return self.addAtomExtraAssumeCapacity(extra);
|
||||
}
|
||||
|
||||
fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 {
|
||||
const index = @as(u32, @intCast(self.atoms_extra.items.len));
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields) |field| {
|
||||
self.atoms_extra.appendAssumeCapacity(switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
});
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
pub fn atomExtra(self: ZigObject, index: u32) Atom.Extra {
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
var i: usize = index;
|
||||
var result: Atom.Extra = undefined;
|
||||
inline for (fields) |field| {
|
||||
@field(result, field.name) = switch (field.type) {
|
||||
u32 => self.atoms_extra.items[i],
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
|
||||
assert(index > 0);
|
||||
const fields = @typeInfo(Atom.Extra).Struct.fields;
|
||||
inline for (fields, 0..) |field, i| {
|
||||
self.atoms_extra.items[index + i] = switch (field.type) {
|
||||
u32 => @field(extra, field.name),
|
||||
else => @compileError("bad field type"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fmtSymtab(self: *ZigObject, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
|
||||
return .{ .data = .{
|
||||
.self = self,
|
||||
@ -1578,9 +1641,9 @@ fn formatAtoms(
|
||||
_ = unused_fmt_string;
|
||||
_ = options;
|
||||
try writer.writeAll(" atoms\n");
|
||||
for (ctx.self.atoms.items) |atom_index| {
|
||||
const atom = ctx.elf_file.atom(atom_index) orelse continue;
|
||||
try writer.print(" {}\n", .{atom.fmt(ctx.elf_file)});
|
||||
for (ctx.self.atoms_indexes.items) |atom_index| {
|
||||
const atom_ptr = ctx.self.atom(atom_index) orelse continue;
|
||||
try writer.print(" {}\n", .{atom_ptr.fmt(ctx.elf_file)});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -42,8 +42,8 @@ pub const Fde = struct {
|
||||
const object = elf_file.file(fde.file_index).?.object;
|
||||
const rel = fde.relocs(elf_file)[0];
|
||||
const sym = object.symtab.items[rel.r_sym()];
|
||||
const atom_index = object.atoms.items[sym.st_shndx];
|
||||
return elf_file.atom(atom_index).?;
|
||||
const atom_index = object.atoms_indexes.items[sym.st_shndx];
|
||||
return object.atom(atom_index).?;
|
||||
}
|
||||
|
||||
pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
|
||||
|
||||
@ -98,11 +98,34 @@ pub const File = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn atom(file: File, atom_index: Atom.Index) ?*Atom {
|
||||
return switch (file) {
|
||||
.shared_object => unreachable,
|
||||
.linker_defined => null,
|
||||
inline else => |x| x.atom(atom_index),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn atoms(file: File) []const Atom.Index {
|
||||
return switch (file) {
|
||||
.linker_defined, .shared_object => &[0]Atom.Index{},
|
||||
.zig_object => |x| x.atoms.items,
|
||||
.object => |x| x.atoms.items,
|
||||
.shared_object => unreachable,
|
||||
.linker_defined => &[0]Atom.Index{},
|
||||
.zig_object => |x| x.atoms_indexes.items,
|
||||
.object => |x| x.atoms_indexes.items,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn atomExtra(file: File, extra_index: u32) Atom.Extra {
|
||||
return switch (file) {
|
||||
.shared_object, .linker_defined => unreachable,
|
||||
inline else => |x| x.atomExtra(extra_index),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setAtomExtra(file: File, extra_index: u32, extra: Atom.Extra) void {
|
||||
return switch (file) {
|
||||
.shared_object, .linker_defined => unreachable,
|
||||
inline else => |x| x.setAtomExtra(extra_index, extra),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ fn collectRoots(roots: *std.ArrayList(*Atom), files: []const File.Index, elf_fil
|
||||
const file = elf_file.file(index).?;
|
||||
|
||||
for (file.atoms()) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
const atom = file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
@ -120,8 +120,9 @@ fn mark(roots: std.ArrayList(*Atom), elf_file: *Elf) void {
|
||||
|
||||
fn prune(files: []const File.Index, elf_file: *Elf) void {
|
||||
for (files) |index| {
|
||||
for (elf_file.file(index).?.atoms()) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
const file = elf_file.file(index).?;
|
||||
for (file.atoms()) |atom_index| {
|
||||
const atom = file.atom(atom_index) orelse continue;
|
||||
if (atom.flags.alive and !atom.flags.visited) {
|
||||
atom.flags.alive = false;
|
||||
atom.markFdesDead(elf_file);
|
||||
@ -133,8 +134,9 @@ fn prune(files: []const File.Index, elf_file: *Elf) void {
|
||||
pub fn dumpPrunedAtoms(elf_file: *Elf) !void {
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
for (elf_file.objects.items) |index| {
|
||||
for (elf_file.file(index).?.object.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
const file = elf_file.file(index).?;
|
||||
for (file.atoms()) |atom_index| {
|
||||
const atom = file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive)
|
||||
// TODO should we simply print to stderr?
|
||||
try stderr.print("link: removing unused section '{s}' in file '{}'\n", .{
|
||||
|
||||
@ -341,8 +341,8 @@ fn initComdatGroups(elf_file: *Elf) !void {
|
||||
fn updateSectionSizes(elf_file: *Elf) !void {
|
||||
for (elf_file.output_sections.keys(), elf_file.output_sections.values()) |shndx, atom_list| {
|
||||
const shdr = &elf_file.shdrs.items[shndx];
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = elf_file.atom(atom_index) orelse continue;
|
||||
for (atom_list.items) |ref| {
|
||||
const atom_ptr = elf_file.atom(ref) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const offset = atom_ptr.alignment.forward(shdr.sh_size);
|
||||
const padding = offset - shdr.sh_size;
|
||||
@ -354,8 +354,8 @@ fn updateSectionSizes(elf_file: *Elf) !void {
|
||||
|
||||
for (elf_file.output_rela_sections.values()) |sec| {
|
||||
const shdr = &elf_file.shdrs.items[sec.shndx];
|
||||
for (sec.atom_list.items) |atom_index| {
|
||||
const atom_ptr = elf_file.atom(atom_index) orelse continue;
|
||||
for (sec.atom_list.items) |ref| {
|
||||
const atom_ptr = elf_file.atom(ref) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
const relocs = atom_ptr.relocs(elf_file);
|
||||
shdr.sh_size += shdr.sh_entsize * relocs.len;
|
||||
@ -448,16 +448,16 @@ fn writeAtoms(elf_file: *Elf) !void {
|
||||
0;
|
||||
@memset(buffer, padding_byte);
|
||||
|
||||
for (atom_list.items) |atom_index| {
|
||||
const atom_ptr = elf_file.atom(atom_index).?;
|
||||
for (atom_list.items) |ref| {
|
||||
const atom_ptr = elf_file.atom(ref).?;
|
||||
assert(atom_ptr.flags.alive);
|
||||
|
||||
const offset = math.cast(usize, atom_ptr.value - @as(i64, @intCast(shdr.sh_addr - base_offset))) orelse
|
||||
return error.Overflow;
|
||||
const size = math.cast(usize, atom_ptr.size) orelse return error.Overflow;
|
||||
|
||||
log.debug("writing atom({d}) from 0x{x} to 0x{x}", .{
|
||||
atom_index,
|
||||
log.debug("writing atom({}) from 0x{x} to 0x{x}", .{
|
||||
ref,
|
||||
sh_offset + offset,
|
||||
sh_offset + offset + size,
|
||||
});
|
||||
@ -465,8 +465,8 @@ fn writeAtoms(elf_file: *Elf) !void {
|
||||
// TODO decompress directly into provided buffer
|
||||
const out_code = buffer[offset..][0..size];
|
||||
const in_code = switch (atom_ptr.file(elf_file).?) {
|
||||
.object => |x| try x.codeDecompressAlloc(elf_file, atom_index),
|
||||
.zig_object => |x| try x.codeAlloc(elf_file, atom_index),
|
||||
.object => |x| try x.codeDecompressAlloc(elf_file, ref.index),
|
||||
.zig_object => |x| try x.codeAlloc(elf_file, ref.index),
|
||||
else => unreachable,
|
||||
};
|
||||
defer gpa.free(in_code);
|
||||
@ -490,8 +490,8 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
|
||||
var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);
|
||||
defer relocs.deinit();
|
||||
|
||||
for (sec.atom_list.items) |atom_index| {
|
||||
const atom_ptr = elf_file.atom(atom_index) orelse continue;
|
||||
for (sec.atom_list.items) |ref| {
|
||||
const atom_ptr = elf_file.atom(ref) orelse continue;
|
||||
if (!atom_ptr.flags.alive) continue;
|
||||
try atom_ptr.writeRelocs(elf_file, &relocs);
|
||||
}
|
||||
|
||||
@ -1705,14 +1705,14 @@ pub const ComdatGroupSection = struct {
|
||||
const shdr = object.shdrs.items[shndx];
|
||||
switch (shdr.sh_type) {
|
||||
elf.SHT_RELA => {
|
||||
const atom_index = object.atoms.items[shdr.sh_info];
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
const atom_index = object.atoms_indexes.items[shdr.sh_info];
|
||||
const atom = object.atom(atom_index).?;
|
||||
const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;
|
||||
try writer.writeInt(u32, rela.shndx, .little);
|
||||
},
|
||||
else => {
|
||||
const atom_index = object.atoms.items[shndx];
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
const atom_index = object.atoms_indexes.items[shndx];
|
||||
const atom = object.atom(atom_index).?;
|
||||
try writer.writeInt(u32, atom.outputShndx().?, .little);
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,8 +6,8 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
|
||||
const atoms = elf_file.output_sections.get(shndx).?.items;
|
||||
assert(atoms.len > 0);
|
||||
|
||||
for (atoms) |atom_index| {
|
||||
elf_file.atom(atom_index).?.value = -1;
|
||||
for (atoms) |ref| {
|
||||
elf_file.atom(ref).?.value = -1;
|
||||
}
|
||||
|
||||
var i: usize = 0;
|
||||
@ -19,8 +19,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
|
||||
i += 1;
|
||||
|
||||
while (i < atoms.len) : (i += 1) {
|
||||
const atom_index = atoms[i];
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
const atom = elf_file.atom(atoms[i]).?;
|
||||
assert(atom.flags.alive);
|
||||
if (@as(i64, @intCast(atom.alignment.forward(shdr.sh_size))) - start_atom.value >= max_distance)
|
||||
break;
|
||||
@ -33,10 +32,10 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
|
||||
thunk.output_section_index = shndx;
|
||||
|
||||
// Scan relocs in the group and create trampolines for any unreachable callsite
|
||||
for (atoms[start..i]) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
for (atoms[start..i]) |ref| {
|
||||
const atom = elf_file.atom(ref).?;
|
||||
const file = atom.file(elf_file).?;
|
||||
log.debug("atom({d}) {s}", .{ atom_index, atom.name(elf_file) });
|
||||
log.debug("atom({}) {s}", .{ ref, atom.name(elf_file) });
|
||||
for (atom.relocs(elf_file)) |rel| {
|
||||
const is_reachable = switch (cpu_arch) {
|
||||
.aarch64 => aarch64.isReachable(atom, rel, elf_file),
|
||||
@ -51,7 +50,7 @@ pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
|
||||
};
|
||||
try thunk.symbols.put(gpa, target, {});
|
||||
}
|
||||
try atom.addExtra(.{ .thunk = thunk_index }, elf_file);
|
||||
atom.addExtra(.{ .thunk = thunk_index }, elf_file);
|
||||
atom.flags.thunk = true;
|
||||
}
|
||||
|
||||
|
||||
@ -45,8 +45,7 @@ pub fn deinit(self: *InternalObject, allocator: Allocator) void {
|
||||
|
||||
pub fn init(self: *InternalObject, allocator: Allocator) !void {
|
||||
// Atom at index 0 is reserved as null atom.
|
||||
try self.atoms.append(allocator, .{});
|
||||
try self.atoms_extra.append(allocator, 0);
|
||||
try self.atoms.append(allocator, .{ .extra = try self.addAtomExtra(allocator, .{}) });
|
||||
// Null byte in strtab
|
||||
try self.strtab.append(allocator, 0);
|
||||
}
|
||||
|
||||
@ -1634,7 +1634,7 @@ fn isThreadlocal(macho_file: *MachO, decl_index: InternPool.DeclIndex) bool {
|
||||
|
||||
fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
|
||||
try self.atoms.ensureUnusedCapacity(allocator, 1);
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, 1);
|
||||
try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
|
||||
return self.addAtomAssumeCapacity();
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user