authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-10 15:32:58+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-10 15:32:58+01:00
logc1bda06c14250f6751b834331a0f9c40f409c7d1
treed43996ee94cd2ae88ee32966064a08520755609d
parent4ba4f94c93d5eb1945f1b2c8c53a45cbee609d3b
parent1a6b2e84ac5d88f00bfb281c8101f2b69a962b67
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19225 from ziglang/elf-aarch64

elf: port aarch64 support from zld

14 files changed, 902 insertions(+), 366 deletions(-)

CMakeLists.txt+1
......@@ -598,6 +598,7 @@ set(ZIG_STAGE2_SOURCES
598598 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocatable.zig"
599599 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocation.zig"
600600 "${CMAKE_SOURCE_DIR}/src/link/Elf/synthetic_sections.zig"
601 "${CMAKE_SOURCE_DIR}/src/link/Elf/thunks.zig"
601602 "${CMAKE_SOURCE_DIR}/src/link/MachO.zig"
602603 "${CMAKE_SOURCE_DIR}/src/link/MachO/Archive.zig"
603604 "${CMAKE_SOURCE_DIR}/src/link/MachO/Atom.zig"
src/link/Elf.zig+92-24
......@@ -206,6 +206,9 @@ num_ifunc_dynrelocs: usize = 0,
206206/// List of atoms that are owned directly by the linker.
207207atoms: std.ArrayListUnmanaged(Atom) = .{},
208208
209/// List of range extension thunks.
210thunks: std.ArrayListUnmanaged(Thunk) = .{},
211
209212/// Table of last atom index in a section and matching atom free list if any.
210213last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
211214
......@@ -255,7 +258,7 @@ pub fn createEmpty(
255258 };
256259
257260 const page_size: u32 = switch (target.cpu.arch) {
258 .powerpc64le => 0x10000,
261 .aarch64, .powerpc64le => 0x10000,
259262 .sparc64 => 0x2000,
260263 else => 0x1000,
261264 };
......@@ -488,6 +491,7 @@ pub fn deinit(self: *Elf) void {
488491 self.start_stop_indexes.deinit(gpa);
489492
490493 self.atoms.deinit(gpa);
494 self.thunks.deinit(gpa);
491495 for (self.last_atom_and_free_list_table.values()) |*value| {
492496 value.free_list.deinit(gpa);
493497 }
......@@ -1373,7 +1377,14 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
13731377 try self.writePhdrTable();
13741378 try self.writeShdrTable();
13751379 try self.writeAtoms();
1376 try self.writeSyntheticSections();
1380 self.writeSyntheticSections() catch |err| switch (err) {
1381 error.RelocFailure => return error.FlushFailure,
1382 error.UnsupportedCpuArch => {
1383 try self.reportUnsupportedCpuArch();
1384 return error.FlushFailure;
1385 },
1386 else => |e| return e,
1387 };
13771388
13781389 if (self.entry_index == null and self.base.isExe()) {
13791390 log.debug("flushing. no_entry_point_found = true", .{});
......@@ -2098,7 +2109,6 @@ fn scanRelocs(self: *Elf) !void {
20982109 }
20992110 if (sym.flags.needs_tlsdesc) {
21002111 log.debug("'{s}' needs TLSDESC", .{sym.name(self)});
2101 try self.dynsym.addSymbol(index, self);
21022112 try self.got.addTlsDescSymbol(index, self);
21032113 }
21042114 }
......@@ -3164,11 +3174,20 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
31643174 }
31653175
31663176 // _GLOBAL_OFFSET_TABLE_
3167 if (self.got_plt_section_index) |shndx| {
3168 const shdr = &self.shdrs.items[shndx];
3169 const symbol_ptr = self.symbol(self.got_index.?);
3170 symbol_ptr.value = shdr.sh_addr;
3171 symbol_ptr.output_section_index = shndx;
3177 if (self.getTarget().cpu.arch == .x86_64) {
3178 if (self.got_plt_section_index) |shndx| {
3179 const shdr = self.shdrs.items[shndx];
3180 const sym = self.symbol(self.got_index.?);
3181 sym.value = shdr.sh_addr;
3182 sym.output_section_index = shndx;
3183 }
3184 } else {
3185 if (self.got_section_index) |shndx| {
3186 const shdr = self.shdrs.items[shndx];
3187 const sym = self.symbol(self.got_index.?);
3188 sym.value = shdr.sh_addr;
3189 sym.output_section_index = shndx;
3190 }
31723191 }
31733192
31743193 // _PROCEDURE_LINKAGE_TABLE_
......@@ -3578,7 +3597,7 @@ fn sortInitFini(self: *Elf) !void {
35783597 }
35793598 };
35803599
3581 for (self.shdrs.items, 0..) |*shdr, shndx| {
3600 for (self.shdrs.items, 0..) |shdr, shndx| {
35823601 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
35833602
35843603 var is_init_fini = false;
......@@ -4023,6 +4042,8 @@ fn updateSectionSizes(self: *Elf) !void {
40234042 const target = self.base.comp.root_mod.resolved_target.result;
40244043 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
40254044 const shdr = &self.shdrs.items[shndx];
4045 if (atom_list.items.len == 0) continue;
4046 if (self.requiresThunks() and shdr.sh_flags & elf.SHF_EXECINSTR != 0) continue;
40264047 for (atom_list.items) |atom_index| {
40274048 const atom_ptr = self.atom(atom_index) orelse continue;
40284049 if (!atom_ptr.flags.alive) continue;
......@@ -4034,6 +4055,17 @@ fn updateSectionSizes(self: *Elf) !void {
40344055 }
40354056 }
40364057
4058 if (self.requiresThunks()) {
4059 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
4060 const shdr = self.shdrs.items[shndx];
4061 if (shdr.sh_flags & elf.SHF_EXECINSTR == 0) continue;
4062 if (atom_list.items.len == 0) continue;
4063
4064 // Create jump/branch range extenders if needed.
4065 try thunks.createThunks(shndx, self);
4066 }
4067 }
4068
40374069 if (self.eh_frame_section_index) |index| {
40384070 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
40394071 }
......@@ -4047,7 +4079,7 @@ fn updateSectionSizes(self: *Elf) !void {
40474079 }
40484080
40494081 if (self.plt_section_index) |index| {
4050 self.shdrs.items[index].sh_size = self.plt.size();
4082 self.shdrs.items[index].sh_size = self.plt.size(self);
40514083 }
40524084
40534085 if (self.got_plt_section_index) |index| {
......@@ -4055,7 +4087,7 @@ fn updateSectionSizes(self: *Elf) !void {
40554087 }
40564088
40574089 if (self.plt_got_section_index) |index| {
4058 self.shdrs.items[index].sh_size = self.plt_got.size();
4090 self.shdrs.items[index].sh_size = self.plt_got.size(self);
40594091 }
40604092
40614093 if (self.rela_dyn_section_index) |shndx| {
......@@ -4490,7 +4522,7 @@ fn writeAtoms(self: *Elf) !void {
44904522 const buffer = try gpa.alloc(u8, sh_size);
44914523 defer gpa.free(buffer);
44924524 const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and
4493 shdr.sh_flags & elf.SHF_EXECINSTR != 0)
4525 shdr.sh_flags & elf.SHF_EXECINSTR != 0 and self.getTarget().cpu.arch == .x86_64)
44944526 0xcc // int3
44954527 else
44964528 0;
......@@ -4561,6 +4593,13 @@ pub fn updateSymtabSize(self: *Elf) !void {
45614593 nlocals += 1;
45624594 }
45634595
4596 for (self.thunks.items) |*th| {
4597 th.output_symtab_ctx.ilocal = nlocals + 1;
4598 th.calcSymtabSize(self);
4599 nlocals += th.output_symtab_ctx.nlocals;
4600 strsize += th.output_symtab_ctx.strsize;
4601 }
4602
45644603 for (files.items) |index| {
45654604 const file_ptr = self.file(index).?;
45664605 const ctx = switch (file_ptr) {
......@@ -4692,14 +4731,7 @@ fn writeSyntheticSections(self: *Elf) !void {
46924731 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
46934732 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
46944733 defer buffer.deinit();
4695 eh_frame.writeEhFrame(self, buffer.writer()) catch |err| switch (err) {
4696 error.RelocFailure => return error.FlushFailure,
4697 error.UnsupportedCpuArch => {
4698 try self.reportUnsupportedCpuArch();
4699 return error.FlushFailure;
4700 },
4701 else => |e| return e,
4702 };
4734 try eh_frame.writeEhFrame(self, buffer.writer());
47034735 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
47044736 }
47054737
......@@ -4731,7 +4763,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47314763
47324764 if (self.plt_section_index) |shndx| {
47334765 const shdr = self.shdrs.items[shndx];
4734 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size());
4766 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));
47354767 defer buffer.deinit();
47364768 try self.plt.write(self, buffer.writer());
47374769 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
......@@ -4747,7 +4779,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47474779
47484780 if (self.plt_got_section_index) |shndx| {
47494781 const shdr = self.shdrs.items[shndx];
4750 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size());
4782 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
47514783 defer buffer.deinit();
47524784 try self.plt_got.write(self, buffer.writer());
47534785 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
......@@ -4798,6 +4830,10 @@ pub fn writeSymtab(self: *Elf) !void {
47984830
47994831 self.writeSectionSymbols();
48004832
4833 for (self.thunks.items) |th| {
4834 th.writeSymtab(self);
4835 }
4836
48014837 if (self.zigObjectPtr()) |zig_object| {
48024838 zig_object.asFile().writeSymtab(self);
48034839 }
......@@ -5393,6 +5429,18 @@ pub fn addAtom(self: *Elf) !Atom.Index {
53935429 return index;
53945430}
53955431
5432pub fn addThunk(self: *Elf) !Thunk.Index {
5433 const index = @as(Thunk.Index, @intCast(self.thunks.items.len));
5434 const th = try self.thunks.addOne(self.base.comp.gpa);
5435 th.* = .{};
5436 return index;
5437}
5438
5439pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk {
5440 assert(index < self.thunks.items.len);
5441 return &self.thunks.items[index];
5442}
5443
53965444pub fn file(self: *Elf, index: File.Index) ?File {
53975445 const tag = self.files.items(.tags)[index];
53985446 return switch (tag) {
......@@ -5572,11 +5620,17 @@ pub fn gotAddress(self: *Elf) u64 {
55725620pub fn tpAddress(self: *Elf) u64 {
55735621 const index = self.phdr_tls_index orelse return 0;
55745622 const phdr = self.phdrs.items[index];
5575 return mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align);
5623 return switch (self.getTarget().cpu.arch) {
5624 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
5625 .aarch64 => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align),
5626 else => @panic("TODO implement getTpAddress for this arch"),
5627 };
55765628}
55775629
55785630pub fn dtpAddress(self: *Elf) u64 {
5579 return self.tlsAddress();
5631 const index = self.phdr_tls_index orelse return 0;
5632 const phdr = self.phdrs.items[index];
5633 return phdr.p_vaddr;
55805634}
55815635
55825636pub fn tlsAddress(self: *Elf) u64 {
......@@ -5943,6 +5997,10 @@ fn fmtDumpState(
59435997 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});
59445998 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
59455999 }
6000 try writer.writeAll("thunks\n");
6001 for (self.thunks.items, 0..) |th, index| {
6002 try writer.print("thunk({d}) : {}\n", .{ index, th.fmt(self) });
6003 }
59466004 try writer.print("{}\n", .{self.zig_got.fmt(self)});
59476005 try writer.print("{}\n", .{self.got.fmt(self)});
59486006 try writer.print("{}\n", .{self.plt.fmt(self)});
......@@ -6010,6 +6068,14 @@ pub fn getTarget(self: Elf) std.Target {
60106068 return self.base.comp.root_mod.resolved_target.result;
60116069}
60126070
6071fn requiresThunks(self: Elf) bool {
6072 return switch (self.getTarget().cpu.arch) {
6073 .aarch64 => true,
6074 .x86_64, .riscv64 => false,
6075 else => @panic("TODO unimplemented architecture"),
6076 };
6077}
6078
60136079/// The following three values are only observed at compile-time and used to emit a compile error
60146080/// to remind the programmer to update expected maximum numbers of different program header types
60156081/// so that we reserve enough space for the program header table up-front.
......@@ -6140,6 +6206,7 @@ const musl = @import("../musl.zig");
61406206const relocatable = @import("Elf/relocatable.zig");
61416207const relocation = @import("Elf/relocation.zig");
61426208const target_util = @import("../target.zig");
6209const thunks = @import("Elf/thunks.zig");
61436210const trace = @import("../tracy.zig").trace;
61446211const synthetic_sections = @import("Elf/synthetic_sections.zig");
61456212
......@@ -6172,6 +6239,7 @@ const PltGotSection = synthetic_sections.PltGotSection;
61726239const SharedObject = @import("Elf/SharedObject.zig");
61736240const Symbol = @import("Elf/Symbol.zig");
61746241const StringTable = @import("StringTable.zig");
6242const Thunk = thunks.Thunk;
61756243const TypedValue = @import("../TypedValue.zig");
61766244const VerneedSection = synthetic_sections.VerneedSection;
61776245const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/Atom.zig+187-27
......@@ -31,6 +31,9 @@ rel_num: u32 = 0,
3131/// Index of this atom in the linker's atoms table.
3232atom_index: Index = 0,
3333
34/// Index of the thunk for this atom.
35thunk_index: Thunk.Index = 0,
36
3437/// Flags we use for state tracking.
3538flags: Flags = .{},
3639
......@@ -64,6 +67,10 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
6467 return elf_file.file(self.file_index);
6568}
6669
70pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
71 return elf_file.thunk(self.thunk_index);
72}
73
6774pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
6875 return switch (self.file(elf_file).?) {
6976 .object => |x| x.shdrs.items[self.input_section_index],
......@@ -1592,6 +1599,8 @@ const aarch64 = struct {
15921599 _ = it;
15931600
15941601 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1602 const is_dyn_lib = elf_file.base.isDynLib();
1603
15951604 switch (r_type) {
15961605 .ABS64 => {
15971606 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
......@@ -1620,6 +1629,35 @@ const aarch64 = struct {
16201629 }
16211630 },
16221631
1632 .TLSLE_ADD_TPREL_HI12,
1633 .TLSLE_ADD_TPREL_LO12_NC,
1634 => {
1635 if (is_dyn_lib) try atom.reportPicError(symbol, rel, elf_file);
1636 },
1637
1638 .TLSIE_ADR_GOTTPREL_PAGE21,
1639 .TLSIE_LD64_GOTTPREL_LO12_NC,
1640 => {
1641 symbol.flags.needs_gottp = true;
1642 },
1643
1644 .TLSGD_ADR_PAGE21,
1645 .TLSGD_ADD_LO12_NC,
1646 => {
1647 symbol.flags.needs_tlsgd = true;
1648 },
1649
1650 .TLSDESC_ADR_PAGE21,
1651 .TLSDESC_LD64_LO12,
1652 .TLSDESC_ADD_LO12,
1653 .TLSDESC_CALL,
1654 => {
1655 const should_relax = elf_file.base.isStatic() or (!is_dyn_lib and !symbol.flags.import);
1656 if (!should_relax) {
1657 symbol.flags.needs_tlsdesc = true;
1658 }
1659 },
1660
16231661 .ADD_ABS_LO12_NC,
16241662 .ADR_PREL_LO21,
16251663 .LDST8_ABS_LO12_NC,
......@@ -1627,6 +1665,8 @@ const aarch64 = struct {
16271665 .LDST32_ABS_LO12_NC,
16281666 .LDST64_ABS_LO12_NC,
16291667 .LDST128_ABS_LO12_NC,
1668 .PREL32,
1669 .PREL64,
16301670 => {},
16311671
16321672 else => try atom.reportUnhandledRelocError(rel, elf_file),
......@@ -1640,7 +1680,7 @@ const aarch64 = struct {
16401680 target: *const Symbol,
16411681 args: ResolveArgs,
16421682 it: *RelocsIterator,
1643 code: []u8,
1683 code_buffer: []u8,
16441684 stream: anytype,
16451685 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
16461686 _ = it;
......@@ -1648,9 +1688,10 @@ const aarch64 = struct {
16481688 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
16491689 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
16501690 const cwriter = stream.writer();
1691 const code = code_buffer[r_offset..][0..4];
1692 const file_ptr = atom.file(elf_file).?;
16511693
16521694 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1653 _ = TP;
16541695 _ = DTP;
16551696 _ = ZIG_GOT;
16561697
......@@ -1669,20 +1710,27 @@ const aarch64 = struct {
16691710 .CALL26,
16701711 .JUMP26,
16711712 => {
1672 // TODO: add thunk support
1673 const disp: i28 = math.cast(i28, S + A - P) orelse {
1674 var err = try elf_file.addErrorWithNotes(1);
1675 try err.addMsg(elf_file, "TODO: branch relocation target ({s}) exceeds max jump distance", .{
1676 target.name(elf_file),
1677 });
1678 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{
1679 atom.file(elf_file).?.fmtPath(),
1680 atom.name(elf_file),
1681 r_offset,
1682 });
1683 return;
1713 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
1714 const th = atom.thunk(elf_file);
1715 const target_index = switch (file_ptr) {
1716 .zig_object => |x| x.symbol(rel.r_sym()),
1717 .object => |x| x.symbols.items[rel.r_sym()],
1718 else => unreachable,
1719 };
1720 const S_: i64 = @intCast(th.targetAddress(target_index, elf_file));
1721 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
16841722 };
1685 try aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]);
1723 aarch64_util.writeBranchImm(disp, code);
1724 },
1725
1726 .PREL32 => {
1727 const value = math.cast(i32, S + A - P) orelse return error.Overflow;
1728 mem.writeInt(u32, code, @bitCast(value), .little);
1729 },
1730
1731 .PREL64 => {
1732 const value = S + A - P;
1733 mem.writeInt(u64, code_buffer[r_offset..][0..8], @bitCast(value), .little);
16861734 },
16871735
16881736 .ADR_PREL_PG_HI21 => {
......@@ -1690,14 +1738,14 @@ const aarch64 = struct {
16901738 const saddr = @as(u64, @intCast(P));
16911739 const taddr = @as(u64, @intCast(S + A));
16921740 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1693 try aarch64_util.writePages(pages, code[r_offset..][0..4]);
1741 aarch64_util.writeAdrpInst(pages, code);
16941742 },
16951743
16961744 .ADR_GOT_PAGE => if (target.flags.has_got) {
16971745 const saddr = @as(u64, @intCast(P));
16981746 const taddr = @as(u64, @intCast(G + GOT + A));
16991747 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1700 try aarch64_util.writePages(pages, code[r_offset..][0..4]);
1748 aarch64_util.writeAdrpInst(pages, code);
17011749 } else {
17021750 // TODO: relax
17031751 var err = try elf_file.addErrorWithNotes(1);
......@@ -1712,10 +1760,14 @@ const aarch64 = struct {
17121760 .LD64_GOT_LO12_NC => {
17131761 assert(target.flags.has_got);
17141762 const taddr = @as(u64, @intCast(G + GOT + A));
1715 try aarch64_util.writePageOffset(.load_store_64, taddr, code[r_offset..][0..4]);
1763 aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code);
1764 },
1765
1766 .ADD_ABS_LO12_NC => {
1767 const taddr = @as(u64, @intCast(S + A));
1768 aarch64_util.writeAddImmInst(@truncate(taddr), code);
17161769 },
17171770
1718 .ADD_ABS_LO12_NC,
17191771 .LDST8_ABS_LO12_NC,
17201772 .LDST16_ABS_LO12_NC,
17211773 .LDST32_ABS_LO12_NC,
......@@ -1724,16 +1776,121 @@ const aarch64 = struct {
17241776 => {
17251777 // TODO: NC means no overflow check
17261778 const taddr = @as(u64, @intCast(S + A));
1727 const kind: aarch64_util.PageOffsetInstKind = switch (r_type) {
1728 .ADD_ABS_LO12_NC => .arithmetic,
1729 .LDST8_ABS_LO12_NC => .load_store_8,
1730 .LDST16_ABS_LO12_NC => .load_store_16,
1731 .LDST32_ABS_LO12_NC => .load_store_32,
1732 .LDST64_ABS_LO12_NC => .load_store_64,
1733 .LDST128_ABS_LO12_NC => .load_store_128,
1779 const offset: u12 = switch (r_type) {
1780 .LDST8_ABS_LO12_NC => @truncate(taddr),
1781 .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2),
1782 .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4),
1783 .LDST64_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 8),
1784 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
17341785 else => unreachable,
17351786 };
1736 try aarch64_util.writePageOffset(kind, taddr, code[r_offset..][0..4]);
1787 aarch64_util.writeLoadStoreRegInst(offset, code);
1788 },
1789
1790 .TLSLE_ADD_TPREL_HI12 => {
1791 const value = math.cast(i12, (S + A - TP) >> 12) orelse
1792 return error.Overflow;
1793 aarch64_util.writeAddImmInst(@bitCast(value), code);
1794 },
1795
1796 .TLSLE_ADD_TPREL_LO12_NC => {
1797 const value: i12 = @truncate(S + A - TP);
1798 aarch64_util.writeAddImmInst(@bitCast(value), code);
1799 },
1800
1801 .TLSIE_ADR_GOTTPREL_PAGE21 => {
1802 const S_: i64 = @intCast(target.gotTpAddress(elf_file));
1803 const saddr: u64 = @intCast(P);
1804 const taddr: u64 = @intCast(S_ + A);
1805 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1806 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
1807 aarch64_util.writeAdrpInst(pages, code);
1808 },
1809
1810 .TLSIE_LD64_GOTTPREL_LO12_NC => {
1811 const S_: i64 = @intCast(target.gotTpAddress(elf_file));
1812 const taddr: u64 = @intCast(S_ + A);
1813 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1814 const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);
1815 aarch64_util.writeLoadStoreRegInst(offset, code);
1816 },
1817
1818 .TLSGD_ADR_PAGE21 => {
1819 const S_: i64 = @intCast(target.tlsGdAddress(elf_file));
1820 const saddr: u64 = @intCast(P);
1821 const taddr: u64 = @intCast(S_ + A);
1822 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1823 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
1824 aarch64_util.writeAdrpInst(pages, code);
1825 },
1826
1827 .TLSGD_ADD_LO12_NC => {
1828 const S_: i64 = @intCast(target.tlsGdAddress(elf_file));
1829 const taddr: u64 = @intCast(S_ + A);
1830 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1831 const offset: u12 = @truncate(taddr);
1832 aarch64_util.writeAddImmInst(offset, code);
1833 },
1834
1835 .TLSDESC_ADR_PAGE21 => {
1836 if (target.flags.has_tlsdesc) {
1837 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1838 const saddr: u64 = @intCast(P);
1839 const taddr: u64 = @intCast(S_ + A);
1840 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1841 const pages: u21 = @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr));
1842 aarch64_util.writeAdrpInst(pages, code);
1843 } else {
1844 relocs_log.debug(" relaxing adrp => nop", .{});
1845 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
1846 }
1847 },
1848
1849 .TLSDESC_LD64_LO12 => {
1850 if (target.flags.has_tlsdesc) {
1851 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1852 const taddr: u64 = @intCast(S_ + A);
1853 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1854 const offset: u12 = try math.divExact(u12, @truncate(taddr), 8);
1855 aarch64_util.writeLoadStoreRegInst(offset, code);
1856 } else {
1857 relocs_log.debug(" relaxing ldr => nop", .{});
1858 mem.writeInt(u32, code, Instruction.nop().toU32(), .little);
1859 }
1860 },
1861
1862 .TLSDESC_ADD_LO12 => {
1863 if (target.flags.has_tlsdesc) {
1864 const S_: i64 = @intCast(target.tlsDescAddress(elf_file));
1865 const taddr: u64 = @intCast(S_ + A);
1866 relocs_log.debug(" [{x} => {x}]", .{ P, taddr });
1867 const offset: u12 = @truncate(taddr);
1868 aarch64_util.writeAddImmInst(offset, code);
1869 } else {
1870 const old_inst = Instruction{
1871 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
1872 Instruction,
1873 Instruction.add_subtract_immediate,
1874 ), code),
1875 };
1876 const rd: Register = @enumFromInt(old_inst.add_subtract_immediate.rd);
1877 relocs_log.debug(" relaxing add({s}) => movz(x0, {x})", .{ @tagName(rd), S + A - TP });
1878 const value: u16 = @bitCast(math.cast(i16, (S + A - TP) >> 16) orelse return error.Overflow);
1879 mem.writeInt(u32, code, Instruction.movz(.x0, value, 16).toU32(), .little);
1880 }
1881 },
1882
1883 .TLSDESC_CALL => if (!target.flags.has_tlsdesc) {
1884 const old_inst = Instruction{
1885 .unconditional_branch_register = mem.bytesToValue(std.meta.TagPayload(
1886 Instruction,
1887 Instruction.unconditional_branch_register,
1888 ), code),
1889 };
1890 const rn: Register = @enumFromInt(old_inst.unconditional_branch_register.rn);
1891 relocs_log.debug(" relaxing br({s}) => movk(x0, {x})", .{ @tagName(rn), S + A - TP });
1892 const value: u16 = @bitCast(@as(i16, @truncate(S + A - TP)));
1893 mem.writeInt(u32, code, Instruction.movk(.x0, value, 0).toU32(), .little);
17371894 },
17381895
17391896 else => try atom.reportUnhandledRelocError(rel, elf_file),
......@@ -1768,6 +1925,8 @@ const aarch64 = struct {
17681925 }
17691926
17701927 const aarch64_util = @import("../aarch64.zig");
1928 const Instruction = aarch64_util.Instruction;
1929 const Register = aarch64_util.Register;
17711930};
17721931
17731932const riscv = struct {
......@@ -2025,3 +2184,4 @@ const Fde = eh_frame.Fde;
20252184const File = @import("file.zig").File;
20262185const Object = @import("Object.zig");
20272186const Symbol = @import("Symbol.zig");
2187const Thunk = @import("thunks.zig").Thunk;
src/link/Elf/LdScript.zig+1
......@@ -139,6 +139,7 @@ const Parser = struct {
139139 } else return error.UnexpectedToken;
140140 };
141141 if (std.mem.eql(u8, value, "elf64-x86-64")) return .x86_64;
142 if (std.mem.eql(u8, value, "elf64-littleaarch64")) return .aarch64;
142143 return error.UnknownCpuArch;
143144 }
144145
src/link/Elf/Object.zig+5-6
......@@ -371,17 +371,16 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
371371 const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
372372 elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)),
373373 else => {},
374 } else {
375 // TODO: convert into an error
376 log.debug("{s}: missing reloc section for unwind info section", .{self.fmtPath()});
377 return;
378 };
374 } else null;
379375
380376 const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx);
381377 defer allocator.free(raw);
382378 const data_start = @as(u32, @intCast(self.eh_frame_data.items.len));
383379 try self.eh_frame_data.appendSlice(allocator, raw);
384 const relocs = try self.preadRelocsAlloc(allocator, handle, relocs_shndx);
380 const relocs = if (relocs_shndx) |index|
381 try self.preadRelocsAlloc(allocator, handle, index)
382 else
383 &[0]elf.Elf64_Rela{};
385384 defer allocator.free(relocs);
386385 const rel_start = @as(u32, @intCast(self.relocs.items.len));
387386 try self.relocs.appendUnalignedSlice(allocator, relocs);
src/link/Elf/Symbol.zig+6-3
......@@ -139,14 +139,16 @@ 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 {
146147 if (!symbol.flags.has_plt) return 0;
147148 const extras = symbol.extra(elf_file).?;
148149 const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?];
149 return shdr.sh_addr + extras.plt * 16 + PltSection.preamble_size;
150 const cpu_arch = elf_file.getTarget().cpu.arch;
151 return shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch);
150152}
151153
152154pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) u64 {
......@@ -251,7 +253,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
251253 break :blk 0;
252254 }
253255 if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file);
254 const shdr = &elf_file.shdrs.items[st_shndx];
256 const shdr = elf_file.shdrs.items[st_shndx];
255257 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
256258 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
257259 break :blk symbol.address(.{ .plt = false }, elf_file);
......@@ -441,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;
441443const LinkerDefined = @import("LinkerDefined.zig");
442444const Object = @import("Object.zig");
443445const PltSection = synthetic_sections.PltSection;
446const PltGotSection = synthetic_sections.PltGotSection;
444447const SharedObject = @import("SharedObject.zig");
445448const Symbol = @This();
446449const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/eh_frame.zig+1
......@@ -214,6 +214,7 @@ pub const Iterator = struct {
214214 const reader = stream.reader();
215215
216216 const size = try reader.readInt(u32, .little);
217 if (size == 0) return null;
217218 if (size == 0xFFFFFFFF) @panic("TODO");
218219
219220 const id = try reader.readInt(u32, .little);
src/link/Elf/synthetic_sections.zig+190-50
......@@ -634,8 +634,17 @@ pub const GotSection = struct {
634634 }
635635 },
636636 .tlsdesc => {
637 try writeInt(0, elf_file, writer);
638 try writeInt(0, elf_file, writer);
637 if (symbol.?.flags.import) {
638 try writeInt(0, elf_file, writer);
639 try writeInt(0, elf_file, writer);
640 } else {
641 try writeInt(0, elf_file, writer);
642 const offset = if (apply_relocs)
643 @as(i64, @intCast(symbol.?.address(.{}, elf_file))) - @as(i64, @intCast(elf_file.tlsAddress()))
644 else
645 0;
646 try writeInt(offset, elf_file, writer);
647 }
639648 },
640649 }
641650 }
......@@ -738,8 +747,9 @@ pub const GotSection = struct {
738747 const offset = symbol.?.tlsDescAddress(elf_file);
739748 elf_file.addRelaDynAssumeCapacity(.{
740749 .offset = offset,
741 .sym = extra.?.dynamic,
750 .sym = if (symbol.?.flags.import) extra.?.dynamic else 0,
742751 .type = relocation.encode(.tlsdesc, cpu_arch),
752 .addend = if (symbol.?.flags.import) 0 else @intCast(symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()),
743753 });
744754 },
745755 }
......@@ -857,8 +867,6 @@ pub const PltSection = struct {
857867 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
858868 output_symtab_ctx: Elf.SymtabCtx = .{},
859869
860 pub const preamble_size = 32;
861
862870 pub fn deinit(plt: *PltSection, allocator: Allocator) void {
863871 plt.symbols.deinit(allocator);
864872 }
......@@ -877,39 +885,33 @@ pub const PltSection = struct {
877885 try plt.symbols.append(gpa, sym_index);
878886 }
879887
880 pub fn size(plt: PltSection) usize {
881 return preamble_size + plt.symbols.items.len * 16;
888 pub fn size(plt: PltSection, elf_file: *Elf) usize {
889 const cpu_arch = elf_file.getTarget().cpu.arch;
890 return preambleSize(cpu_arch) + plt.symbols.items.len * entrySize(cpu_arch);
882891 }
883892
884 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
885 const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr;
886 const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr;
887 var preamble = [_]u8{
888 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
889 0x41, 0x53, // push r11
890 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // push qword ptr [rip] -> .got.plt[1]
891 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[2]
893 pub fn preambleSize(cpu_arch: std.Target.Cpu.Arch) usize {
894 return switch (cpu_arch) {
895 .x86_64 => 32,
896 .aarch64 => 8 * @sizeOf(u32),
897 else => @panic("TODO implement preambleSize for this cpu arch"),
892898 };
893 var disp = @as(i64, @intCast(got_plt_addr + 8)) - @as(i64, @intCast(plt_addr + 8)) - 4;
894 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);
895 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
896 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
897 try writer.writeAll(&preamble);
898 try writer.writeByteNTimes(0xcc, preamble_size - preamble.len);
899
900 for (plt.symbols.items, 0..) |sym_index, i| {
901 const sym = elf_file.symbol(sym_index);
902 const target_addr = sym.gotPltAddress(elf_file);
903 const source_addr = sym.pltAddress(elf_file);
904 disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4;
905 var entry = [_]u8{
906 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
907 0x41, 0xbb, 0x00, 0x00, 0x00, 0x00, // mov r11d, N
908 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[N]
909 };
910 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);
911 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);
912 try writer.writeAll(&entry);
899 }
900
901 pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize {
902 return switch (cpu_arch) {
903 .x86_64 => 16,
904 .aarch64 => 4 * @sizeOf(u32),
905 else => @panic("TODO implement entrySize for this cpu arch"),
906 };
907 }
908
909 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
910 const cpu_arch = elf_file.getTarget().cpu.arch;
911 switch (cpu_arch) {
912 .x86_64 => try x86_64.write(plt, elf_file, writer),
913 .aarch64 => try aarch64.write(plt, elf_file, writer),
914 else => return error.UnsupportedCpuArch,
913915 }
914916 }
915917
......@@ -946,6 +948,7 @@ pub const PltSection = struct {
946948 }
947949
948950 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
951 const cpu_arch = elf_file.getTarget().cpu.arch;
949952 for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
950953 const sym = elf_file.symbol(sym_index);
951954 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
......@@ -958,7 +961,7 @@ pub const PltSection = struct {
958961 .st_other = 0,
959962 .st_shndx = @intCast(elf_file.plt_section_index.?),
960963 .st_value = sym.pltAddress(elf_file),
961 .st_size = 16,
964 .st_size = entrySize(cpu_arch),
962965 };
963966 }
964967 }
......@@ -992,6 +995,97 @@ pub const PltSection = struct {
992995 });
993996 }
994997 }
998
999 const x86_64 = struct {
1000 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
1001 const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr;
1002 const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr;
1003 var preamble = [_]u8{
1004 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1005 0x41, 0x53, // push r11
1006 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // push qword ptr [rip] -> .got.plt[1]
1007 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[2]
1008 };
1009 var disp = @as(i64, @intCast(got_plt_addr + 8)) - @as(i64, @intCast(plt_addr + 8)) - 4;
1010 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);
1011 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;
1012 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);
1013 try writer.writeAll(&preamble);
1014 try writer.writeByteNTimes(0xcc, preambleSize(.x86_64) - preamble.len);
1015
1016 for (plt.symbols.items, 0..) |sym_index, i| {
1017 const sym = elf_file.symbol(sym_index);
1018 const target_addr = sym.gotPltAddress(elf_file);
1019 const source_addr = sym.pltAddress(elf_file);
1020 disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4;
1021 var entry = [_]u8{
1022 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1023 0x41, 0xbb, 0x00, 0x00, 0x00, 0x00, // mov r11d, N
1024 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[N]
1025 };
1026 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little);
1027 mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little);
1028 try writer.writeAll(&entry);
1029 }
1030 }
1031 };
1032
1033 const aarch64 = struct {
1034 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
1035 {
1036 const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr;
1037 const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr;
1038 // TODO: relax if possible
1039 // .got.plt[2]
1040 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
1041 const ldr_off = try math.divExact(u12, @truncate(got_plt_addr + 16), 8);
1042 const add_off: u12 = @truncate(got_plt_addr + 16);
1043
1044 const preamble = &[_]Instruction{
1045 Instruction.stp(
1046 .x16,
1047 .x30,
1048 Register.sp,
1049 Instruction.LoadStorePairOffset.pre_index(-16),
1050 ),
1051 Instruction.adrp(.x16, pages),
1052 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),
1053 Instruction.add(.x16, .x16, add_off, false),
1054 Instruction.br(.x17),
1055 Instruction.nop(),
1056 Instruction.nop(),
1057 Instruction.nop(),
1058 };
1059 comptime assert(preamble.len == 8);
1060 for (preamble) |inst| {
1061 try writer.writeInt(u32, inst.toU32(), .little);
1062 }
1063 }
1064
1065 for (plt.symbols.items) |sym_index| {
1066 const sym = elf_file.symbol(sym_index);
1067 const target_addr = sym.gotPltAddress(elf_file);
1068 const source_addr = sym.pltAddress(elf_file);
1069 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
1070 const ldr_off = try math.divExact(u12, @truncate(target_addr), 8);
1071 const add_off: u12 = @truncate(target_addr);
1072 const insts = &[_]Instruction{
1073 Instruction.adrp(.x16, pages),
1074 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),
1075 Instruction.add(.x16, .x16, add_off, false),
1076 Instruction.br(.x17),
1077 };
1078 comptime assert(insts.len == 4);
1079 for (insts) |inst| {
1080 try writer.writeInt(u32, inst.toU32(), .little);
1081 }
1082 }
1083 }
1084
1085 const aarch64_util = @import("../aarch64.zig");
1086 const Instruction = aarch64_util.Instruction;
1087 const Register = aarch64_util.Register;
1088 };
9951089};
9961090
9971091pub const GotPltSection = struct {
......@@ -1046,23 +1140,24 @@ pub const PltGotSection = struct {
10461140 try plt_got.symbols.append(gpa, sym_index);
10471141 }
10481142
1049 pub fn size(plt_got: PltGotSection) usize {
1050 return plt_got.symbols.items.len * 16;
1143 pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
1144 return plt_got.symbols.items.len * entrySize(elf_file.getTarget().cpu.arch);
1145 }
1146
1147 pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize {
1148 return switch (cpu_arch) {
1149 .x86_64 => 16,
1150 .aarch64 => 4 * @sizeOf(u32),
1151 else => @panic("TODO implement PltGotSection.entrySize for this arch"),
1152 };
10511153 }
10521154
10531155 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1054 for (plt_got.symbols.items) |sym_index| {
1055 const sym = elf_file.symbol(sym_index);
1056 const target_addr = sym.gotAddress(elf_file);
1057 const source_addr = sym.pltGotAddress(elf_file);
1058 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
1059 var entry = [_]u8{
1060 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1061 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
1062 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1063 };
1064 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
1065 try writer.writeAll(&entry);
1156 const cpu_arch = elf_file.getTarget().cpu.arch;
1157 switch (cpu_arch) {
1158 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
1159 .aarch64 => try aarch64.write(plt_got, elf_file, writer),
1160 else => return error.UnsupportedCpuArch,
10661161 }
10671162 }
10681163
......@@ -1091,6 +1186,50 @@ pub const PltGotSection = struct {
10911186 };
10921187 }
10931188 }
1189
1190 const x86_64 = struct {
1191 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1192 for (plt_got.symbols.items) |sym_index| {
1193 const sym = elf_file.symbol(sym_index);
1194 const target_addr = sym.gotAddress(elf_file);
1195 const source_addr = sym.pltGotAddress(elf_file);
1196 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;
1197 var entry = [_]u8{
1198 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
1199 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N]
1200 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc,
1201 };
1202 mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little);
1203 try writer.writeAll(&entry);
1204 }
1205 }
1206 };
1207
1208 const aarch64 = struct {
1209 fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1210 for (plt_got.symbols.items) |sym_index| {
1211 const sym = elf_file.symbol(sym_index);
1212 const target_addr = sym.gotAddress(elf_file);
1213 const source_addr = sym.pltGotAddress(elf_file);
1214 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
1215 const off = try math.divExact(u12, @truncate(target_addr), 8);
1216 const insts = &[_]Instruction{
1217 Instruction.adrp(.x16, pages),
1218 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),
1219 Instruction.br(.x17),
1220 Instruction.nop(),
1221 };
1222 comptime assert(insts.len == 4);
1223 for (insts) |inst| {
1224 try writer.writeInt(u32, inst.toU32(), .little);
1225 }
1226 }
1227 }
1228
1229 const aarch64_util = @import("../aarch64.zig");
1230 const Instruction = aarch64_util.Instruction;
1231 const Register = aarch64_util.Register;
1232 };
10941233};
10951234
10961235pub const CopyRelSection = struct {
......@@ -1629,6 +1768,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
16291768const assert = std.debug.assert;
16301769const builtin = @import("builtin");
16311770const elf = std.elf;
1771const math = std.math;
16321772const mem = std.mem;
16331773const log = std.log.scoped(.link);
16341774const relocation = @import("relocation.zig");
src/link/Elf/thunks.zig created+243
......@@ -0,0 +1,243 @@
1pub fn createThunks(shndx: u32, elf_file: *Elf) !void {
2 const gpa = elf_file.base.comp.gpa;
3 const cpu_arch = elf_file.getTarget().cpu.arch;
4 const shdr = &elf_file.shdrs.items[shndx];
5 const atoms = elf_file.output_sections.get(shndx).?.items;
6 assert(atoms.len > 0);
7
8 for (atoms) |atom_index| {
9 elf_file.atom(atom_index).?.value = @bitCast(@as(i64, -1));
10 }
11
12 var i: usize = 0;
13 while (i < atoms.len) {
14 const start = i;
15 const start_atom = elf_file.atom(atoms[start]).?;
16 assert(start_atom.flags.alive);
17 start_atom.value = try advance(shdr, start_atom.size, start_atom.alignment);
18 i += 1;
19
20 while (i < atoms.len and
21 shdr.sh_size - start_atom.value < maxAllowedDistance(cpu_arch)) : (i += 1)
22 {
23 const atom_index = atoms[i];
24 const atom = elf_file.atom(atom_index).?;
25 assert(atom.flags.alive);
26 atom.value = try advance(shdr, atom.size, atom.alignment);
27 }
28
29 // Insert a thunk at the group end
30 const thunk_index = try elf_file.addThunk();
31 const thunk = elf_file.thunk(thunk_index);
32 thunk.output_section_index = shndx;
33
34 // Scan relocs in the group and create trampolines for any unreachable callsite
35 for (atoms[start..i]) |atom_index| {
36 const atom = elf_file.atom(atom_index).?;
37 const file = atom.file(elf_file).?;
38 log.debug("atom({d}) {s}", .{ atom_index, atom.name(elf_file) });
39 for (atom.relocs(elf_file)) |rel| {
40 const is_reachable = switch (cpu_arch) {
41 .aarch64 => aarch64.isReachable(atom, rel, elf_file),
42 .x86_64, .riscv64 => unreachable,
43 else => @panic("unsupported arch"),
44 };
45 if (is_reachable) continue;
46 const target = switch (file) {
47 .zig_object => |x| x.symbol(rel.r_sym()),
48 .object => |x| x.symbols.items[rel.r_sym()],
49 else => unreachable,
50 };
51 try thunk.symbols.put(gpa, target, {});
52 }
53 atom.thunk_index = thunk_index;
54 }
55
56 thunk.value = try advance(shdr, thunk.size(elf_file), Atom.Alignment.fromNonzeroByteUnits(2));
57
58 log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(elf_file) });
59 }
60}
61
62fn advance(shdr: *elf.Elf64_Shdr, size: u64, alignment: Atom.Alignment) !u64 {
63 const offset = alignment.forward(shdr.sh_size);
64 const padding = offset - shdr.sh_size;
65 shdr.sh_size += padding + size;
66 shdr.sh_addralign = @max(shdr.sh_addralign, alignment.toByteUnits(1));
67 return offset;
68}
69
70/// A branch will need an extender if its target is larger than
71/// `2^(jump_bits - 1) - margin` where margin is some arbitrary number.
72fn maxAllowedDistance(cpu_arch: std.Target.Cpu.Arch) u32 {
73 return switch (cpu_arch) {
74 .aarch64 => 0x500_000,
75 .x86_64, .riscv64 => unreachable,
76 else => @panic("unhandled arch"),
77 };
78}
79
80pub const Thunk = struct {
81 value: u64 = 0,
82 output_section_index: u32 = 0,
83 symbols: std.AutoArrayHashMapUnmanaged(Symbol.Index, void) = .{},
84 output_symtab_ctx: Elf.SymtabCtx = .{},
85
86 pub fn deinit(thunk: *Thunk, allocator: Allocator) void {
87 thunk.symbols.deinit(allocator);
88 }
89
90 pub fn size(thunk: Thunk, elf_file: *Elf) usize {
91 const cpu_arch = elf_file.getTarget().cpu.arch;
92 return thunk.symbols.keys().len * trampolineSize(cpu_arch);
93 }
94
95 pub fn address(thunk: Thunk, elf_file: *Elf) u64 {
96 const shdr = elf_file.shdrs.items[thunk.output_section_index];
97 return shdr.sh_addr + thunk.value;
98 }
99
100 pub fn targetAddress(thunk: Thunk, sym_index: Symbol.Index, elf_file: *Elf) u64 {
101 const cpu_arch = elf_file.getTarget().cpu.arch;
102 return thunk.address(elf_file) + thunk.symbols.getIndex(sym_index).? * trampolineSize(cpu_arch);
103 }
104
105 pub fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
106 switch (elf_file.options.cpu_arch.?) {
107 .aarch64 => try aarch64.write(thunk, elf_file, writer),
108 .x86_64, .riscv64 => unreachable,
109 else => @panic("unhandled arch"),
110 }
111 }
112
113 pub fn calcSymtabSize(thunk: *Thunk, elf_file: *Elf) void {
114 thunk.output_symtab_ctx.nlocals = @as(u32, @intCast(thunk.symbols.keys().len));
115 for (thunk.symbols.keys()) |sym_index| {
116 const sym = elf_file.symbol(sym_index);
117 thunk.output_symtab_ctx.strsize += @as(u32, @intCast(sym.name(elf_file).len + "$thunk".len + 1));
118 }
119 }
120
121 pub fn writeSymtab(thunk: Thunk, elf_file: *Elf) void {
122 const cpu_arch = elf_file.getTarget().cpu.arch;
123 for (thunk.symbols.keys(), thunk.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
124 const sym = elf_file.symbol(sym_index);
125 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
126 elf_file.strtab.appendSliceAssumeCapacity(sym.name(elf_file));
127 elf_file.strtab.appendSliceAssumeCapacity("$thunk");
128 elf_file.strtab.appendAssumeCapacity(0);
129 elf_file.symtab.items[ilocal] = .{
130 .st_name = st_name,
131 .st_info = elf.STT_FUNC,
132 .st_other = 0,
133 .st_shndx = @intCast(thunk.output_section_index),
134 .st_value = thunk.targetAddress(sym_index, elf_file),
135 .st_size = trampolineSize(cpu_arch),
136 };
137 }
138 }
139
140 fn trampolineSize(cpu_arch: std.Target.Cpu.Arch) usize {
141 return switch (cpu_arch) {
142 .aarch64 => aarch64.trampoline_size,
143 .x86_64, .riscv64 => unreachable,
144 else => @panic("unhandled arch"),
145 };
146 }
147
148 pub fn format(
149 thunk: Thunk,
150 comptime unused_fmt_string: []const u8,
151 options: std.fmt.FormatOptions,
152 writer: anytype,
153 ) !void {
154 _ = thunk;
155 _ = unused_fmt_string;
156 _ = options;
157 _ = writer;
158 @compileError("do not format Thunk directly");
159 }
160
161 pub fn fmt(thunk: Thunk, elf_file: *Elf) std.fmt.Formatter(format2) {
162 return .{ .data = .{
163 .thunk = thunk,
164 .elf_file = elf_file,
165 } };
166 }
167
168 const FormatContext = struct {
169 thunk: Thunk,
170 elf_file: *Elf,
171 };
172
173 fn format2(
174 ctx: FormatContext,
175 comptime unused_fmt_string: []const u8,
176 options: std.fmt.FormatOptions,
177 writer: anytype,
178 ) !void {
179 _ = options;
180 _ = unused_fmt_string;
181 const thunk = ctx.thunk;
182 const elf_file = ctx.elf_file;
183 try writer.print("@{x} : size({x})\n", .{ thunk.value, thunk.size(elf_file) });
184 for (thunk.symbols.keys()) |index| {
185 const sym = elf_file.symbol(index);
186 try writer.print(" %{d} : {s} : @{x}\n", .{ index, sym.name(elf_file), sym.value });
187 }
188 }
189
190 pub const Index = u32;
191};
192
193const aarch64 = struct {
194 fn isReachable(atom: *const Atom, rel: elf.Elf64_Rela, elf_file: *Elf) bool {
195 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
196 if (r_type != .CALL26 and r_type != .JUMP26) return true;
197 const file = atom.file(elf_file).?;
198 const target_index = switch (file) {
199 .zig_object => |x| x.symbol(rel.r_sym()),
200 .object => |x| x.symbols.items[rel.r_sym()],
201 else => unreachable,
202 };
203 const target = elf_file.symbol(target_index);
204 if (target.flags.has_plt) return false;
205 if (atom.output_section_index != target.output_section_index) return false;
206 const target_atom = target.atom(elf_file).?;
207 if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false;
208 const saddr = @as(i64, @intCast(atom.address(elf_file) + rel.r_offset));
209 const taddr: i64 = @intCast(target.address(.{}, elf_file));
210 _ = math.cast(i28, taddr + rel.r_addend - saddr) orelse return false;
211 return true;
212 }
213
214 fn write(thunk: Thunk, elf_file: *Elf, writer: anytype) !void {
215 for (thunk.symbols.keys(), 0..) |sym_index, i| {
216 const sym = elf_file.symbol(sym_index);
217 const saddr = thunk.address(elf_file) + i * trampoline_size;
218 const taddr = sym.address(.{}, elf_file);
219 const pages = try util.calcNumberOfPages(saddr, taddr);
220 try writer.writeInt(u32, Instruction.adrp(.x16, pages).toU32(), .little);
221 const off: u12 = @truncate(taddr);
222 try writer.writeInt(u32, Instruction.add(.x16, .x16, off, false).toU32(), .little);
223 try writer.writeInt(u32, Instruction.br(.x16).toU32(), .little);
224 }
225 }
226
227 const trampoline_size = 3 * @sizeOf(u32);
228
229 const util = @import("../aarch64.zig");
230 const Instruction = util.Instruction;
231};
232
233const assert = std.debug.assert;
234const elf = std.elf;
235const log = std.log.scoped(.link);
236const math = std.math;
237const mem = std.mem;
238const std = @import("std");
239
240const Allocator = mem.Allocator;
241const Atom = @import("Atom.zig");
242const Elf = @import("../Elf.zig");
243const Symbol = @import("Symbol.zig");
src/link/MachO/Atom.zig+25-7
......@@ -700,7 +700,7 @@ fn resolveRelocInner(
700700 const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));
701701 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
702702 };
703 try aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);
703 aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);
704704 },
705705 else => unreachable,
706706 }
......@@ -771,7 +771,7 @@ fn resolveRelocInner(
771771 break :target math.cast(u64, target) orelse return error.Overflow;
772772 };
773773 const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target)));
774 try aarch64.writePages(pages, code[rel_offset..][0..4]);
774 aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]);
775775 },
776776
777777 .pageoff => {
......@@ -780,8 +780,26 @@ fn resolveRelocInner(
780780 assert(!rel.meta.pcrel);
781781 const target = math.cast(u64, S + A) orelse return error.Overflow;
782782 const inst_code = code[rel_offset..][0..4];
783 const kind = aarch64.classifyInst(inst_code);
784 try aarch64.writePageOffset(kind, target, inst_code);
783 if (aarch64.isArithmeticOp(inst_code)) {
784 aarch64.writeAddImmInst(@truncate(target), inst_code);
785 } else {
786 var inst = aarch64.Instruction{
787 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
788 aarch64.Instruction,
789 aarch64.Instruction.load_store_register,
790 ), inst_code),
791 };
792 inst.load_store_register.offset = switch (inst.load_store_register.size) {
793 0 => if (inst.load_store_register.v == 1)
794 try math.divExact(u12, @truncate(target), 16)
795 else
796 @truncate(target),
797 1 => try math.divExact(u12, @truncate(target), 2),
798 2 => try math.divExact(u12, @truncate(target), 4),
799 3 => try math.divExact(u12, @truncate(target), 8),
800 };
801 try writer.writeInt(u32, inst.toU32(), .little);
802 }
785803 },
786804
787805 .got_load_pageoff => {
......@@ -789,7 +807,7 @@ fn resolveRelocInner(
789807 assert(rel.meta.length == 2);
790808 assert(!rel.meta.pcrel);
791809 const target = math.cast(u64, G + A) orelse return error.Overflow;
792 try aarch64.writePageOffset(.load_store_64, target, code[rel_offset..][0..4]);
810 aarch64.writeLoadStoreRegInst(try math.divExact(u12, @truncate(target), 8), code[rel_offset..][0..4]);
793811 },
794812
795813 .tlvp_pageoff => {
......@@ -841,7 +859,7 @@ fn resolveRelocInner(
841859 .load_store_register = .{
842860 .rt = reg_info.rd,
843861 .rn = reg_info.rn,
844 .offset = try aarch64.calcPageOffset(.load_store_64, target),
862 .offset = try math.divExact(u12, @truncate(target), 8),
845863 .opc = 0b01,
846864 .op1 = 0b01,
847865 .v = 0,
......@@ -851,7 +869,7 @@ fn resolveRelocInner(
851869 .add_subtract_immediate = .{
852870 .rd = reg_info.rd,
853871 .rn = reg_info.rn,
854 .imm12 = try aarch64.calcPageOffset(.arithmetic, target),
872 .imm12 = @truncate(target),
855873 .sh = 0,
856874 .s = 0,
857875 .op = 0,
src/link/MachO/synthetic.zig+5-5
......@@ -269,7 +269,7 @@ pub const StubsSection = struct {
269269 // TODO relax if possible
270270 const pages = try aarch64.calcNumberOfPages(source, target);
271271 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
272 const off = try aarch64.calcPageOffset(.load_store_64, target);
272 const off = try math.divExact(u12, @truncate(target), 8);
273273 try writer.writeInt(
274274 u32,
275275 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
......@@ -413,7 +413,7 @@ pub const StubsHelperSection = struct {
413413 // TODO relax if possible
414414 const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr);
415415 try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);
416 const off = try aarch64.calcPageOffset(.arithmetic, dyld_private_addr);
416 const off: u12 = @truncate(dyld_private_addr);
417417 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);
418418 }
419419 try writer.writeInt(u32, aarch64.Instruction.stp(
......@@ -426,7 +426,7 @@ pub const StubsHelperSection = struct {
426426 // TODO relax if possible
427427 const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr);
428428 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
429 const off = try aarch64.calcPageOffset(.load_store_64, dyld_stub_binder_addr);
429 const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);
430430 try writer.writeInt(u32, aarch64.Instruction.ldr(
431431 .x16,
432432 .x16,
......@@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct {
681681 const source = addr;
682682 const pages = try aarch64.calcNumberOfPages(source, target);
683683 try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);
684 const off = try aarch64.calcPageOffset(.load_store_64, target);
684 const off = try math.divExact(u12, @truncate(target), 8);
685685 try writer.writeInt(
686686 u32,
687687 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
......@@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct {
694694 const source = addr + 2 * @sizeOf(u32);
695695 const pages = try aarch64.calcNumberOfPages(source, target);
696696 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
697 const off = try aarch64.calcPageOffset(.load_store_64, target);
697 const off = try math.divExact(u12, @truncate(target), 8);
698698 try writer.writeInt(
699699 u32,
700700 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
src/link/MachO/thunks.zig+1-1
......@@ -101,7 +101,7 @@ pub const Thunk = struct {
101101 const taddr = sym.getAddress(.{}, macho_file);
102102 const pages = try aarch64.calcNumberOfPages(saddr, taddr);
103103 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
104 const off = try aarch64.calcPageOffset(.arithmetic, taddr);
104 const off: u12 = @truncate(taddr);
105105 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);
106106 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
107107 }
src/link/aarch64.zig+16-56
......@@ -3,66 +3,26 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
33 return ((group_decode >> 2) == 4);
44}
55
6pub const PageOffsetInstKind = enum {
7 arithmetic,
8 load_store_8,
9 load_store_16,
10 load_store_32,
11 load_store_64,
12 load_store_128,
13};
14
15pub fn classifyInst(code: *const [4]u8) PageOffsetInstKind {
16 if (isArithmeticOp(code)) return .arithmetic;
17 const inst = Instruction{
18 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
7 var inst = Instruction{
8 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
199 Instruction,
20 Instruction.load_store_register,
10 Instruction.add_subtract_immediate,
2111 ), code),
2212 };
23 return switch (inst.load_store_register.size) {
24 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8,
25 1 => .load_store_16,
26 2 => .load_store_32,
27 3 => .load_store_64,
28 };
13 inst.add_subtract_immediate.imm12 = value;
14 mem.writeInt(u32, code, inst.toU32(), .little);
2915}
3016
31pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 {
32 const narrowed = @as(u12, @truncate(taddr));
33 return switch (kind) {
34 .arithmetic, .load_store_8 => narrowed,
35 .load_store_16 => try math.divExact(u12, narrowed, 2),
36 .load_store_32 => try math.divExact(u12, narrowed, 4),
37 .load_store_64 => try math.divExact(u12, narrowed, 8),
38 .load_store_128 => try math.divExact(u12, narrowed, 16),
17pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {
18 var inst: Instruction = .{
19 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
20 Instruction,
21 Instruction.load_store_register,
22 ), code),
3923 };
40}
41
42pub fn writePageOffset(kind: PageOffsetInstKind, taddr: u64, code: *[4]u8) !void {
43 const value = try calcPageOffset(kind, taddr);
44 switch (kind) {
45 .arithmetic => {
46 var inst = Instruction{
47 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
48 Instruction,
49 Instruction.add_subtract_immediate,
50 ), code),
51 };
52 inst.add_subtract_immediate.imm12 = value;
53 mem.writeInt(u32, code, inst.toU32(), .little);
54 },
55 else => {
56 var inst: Instruction = .{
57 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
58 Instruction,
59 Instruction.load_store_register,
60 ), code),
61 };
62 inst.load_store_register.offset = value;
63 mem.writeInt(u32, code, inst.toU32(), .little);
64 },
65 }
24 inst.load_store_register.offset = value;
25 mem.writeInt(u32, code, inst.toU32(), .little);
6626}
6727
6828pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
......@@ -72,7 +32,7 @@ pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
7232 return pages;
7333}
7434
75pub fn writePages(pages: u21, code: *[4]u8) !void {
35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
7636 var inst = Instruction{
7737 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(
7838 Instruction,
......@@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void {
8444 mem.writeInt(u32, code, inst.toU32(), .little);
8545}
8646
87pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {
47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
8848 var inst = Instruction{
8949 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(
9050 Instruction,
test/link/elf.zig+129-187
......@@ -20,30 +20,142 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
2020 .os_tag = .linux,
2121 .abi = .gnu,
2222 });
23 const aarch64_musl = b.resolveTargetQuery(.{
24 .cpu_arch = .aarch64,
25 .os_tag = .linux,
26 .abi = .musl,
27 });
23 // const aarch64_musl = b.resolveTargetQuery(.{
24 // .cpu_arch = .aarch64,
25 // .os_tag = .linux,
26 // .abi = .musl,
27 // });
28 // const aarch64_gnu = b.resolveTargetQuery(.{
29 // .cpu_arch = .aarch64,
30 // .os_tag = .linux,
31 // .abi = .gnu,
32 // });
2833 const riscv64_musl = b.resolveTargetQuery(.{
2934 .cpu_arch = .riscv64,
3035 .os_tag = .linux,
3136 .abi = .musl,
3237 });
3338
34 // x86_64 tests
35 // Exercise linker in -r mode
36 elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));
37 elf_step.dependOn(testEmitRelocatable(b, .{ .target = x86_64_musl }));
38 elf_step.dependOn(testRelocatableArchive(b, .{ .target = x86_64_musl }));
39 elf_step.dependOn(testRelocatableEhFrame(b, .{ .target = x86_64_musl }));
40 elf_step.dependOn(testRelocatableNoEhFrame(b, .{ .target = x86_64_musl }));
39 // Common tests
40 for (&[_]std.Target.Cpu.Arch{
41 .x86_64,
42 .aarch64,
43 }) |cpu_arch| {
44 const musl_target = b.resolveTargetQuery(.{
45 .cpu_arch = cpu_arch,
46 .os_tag = .linux,
47 .abi = .musl,
48 });
49 const gnu_target = b.resolveTargetQuery(.{
50 .cpu_arch = cpu_arch,
51 .os_tag = .linux,
52 .abi = .gnu,
53 });
4154
42 // Exercise linker in ar mode
43 elf_step.dependOn(testEmitStaticLib(b, .{ .target = x86_64_musl }));
44 elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));
55 // Exercise linker in -r mode
56 elf_step.dependOn(testEmitRelocatable(b, .{ .target = musl_target }));
57 elf_step.dependOn(testRelocatableArchive(b, .{ .target = musl_target }));
58 elf_step.dependOn(testRelocatableEhFrame(b, .{ .target = musl_target }));
59 elf_step.dependOn(testRelocatableNoEhFrame(b, .{ .target = musl_target }));
60
61 // Exercise linker in ar mode
62 elf_step.dependOn(testEmitStaticLib(b, .{ .target = musl_target }));
63
64 // Exercise linker with LLVM backend
65 // musl tests
66 elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target }));
67 elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target }));
68 elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target }));
69 elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target }));
70 elf_step.dependOn(testEntryPoint(b, .{ .target = musl_target }));
71 elf_step.dependOn(testGcSections(b, .{ .target = musl_target }));
72 elf_step.dependOn(testImageBase(b, .{ .target = musl_target }));
73 elf_step.dependOn(testInitArrayOrder(b, .{ .target = musl_target }));
74 elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = musl_target }));
75 // https://github.com/ziglang/zig/issues/17449
76 // elf_step.dependOn(testLargeBss(b, .{ .target = musl_target }));
77 elf_step.dependOn(testLinkingC(b, .{ .target = musl_target }));
78 elf_step.dependOn(testLinkingCpp(b, .{ .target = musl_target }));
79 elf_step.dependOn(testLinkingZig(b, .{ .target = musl_target }));
80 // https://github.com/ziglang/zig/issues/17451
81 // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = musl_target }));
82 elf_step.dependOn(testTlsStatic(b, .{ .target = musl_target }));
83 elf_step.dependOn(testStrip(b, .{ .target = musl_target }));
84
85 // glibc tests
86 elf_step.dependOn(testAsNeeded(b, .{ .target = gnu_target }));
87 // https://github.com/ziglang/zig/issues/17430
88 // elf_step.dependOn(testCanonicalPlt(b, .{ .target = gnu_target }));
89 elf_step.dependOn(testCopyrel(b, .{ .target = gnu_target }));
90 // https://github.com/ziglang/zig/issues/17430
91 // elf_step.dependOn(testCopyrelAlias(b, .{ .target = gnu_target }));
92 // https://github.com/ziglang/zig/issues/17430
93 // elf_step.dependOn(testCopyrelAlignment(b, .{ .target = gnu_target }));
94 elf_step.dependOn(testDsoPlt(b, .{ .target = gnu_target }));
95 elf_step.dependOn(testDsoUndef(b, .{ .target = gnu_target }));
96 elf_step.dependOn(testExportDynamic(b, .{ .target = gnu_target }));
97 elf_step.dependOn(testExportSymbolsFromExe(b, .{ .target = gnu_target }));
98 // https://github.com/ziglang/zig/issues/17430
99 // elf_step.dependOn(testFuncAddress(b, .{ .target = gnu_target }));
100 elf_step.dependOn(testHiddenWeakUndef(b, .{ .target = gnu_target }));
101 elf_step.dependOn(testIFuncAlias(b, .{ .target = gnu_target }));
102 // https://github.com/ziglang/zig/issues/17430
103 // elf_step.dependOn(testIFuncDlopen(b, .{ .target = gnu_target }));
104 elf_step.dependOn(testIFuncDso(b, .{ .target = gnu_target }));
105 elf_step.dependOn(testIFuncDynamic(b, .{ .target = gnu_target }));
106 elf_step.dependOn(testIFuncExport(b, .{ .target = gnu_target }));
107 elf_step.dependOn(testIFuncFuncPtr(b, .{ .target = gnu_target }));
108 elf_step.dependOn(testIFuncNoPlt(b, .{ .target = gnu_target }));
109 // https://github.com/ziglang/zig/issues/17430 ??
110 // elf_step.dependOn(testIFuncStatic(b, .{ .target = gnu_target }));
111 // elf_step.dependOn(testIFuncStaticPie(b, .{ .target = gnu_target }));
112 elf_step.dependOn(testInitArrayOrder(b, .{ .target = gnu_target }));
113 elf_step.dependOn(testLargeAlignmentDso(b, .{ .target = gnu_target }));
114 elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = gnu_target }));
115 elf_step.dependOn(testLargeBss(b, .{ .target = gnu_target }));
116 elf_step.dependOn(testLinkOrder(b, .{ .target = gnu_target }));
117 elf_step.dependOn(testLdScript(b, .{ .target = gnu_target }));
118 elf_step.dependOn(testLdScriptPathError(b, .{ .target = gnu_target }));
119 elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true }));
120 elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true }));
121 // https://github.com/ziglang/zig/issues/17451
122 // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = gnu_target }));
123 elf_step.dependOn(testPie(b, .{ .target = gnu_target }));
124 elf_step.dependOn(testPltGot(b, .{ .target = gnu_target }));
125 elf_step.dependOn(testPreinitArray(b, .{ .target = gnu_target }));
126 elf_step.dependOn(testSharedAbsSymbol(b, .{ .target = gnu_target }));
127 elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = gnu_target }));
128 elf_step.dependOn(testTlsDso(b, .{ .target = gnu_target }));
129 elf_step.dependOn(testTlsGd(b, .{ .target = gnu_target }));
130 elf_step.dependOn(testTlsGdNoPlt(b, .{ .target = gnu_target }));
131 elf_step.dependOn(testTlsGdToIe(b, .{ .target = gnu_target }));
132 elf_step.dependOn(testTlsIe(b, .{ .target = gnu_target }));
133 elf_step.dependOn(testTlsLargeAlignment(b, .{ .target = gnu_target }));
134 elf_step.dependOn(testTlsLargeTbss(b, .{ .target = gnu_target }));
135 elf_step.dependOn(testTlsLargeStaticImage(b, .{ .target = gnu_target }));
136 elf_step.dependOn(testTlsLd(b, .{ .target = gnu_target }));
137 elf_step.dependOn(testTlsLdDso(b, .{ .target = gnu_target }));
138 elf_step.dependOn(testTlsLdNoPlt(b, .{ .target = gnu_target }));
139 // https://github.com/ziglang/zig/issues/17430
140 // elf_step.dependOn(testTlsNoPic(b, .{ .target = gnu_target }));
141 elf_step.dependOn(testTlsOffsetAlignment(b, .{ .target = gnu_target }));
142 elf_step.dependOn(testTlsPic(b, .{ .target = gnu_target }));
143 elf_step.dependOn(testTlsSmallAlignment(b, .{ .target = gnu_target }));
144 elf_step.dependOn(testUnknownFileTypeError(b, .{ .target = gnu_target }));
145 elf_step.dependOn(testUnresolvedError(b, .{ .target = gnu_target }));
146 elf_step.dependOn(testWeakExports(b, .{ .target = gnu_target }));
147 elf_step.dependOn(testWeakUndefsDso(b, .{ .target = gnu_target }));
148 elf_step.dependOn(testZNow(b, .{ .target = gnu_target }));
149 elf_step.dependOn(testZStackSize(b, .{ .target = gnu_target }));
150 }
45151
46 // Exercise linker with self-hosted backend (no LLVM)
152 // x86_64 specific tests
153 elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_musl }));
154 elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu }));
155
156 // x86_64 self-hosted backend
157 elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));
158 elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));
47159 elf_step.dependOn(testGcSectionsZig(b, .{ .use_llvm = false, .target = default_target }));
48160 elf_step.dependOn(testLinkingObj(b, .{ .use_llvm = false, .target = default_target }));
49161 elf_step.dependOn(testLinkingStaticLib(b, .{ .use_llvm = false, .target = default_target }));
......@@ -51,99 +163,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
51163 elf_step.dependOn(testImportingDataDynamic(b, .{ .use_llvm = false, .target = x86_64_gnu }));
52164 elf_step.dependOn(testImportingDataStatic(b, .{ .use_llvm = false, .target = x86_64_musl }));
53165
54 // Exercise linker with LLVM backend
55 // musl tests
56 elf_step.dependOn(testAbsSymbols(b, .{ .target = x86_64_musl }));
57 elf_step.dependOn(testCommonSymbols(b, .{ .target = x86_64_musl }));
58 elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = x86_64_musl }));
59 elf_step.dependOn(testEmptyObject(b, .{ .target = x86_64_musl }));
60 elf_step.dependOn(testEntryPoint(b, .{ .target = x86_64_musl }));
61 elf_step.dependOn(testGcSections(b, .{ .target = x86_64_musl }));
62 elf_step.dependOn(testImageBase(b, .{ .target = x86_64_musl }));
63 elf_step.dependOn(testInitArrayOrder(b, .{ .target = x86_64_musl }));
64 elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = x86_64_musl }));
65 // https://github.com/ziglang/zig/issues/17449
66 // elf_step.dependOn(testLargeBss(b, .{ .target = x86_64_musl }));
67 elf_step.dependOn(testLinkingC(b, .{ .target = x86_64_musl }));
68 elf_step.dependOn(testLinkingCpp(b, .{ .target = x86_64_musl }));
69 elf_step.dependOn(testLinkingZig(b, .{ .target = x86_64_musl }));
70 // https://github.com/ziglang/zig/issues/17451
71 // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = x86_64_musl }));
72 elf_step.dependOn(testTlsStatic(b, .{ .target = x86_64_musl }));
73 elf_step.dependOn(testStrip(b, .{ .target = x86_64_musl }));
74
75 // glibc tests
76 elf_step.dependOn(testAsNeeded(b, .{ .target = x86_64_gnu }));
77 // https://github.com/ziglang/zig/issues/17430
78 // elf_step.dependOn(testCanonicalPlt(b, .{ .target = x86_64_gnu }));
79 elf_step.dependOn(testCopyrel(b, .{ .target = x86_64_gnu }));
80 // https://github.com/ziglang/zig/issues/17430
81 // elf_step.dependOn(testCopyrelAlias(b, .{ .target = x86_64_gnu }));
82 // https://github.com/ziglang/zig/issues/17430
83 // elf_step.dependOn(testCopyrelAlignment(b, .{ .target = x86_64_gnu }));
84 elf_step.dependOn(testDsoPlt(b, .{ .target = x86_64_gnu }));
85 elf_step.dependOn(testDsoUndef(b, .{ .target = x86_64_gnu }));
86 elf_step.dependOn(testExportDynamic(b, .{ .target = x86_64_gnu }));
87 elf_step.dependOn(testExportSymbolsFromExe(b, .{ .target = x86_64_gnu }));
88 // https://github.com/ziglang/zig/issues/17430
89 // elf_step.dependOn(testFuncAddress(b, .{ .target = x86_64_gnu }));
90 elf_step.dependOn(testHiddenWeakUndef(b, .{ .target = x86_64_gnu }));
91 elf_step.dependOn(testIFuncAlias(b, .{ .target = x86_64_gnu }));
92 // https://github.com/ziglang/zig/issues/17430
93 // elf_step.dependOn(testIFuncDlopen(b, .{ .target = x86_64_gnu }));
94 elf_step.dependOn(testIFuncDso(b, .{ .target = x86_64_gnu }));
95 elf_step.dependOn(testIFuncDynamic(b, .{ .target = x86_64_gnu }));
96 elf_step.dependOn(testIFuncExport(b, .{ .target = x86_64_gnu }));
97 elf_step.dependOn(testIFuncFuncPtr(b, .{ .target = x86_64_gnu }));
98 elf_step.dependOn(testIFuncNoPlt(b, .{ .target = x86_64_gnu }));
99 // https://github.com/ziglang/zig/issues/17430 ??
100 // elf_step.dependOn(testIFuncStatic(b, .{ .target = x86_64_gnu }));
101 // elf_step.dependOn(testIFuncStaticPie(b, .{ .target = x86_64_gnu }));
102 elf_step.dependOn(testInitArrayOrder(b, .{ .target = x86_64_gnu }));
103 elf_step.dependOn(testLargeAlignmentDso(b, .{ .target = x86_64_gnu }));
104 elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = x86_64_gnu }));
105 elf_step.dependOn(testLargeBss(b, .{ .target = x86_64_gnu }));
106 elf_step.dependOn(testLinkOrder(b, .{ .target = x86_64_gnu }));
107 elf_step.dependOn(testLdScript(b, .{ .target = x86_64_gnu }));
108 elf_step.dependOn(testLdScriptPathError(b, .{ .target = x86_64_gnu }));
109 elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = x86_64_gnu, .use_lld = true }));
110 elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = x86_64_gnu, .use_lld = true }));
111 elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_gnu }));
112 // https://github.com/ziglang/zig/issues/17451
113 // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = x86_64_gnu }));
114 elf_step.dependOn(testPie(b, .{ .target = x86_64_gnu }));
115 elf_step.dependOn(testPltGot(b, .{ .target = x86_64_gnu }));
116 elf_step.dependOn(testPreinitArray(b, .{ .target = x86_64_gnu }));
117 elf_step.dependOn(testSharedAbsSymbol(b, .{ .target = x86_64_gnu }));
118 elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = x86_64_gnu }));
119 elf_step.dependOn(testTlsDso(b, .{ .target = x86_64_gnu }));
120 elf_step.dependOn(testTlsGd(b, .{ .target = x86_64_gnu }));
121 elf_step.dependOn(testTlsGdNoPlt(b, .{ .target = x86_64_gnu }));
122 elf_step.dependOn(testTlsGdToIe(b, .{ .target = x86_64_gnu }));
123 elf_step.dependOn(testTlsIe(b, .{ .target = x86_64_gnu }));
124 elf_step.dependOn(testTlsLargeAlignment(b, .{ .target = x86_64_gnu }));
125 elf_step.dependOn(testTlsLargeTbss(b, .{ .target = x86_64_gnu }));
126 elf_step.dependOn(testTlsLargeStaticImage(b, .{ .target = x86_64_gnu }));
127 elf_step.dependOn(testTlsLd(b, .{ .target = x86_64_gnu }));
128 elf_step.dependOn(testTlsLdDso(b, .{ .target = x86_64_gnu }));
129 elf_step.dependOn(testTlsLdNoPlt(b, .{ .target = x86_64_gnu }));
130 // https://github.com/ziglang/zig/issues/17430
131 // elf_step.dependOn(testTlsNoPic(b, .{ .target = x86_64_gnu }));
132 elf_step.dependOn(testTlsOffsetAlignment(b, .{ .target = x86_64_gnu }));
133 elf_step.dependOn(testTlsPic(b, .{ .target = x86_64_gnu }));
134 elf_step.dependOn(testTlsSmallAlignment(b, .{ .target = x86_64_gnu }));
135 elf_step.dependOn(testUnknownFileTypeError(b, .{ .target = x86_64_gnu }));
136 elf_step.dependOn(testUnresolvedError(b, .{ .target = x86_64_gnu }));
137 elf_step.dependOn(testWeakExports(b, .{ .target = x86_64_gnu }));
138 elf_step.dependOn(testWeakUndefsDso(b, .{ .target = x86_64_gnu }));
139 elf_step.dependOn(testZNow(b, .{ .target = x86_64_gnu }));
140 elf_step.dependOn(testZStackSize(b, .{ .target = x86_64_gnu }));
141 elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu }));
142
143 // aarch64 tests
144 elf_step.dependOn(testLinkingC(b, .{ .target = aarch64_musl }));
145
146 // riscv64 tests
166 // riscv64 linker backend is currently not complete enough to support more
147167 elf_step.dependOn(testLinkingC(b, .{ .target = riscv64_musl }));
148168
149169 return elf_step;
......@@ -239,8 +259,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {
239259 exe.addLibraryPath(libbaz.getEmittedBinDirectory());
240260 exe.addRPath(libbaz.getEmittedBinDirectory());
241261 exe.linkLibC();
242 // https://github.com/ziglang/zig/issues/17619
243 exe.pie = true;
244262
245263 const run = addRunArtifact(exe);
246264 run.expectStdOutEqual("42\n");
......@@ -269,8 +287,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {
269287 exe.addLibraryPath(libbaz.getEmittedBinDirectory());
270288 exe.addRPath(libbaz.getEmittedBinDirectory());
271289 exe.linkLibC();
272 // https://github.com/ziglang/zig/issues/17619
273 exe.pie = true;
274290
275291 const run = addRunArtifact(exe);
276292 run.expectStdOutEqual("42\n");
......@@ -489,8 +505,6 @@ fn testCopyrel(b: *Build, opts: Options) *Step {
489505 });
490506 exe.linkLibrary(dso);
491507 exe.linkLibC();
492 // https://github.com/ziglang/zig/issues/17619
493 exe.pie = true;
494508
495509 const run = addRunArtifact(exe);
496510 run.expectStdOutEqual("3 5\n");
......@@ -656,8 +670,6 @@ fn testDsoPlt(b: *Build, opts: Options) *Step {
656670 , &.{});
657671 exe.linkLibrary(dso);
658672 exe.linkLibC();
659 // https://github.com/ziglang/zig/issues/17619
660 exe.pie = true;
661673
662674 const run = addRunArtifact(exe);
663675 run.expectStdOutEqual("Hello WORLD\n");
......@@ -695,8 +707,6 @@ fn testDsoUndef(b: *Build, opts: Options) *Step {
695707 \\}
696708 , &.{});
697709 exe.linkLibC();
698 // https://github.com/ziglang/zig/issues/17619
699 exe.pie = true;
700710
701711 const run = addRunArtifact(exe);
702712 run.expectExitCode(0);
......@@ -1280,8 +1290,6 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step {
12801290 , &.{});
12811291 exe.root_module.pic = true;
12821292 exe.linkLibC();
1283 // https://github.com/ziglang/zig/issues/17619
1284 exe.pie = true;
12851293
12861294 const run = addRunArtifact(exe);
12871295 run.expectExitCode(0);
......@@ -1396,8 +1404,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {
13961404 addCSourceBytes(exe, main_c, &.{});
13971405 exe.linkLibC();
13981406 exe.link_z_lazy = true;
1399 // https://github.com/ziglang/zig/issues/17619
1400 exe.pie = true;
14011407
14021408 const run = addRunArtifact(exe);
14031409 run.expectStdOutEqual("Hello world\n");
......@@ -1407,8 +1413,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {
14071413 const exe = addExecutable(b, opts, .{ .name = "other" });
14081414 addCSourceBytes(exe, main_c, &.{});
14091415 exe.linkLibC();
1410 // https://github.com/ziglang/zig/issues/17619
1411 exe.pie = true;
14121416
14131417 const run = addRunArtifact(exe);
14141418 run.expectStdOutEqual("Hello world\n");
......@@ -1472,8 +1476,6 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step {
14721476 , &.{});
14731477 exe.root_module.pic = true;
14741478 exe.linkLibC();
1475 // https://github.com/ziglang/zig/issues/17619
1476 exe.pie = true;
14771479
14781480 const run = addRunArtifact(exe);
14791481 run.expectStdOutEqual("3\n");
......@@ -1503,8 +1505,6 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step {
15031505 , &.{"-fno-plt"});
15041506 exe.root_module.pic = true;
15051507 exe.linkLibC();
1506 // https://github.com/ziglang/zig/issues/17619
1507 exe.pie = true;
15081508
15091509 const run = addRunArtifact(exe);
15101510 run.expectStdOutEqual("Hello world\n");
......@@ -1834,8 +1834,6 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step {
18341834 , &.{});
18351835 exe.linkLibrary(dso);
18361836 exe.linkLibC();
1837 // https://github.com/ziglang/zig/issues/17619
1838 exe.pie = true;
18391837
18401838 const run = addRunArtifact(exe);
18411839 run.expectStdOutEqual("Hello world");
......@@ -1870,8 +1868,6 @@ fn testLargeAlignmentExe(b: *Build, opts: Options) *Step {
18701868 , &.{});
18711869 exe.link_function_sections = true;
18721870 exe.linkLibC();
1873 // https://github.com/ziglang/zig/issues/17619
1874 exe.pie = true;
18751871
18761872 const check = exe.checkObject();
18771873 check.checkInSymtab();
......@@ -1900,8 +1896,6 @@ fn testLargeBss(b: *Build, opts: Options) *Step {
19001896 \\}
19011897 , &.{});
19021898 exe.linkLibC();
1903 // https://github.com/ziglang/zig/issues/17619
1904 exe.pie = true;
19051899
19061900 const run = addRunArtifact(exe);
19071901 run.expectExitCode(0);
......@@ -1995,8 +1989,6 @@ fn testLdScript(b: *Build, opts: Options) *Step {
19951989 exe.addLibraryPath(dso.getEmittedBinDirectory());
19961990 exe.addRPath(dso.getEmittedBinDirectory());
19971991 exe.linkLibC();
1998 // https://github.com/ziglang/zig/issues/17619
1999 exe.pie = true;
20001992
20011993 const run = addRunArtifact(exe);
20021994 run.expectExitCode(0);
......@@ -2348,8 +2340,6 @@ fn testPltGot(b: *Build, opts: Options) *Step {
23482340 exe.linkLibrary(dso);
23492341 exe.root_module.pic = true;
23502342 exe.linkLibC();
2351 // https://github.com/ziglang/zig/issues/17619
2352 exe.pie = true;
23532343
23542344 const run = addRunArtifact(exe);
23552345 run.expectStdOutEqual("Hello world\n");
......@@ -2752,8 +2742,6 @@ fn testTlsDso(b: *Build, opts: Options) *Step {
27522742 , &.{});
27532743 exe.linkLibrary(dso);
27542744 exe.linkLibC();
2755 // https://github.com/ziglang/zig/issues/17619
2756 exe.pie = true;
27572745
27582746 const run = addRunArtifact(exe);
27592747 run.expectStdOutEqual("5 3 5 3 5 3\n");
......@@ -2912,8 +2900,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {
29122900 exe.linkLibrary(a_so);
29132901 exe.linkLibrary(b_so);
29142902 exe.linkLibC();
2915 // https://github.com/ziglang/zig/issues/17619
2916 exe.pie = true;
29172903
29182904 const run = addRunArtifact(exe);
29192905 run.expectStdOutEqual("1 2 3 4 5 6\n");
......@@ -2927,8 +2913,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {
29272913 exe.linkLibrary(b_so);
29282914 exe.linkLibC();
29292915 // exe.link_relax = false; // TODO
2930 // https://github.com/ziglang/zig/issues/17619
2931 exe.pie = true;
29322916
29332917 const run = addRunArtifact(exe);
29342918 run.expectStdOutEqual("1 2 3 4 5 6\n");
......@@ -2976,8 +2960,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {
29762960 exe.addObject(b_o);
29772961 exe.linkLibrary(dso);
29782962 exe.linkLibC();
2979 // https://github.com/ziglang/zig/issues/17619
2980 exe.pie = true;
29812963
29822964 const run = addRunArtifact(exe);
29832965 run.expectStdOutEqual("1 2 3\n");
......@@ -2993,8 +2975,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {
29932975 exe.addObject(b_o);
29942976 exe.linkLibrary(dso);
29952977 exe.linkLibC();
2996 // https://github.com/ziglang/zig/issues/17619
2997 exe.pie = true;
29982978
29992979 const run = addRunArtifact(exe);
30002980 run.expectStdOutEqual("1 2 3\n");
......@@ -3076,8 +3056,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {
30763056 exe.addObject(main_o);
30773057 exe.linkLibrary(dso);
30783058 exe.linkLibC();
3079 // https://github.com/ziglang/zig/issues/17619
3080 exe.pie = true;
30813059
30823060 const run = addRunArtifact(exe);
30833061 run.expectStdOutEqual(exp_stdout);
......@@ -3090,8 +3068,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {
30903068 exe.linkLibrary(dso);
30913069 exe.linkLibC();
30923070 // exe.link_relax = false; // TODO
3093 // https://github.com/ziglang/zig/issues/17619
3094 exe.pie = true;
30953071
30963072 const run = addRunArtifact(exe);
30973073 run.expectStdOutEqual(exp_stdout);
......@@ -3147,8 +3123,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {
31473123 exe.addObject(c_o);
31483124 exe.linkLibrary(dso);
31493125 exe.linkLibC();
3150 // https://github.com/ziglang/zig/issues/17619
3151 exe.pie = true;
31523126
31533127 const run = addRunArtifact(exe);
31543128 run.expectStdOutEqual("42 1 2 3\n");
......@@ -3161,8 +3135,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {
31613135 exe.addObject(b_o);
31623136 exe.addObject(c_o);
31633137 exe.linkLibC();
3164 // https://github.com/ziglang/zig/issues/17619
3165 exe.pie = true;
31663138
31673139 const run = addRunArtifact(exe);
31683140 run.expectStdOutEqual("42 1 2 3\n");
......@@ -3196,8 +3168,6 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step {
31963168 \\}
31973169 , &.{});
31983170 exe.linkLibC();
3199 // https://github.com/ziglang/zig/issues/17619
3200 exe.pie = true;
32013171
32023172 const run = addRunArtifact(exe);
32033173 run.expectStdOutEqual("3 0 5 0 0 0\n");
......@@ -3220,8 +3190,6 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step {
32203190 , &.{});
32213191 exe.root_module.pic = true;
32223192 exe.linkLibC();
3223 // https://github.com/ziglang/zig/issues/17619
3224 exe.pie = true;
32253193
32263194 const run = addRunArtifact(exe);
32273195 run.expectStdOutEqual("1 2 3 0 5\n");
......@@ -3266,8 +3234,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {
32663234 exe.addObject(main_o);
32673235 exe.addObject(a_o);
32683236 exe.linkLibC();
3269 // https://github.com/ziglang/zig/issues/17619
3270 exe.pie = true;
32713237
32723238 const run = addRunArtifact(exe);
32733239 run.expectStdOutEqual(exp_stdout);
......@@ -3280,8 +3246,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {
32803246 exe.addObject(a_o);
32813247 exe.linkLibC();
32823248 // exe.link_relax = false; // TODO
3283 // https://github.com/ziglang/zig/issues/17619
3284 exe.pie = true;
32853249
32863250 const run = addRunArtifact(exe);
32873251 run.expectStdOutEqual(exp_stdout);
......@@ -3315,8 +3279,6 @@ fn testTlsLdDso(b: *Build, opts: Options) *Step {
33153279 , &.{});
33163280 exe.linkLibrary(dso);
33173281 exe.linkLibC();
3318 // https://github.com/ziglang/zig/issues/17619
3319 exe.pie = true;
33203282
33213283 const run = addRunArtifact(exe);
33223284 run.expectStdOutEqual("1 2\n");
......@@ -3360,8 +3322,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {
33603322 exe.addObject(a_o);
33613323 exe.addObject(b_o);
33623324 exe.linkLibC();
3363 // https://github.com/ziglang/zig/issues/17619
3364 exe.pie = true;
33653325
33663326 const run = addRunArtifact(exe);
33673327 run.expectStdOutEqual("3 5 3 5\n");
......@@ -3374,8 +3334,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {
33743334 exe.addObject(b_o);
33753335 exe.linkLibC();
33763336 // exe.link_relax = false; // TODO
3377 // https://github.com/ziglang/zig/issues/17619
3378 exe.pie = true;
33793337
33803338 const run = addRunArtifact(exe);
33813339 run.expectStdOutEqual("3 5 3 5\n");
......@@ -3461,8 +3419,6 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step {
34613419 exe.addRPath(dso.getEmittedBinDirectory());
34623420 exe.linkLibC();
34633421 exe.root_module.pic = true;
3464 // https://github.com/ziglang/zig/issues/17619
3465 exe.pie = true;
34663422
34673423 const run = addRunArtifact(exe);
34683424 run.expectExitCode(0);
......@@ -3499,8 +3455,6 @@ fn testTlsPic(b: *Build, opts: Options) *Step {
34993455 , &.{});
35003456 exe.addObject(obj);
35013457 exe.linkLibC();
3502 // https://github.com/ziglang/zig/issues/17619
3503 exe.pie = true;
35043458
35053459 const run = addRunArtifact(exe);
35063460 run.expectStdOutEqual("3 5 3 5\n");
......@@ -3548,8 +3502,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {
35483502 exe.addObject(b_o);
35493503 exe.addObject(c_o);
35503504 exe.linkLibC();
3551 // https://github.com/ziglang/zig/issues/17619
3552 exe.pie = true;
35533505
35543506 const run = addRunArtifact(exe);
35553507 run.expectStdOutEqual("42\n");
......@@ -3565,8 +3517,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {
35653517 exe.addObject(c_o);
35663518 exe.linkLibrary(dso);
35673519 exe.linkLibC();
3568 // https://github.com/ziglang/zig/issues/17619
3569 exe.pie = true;
35703520
35713521 const run = addRunArtifact(exe);
35723522 run.expectStdOutEqual("42\n");
......@@ -3717,8 +3667,6 @@ fn testWeakExports(b: *Build, opts: Options) *Step {
37173667 const exe = addExecutable(b, opts, .{ .name = "main" });
37183668 exe.addObject(obj);
37193669 exe.linkLibC();
3720 // https://github.com/ziglang/zig/issues/17619
3721 exe.pie = true;
37223670
37233671 const check = exe.checkObject();
37243672 check.checkInDynamicSymtab();
......@@ -3751,8 +3699,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {
37513699 , &.{});
37523700 exe.linkLibrary(dso);
37533701 exe.linkLibC();
3754 // https://github.com/ziglang/zig/issues/17619
3755 exe.pie = true;
37563702
37573703 const run = addRunArtifact(exe);
37583704 run.expectStdOutEqual("bar=-1\n");
......@@ -3769,8 +3715,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {
37693715 , &.{});
37703716 exe.linkLibrary(dso);
37713717 exe.linkLibC();
3772 // https://github.com/ziglang/zig/issues/17619
3773 exe.pie = true;
37743718
37753719 const run = addRunArtifact(exe);
37763720 run.expectStdOutEqual("bar=5\n");
......@@ -3885,8 +3829,6 @@ fn testZText(b: *Build, opts: Options) *Step {
38853829 , &.{});
38863830 exe.linkLibrary(dso);
38873831 exe.linkLibC();
3888 // https://github.com/ziglang/zig/issues/17619
3889 exe.pie = true;
38903832
38913833 const run = addRunArtifact(exe);
38923834 run.expectStdOutEqual("3\n");