authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-07 22:46:07+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-08 22:46:17+01:00
log0af5d2e9b6393de460106f9f53a68374e636087a
tree255fec5299f8c15013317c81c1dd238adae16444
parent1cf45fb20916568659fcce33dfcfd97013712270

elf+aarch64: implement .plt.got


3 files changed, 64 insertions(+), 17 deletions(-)

src/link/Elf.zig+2-2
......@@ -4062,7 +4062,7 @@ fn updateSectionSizes(self: *Elf) !void {
40624062 }
40634063
40644064 if (self.plt_got_section_index) |index| {
4065 self.shdrs.items[index].sh_size = self.plt_got.size();
4065 self.shdrs.items[index].sh_size = self.plt_got.size(self);
40664066 }
40674067
40684068 if (self.rela_dyn_section_index) |shndx| {
......@@ -4747,7 +4747,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47474747
47484748 if (self.plt_got_section_index) |shndx| {
47494749 const shdr = self.shdrs.items[shndx];
4750 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size());
4750 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
47514751 defer buffer.deinit();
47524752 try self.plt_got.write(self, buffer.writer());
47534753 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
src/link/Elf/Symbol.zig+3-1
......@@ -139,7 +139,8 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) u64 {
139139 if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
140140 const extras = symbol.extra(elf_file).?;
141141 const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];
142 return shdr.sh_addr + extras.plt_got * 16;
142 const cpu_arch = elf_file.getTarget().cpu.arch;
143 return shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch);
143144}
144145
145146pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 {
......@@ -442,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;
442443const LinkerDefined = @import("LinkerDefined.zig");
443444const Object = @import("Object.zig");
444445const PltSection = synthetic_sections.PltSection;
446const PltGotSection = synthetic_sections.PltGotSection;
445447const SharedObject = @import("SharedObject.zig");
446448const Symbol = @This();
447449const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/synthetic_sections.zig+59-14
......@@ -1130,23 +1130,24 @@ pub const PltGotSection = struct {
11301130 try plt_got.symbols.append(gpa, sym_index);
11311131 }
11321132
1133 pub fn size(plt_got: PltGotSection) usize {
1134 return plt_got.symbols.items.len * 16;
1133 pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
1134 return plt_got.symbols.items.len * entrySize(elf_file.getTarget().cpu.arch);
1135 }
1136
1137 pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize {
1138 return switch (cpu_arch) {
1139 .x86_64 => 16,
1140 .aarch64 => 4 * @sizeOf(u32),
1141 else => @panic("TODO implement PltGotSection.entrySize for this arch"),
1142 };
11351143 }
11361144
11371145 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1138 for (plt_got.symbols.items) |sym_index| {
1139 const sym = elf_file.symbol(sym_index);
1140 const target_addr = sym.gotAddress(elf_file);
1141 const source_addr = sym.pltGotAddress(elf_file);
1142 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
1143 var entry = [_]u8{
1144 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1145 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
1146 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1147 };
1148 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
1149 try writer.writeAll(&entry);
1146 const cpu_arch = elf_file.getTarget().cpu.arch;
1147 switch (cpu_arch) {
1148 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
1149 .aarch64 => try aarch64.write(plt_got, elf_file, writer),
1150 else => return error.UnsupportedCpuArch,
11501151 }
11511152 }
11521153
......@@ -1175,6 +1176,50 @@ pub const PltGotSection = struct {
11751176 };
11761177 }
11771178 }
1179
1180 const x86_64 = struct {
1181 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1182 for (plt_got.symbols.items) |sym_index| {
1183 const sym = elf_file.symbol(sym_index);
1184 const target_addr = sym.gotAddress(elf_file);
1185 const source_addr = sym.pltGotAddress(elf_file);
1186 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
1187 var entry = [_]u8{
1188 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1189 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
1190 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1191 };
1192 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
1193 try writer.writeAll(&entry);
1194 }
1195 }
1196 };
1197
1198 const aarch64 = struct {
1199 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1200 for (plt_got.symbols.items) |sym_index| {
1201 const sym = elf_file.symbol(sym_index);
1202 const target_addr = sym.gotAddress(elf_file);
1203 const source_addr = sym.pltGotAddress(elf_file);
1204 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
1205 const off = try aarch64_util.calcPageOffset(.load_store_64, target_addr);
1206 const insts = &[_]Instruction{
1207 Instruction.adrp(.x16, pages),
1208 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),
1209 Instruction.br(.x17),
1210 Instruction.nop(),
1211 };
1212 comptime assert(insts.len == 4);
1213 for (insts) |inst| {
1214 try writer.writeInt(u32, inst.toU32(), .little);
1215 }
1216 }
1217 }
1218
1219 const aarch64_util = @import("../aarch64.zig");
1220 const Instruction = aarch64_util.Instruction;
1221 const Register = aarch64_util.Register;
1222 };
11781223};
11791224
11801225pub const CopyRelSection = struct {