mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
elf+aarch64: implement .plt.got
This commit is contained in:
parent
1cf45fb209
commit
0af5d2e9b6
@ -4062,7 +4062,7 @@ fn updateSectionSizes(self: *Elf) !void {
|
||||
}
|
||||
|
||||
if (self.plt_got_section_index) |index| {
|
||||
self.shdrs.items[index].sh_size = self.plt_got.size();
|
||||
self.shdrs.items[index].sh_size = self.plt_got.size(self);
|
||||
}
|
||||
|
||||
if (self.rela_dyn_section_index) |shndx| {
|
||||
@ -4747,7 +4747,7 @@ fn writeSyntheticSections(self: *Elf) !void {
|
||||
|
||||
if (self.plt_got_section_index) |shndx| {
|
||||
const shdr = self.shdrs.items[shndx];
|
||||
var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size());
|
||||
var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
|
||||
defer buffer.deinit();
|
||||
try self.plt_got.write(self, buffer.writer());
|
||||
try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
|
||||
|
||||
@ -139,7 +139,8 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) u64 {
|
||||
if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
|
||||
const extras = symbol.extra(elf_file).?;
|
||||
const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];
|
||||
return shdr.sh_addr + extras.plt_got * 16;
|
||||
const cpu_arch = elf_file.getTarget().cpu.arch;
|
||||
return shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch);
|
||||
}
|
||||
|
||||
pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 {
|
||||
@ -442,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;
|
||||
const LinkerDefined = @import("LinkerDefined.zig");
|
||||
const Object = @import("Object.zig");
|
||||
const PltSection = synthetic_sections.PltSection;
|
||||
const PltGotSection = synthetic_sections.PltGotSection;
|
||||
const SharedObject = @import("SharedObject.zig");
|
||||
const Symbol = @This();
|
||||
const ZigGotSection = synthetic_sections.ZigGotSection;
|
||||
|
||||
@ -1130,23 +1130,24 @@ pub const PltGotSection = struct {
|
||||
try plt_got.symbols.append(gpa, sym_index);
|
||||
}
|
||||
|
||||
pub fn size(plt_got: PltGotSection) usize {
|
||||
return plt_got.symbols.items.len * 16;
|
||||
pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
|
||||
return plt_got.symbols.items.len * entrySize(elf_file.getTarget().cpu.arch);
|
||||
}
|
||||
|
||||
pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize {
|
||||
return switch (cpu_arch) {
|
||||
.x86_64 => 16,
|
||||
.aarch64 => 4 * @sizeOf(u32),
|
||||
else => @panic("TODO implement PltGotSection.entrySize for this arch"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
|
||||
for (plt_got.symbols.items) |sym_index| {
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
const target_addr = sym.gotAddress(elf_file);
|
||||
const source_addr = sym.pltGotAddress(elf_file);
|
||||
const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
|
||||
var entry = [_]u8{
|
||||
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
|
||||
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
|
||||
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
|
||||
};
|
||||
mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
|
||||
try writer.writeAll(&entry);
|
||||
const cpu_arch = elf_file.getTarget().cpu.arch;
|
||||
switch (cpu_arch) {
|
||||
.x86_64 => try x86_64.write(plt_got, elf_file, writer),
|
||||
.aarch64 => try aarch64.write(plt_got, elf_file, writer),
|
||||
else => return error.UnsupportedCpuArch,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1175,6 +1176,50 @@ pub const PltGotSection = struct {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const x86_64 = struct {
|
||||
pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
|
||||
for (plt_got.symbols.items) |sym_index| {
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
const target_addr = sym.gotAddress(elf_file);
|
||||
const source_addr = sym.pltGotAddress(elf_file);
|
||||
const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
|
||||
var entry = [_]u8{
|
||||
0xf3, 0x0f, 0x1e, 0xfa, // endbr64
|
||||
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
|
||||
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
|
||||
};
|
||||
mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
|
||||
try writer.writeAll(&entry);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const aarch64 = struct {
|
||||
fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
|
||||
for (plt_got.symbols.items) |sym_index| {
|
||||
const sym = elf_file.symbol(sym_index);
|
||||
const target_addr = sym.gotAddress(elf_file);
|
||||
const source_addr = sym.pltGotAddress(elf_file);
|
||||
const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
|
||||
const off = try aarch64_util.calcPageOffset(.load_store_64, target_addr);
|
||||
const insts = &[_]Instruction{
|
||||
Instruction.adrp(.x16, pages),
|
||||
Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),
|
||||
Instruction.br(.x17),
|
||||
Instruction.nop(),
|
||||
};
|
||||
comptime assert(insts.len == 4);
|
||||
for (insts) |inst| {
|
||||
try writer.writeInt(u32, inst.toU32(), .little);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const aarch64_util = @import("../aarch64.zig");
|
||||
const Instruction = aarch64_util.Instruction;
|
||||
const Register = aarch64_util.Register;
|
||||
};
|
||||
};
|
||||
|
||||
pub const CopyRelSection = struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user