Commit 0af5d2e9b6
Changed files (3)
src
src/link/Elf/Symbol.zig
@@ -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;
src/link/Elf/synthetic_sections.zig
@@ -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 {
src/link/Elf.zig
@@ -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);