Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

elf: replace .got.zig with a zig jump table #21065

Merged
merged 39 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
27e1e63
elf: introduce OffsetTable in ZigObject for funcs only
kubkon Aug 8, 2024
67e703d
elf: allocate new offset table via Atom.allocate mechanism
kubkon Aug 8, 2024
24b915c
elf: write offset table entry if dirty
kubkon Aug 8, 2024
97a65ea
elf: dirty offset table entry on moving Atom in off/addr space
kubkon Aug 8, 2024
7556b32
elf: indirect via offset table in the linker away from backend
kubkon Aug 8, 2024
4c2b34e
elf: relax R_X86_64_32 into jump table indirection if zig_offset_tabl…
kubkon Aug 9, 2024
d328140
elf: nuke ZigGotSection from existence
kubkon Aug 9, 2024
d7c5fbc
elf: emit a jump table in place of offset table for functions
kubkon Aug 12, 2024
5fd53dc
x86_64: start converting away from .got.zig knowledge
kubkon Aug 12, 2024
f968dd0
comp: actually report codegen errors
kubkon Aug 12, 2024
16abf51
x86_64: handle lea_symbol returned by genNavRef
kubkon Aug 12, 2024
e3f6eba
x86_64+elf: fix jump table indirection for functions
kubkon Aug 12, 2024
e1ce9a7
elf: add poorman's reporting tool for unallocated NAVs/UAVs
kubkon Aug 12, 2024
78b1c73
elf: rename OffsetTable to JumpTable
kubkon Aug 12, 2024
ffcf047
x86_64: remove handling of .call since it's unused for now
kubkon Aug 12, 2024
d25c93a
x86_64: emit call rel32 for near calls with linker reloc
kubkon Aug 13, 2024
ce8886d
elf: make zig jump table indirection implicit via Symbol.address
kubkon Aug 13, 2024
57f7209
elf: replace use of linker_extern_fn with more generic Immediate.reloc
kubkon Aug 13, 2024
edd72c7
elf: fix circular dep loop in zig jump table
kubkon Aug 13, 2024
afaec5c
x86_64: fix generating lazy symbol refs
kubkon Aug 13, 2024
39ee346
elf: make .text.zig bigger now that jump table is part of it
kubkon Aug 13, 2024
df80ccf
elf: pretty print alingment when pretty printing atoms
kubkon Aug 13, 2024
9daf5e8
elf: commit non-indirected symbol address to symtab
kubkon Aug 13, 2024
49d78cc
elf: only apply zig jump table indirection to function calls (PLT32)
kubkon Aug 13, 2024
97ab420
elf: do not emit zig jump table in relocatables
kubkon Aug 13, 2024
1bd54a5
fix compile errors in other codegen backends
kubkon Aug 13, 2024
f26573f
elf: re-use old atom slot for a trampoline to that atom
kubkon Aug 14, 2024
b8203fa
elf: check for relocs before deciding on shndx in getNavShdrIndex
kubkon Aug 15, 2024
c9db887
builtin: init test_functions to empty slice to avoid coercing to unde…
kubkon Aug 15, 2024
2e8351c
elf: fix up riscv for `.got.zig` rewrite
Rexicon226 Aug 15, 2024
8a0cb70
elf: introduce Symbol.flags.is_extern_ptr for refs potentially needin…
kubkon Aug 15, 2024
0fd0b11
riscv: do not emit GOT relocations for special linker symbols
kubkon Aug 15, 2024
f0df0ac
x86_64: fix handling on externs in lower/emit
kubkon Aug 15, 2024
c792904
elf: fix GOT32 reloc resolution logic
kubkon Aug 15, 2024
79418fa
riscv: remove redundant by-symbol-name check; just check for PIC and …
kubkon Aug 15, 2024
4d5bf0f
x86_64: deref GOT pointer when requesting var value
kubkon Aug 15, 2024
9473d76
test/elf: enhance testImportingDataDynamic
kubkon Aug 15, 2024
624016e
riscv64: fix incorrect branch target
jacobly0 Aug 16, 2024
73f385e
Update src/arch/x86_64/CodeGen.zig
kubkon Aug 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Builtin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {

if (opts.is_test) {
try buffer.appendSlice(
\\pub var test_functions: []const std.builtin.TestFn = undefined; // overwritten later
\\pub var test_functions: []const std.builtin.TestFn = &.{}; // overwritten later
\\
);
}
Expand Down
7 changes: 7 additions & 0 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3092,6 +3092,10 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
if (zcu.intern_pool.global_error_set.getNamesFromMainThread().len > zcu.error_limit) {
total += 1;
}

for (zcu.failed_codegen.keys()) |_| {
total += 1;
}
}

