mirror of
https://github.com/ziglang/zig.git
synced 2026-01-03 03:53:20 +00:00
elf: simplify handling of relocs for atoms
This commit is contained in:
parent
4b082d89c9
commit
d07edfabd6
@ -135,10 +135,6 @@ last_atom_and_free_list_table: std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFre
|
||||
/// with `Decl` `main`, and lives as long as that `Decl`.
|
||||
unnamed_consts: UnnamedConstTable = .{},
|
||||
|
||||
/// A table of relocations indexed by the owning them `TextBlock`.
|
||||
relocs: RelocTable = .{},
|
||||
|
||||
const RelocTable = std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Reloc));
|
||||
const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Symbol.Index));
|
||||
const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata);
|
||||
|
||||
@ -293,14 +289,6 @@ pub fn deinit(self: *Elf) void {
|
||||
self.unnamed_consts.deinit(gpa);
|
||||
}
|
||||
|
||||
{
|
||||
var it = self.relocs.valueIterator();
|
||||
while (it.next()) |relocs| {
|
||||
relocs.deinit(gpa);
|
||||
}
|
||||
self.relocs.deinit(gpa);
|
||||
}
|
||||
|
||||
if (self.dwarf) |*dw| {
|
||||
dw.deinit();
|
||||
}
|
||||
@ -312,12 +300,11 @@ pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.
|
||||
const this_sym_index = try self.getOrCreateMetadataForDecl(decl_index);
|
||||
const this_sym = self.symbol(this_sym_index);
|
||||
const vaddr = this_sym.value;
|
||||
const parent_atom_index = self.symbol(reloc_info.parent_atom_index).atom_index;
|
||||
try Atom.addRelocation(self, parent_atom_index, .{
|
||||
const parent_atom = self.symbol(reloc_info.parent_atom_index).atom(self).?;
|
||||
try parent_atom.addReloc(self, .{
|
||||
.target = this_sym_index,
|
||||
.offset = reloc_info.offset,
|
||||
.addend = reloc_info.addend,
|
||||
.prev_vaddr = vaddr,
|
||||
});
|
||||
|
||||
return vaddr;
|
||||
@ -1032,38 +1019,9 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
|
||||
// Beyond this point, everything has been allocated a virtual address and we can resolve
|
||||
// the relocations.
|
||||
{
|
||||
var it = self.relocs.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const atom_index = entry.key_ptr.*;
|
||||
const relocs = entry.value_ptr.*;
|
||||
const atom_ptr = self.atom(atom_index).?;
|
||||
const source_shdr = &self.shdrs.items[atom_ptr.output_section_index];
|
||||
|
||||
log.debug("relocating '{s}'", .{atom_ptr.name(self)});
|
||||
|
||||
for (relocs.items) |*reloc| {
|
||||
const target_sym = self.symbol(reloc.target);
|
||||
const target_vaddr = target_sym.value + reloc.addend;
|
||||
|
||||
if (target_vaddr == reloc.prev_vaddr) continue;
|
||||
|
||||
const section_offset = (atom_ptr.value + reloc.offset) - source_shdr.sh_addr;
|
||||
const file_offset = source_shdr.sh_offset + section_offset;
|
||||
|
||||
log.debug(" ({x}: [() => 0x{x}] ({s}))", .{
|
||||
reloc.offset,
|
||||
target_vaddr,
|
||||
target_sym.name(self),
|
||||
});
|
||||
|
||||
switch (self.ptr_width) {
|
||||
.p32 => try self.base.file.?.pwriteAll(mem.asBytes(&@as(u32, @intCast(target_vaddr))), file_offset),
|
||||
.p64 => try self.base.file.?.pwriteAll(mem.asBytes(&target_vaddr), file_offset),
|
||||
}
|
||||
|
||||
reloc.prev_vaddr = target_vaddr;
|
||||
}
|
||||
if (self.zig_module_index) |index| {
|
||||
for (self.file(index).?.zig_module.atoms.items) |atom_index| {
|
||||
try self.atom(atom_index).?.resolveRelocs(self);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2313,7 +2271,7 @@ pub fn updateFunc(self: *Elf, mod: *Module, func_index: InternPool.Index, air: A
|
||||
|
||||
const sym_index = try self.getOrCreateMetadataForDecl(decl_index);
|
||||
self.freeUnnamedConsts(decl_index);
|
||||
Atom.freeRelocations(self, self.symbol(sym_index).atom_index);
|
||||
self.symbol(sym_index).atom(self).?.freeRelocs(self);
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
@ -2378,7 +2336,7 @@ pub fn updateDecl(
|
||||
}
|
||||
|
||||
const sym_index = try self.getOrCreateMetadataForDecl(decl_index);
|
||||
Atom.freeRelocations(self, self.symbol(sym_index).atom_index);
|
||||
self.symbol(sym_index).atom(self).?.freeRelocs(self);
|
||||
|
||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||
defer code_buffer.deinit();
|
||||
|
||||
@ -14,13 +14,13 @@ size: u64 = 0,
|
||||
alignment: u8 = 0,
|
||||
|
||||
/// Index of the input section.
|
||||
input_section_index: u16 = 0,
|
||||
input_section_index: Index = 0,
|
||||
|
||||
/// Index of the output section.
|
||||
output_section_index: u16 = 0,
|
||||
|
||||
/// Index of the input section containing this atom's relocs.
|
||||
relocs_section_index: u16 = 0,
|
||||
relocs_section_index: Index = 0,
|
||||
|
||||
/// Index of this atom in the linker's atoms table.
|
||||
atom_index: Index = 0,
|
||||
@ -64,20 +64,6 @@ pub fn freeListEligible(self: Atom, elf_file: *Elf) bool {
|
||||
return surplus >= Elf.min_text_capacity;
|
||||
}
|
||||
|
||||
pub fn addRelocation(elf_file: *Elf, atom_index: Index, reloc: Reloc) !void {
|
||||
const gpa = elf_file.base.allocator;
|
||||
const gop = try elf_file.relocs.getOrPut(gpa, atom_index);
|
||||
if (!gop.found_existing) {
|
||||
gop.value_ptr.* = .{};
|
||||
}
|
||||
try gop.value_ptr.append(gpa, reloc);
|
||||
}
|
||||
|
||||
pub fn freeRelocations(elf_file: *Elf, atom_index: Index) void {
|
||||
var removed_relocs = elf_file.relocs.fetchRemove(atom_index);
|
||||
if (removed_relocs) |*relocs| relocs.value.deinit(elf_file.base.allocator);
|
||||
}
|
||||
|
||||
pub fn allocate(self: *Atom, elf_file: *Elf) !void {
|
||||
const shdr = &elf_file.shdrs.items[self.output_section_index];
|
||||
const meta = elf_file.last_atom_and_free_list_table.getPtr(self.output_section_index).?;
|
||||
@ -205,8 +191,6 @@ 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) });
|
||||
|
||||
Atom.freeRelocations(elf_file, self.atom_index);
|
||||
|
||||
const gpa = elf_file.base.allocator;
|
||||
const shndx = self.output_section_index;
|
||||
const meta = elf_file.last_atom_and_free_list_table.getPtr(shndx).?;
|
||||
@ -256,23 +240,70 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
self.next_index = 0;
|
||||
}
|
||||
|
||||
// TODO create relocs free list
|
||||
self.freeRelocs(elf_file);
|
||||
self.* = .{};
|
||||
}
|
||||
|
||||
pub const Index = u32;
|
||||
pub fn relocs(self: Atom, elf_file: *Elf) []const Relocation {
|
||||
const file_ptr = elf_file.file(self.file_index).?;
|
||||
if (file_ptr != .zig_module) @panic("TODO");
|
||||
const zig_module = file_ptr.zig_module;
|
||||
return zig_module.relocs.items[self.relocs_section_index].items;
|
||||
}
|
||||
|
||||
pub const Reloc = struct {
|
||||
target: u32,
|
||||
offset: u64,
|
||||
addend: u32,
|
||||
prev_vaddr: u64,
|
||||
};
|
||||
pub fn addReloc(self: Atom, elf_file: *Elf, reloc: Relocation) !void {
|
||||
const gpa = elf_file.base.allocator;
|
||||
const file_ptr = elf_file.file(self.file_index).?;
|
||||
assert(file_ptr == .zig_module);
|
||||
const zig_module = file_ptr.zig_module;
|
||||
const rels = &zig_module.relocs.items[self.relocs_section_index];
|
||||
try rels.append(gpa, reloc);
|
||||
}
|
||||
|
||||
pub fn freeRelocs(self: Atom, elf_file: *Elf) void {
|
||||
const file_ptr = elf_file.file(self.file_index).?;
|
||||
assert(file_ptr == .zig_module);
|
||||
const zig_module = file_ptr.zig_module;
|
||||
zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity();
|
||||
}
|
||||
|
||||
/// TODO mark relocs dirty
|
||||
pub fn resolveRelocs(self: Atom, elf_file: *Elf) !void {
|
||||
relocs_log.debug("0x{x}: {s}", .{ self.value, self.name(elf_file) });
|
||||
const shdr = &elf_file.shdrs.items[self.output_section_index];
|
||||
for (self.relocs(elf_file)) |reloc| {
|
||||
const target_sym = elf_file.symbol(reloc.target);
|
||||
const target_vaddr = target_sym.value + reloc.addend;
|
||||
const section_offset = (self.value + reloc.offset) - shdr.sh_addr;
|
||||
const file_offset = shdr.sh_offset + section_offset;
|
||||
|
||||
relocs_log.debug(" ({x}: [() => 0x{x}] ({s}))", .{
|
||||
reloc.offset,
|
||||
target_vaddr,
|
||||
target_sym.name(elf_file),
|
||||
});
|
||||
|
||||
switch (elf_file.ptr_width) {
|
||||
.p32 => try elf_file.base.file.?.pwriteAll(
|
||||
std.mem.asBytes(&@as(u32, @intCast(target_vaddr))),
|
||||
file_offset,
|
||||
),
|
||||
.p64 => try elf_file.base.file.?.pwriteAll(std.mem.asBytes(&target_vaddr), file_offset),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const Index = u32;
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const elf = std.elf;
|
||||
const log = std.log.scoped(.link);
|
||||
const relocs_log = std.log.scoped(.link_relocs);
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const Atom = @This();
|
||||
const Elf = @import("../Elf.zig");
|
||||
const File = @import("file.zig").File;
|
||||
const Relocation = @import("Relocation.zig");
|
||||
|
||||
8
src/link/Elf/Relocation.zig
Normal file
8
src/link/Elf/Relocation.zig
Normal file
@ -0,0 +1,8 @@
|
||||
target: Symbol.Index,
|
||||
offset: u64,
|
||||
addend: u32,
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const Symbol = @import("Symbol.zig");
|
||||
const Relocation = @This();
|
||||
@ -9,6 +9,7 @@ elf_global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
|
||||
global_symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
|
||||
|
||||
atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
|
||||
relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(Relocation)) = .{},
|
||||
|
||||
alive: bool = true,
|
||||
|
||||
@ -20,6 +21,10 @@ pub fn deinit(self: *ZigModule, allocator: Allocator) void {
|
||||
self.elf_global_symbols.deinit(allocator);
|
||||
self.global_symbols.deinit(allocator);
|
||||
self.atoms.deinit(allocator);
|
||||
for (self.relocs.items) |*list| {
|
||||
list.deinit(allocator);
|
||||
}
|
||||
self.relocs.deinit(allocator);
|
||||
}
|
||||
|
||||
pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !Symbol.Index {
|
||||
@ -34,6 +39,10 @@ pub fn createAtom(self: *ZigModule, output_section_index: u16, elf_file: *Elf) !
|
||||
symbol_ptr.output_section_index = output_section_index;
|
||||
const local_esym = symbol_ptr.sourceSymbol(elf_file);
|
||||
local_esym.st_shndx = output_section_index;
|
||||
const relocs_index = @as(Atom.Index, @intCast(self.relocs.items.len));
|
||||
const relocs = try self.relocs.addOne(gpa);
|
||||
relocs.* = .{};
|
||||
atom_ptr.relocs_section_index = relocs_index;
|
||||
try self.atoms.append(gpa, atom_index);
|
||||
return symbol_index;
|
||||
}
|
||||
@ -184,5 +193,6 @@ const Atom = @import("Atom.zig");
|
||||
const Elf = @import("../Elf.zig");
|
||||
const File = @import("file.zig").File;
|
||||
const Module = @import("../../Module.zig");
|
||||
const ZigModule = @This();
|
||||
const Relocation = @import("Relocation.zig");
|
||||
const Symbol = @import("Symbol.zig");
|
||||
const ZigModule = @This();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user