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 {...@@ -4062,7 +4062,7 @@ fn updateSectionSizes(self: *Elf) !void {
4062 }4062 }
40634063
4064 if (self.plt_got_section_index) |index| {4064 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);
4066 }4066 }
40674067
4068 if (self.rela_dyn_section_index) |shndx| {4068 if (self.rela_dyn_section_index) |shndx| {
...@@ -4747,7 +4747,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4747,7 +4747,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47474747
4748 if (self.plt_got_section_index) |shndx| {4748 if (self.plt_got_section_index) |shndx| {
4749 const shdr = self.shdrs.items[shndx];4749 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));
4751 defer buffer.deinit();4751 defer buffer.deinit();
4752 try self.plt_got.write(self, buffer.writer());4752 try self.plt_got.write(self, buffer.writer());
4753 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4753 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 {...@@ -139,7 +139,8 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) u64 {
139 if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;139 if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
140 const extras = symbol.extra(elf_file).?;140 const extras = symbol.extra(elf_file).?;
141 const shdr = elf_file.shdrs.items[elf_file.plt_got_section_index.?];141 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);
143}144}
144145
145pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 {146pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 {
...@@ -442,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;...@@ -442,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;
442const LinkerDefined = @import("LinkerDefined.zig");443const LinkerDefined = @import("LinkerDefined.zig");
443const Object = @import("Object.zig");444const Object = @import("Object.zig");
444const PltSection = synthetic_sections.PltSection;445const PltSection = synthetic_sections.PltSection;
446const PltGotSection = synthetic_sections.PltGotSection;
445const SharedObject = @import("SharedObject.zig");447const SharedObject = @import("SharedObject.zig");
446const Symbol = @This();448const Symbol = @This();
447const ZigGotSection = synthetic_sections.ZigGotSection;449const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/synthetic_sections.zig+59-14
...@@ -1130,23 +1130,24 @@ pub const PltGotSection = struct {...@@ -1130,23 +1130,24 @@ pub const PltGotSection = struct {
1130 try plt_got.symbols.append(gpa, sym_index);1130 try plt_got.symbols.append(gpa, sym_index);
1131 }1131 }
11321132
1133 pub fn size(plt_got: PltGotSection) usize {1133 pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
1134 return plt_got.symbols.items.len * 16;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 };
1135 }1143 }
11361144
1137 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {1145 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1138 for (plt_got.symbols.items) |sym_index| {1146 const cpu_arch = elf_file.getTarget().cpu.arch;
1139 const sym = elf_file.symbol(sym_index);1147 switch (cpu_arch) {
1140 const target_addr = sym.gotAddress(elf_file);1148 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
1141 const source_addr = sym.pltGotAddress(elf_file);1149 .aarch64 => try aarch64.write(plt_got, elf_file, writer),
1142 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;1150 else => return error.UnsupportedCpuArch,
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);
1150 }1151 }
1151 }1152 }
11521153
...@@ -1175,6 +1176,50 @@ pub const PltGotSection = struct {...@@ -1175,6 +1176,50 @@ pub const PltGotSection = struct {
1175 };1176 };
1176 }1177 }
1177 }1178 }
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 };
1178};1223};
11791224
1180pub const CopyRelSection = struct {1225pub const CopyRelSection = struct {