// The "no entry point found" error only counts if there are no semantic analysis errors.
Expand Down Expand Up @@ -3237,6 +3241,9 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
}
}
}
for (zcu.failed_codegen.values()) |error_msg| {
try addModuleErrorMsg(zcu, &bundle, error_msg.*, &all_references);
}
for (zcu.failed_exports.values()) |value| {
try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
}
Expand Down
41 changes: 7 additions & 34 deletions src/arch/aarch64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4352,24 +4352,10 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
// on linking.
if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
.func => |func| {
if (self.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
const got_addr = @as(u32, @intCast(sym.zigGotAddress(elf_file)));
try self.genSetReg(Type.usize, .x30, .{ .memory = got_addr });
} else if (self.bin_file.cast(.macho)) |macho_file| {
_ = macho_file;
@panic("TODO airCall");
// const atom = try macho_file.getOrCreateAtomForNav(func.owner_nav);
// const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
// try self.genSetReg(Type.u64, .x30, .{
// .linker_load = .{
// .type = .got,
// .sym_index = sym_index,
// },
// });
if (self.bin_file.cast(.elf)) |_| {
return self.fail("TODO implement calling functions for Elf", .{});
} else if (self.bin_file.cast(.macho)) |_| {
return self.fail("TODO implement calling functions for MachO", .{});
} else if (self.bin_file.cast(.coff)) |coff_file| {
const atom = try coff_file.getOrCreateAtomForNav(func.owner_nav);
const sym_index = coff_file.getAtom(atom).getSymbolIndex().?;
Expand All @@ -4393,21 +4379,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
.@"extern" => |@"extern"| {
const nav_name = ip.getNav(@"extern".owner_nav).name.toSlice(ip);
const lib_name = @"extern".lib_name.toSlice(ip);
if (self.bin_file.cast(.macho)) |macho_file| {
_ = macho_file;
@panic("TODO airCall");
// const sym_index = try macho_file.getGlobalSymbol(nav_name, lib_name);
// const atom = try macho_file.getOrCreateAtomForNav(self.owner_nav);
// const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
// _ = try self.addInst(.{
// .tag = .call_extern,
// .data = .{
// .relocation = .{
// .atom_index = atom_index,
// .sym_index = sym_index,
// },
// },
// });
if (self.bin_file.cast(.macho)) |_| {
return self.fail("TODO implement calling extern functions for MachO", .{});
} else if (self.bin_file.cast(.coff)) |coff_file| {
const sym_index = try coff_file.getGlobalSymbol(nav_name, lib_name);
try self.genSetReg(Type.u64, .x30, .{
Expand Down Expand Up @@ -6234,7 +6207,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
.memory => |addr| .{ .memory = addr },
.load_got => |sym_index| .{ .linker_load = .{ .type = .got, .sym_index = sym_index } },
.load_direct => |sym_index| .{ .linker_load = .{ .type = .direct, .sym_index = sym_index } },
.load_symbol, .load_tlv => unreachable, // TODO
.load_symbol, .load_tlv, .lea_symbol => unreachable, // TODO
},
.fail => |msg| {
self.err_msg = msg;
Expand Down
20 changes: 3 additions & 17 deletions src/arch/arm/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4333,22 +4333,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
// Due to incremental compilation, how function calls are generated depends
// on linking.
if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
.func => |func| {
if (self.bin_file.cast(.elf)) |elf_file| {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
const got_addr: u32 = @intCast(sym.zigGotAddress(elf_file));
try self.genSetReg(Type.usize, .lr, .{ .memory = got_addr });
} else if (self.bin_file.cast(.macho)) |_| {
unreachable; // unsupported architecture for MachO
} else {
return self.fail("TODO implement call on {s} for {s}", .{
@tagName(self.bin_file.tag),
@tagName(self.target.cpu.arch),
});
}
.func => {
return self.fail("TODO implement calling functions", .{});
},
.@"extern" => {
return self.fail("TODO implement calling extern functions", .{});
Expand Down Expand Up @@ -6184,7 +6170,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
.load_got, .load_symbol, .load_direct, .load_tlv, .lea_symbol => unreachable, // TODO
.immediate => |imm| .{ .immediate = @truncate(imm) },
.memory => |addr| .{ .memory = addr },
},
Expand Down
11 changes: 6 additions & 5 deletions src/arch/riscv64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4937,7 +4937,7 @@ fn genCall(
if (func.mod.pic) {
return func.fail("TODO: genCall pic", .{});
} else {
try func.genSetReg(Type.u64, .ra, .{ .load_symbol = .{ .sym = sym_index } });
try func.genSetReg(Type.u64, .ra, .{ .lea_symbol = .{ .sym = sym_index } });
_ = try func.addInst(.{
.tag = .jalr,
.data = .{ .i_type = .{
Expand Down Expand Up @@ -6120,7 +6120,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void {
arg_map.get(op_str["%[".len .. mod_index orelse op_str.len - "]".len]) orelse
return func.fail("no matching constraint: '{s}'", .{op_str})
]) {
.load_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: {
.lea_symbol => |sym_off| if (mem.eql(u8, modifier, "plt")) blk: {
assert(sym_off.off == 0);
break :blk .{ .sym = sym_off };
} else return func.fail("invalid modifier: '{s}'", .{modifier}),
Expand Down Expand Up @@ -6388,7 +6388,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
ty,
src_mcv,
),
.load_tlv => {
.load_symbol, .load_tlv => {
const addr_reg, const addr_lock = try func.allocReg(.int);
defer func.register_manager.unlockReg(addr_lock);

Expand Down Expand Up @@ -6433,7 +6433,7 @@ fn genCopy(func: *Func, ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !void {
part_disp += @intCast(dst_ty.abiSize(func.pt));
}
},
else => return func.fail("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
else => return std.debug.panic("TODO: genCopy to {s} from {s}", .{ @tagName(dst_mcv), @tagName(src_mcv) }),
}
}

Expand Down Expand Up @@ -6594,7 +6594,7 @@ fn genInlineMemset(
.tag = .beq,
.data = .{
.b_type = .{
.inst = @intCast(func.mir_instructions.len + 4), // points after the last inst
.inst = @intCast(func.mir_instructions.len + 3), // points after the last inst
.rs1 = count,
.rs2 = .zero,
},
Expand Down Expand Up @@ -8026,6 +8026,7 @@ fn genTypedValue(func: *Func, val: Value) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => unreachable,
.lea_symbol => |sym_index| .{ .lea_symbol = .{ .sym = sym_index } },
.load_symbol => |sym_index| .{ .load_symbol = .{ .sym = sym_index } },
.load_tlv => |sym_index| .{ .lea_tlv = sym_index },
.immediate => |imm| .{ .immediate = imm },
Expand Down
22 changes: 5 additions & 17 deletions src/arch/riscv64/Emit.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,19 @@ pub fn emitMir(emit: *Emit) Error!void {
.fmt = std.meta.activeTag(lowered_inst),
}),
.load_symbol_reloc => |symbol| {
const is_obj_or_static_lib = switch (emit.lower.output_mode) {
.Exe => false,
.Obj => true,
.Lib => emit.lower.link_mode == .static,
};

const elf_file = emit.bin_file.cast(.elf).?;
const zo = elf_file.zigObjectPtr().?;

const atom_ptr = zo.symbol(symbol.atom_index).atom(elf_file).?;
const sym = zo.symbol(symbol.sym_index);

var hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
var lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);

if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
_ = try sym.getOrCreateZigGotEntry(symbol.sym_index, elf_file);

hi_r_type = Elf.R_ZIG_GOT_HI20;
lo_r_type = Elf.R_ZIG_GOT_LO12;
} else if (sym.flags.needs_got) {
hi_r_type = Elf.R_GOT_HI20_STATIC; // TODO: rework this #20887
lo_r_type = Elf.R_GOT_LO12_I_STATIC; // TODO: rework this #20887
if (sym.flags.is_extern_ptr and emit.lower.pic) {
return emit.fail("emit GOT relocation for symbol '{s}'", .{sym.name(elf_file)});
}

const hi_r_type: u32 = @intFromEnum(std.elf.R_RISCV.HI20);
const lo_r_type: u32 = @intFromEnum(std.elf.R_RISCV.LO12_I);

try atom_ptr.addReloc(elf_file, .{
.r_offset = start_offset,
.r_info = (@as(u64, @intCast(symbol.sym_index)) << 32) | hi_r_type,
Expand Down
32 changes: 3 additions & 29 deletions src/arch/sparc64/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1349,34 +1349,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
// Due to incremental compilation, how function calls are generated depends
// on linking.
if (try self.air.value(callee, pt)) |func_value| switch (ip.indexToKey(func_value.toIntern())) {
.func => |func| {
const got_addr = if (self.bin_file.cast(.elf)) |elf_file| blk: {
const zo = elf_file.zigObjectPtr().?;
const sym_index = try zo.getOrCreateMetadataForNav(elf_file, func.owner_nav);
const sym = zo.symbol(sym_index);
_ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
break :blk @as(u32, @intCast(sym.zigGotAddress(elf_file)));
} else @panic("TODO SPARCv9 currently does not support non-ELF binaries");

try self.genSetReg(Type.usize, .o7, .{ .memory = got_addr });

_ = try self.addInst(.{
.tag = .jmpl,
.data = .{
.arithmetic_3op = .{
.is_imm = false,
.rd = .o7,
.rs1 = .o7,
.rs2_or_imm = .{ .rs2 = .g0 },
},
},
});

// TODO Find a way to fill this delay slot
_ = try self.addInst(.{
.tag = .nop,
.data = .{ .nop = {} },
});
.func => {
return self.fail("TODO implement calling functions", .{});
},
.@"extern" => {
return self.fail("TODO implement calling extern functions", .{});
Expand Down Expand Up @@ -4153,7 +4127,7 @@ fn genTypedValue(self: *Self, val: Value) InnerError!MCValue {
.mcv => |mcv| switch (mcv) {
.none => .none,
.undef => .undef,
.load_got, .load_symbol, .load_direct, .load_tlv => unreachable, // TODO
.load_got, .load_symbol, .load_direct, .load_tlv, .lea_symbol => unreachable, // TODO
.immediate => |imm| .{ .immediate = imm },
.memory => |addr| .{ .memory = addr },
},
Expand Down
Loading