mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 05:20:34 +00:00
elf: refactor object.shdrContents to never error out
This commit is contained in:
parent
53340544c6
commit
9ccd94d560
@ -1235,7 +1235,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
||||
// input Object files.
|
||||
// Any qualifing unresolved symbol will be upgraded to an absolute, weak
|
||||
// symbol for potential resolution at load-time.
|
||||
try self.resolveSymbols();
|
||||
self.resolveSymbols();
|
||||
self.markEhFrameAtomsDead();
|
||||
self.markImportsExports();
|
||||
self.claimUnresolved();
|
||||
|
||||
@ -1610,7 +1611,7 @@ fn parseArchive(
|
||||
/// 4. Reset state of all resolved globals since we will redo this bit on the pruned set.
|
||||
/// 5. Remove references to dead objects/shared objects
|
||||
/// 6. Re-run symbol resolution on pruned objects and shared objects sets.
|
||||
fn resolveSymbols(self: *Elf) error{Overflow}!void {
|
||||
fn resolveSymbols(self: *Elf) void {
|
||||
// Resolve symbols in the ZigModule. For now, we assume that it's always live.
|
||||
if (self.zig_module_index) |index| self.file(index).?.resolveSymbols(self);
|
||||
// Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
|
||||
@ -1652,11 +1653,11 @@ fn resolveSymbols(self: *Elf) error{Overflow}!void {
|
||||
const cg = self.comdatGroup(cg_index);
|
||||
const cg_owner = self.comdatGroupOwner(cg.owner);
|
||||
if (cg_owner.file != index) {
|
||||
for (try object.comdatGroupMembers(cg.shndx)) |shndx| {
|
||||
for (object.comdatGroupMembers(cg.shndx)) |shndx| {
|
||||
const atom_index = object.atoms.items[shndx];
|
||||
if (self.atom(atom_index)) |atom_ptr| {
|
||||
atom_ptr.flags.alive = false;
|
||||
// atom_ptr.markFdesDead(self);
|
||||
atom_ptr.markFdesDead(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1680,6 +1681,14 @@ fn markLive(self: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn markEhFrameAtomsDead(self: *Elf) void {
|
||||
for (self.objects.items) |index| {
|
||||
const file_ptr = self.file(index).?;
|
||||
if (!file_ptr.isAlive()) continue;
|
||||
file_ptr.object.markEhFrameAtomsDead(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn markImportsExports(self: *Elf) void {
|
||||
const mark = struct {
|
||||
fn mark(elf_file: *Elf, file_index: File.Index) void {
|
||||
@ -3389,17 +3398,39 @@ fn initSections(self: *Elf) !void {
|
||||
.p32 => true,
|
||||
.p64 => false,
|
||||
};
|
||||
const ptr_size = self.ptrWidthBytes();
|
||||
|
||||
for (self.objects.items) |index| {
|
||||
try self.file(index).?.object.initOutputSections(self);
|
||||
}
|
||||
|
||||
const needs_eh_frame = for (self.objects.items) |index| {
|
||||
if (self.file(index).?.object.cies.items.len > 0) break true;
|
||||
} else false;
|
||||
if (needs_eh_frame) {
|
||||
self.eh_frame_section_index = try self.addSection(.{
|
||||
.name = ".eh_frame",
|
||||
.type = elf.SHT_PROGBITS,
|
||||
.flags = elf.SHF_ALLOC,
|
||||
.addralign = ptr_size,
|
||||
});
|
||||
|
||||
if (self.base.options.eh_frame_hdr) {
|
||||
self.eh_frame_hdr_section_index = try self.addSection(.{
|
||||
.name = ".eh_frame_hdr",
|
||||
.type = elf.SHT_PROGBITS,
|
||||
.flags = elf.SHF_ALLOC,
|
||||
.addralign = ptr_size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (self.got.entries.items.len > 0 and self.got_section_index == null) {
|
||||
self.got_section_index = try self.addSection(.{
|
||||
.name = ".got",
|
||||
.type = elf.SHT_PROGBITS,
|
||||
.flags = elf.SHF_ALLOC | elf.SHF_WRITE,
|
||||
.addralign = self.ptrWidthBytes(),
|
||||
.addralign = ptr_size,
|
||||
});
|
||||
}
|
||||
|
||||
@ -3533,6 +3564,18 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
self.file(index).?.object.updateSectionSizes(self);
|
||||
}
|
||||
|
||||
if (self.eh_frame_section_index) |index| {
|
||||
const shdr = &self.shdrs.items[index];
|
||||
shdr.sh_size = try eh_frame.calcEhFrameSize(self);
|
||||
shdr.sh_addralign = @alignOf(u64);
|
||||
}
|
||||
|
||||
if (self.eh_frame_hdr_section_index) |index| {
|
||||
const shdr = &self.shdrs.items[index];
|
||||
shdr.sh_size = eh_frame.calcEhFrameHdrSize(self);
|
||||
shdr.sh_addralign = @alignOf(u32);
|
||||
}
|
||||
|
||||
if (self.got_section_index) |index| {
|
||||
self.shdrs.items[index].sh_size = self.got.size(self);
|
||||
}
|
||||
@ -4937,6 +4980,7 @@ const math = std.math;
|
||||
const mem = std.mem;
|
||||
|
||||
const codegen = @import("../codegen.zig");
|
||||
const eh_frame = @import("Elf/eh_frame.zig");
|
||||
const glibc = @import("../glibc.zig");
|
||||
const link = @import("../link.zig");
|
||||
const lldMain = @import("../main.zig").lldMain;
|
||||
|
||||
@ -49,7 +49,7 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
|
||||
return elf_file.file(self.file_index);
|
||||
}
|
||||
|
||||
pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
|
||||
pub fn inputShdr(self: Atom, elf_file: *Elf) Object.ElfShdr {
|
||||
const object = self.file(elf_file).?.object;
|
||||
return object.shdrs.items[self.input_section_index];
|
||||
}
|
||||
@ -272,7 +272,7 @@ pub fn free(self: *Atom, elf_file: *Elf) void {
|
||||
self.* = .{};
|
||||
}
|
||||
|
||||
pub fn relocs(self: Atom, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela {
|
||||
pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
|
||||
return switch (self.file(elf_file).?) {
|
||||
.zig_module => |x| x.relocs.items[self.relocs_section_index].items,
|
||||
.object => |x| x.getRelocs(self.relocs_section_index),
|
||||
@ -280,6 +280,18 @@ pub fn relocs(self: Atom, elf_file: *Elf) error{Overflow}![]align(1) const elf.E
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fdes(self: Atom, elf_file: *Elf) []Fde {
|
||||
if (self.fde_start == self.fde_end) return &[0]Fde{};
|
||||
const object = self.file(elf_file).?.object;
|
||||
return object.fdes.items[self.fde_start..self.fde_end];
|
||||
}
|
||||
|
||||
pub fn markFdesDead(self: Atom, elf_file: *Elf) void {
|
||||
for (self.fdes(elf_file)) |*fde| {
|
||||
fde.alive = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn addReloc(self: Atom, elf_file: *Elf, reloc: elf.Elf64_Rela) !void {
|
||||
const gpa = elf_file.base.allocator;
|
||||
const file_ptr = self.file(elf_file).?;
|
||||
@ -296,8 +308,8 @@ pub fn freeRelocs(self: Atom, elf_file: *Elf) void {
|
||||
zig_module.relocs.items[self.relocs_section_index].clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) error{Overflow}!bool {
|
||||
for (try self.relocs(elf_file)) |rel| {
|
||||
pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) bool {
|
||||
for (self.relocs(elf_file)) |rel| {
|
||||
if (rel.r_type() == elf.R_X86_64_GOTTPOFF) return true;
|
||||
}
|
||||
return false;
|
||||
@ -306,7 +318,7 @@ pub fn scanRelocsRequiresCode(self: Atom, elf_file: *Elf) error{Overflow}!bool {
|
||||
pub fn scanRelocs(self: Atom, elf_file: *Elf, code: ?[]const u8, undefs: anytype) !void {
|
||||
const is_dyn_lib = elf_file.isDynLib();
|
||||
const file_ptr = self.file(elf_file).?;
|
||||
const rels = try self.relocs(elf_file);
|
||||
const rels = self.relocs(elf_file);
|
||||
var i: usize = 0;
|
||||
while (i < rels.len) : (i += 1) {
|
||||
const rel = rels[i];
|
||||
@ -456,7 +468,7 @@ pub fn resolveRelocs(self: Atom, elf_file: *Elf, code: []u8) !void {
|
||||
var stream = std.io.fixedBufferStream(code);
|
||||
const cwriter = stream.writer();
|
||||
|
||||
const rels = try self.relocs(elf_file);
|
||||
const rels = self.relocs(elf_file);
|
||||
var i: usize = 0;
|
||||
while (i < rels.len) : (i += 1) {
|
||||
const rel = rels[i];
|
||||
@ -841,11 +853,14 @@ const x86_64 = struct {
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const elf = std.elf;
|
||||
const eh_frame = @import("eh_frame.zig");
|
||||
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 Fde = eh_frame.Fde;
|
||||
const File = @import("file.zig").File;
|
||||
const Object = @import("Object.zig");
|
||||
const Symbol = @import("Symbol.zig");
|
||||
|
||||
@ -4,7 +4,7 @@ data: []const u8,
|
||||
index: File.Index,
|
||||
|
||||
header: ?elf.Elf64_Ehdr = null,
|
||||
shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{},
|
||||
shdrs: std.ArrayListUnmanaged(ElfShdr) = .{},
|
||||
strings: StringTable(.object_strings) = .{},
|
||||
symtab: []align(1) const elf.Elf64_Sym = &[0]elf.Elf64_Sym{},
|
||||
strtab: []const u8 = &[0]u8{},
|
||||
@ -64,8 +64,13 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
|
||||
[*]align(1) const elf.Elf64_Shdr,
|
||||
@ptrCast(self.data.ptr + shoff),
|
||||
)[0..self.header.?.e_shnum];
|
||||
try self.shdrs.appendUnalignedSlice(gpa, shdrs);
|
||||
try self.strings.buffer.appendSlice(gpa, try self.shdrContents(self.header.?.e_shstrndx));
|
||||
try self.shdrs.ensureTotalCapacityPrecise(gpa, shdrs.len);
|
||||
|
||||
for (shdrs) |shdr| {
|
||||
self.shdrs.appendAssumeCapacity(try ElfShdr.fromElf64Shdr(shdr));
|
||||
}
|
||||
|
||||
try self.strings.buffer.appendSlice(gpa, self.shdrContents(self.header.?.e_shstrndx));
|
||||
|
||||
const symtab_index = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
|
||||
elf.SHT_SYMTAB => break @as(u16, @intCast(i)),
|
||||
@ -76,21 +81,21 @@ pub fn parse(self: *Object, elf_file: *Elf) !void {
|
||||
const shdr = shdrs[index];
|
||||
self.first_global = shdr.sh_info;
|
||||
|
||||
const symtab = try self.shdrContents(index);
|
||||
const symtab = self.shdrContents(index);
|
||||
const nsyms = @divExact(symtab.len, @sizeOf(elf.Elf64_Sym));
|
||||
self.symtab = @as([*]align(1) const elf.Elf64_Sym, @ptrCast(symtab.ptr))[0..nsyms];
|
||||
self.strtab = try self.shdrContents(@as(u16, @intCast(shdr.sh_link)));
|
||||
self.strtab = self.shdrContents(@as(u16, @intCast(shdr.sh_link)));
|
||||
}
|
||||
|
||||
try self.initAtoms(elf_file);
|
||||
try self.initSymtab(elf_file);
|
||||
|
||||
// for (self.shdrs.items, 0..) |shdr, i| {
|
||||
// const atom = elf_file.atom(self.atoms.items[i]) orelse continue;
|
||||
// if (!atom.alive) continue;
|
||||
// if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame"))
|
||||
// try self.parseEhFrame(@as(u16, @intCast(i)), 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;
|
||||
if (shdr.sh_type == elf.SHT_X86_64_UNWIND or mem.eql(u8, atom.name(elf_file), ".eh_frame"))
|
||||
try self.parseEhFrame(@as(u16, @intCast(i)), elf_file);
|
||||
}
|
||||
}
|
||||
|
||||
fn initAtoms(self: *Object, elf_file: *Elf) !void {
|
||||
@ -120,7 +125,7 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {
|
||||
};
|
||||
|
||||
const shndx = @as(u16, @intCast(i));
|
||||
const group_raw_data = try self.shdrContents(shndx);
|
||||
const group_raw_data = self.shdrContents(shndx);
|
||||
const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32));
|
||||
const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];
|
||||
|
||||
@ -173,11 +178,11 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {
|
||||
|
||||
fn addAtom(
|
||||
self: *Object,
|
||||
shdr: elf.Elf64_Shdr,
|
||||
shdr: ElfShdr,
|
||||
shndx: u16,
|
||||
name: [:0]const u8,
|
||||
elf_file: *Elf,
|
||||
) error{ OutOfMemory, Overflow }!void {
|
||||
) error{OutOfMemory}!void {
|
||||
const atom_index = try elf_file.addAtom();
|
||||
const atom = elf_file.atom(atom_index).?;
|
||||
atom.atom_index = atom_index;
|
||||
@ -188,7 +193,7 @@ fn addAtom(
|
||||
self.atoms.items[shndx] = atom_index;
|
||||
|
||||
if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
|
||||
const data = try self.shdrContents(shndx);
|
||||
const data = self.shdrContents(shndx);
|
||||
const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
|
||||
atom.size = chdr.ch_size;
|
||||
atom.alignment = Alignment.fromNonzeroByteUnits(chdr.ch_addralign);
|
||||
@ -198,7 +203,7 @@ fn addAtom(
|
||||
}
|
||||
}
|
||||
|
||||
fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{OutOfMemory}!u16 {
|
||||
fn initOutputSection(self: Object, elf_file: *Elf, shdr: ElfShdr) error{OutOfMemory}!u16 {
|
||||
const name = blk: {
|
||||
const name = self.strings.getAssumeExists(shdr.sh_name);
|
||||
if (shdr.sh_flags & elf.SHF_MERGE != 0) break :blk name;
|
||||
@ -244,7 +249,6 @@ fn initOutputSection(self: Object, elf_file: *Elf, shdr: elf.Elf64_Shdr) error{O
|
||||
}
|
||||
|
||||
fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
|
||||
_ = elf_file;
|
||||
const shdr = self.shdrs.items[index];
|
||||
const name = self.strings.getAssumeExists(shdr.sh_name);
|
||||
const ignore = blk: {
|
||||
@ -252,9 +256,8 @@ fn skipShdr(self: *Object, index: u16, elf_file: *Elf) bool {
|
||||
if (mem.startsWith(u8, name, ".comment")) break :blk true;
|
||||
if (mem.startsWith(u8, name, ".llvm_addrsig")) break :blk true;
|
||||
if (mem.startsWith(u8, name, ".eh_frame")) break :blk true;
|
||||
// if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
|
||||
// mem.startsWith(u8, name, ".debug")) break :blk true;
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC == 0 and mem.startsWith(u8, name, ".debug")) break :blk true;
|
||||
if (elf_file.base.options.strip and shdr.sh_flags & elf.SHF_ALLOC == 0 and
|
||||
mem.startsWith(u8, name, ".debug")) break :blk true;
|
||||
break :blk false;
|
||||
};
|
||||
return ignore;
|
||||
@ -303,8 +306,8 @@ fn parseEhFrame(self: *Object, shndx: u16, elf_file: *Elf) !void {
|
||||
};
|
||||
|
||||
const gpa = elf_file.base.allocator;
|
||||
const raw = try self.shdrContents(shndx);
|
||||
const relocs = try self.getRelocs(relocs_shndx);
|
||||
const raw = self.shdrContents(shndx);
|
||||
const relocs = self.getRelocs(relocs_shndx);
|
||||
const fdes_start = self.fdes.items.len;
|
||||
const cies_start = self.cies.items.len;
|
||||
|
||||
@ -408,7 +411,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
|
||||
const shdr = atom.inputShdr(elf_file);
|
||||
if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
|
||||
if (shdr.sh_type == elf.SHT_NOBITS) continue;
|
||||
if (try atom.scanRelocsRequiresCode(elf_file)) {
|
||||
if (atom.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);
|
||||
@ -418,7 +421,7 @@ pub fn scanRelocs(self: *Object, elf_file: *Elf, undefs: anytype) !void {
|
||||
}
|
||||
|
||||
for (self.cies.items) |cie| {
|
||||
for (try cie.relocs(elf_file)) |rel| {
|
||||
for (cie.relocs(elf_file)) |rel| {
|
||||
const sym = elf_file.symbol(self.symbols.items[rel.r_sym()]);
|
||||
if (sym.flags.import) {
|
||||
if (sym.type(elf_file) != elf.STT_FUNC)
|
||||
@ -518,6 +521,15 @@ pub fn markLive(self: *Object, elf_file: *Elf) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn markEhFrameAtomsDead(self: Object, elf_file: *Elf) void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
const is_eh_frame = 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;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checkDuplicates(self: *Object, elf_file: *Elf) void {
|
||||
const first_global = self.first_global orelse return;
|
||||
for (self.globals(), 0..) |index, i| {
|
||||
@ -747,12 +759,10 @@ pub fn globals(self: Object) []const Symbol.Index {
|
||||
return self.symbols.items[start..];
|
||||
}
|
||||
|
||||
fn shdrContents(self: Object, index: u32) error{Overflow}![]const u8 {
|
||||
pub fn shdrContents(self: Object, index: u32) []const u8 {
|
||||
assert(index < self.shdrs.items.len);
|
||||
const shdr = self.shdrs.items[index];
|
||||
const offset = math.cast(usize, shdr.sh_offset) orelse return error.Overflow;
|
||||
const size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
|
||||
return self.data[offset..][0..size];
|
||||
return self.data[shdr.sh_offset..][0..shdr.sh_size];
|
||||
}
|
||||
|
||||
/// Returns atom's code and optionally uncompresses data if required (for compressed sections).
|
||||
@ -761,7 +771,7 @@ pub fn codeDecompressAlloc(self: Object, elf_file: *Elf, atom_index: Atom.Index)
|
||||
const gpa = elf_file.base.allocator;
|
||||
const atom_ptr = elf_file.atom(atom_index).?;
|
||||
assert(atom_ptr.file_index == self.index);
|
||||
const data = try self.shdrContents(atom_ptr.input_section_index);
|
||||
const data = self.shdrContents(atom_ptr.input_section_index);
|
||||
const shdr = atom_ptr.inputShdr(elf_file);
|
||||
if (shdr.sh_flags & elf.SHF_COMPRESSED != 0) {
|
||||
const chdr = @as(*align(1) const elf.Elf64_Chdr, @ptrCast(data.ptr)).*;
|
||||
@ -789,8 +799,8 @@ fn getString(self: *Object, off: u32) [:0]const u8 {
|
||||
return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.ptr + off)), 0);
|
||||
}
|
||||
|
||||
pub fn comdatGroupMembers(self: *Object, index: u16) error{Overflow}![]align(1) const u32 {
|
||||
const raw = try self.shdrContents(index);
|
||||
pub fn comdatGroupMembers(self: *Object, index: u16) []align(1) const u32 {
|
||||
const raw = self.shdrContents(index);
|
||||
const nmembers = @divExact(raw.len, @sizeOf(u32));
|
||||
const members = @as([*]align(1) const u32, @ptrCast(raw.ptr))[1..nmembers];
|
||||
return members;
|
||||
@ -800,8 +810,8 @@ pub fn asFile(self: *Object) File {
|
||||
return .{ .object = self };
|
||||
}
|
||||
|
||||
pub fn getRelocs(self: *Object, shndx: u32) error{Overflow}![]align(1) const elf.Elf64_Rela {
|
||||
const raw = try self.shdrContents(shndx);
|
||||
pub fn getRelocs(self: *Object, shndx: u32) []align(1) const elf.Elf64_Rela {
|
||||
const raw = self.shdrContents(shndx);
|
||||
const num = @divExact(raw.len, @sizeOf(elf.Elf64_Rela));
|
||||
return @as([*]align(1) const elf.Elf64_Rela, @ptrCast(raw.ptr))[0..num];
|
||||
}
|
||||
@ -941,7 +951,7 @@ fn formatComdatGroups(
|
||||
const cg = elf_file.comdatGroup(cg_index);
|
||||
const cg_owner = elf_file.comdatGroupOwner(cg.owner);
|
||||
if (cg_owner.file != object.index) continue;
|
||||
const cg_members = object.comdatGroupMembers(cg.shndx) catch continue;
|
||||
const cg_members = object.comdatGroupMembers(cg.shndx);
|
||||
for (cg_members) |shndx| {
|
||||
const atom_index = object.atoms.items[shndx];
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
@ -970,6 +980,34 @@ fn formatPath(
|
||||
} else try writer.writeAll(object.path);
|
||||
}
|
||||
|
||||
pub const ElfShdr = struct {
|
||||
sh_name: u32,
|
||||
sh_type: u32,
|
||||
sh_flags: u64,
|
||||
sh_addr: u64,
|
||||
sh_offset: usize,
|
||||
sh_size: usize,
|
||||
sh_link: u32,
|
||||
sh_info: u32,
|
||||
sh_addralign: u64,
|
||||
sh_entsize: u64,
|
||||
|
||||
fn fromElf64Shdr(shdr: elf.Elf64_Shdr) error{Overflow}!ElfShdr {
|
||||
return .{
|
||||
.sh_name = shdr.sh_name,
|
||||
.sh_type = shdr.sh_type,
|
||||
.sh_flags = shdr.sh_flags,
|
||||
.sh_addr = shdr.sh_addr,
|
||||
.sh_offset = math.cast(usize, shdr.sh_offset) orelse return error.Overflow,
|
||||
.sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow,
|
||||
.sh_link = shdr.sh_link,
|
||||
.sh_info = shdr.sh_info,
|
||||
.sh_addralign = shdr.sh_addralign,
|
||||
.sh_entsize = shdr.sh_entsize,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const Object = @This();
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
@ -145,7 +145,7 @@ pub fn scanRelocs(self: *ZigModule, elf_file: *Elf, undefs: anytype) !void {
|
||||
for (self.atoms.items) |atom_index| {
|
||||
const atom = elf_file.atom(atom_index) orelse continue;
|
||||
if (!atom.flags.alive) continue;
|
||||
if (try atom.scanRelocsRequiresCode(elf_file)) {
|
||||
if (atom.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?
|
||||
|
||||
@ -20,9 +20,9 @@ pub const Fde = struct {
|
||||
return base + fde.out_offset;
|
||||
}
|
||||
|
||||
pub fn data(fde: Fde, elf_file: *Elf) error{Overflow}![]const u8 {
|
||||
pub fn data(fde: Fde, elf_file: *Elf) []const u8 {
|
||||
const object = elf_file.file(fde.file_index).?.object;
|
||||
const contents = try object.shdrContents(fde.input_section_index);
|
||||
const contents = object.shdrContents(fde.input_section_index);
|
||||
return contents[fde.offset..][0..fde.calcSize()];
|
||||
}
|
||||
|
||||
@ -32,24 +32,25 @@ pub const Fde = struct {
|
||||
}
|
||||
|
||||
pub fn ciePointer(fde: Fde, elf_file: *Elf) u32 {
|
||||
return std.mem.readIntLittle(u32, fde.data(elf_file)[4..8]);
|
||||
const fde_data = fde.data(elf_file);
|
||||
return std.mem.readIntLittle(u32, fde_data[4..8]);
|
||||
}
|
||||
|
||||
pub fn calcSize(fde: Fde) u64 {
|
||||
return fde.size + 4;
|
||||
}
|
||||
|
||||
pub fn atom(fde: Fde, elf_file: *Elf) error{Overflow}!*Atom {
|
||||
pub fn atom(fde: Fde, elf_file: *Elf) *Atom {
|
||||
const object = elf_file.file(fde.file_index).?.object;
|
||||
const rel = (try fde.relocs(elf_file))[0];
|
||||
const rel = fde.relocs(elf_file)[0];
|
||||
const sym = object.symtab[rel.r_sym()];
|
||||
const atom_index = object.atoms.items[sym.st_shndx];
|
||||
return elf_file.atom(atom_index).?;
|
||||
}
|
||||
|
||||
pub fn relocs(fde: Fde, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela {
|
||||
pub fn relocs(fde: Fde, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
|
||||
const object = elf_file.file(fde.file_index).?.object;
|
||||
return (try object.getRelocs(fde.rel_section_index))[fde.rel_index..][0..fde.rel_num];
|
||||
return object.getRelocs(fde.rel_section_index)[fde.rel_index..][0..fde.rel_num];
|
||||
}
|
||||
|
||||
pub fn format(
|
||||
@ -88,10 +89,7 @@ pub const Fde = struct {
|
||||
const fde = ctx.fde;
|
||||
const elf_file = ctx.elf_file;
|
||||
const base_addr = fde.address(elf_file);
|
||||
const atom_name = if (fde.atom(elf_file)) |atom_ptr|
|
||||
atom_ptr.name(elf_file)
|
||||
else |_|
|
||||
"";
|
||||
const atom_name = fde.atom(elf_file).name(elf_file);
|
||||
try writer.print("@{x} : size({x}) : cie({d}) : {s}", .{
|
||||
base_addr + fde.out_offset,
|
||||
fde.calcSize(),
|
||||
@ -123,9 +121,9 @@ pub const Cie = struct {
|
||||
return base + cie.out_offset;
|
||||
}
|
||||
|
||||
pub fn data(cie: Cie, elf_file: *Elf) error{Overflow}![]const u8 {
|
||||
pub fn data(cie: Cie, elf_file: *Elf) []const u8 {
|
||||
const object = elf_file.file(cie.file_index).?.object;
|
||||
const contents = try object.shdrContents(cie.input_section_index);
|
||||
const contents = object.shdrContents(cie.input_section_index);
|
||||
return contents[cie.offset..][0..cie.calcSize()];
|
||||
}
|
||||
|
||||
@ -133,16 +131,16 @@ pub const Cie = struct {
|
||||
return cie.size + 4;
|
||||
}
|
||||
|
||||
pub fn relocs(cie: Cie, elf_file: *Elf) error{Overflow}![]align(1) const elf.Elf64_Rela {
|
||||
pub fn relocs(cie: Cie, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
|
||||
const object = elf_file.file(cie.file_index).?.object;
|
||||
return (try object.getRelocs(cie.rel_section_index))[cie.rel_index..][0..cie.rel_num];
|
||||
return object.getRelocs(cie.rel_section_index)[cie.rel_index..][0..cie.rel_num];
|
||||
}
|
||||
|
||||
pub fn eql(cie: Cie, other: Cie, elf_file: *Elf) error{Overflow}!bool {
|
||||
if (!std.mem.eql(u8, try cie.data(elf_file), try other.data(elf_file))) return false;
|
||||
pub fn eql(cie: Cie, other: Cie, elf_file: *Elf) bool {
|
||||
if (!std.mem.eql(u8, cie.data(elf_file), other.data(elf_file))) return false;
|
||||
|
||||
const cie_relocs = try cie.relocs(elf_file);
|
||||
const other_relocs = try other.relocs(elf_file);
|
||||
const cie_relocs = cie.relocs(elf_file);
|
||||
const other_relocs = other.relocs(elf_file);
|
||||
if (cie_relocs.len != other_relocs.len) return false;
|
||||
|
||||
for (cie_relocs, other_relocs) |cie_rel, other_rel| {
|
||||
@ -152,8 +150,8 @@ pub const Cie = struct {
|
||||
|
||||
const cie_object = elf_file.file(cie.file_index).?.object;
|
||||
const other_object = elf_file.file(other.file_index).?.object;
|
||||
const cie_sym = cie_object.symbol(cie_rel.r_sym(), elf_file);
|
||||
const other_sym = other_object.symbol(other_rel.r_sym(), elf_file);
|
||||
const cie_sym = cie_object.symbols.items[cie_rel.r_sym()];
|
||||
const other_sym = other_object.symbols.items[other_rel.r_sym()];
|
||||
if (!std.mem.eql(u8, std.mem.asBytes(&cie_sym), std.mem.asBytes(&other_sym))) return false;
|
||||
}
|
||||
return true;
|
||||
@ -319,10 +317,10 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
|
||||
for (object.cies.items) |cie| {
|
||||
if (!cie.alive) continue;
|
||||
|
||||
const contents = try gpa.dupe(u8, try cie.data(elf_file));
|
||||
const contents = try gpa.dupe(u8, cie.data(elf_file));
|
||||
defer gpa.free(contents);
|
||||
|
||||
for (try cie.relocs(elf_file)) |rel| {
|
||||
for (cie.relocs(elf_file)) |rel| {
|
||||
const sym = object.symbol(rel.r_sym(), elf_file);
|
||||
try resolveReloc(cie, sym, rel, elf_file, contents);
|
||||
}
|
||||
@ -337,7 +335,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
|
||||
for (object.fdes.items) |fde| {
|
||||
if (!fde.alive) continue;
|
||||
|
||||
const contents = try gpa.dupe(u8, try fde.data(elf_file));
|
||||
const contents = try gpa.dupe(u8, fde.data(elf_file));
|
||||
defer gpa.free(contents);
|
||||
|
||||
std.mem.writeIntLittle(
|
||||
@ -346,7 +344,7 @@ pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
|
||||
@as(i32, @truncate(@as(i64, @intCast(fde.out_offset + 4)) - @as(i64, @intCast(fde.cie(elf_file).out_offset)))),
|
||||
);
|
||||
|
||||
for (try fde.relocs(elf_file)) |rel| {
|
||||
for (fde.relocs(elf_file)) |rel| {
|
||||
const sym = object.symbol(rel.r_sym(), elf_file);
|
||||
try resolveReloc(fde, sym, rel, elf_file, contents);
|
||||
}
|
||||
@ -395,7 +393,7 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
|
||||
for (object.fdes.items) |fde| {
|
||||
if (!fde.alive) continue;
|
||||
|
||||
const relocs = try fde.relocs(elf_file);
|
||||
const relocs = fde.relocs(elf_file);
|
||||
assert(relocs.len > 0); // Should this be an error? Things are completely broken anyhow if this trips...
|
||||
const rel = relocs[0];
|
||||
const sym = object.symbol(rel.r_sym(), elf_file);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user