Elf2: implement PLT

This commit is contained in:
Jacob Young 2025-11-11 13:58:06 -05:00
parent 79a9f3a418
commit 61a1cefeb3
4 changed files with 808 additions and 203 deletions

View file

@ -881,7 +881,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
end_offset - 4, end_offset - 4,
@enumFromInt(reloc.target.index), @enumFromInt(reloc.target.index),
reloc.off - 4, reloc.off - 4,
.{ .X86_64 = .PC32 }, .{ .X86_64 = .PLT32 },
) else if (emit.bin_file.cast(.macho)) |macho_file| { ) else if (emit.bin_file.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?; const zo = macho_file.getZigObject().?;
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;
@ -916,7 +916,13 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
.r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type), .r_info = @as(u64, reloc.target.index) << 32 | @intFromEnum(r_type),
.r_addend = reloc.off - 4, .r_addend = reloc.off - 4,
}, zo); }, zo);
} else return emit.fail("TODO implement {s} reloc for {s}", .{ } else if (emit.bin_file.cast(.elf2)) |elf| try elf.addReloc(
@enumFromInt(emit.atom_index),
end_offset - 4,
@enumFromInt(reloc.target.index),
reloc.off - 4,
.{ .X86_64 = if (emit.pic) .TLSLD else unreachable },
) else return emit.fail("TODO implement {s} reloc for {s}", .{
@tagName(reloc.target.type), @tagName(emit.bin_file.tag), @tagName(reloc.target.type), @tagName(emit.bin_file.tag),
}), }),
.tlv => if (emit.bin_file.cast(.elf)) |elf_file| { .tlv => if (emit.bin_file.cast(.elf)) |elf_file| {
@ -933,7 +939,7 @@ fn encodeInst(emit: *Emit, lowered_inst: Instruction, reloc_info: []const RelocI
end_offset - 4, end_offset - 4,
@enumFromInt(reloc.target.index), @enumFromInt(reloc.target.index),
reloc.off, reloc.off,
.{ .X86_64 = .TPOFF32 }, .{ .X86_64 = if (emit.pic) .DTPOFF32 else .TPOFF32 },
) else if (emit.bin_file.cast(.macho)) |macho_file| { ) else if (emit.bin_file.cast(.macho)) |macho_file| {
const zo = macho_file.getZigObject().?; const zo = macho_file.getZigObject().?;
const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?; const atom = zo.symbols.items[emit.atom_index].getAtom(macho_file).?;

View file

@ -1069,7 +1069,7 @@ pub const File = struct {
errdefer archive.file.close(); errdefer archive.file.close();
loadInput(base, .{ .archive = archive }) catch |err| switch (err) { loadInput(base, .{ .archive = archive }) catch |err| switch (err) {
error.BadMagic, error.UnexpectedEndOfFile => { error.BadMagic, error.UnexpectedEndOfFile => {
if (base.tag != .elf) return err; if (base.tag != .elf and base.tag != .elf2) return err;
try loadGnuLdScript(base, path, query, archive.file); try loadGnuLdScript(base, path, query, archive.file);
archive.file.close(); archive.file.close();
return; return;
@ -1091,7 +1091,7 @@ pub const File = struct {
errdefer dso.file.close(); errdefer dso.file.close();
loadInput(base, .{ .dso = dso }) catch |err| switch (err) { loadInput(base, .{ .dso = dso }) catch |err| switch (err) {
error.BadMagic, error.UnexpectedEndOfFile => { error.BadMagic, error.UnexpectedEndOfFile => {
if (base.tag != .elf) return err; if (base.tag != .elf and base.tag != .elf2) return err;
try loadGnuLdScript(base, path, query, dso.file); try loadGnuLdScript(base, path, query, dso.file);
dso.file.close(); dso.file.close();
return; return;
@ -1101,8 +1101,9 @@ pub const File = struct {
} }
fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void { fn loadGnuLdScript(base: *File, path: Path, parent_query: UnresolvedInput.Query, file: fs.File) anyerror!void {
const diags = &base.comp.link_diags; const comp = base.comp;
const gpa = base.comp.gpa; const diags = &comp.link_diags;
const gpa = comp.gpa;
const stat = try file.stat(); const stat = try file.stat();
const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig; const size = std.math.cast(u32, stat.size) orelse return error.FileTooBig;
const buf = try gpa.alloc(u8, size); const buf = try gpa.alloc(u8, size);
@ -1124,7 +1125,11 @@ pub const File = struct {
@panic("TODO"); @panic("TODO");
} else { } else {
if (fs.path.isAbsolute(arg.path)) { if (fs.path.isAbsolute(arg.path)) {
const new_path = Path.initCwd(try gpa.dupe(u8, arg.path)); const new_path = Path.initCwd(path: {
comp.mutex.lock();
defer comp.mutex.unlock();
break :path try comp.arena.dupe(u8, arg.path);
});
switch (Compilation.classifyFileExt(arg.path)) { switch (Compilation.classifyFileExt(arg.path)) {
.shared_library => try openLoadDso(base, new_path, query), .shared_library => try openLoadDso(base, new_path, query),
.object => try openLoadObject(base, new_path), .object => try openLoadObject(base, new_path),

File diff suppressed because it is too large Load diff

View file

@ -213,7 +213,7 @@ pub const Node = extern struct {
defer node_moved.* = false; defer node_moved.* = false;
return node_moved.*; return node_moved.*;
} }
fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { pub fn movedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
if (ni.hasMoved(mf)) return; if (ni.hasMoved(mf)) return;
const node = ni.get(mf); const node = ni.get(mf);
node.flags.moved = true; node.flags.moved = true;
@ -234,7 +234,7 @@ pub const Node = extern struct {
defer node_resized.* = false; defer node_resized.* = false;
return node_resized.*; return node_resized.*;
} }
fn resizedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void { pub fn resizedAssumeCapacity(ni: Node.Index, mf: *MappedFile) void {
const node = ni.get(mf); const node = ni.get(mf);
if (node.flags.resized) return; if (node.flags.resized) return;
node.flags.resized = true; node.flags.resized = true;