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...@@ -598,6 +598,7 @@ set(ZIG_STAGE2_SOURCES
598 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocatable.zig"598 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocatable.zig"
599 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocation.zig"599 "${CMAKE_SOURCE_DIR}/src/link/Elf/relocation.zig"
600 "${CMAKE_SOURCE_DIR}/src/link/Elf/synthetic_sections.zig"600 "${CMAKE_SOURCE_DIR}/src/link/Elf/synthetic_sections.zig"
601 "${CMAKE_SOURCE_DIR}/src/link/Elf/thunks.zig"
601 "${CMAKE_SOURCE_DIR}/src/link/MachO.zig"602 "${CMAKE_SOURCE_DIR}/src/link/MachO.zig"
602 "${CMAKE_SOURCE_DIR}/src/link/MachO/Archive.zig"603 "${CMAKE_SOURCE_DIR}/src/link/MachO/Archive.zig"
603 "${CMAKE_SOURCE_DIR}/src/link/MachO/Atom.zig"604 "${CMAKE_SOURCE_DIR}/src/link/MachO/Atom.zig"
src/link/Elf.zig+92-24
...@@ -206,6 +206,9 @@ num_ifunc_dynrelocs: usize = 0,...@@ -206,6 +206,9 @@ num_ifunc_dynrelocs: usize = 0,
206/// List of atoms that are owned directly by the linker.206/// List of atoms that are owned directly by the linker.
207atoms: std.ArrayListUnmanaged(Atom) = .{},207atoms: std.ArrayListUnmanaged(Atom) = .{},
208208
209/// List of range extension thunks.
210thunks: std.ArrayListUnmanaged(Thunk) = .{},
211
209/// Table of last atom index in a section and matching atom free list if any.212/// Table of last atom index in a section and matching atom free list if any.
210last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},213last_atom_and_free_list_table: LastAtomAndFreeListTable = .{},
211214
...@@ -255,7 +258,7 @@ pub fn createEmpty(...@@ -255,7 +258,7 @@ pub fn createEmpty(
255 };258 };
256259
257 const page_size: u32 = switch (target.cpu.arch) {260 const page_size: u32 = switch (target.cpu.arch) {
258 .powerpc64le => 0x10000,261 .aarch64, .powerpc64le => 0x10000,
259 .sparc64 => 0x2000,262 .sparc64 => 0x2000,
260 else => 0x1000,263 else => 0x1000,
261 };264 };
...@@ -488,6 +491,7 @@ pub fn deinit(self: *Elf) void {...@@ -488,6 +491,7 @@ pub fn deinit(self: *Elf) void {
488 self.start_stop_indexes.deinit(gpa);491 self.start_stop_indexes.deinit(gpa);
489492
490 self.atoms.deinit(gpa);493 self.atoms.deinit(gpa);
494 self.thunks.deinit(gpa);
491 for (self.last_atom_and_free_list_table.values()) |*value| {495 for (self.last_atom_and_free_list_table.values()) |*value| {
492 value.free_list.deinit(gpa);496 value.free_list.deinit(gpa);
493 }497 }
...@@ -1373,7 +1377,14 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)...@@ -1373,7 +1377,14 @@ pub fn flushModule(self: *Elf, arena: Allocator, prog_node: *std.Progress.Node)
1373 try self.writePhdrTable();1377 try self.writePhdrTable();
1374 try self.writeShdrTable();1378 try self.writeShdrTable();
1375 try self.writeAtoms();1379 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
1378 if (self.entry_index == null and self.base.isExe()) {1389 if (self.entry_index == null and self.base.isExe()) {
1379 log.debug("flushing. no_entry_point_found = true", .{});1390 log.debug("flushing. no_entry_point_found = true", .{});
...@@ -2098,7 +2109,6 @@ fn scanRelocs(self: *Elf) !void {...@@ -2098,7 +2109,6 @@ fn scanRelocs(self: *Elf) !void {
2098 }2109 }
2099 if (sym.flags.needs_tlsdesc) {2110 if (sym.flags.needs_tlsdesc) {
2100 log.debug("'{s}' needs TLSDESC", .{sym.name(self)});2111 log.debug("'{s}' needs TLSDESC", .{sym.name(self)});
2101 try self.dynsym.addSymbol(index, self);
2102 try self.got.addTlsDescSymbol(index, self);2112 try self.got.addTlsDescSymbol(index, self);
2103 }2113 }
2104 }2114 }
...@@ -3164,11 +3174,20 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {...@@ -3164,11 +3174,20 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void {
3164 }3174 }
31653175
3166 // _GLOBAL_OFFSET_TABLE_3176 // _GLOBAL_OFFSET_TABLE_
3167 if (self.got_plt_section_index) |shndx| {3177 if (self.getTarget().cpu.arch == .x86_64) {
3168 const shdr = &self.shdrs.items[shndx];3178 if (self.got_plt_section_index) |shndx| {
3169 const symbol_ptr = self.symbol(self.got_index.?);3179 const shdr = self.shdrs.items[shndx];
3170 symbol_ptr.value = shdr.sh_addr;3180 const sym = self.symbol(self.got_index.?);
3171 symbol_ptr.output_section_index = shndx;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 }
3172 }3191 }
31733192
3174 // _PROCEDURE_LINKAGE_TABLE_3193 // _PROCEDURE_LINKAGE_TABLE_
...@@ -3578,7 +3597,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3578,7 +3597,7 @@ fn sortInitFini(self: *Elf) !void {
3578 }3597 }
3579 };3598 };
35803599
3581 for (self.shdrs.items, 0..) |*shdr, shndx| {3600 for (self.shdrs.items, 0..) |shdr, shndx| {
3582 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3601 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
35833602
3584 var is_init_fini = false;3603 var is_init_fini = false;
...@@ -4023,6 +4042,8 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4023,6 +4042,8 @@ fn updateSectionSizes(self: *Elf) !void {
4023 const target = self.base.comp.root_mod.resolved_target.result;4042 const target = self.base.comp.root_mod.resolved_target.result;
4024 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {4043 for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| {
4025 const shdr = &self.shdrs.items[shndx];4044 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;
4026 for (atom_list.items) |atom_index| {4047 for (atom_list.items) |atom_index| {
4027 const atom_ptr = self.atom(atom_index) orelse continue;4048 const atom_ptr = self.atom(atom_index) orelse continue;
4028 if (!atom_ptr.flags.alive) continue;4049 if (!atom_ptr.flags.alive) continue;
...@@ -4034,6 +4055,17 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4034,6 +4055,17 @@ fn updateSectionSizes(self: *Elf) !void {
4034 }4055 }
4035 }4056 }
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
4037 if (self.eh_frame_section_index) |index| {4069 if (self.eh_frame_section_index) |index| {
4038 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);4070 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
4039 }4071 }
...@@ -4047,7 +4079,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4047,7 +4079,7 @@ fn updateSectionSizes(self: *Elf) !void {
4047 }4079 }
40484080
4049 if (self.plt_section_index) |index| {4081 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);
4051 }4083 }
40524084
4053 if (self.got_plt_section_index) |index| {4085 if (self.got_plt_section_index) |index| {
...@@ -4055,7 +4087,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4055,7 +4087,7 @@ fn updateSectionSizes(self: *Elf) !void {
4055 }4087 }
40564088
4057 if (self.plt_got_section_index) |index| {4089 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);
4059 }4091 }
40604092
4061 if (self.rela_dyn_section_index) |shndx| {4093 if (self.rela_dyn_section_index) |shndx| {
...@@ -4490,7 +4522,7 @@ fn writeAtoms(self: *Elf) !void {...@@ -4490,7 +4522,7 @@ fn writeAtoms(self: *Elf) !void {
4490 const buffer = try gpa.alloc(u8, sh_size);4522 const buffer = try gpa.alloc(u8, sh_size);
4491 defer gpa.free(buffer);4523 defer gpa.free(buffer);
4492 const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and4524 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)
4494 0xcc // int34526 0xcc // int3
4495 else4527 else
4496 0;4528 0;
...@@ -4561,6 +4593,13 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4561,6 +4593,13 @@ pub fn updateSymtabSize(self: *Elf) !void {
4561 nlocals += 1;4593 nlocals += 1;
4562 }4594 }
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
4564 for (files.items) |index| {4603 for (files.items) |index| {
4565 const file_ptr = self.file(index).?;4604 const file_ptr = self.file(index).?;
4566 const ctx = switch (file_ptr) {4605 const ctx = switch (file_ptr) {
...@@ -4692,14 +4731,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4692,14 +4731,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4692 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;4731 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
4693 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);4732 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
4694 defer buffer.deinit();4733 defer buffer.deinit();
4695 eh_frame.writeEhFrame(self, buffer.writer()) catch |err| switch (err) {4734 try eh_frame.writeEhFrame(self, buffer.writer());
4696 error.RelocFailure => return error.FlushFailure,
4697 error.UnsupportedCpuArch => {
4698 try self.reportUnsupportedCpuArch();
4699 return error.FlushFailure;
4700 },
4701 else => |e| return e,
4702 };
4703 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4735 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4704 }4736 }
47054737
...@@ -4731,7 +4763,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4731,7 +4763,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47314763
4732 if (self.plt_section_index) |shndx| {4764 if (self.plt_section_index) |shndx| {
4733 const shdr = self.shdrs.items[shndx];4765 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));
4735 defer buffer.deinit();4767 defer buffer.deinit();
4736 try self.plt.write(self, buffer.writer());4768 try self.plt.write(self, buffer.writer());
4737 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4769 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
...@@ -4747,7 +4779,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4747,7 +4779,7 @@ fn writeSyntheticSections(self: *Elf) !void {
47474779
4748 if (self.plt_got_section_index) |shndx| {4780 if (self.plt_got_section_index) |shndx| {
4749 const shdr = self.shdrs.items[shndx];4781 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));
4751 defer buffer.deinit();4783 defer buffer.deinit();
4752 try self.plt_got.write(self, buffer.writer());4784 try self.plt_got.write(self, buffer.writer());
4753 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4785 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
...@@ -4798,6 +4830,10 @@ pub fn writeSymtab(self: *Elf) !void {...@@ -4798,6 +4830,10 @@ pub fn writeSymtab(self: *Elf) !void {
47984830
4799 self.writeSectionSymbols();4831 self.writeSectionSymbols();
48004832
4833 for (self.thunks.items) |th| {
4834 th.writeSymtab(self);
4835 }
4836
4801 if (self.zigObjectPtr()) |zig_object| {4837 if (self.zigObjectPtr()) |zig_object| {
4802 zig_object.asFile().writeSymtab(self);4838 zig_object.asFile().writeSymtab(self);
4803 }4839 }
...@@ -5393,6 +5429,18 @@ pub fn addAtom(self: *Elf) !Atom.Index {...@@ -5393,6 +5429,18 @@ pub fn addAtom(self: *Elf) !Atom.Index {
5393 return index;5429 return index;
5394}5430}
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
5396pub fn file(self: *Elf, index: File.Index) ?File {5444pub fn file(self: *Elf, index: File.Index) ?File {
5397 const tag = self.files.items(.tags)[index];5445 const tag = self.files.items(.tags)[index];
5398 return switch (tag) {5446 return switch (tag) {
...@@ -5572,11 +5620,17 @@ pub fn gotAddress(self: *Elf) u64 {...@@ -5572,11 +5620,17 @@ pub fn gotAddress(self: *Elf) u64 {
5572pub fn tpAddress(self: *Elf) u64 {5620pub fn tpAddress(self: *Elf) u64 {
5573 const index = self.phdr_tls_index orelse return 0;5621 const index = self.phdr_tls_index orelse return 0;
5574 const phdr = self.phdrs.items[index];5622 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 };
5576}5628}
55775629
5578pub fn dtpAddress(self: *Elf) u64 {5630pub 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;
5580}5634}
55815635
5582pub fn tlsAddress(self: *Elf) u64 {5636pub fn tlsAddress(self: *Elf) u64 {
...@@ -5943,6 +5997,10 @@ fn fmtDumpState(...@@ -5943,6 +5997,10 @@ fn fmtDumpState(
5943 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});5997 try writer.print("linker_defined({d}) : (linker defined)\n", .{index});
5944 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});5998 try writer.print("{}\n", .{linker_defined.fmtSymtab(self)});
5945 }5999 }
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 }
5946 try writer.print("{}\n", .{self.zig_got.fmt(self)});6004 try writer.print("{}\n", .{self.zig_got.fmt(self)});
5947 try writer.print("{}\n", .{self.got.fmt(self)});6005 try writer.print("{}\n", .{self.got.fmt(self)});
5948 try writer.print("{}\n", .{self.plt.fmt(self)});6006 try writer.print("{}\n", .{self.plt.fmt(self)});
...@@ -6010,6 +6068,14 @@ pub fn getTarget(self: Elf) std.Target {...@@ -6010,6 +6068,14 @@ pub fn getTarget(self: Elf) std.Target {
6010 return self.base.comp.root_mod.resolved_target.result;6068 return self.base.comp.root_mod.resolved_target.result;
6011}6069}
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
6013/// The following three values are only observed at compile-time and used to emit a compile error6079/// The following three values are only observed at compile-time and used to emit a compile error
6014/// to remind the programmer to update expected maximum numbers of different program header types6080/// to remind the programmer to update expected maximum numbers of different program header types
6015/// so that we reserve enough space for the program header table up-front.6081/// so that we reserve enough space for the program header table up-front.
...@@ -6140,6 +6206,7 @@ const musl = @import("../musl.zig");...@@ -6140,6 +6206,7 @@ const musl = @import("../musl.zig");
6140const relocatable = @import("Elf/relocatable.zig");6206const relocatable = @import("Elf/relocatable.zig");
6141const relocation = @import("Elf/relocation.zig");6207const relocation = @import("Elf/relocation.zig");
6142const target_util = @import("../target.zig");6208const target_util = @import("../target.zig");
6209const thunks = @import("Elf/thunks.zig");
6143const trace = @import("../tracy.zig").trace;6210const trace = @import("../tracy.zig").trace;
6144const synthetic_sections = @import("Elf/synthetic_sections.zig");6211const synthetic_sections = @import("Elf/synthetic_sections.zig");
61456212
...@@ -6172,6 +6239,7 @@ const PltGotSection = synthetic_sections.PltGotSection;...@@ -6172,6 +6239,7 @@ const PltGotSection = synthetic_sections.PltGotSection;
6172const SharedObject = @import("Elf/SharedObject.zig");6239const SharedObject = @import("Elf/SharedObject.zig");
6173const Symbol = @import("Elf/Symbol.zig");6240const Symbol = @import("Elf/Symbol.zig");
6174const StringTable = @import("StringTable.zig");6241const StringTable = @import("StringTable.zig");
6242const Thunk = thunks.Thunk;
6175const TypedValue = @import("../TypedValue.zig");6243const TypedValue = @import("../TypedValue.zig");
6176const VerneedSection = synthetic_sections.VerneedSection;6244const VerneedSection = synthetic_sections.VerneedSection;
6177const ZigGotSection = synthetic_sections.ZigGotSection;6245const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/Atom.zig+187-27
...@@ -31,6 +31,9 @@ rel_num: u32 = 0,...@@ -31,6 +31,9 @@ rel_num: u32 = 0,
31/// Index of this atom in the linker's atoms table.31/// Index of this atom in the linker's atoms table.
32atom_index: Index = 0,32atom_index: Index = 0,
3333
34/// Index of the thunk for this atom.
35thunk_index: Thunk.Index = 0,
36
34/// Flags we use for state tracking.37/// Flags we use for state tracking.
35flags: Flags = .{},38flags: Flags = .{},
3639
...@@ -64,6 +67,10 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {...@@ -64,6 +67,10 @@ pub fn file(self: Atom, elf_file: *Elf) ?File {
64 return elf_file.file(self.file_index);67 return elf_file.file(self.file_index);
65}68}
6669
70pub fn thunk(self: Atom, elf_file: *Elf) *Thunk {
71 return elf_file.thunk(self.thunk_index);
72}
73
67pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {74pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr {
68 return switch (self.file(elf_file).?) {75 return switch (self.file(elf_file).?) {
69 .object => |x| x.shdrs.items[self.input_section_index],76 .object => |x| x.shdrs.items[self.input_section_index],
...@@ -1592,6 +1599,8 @@ const aarch64 = struct {...@@ -1592,6 +1599,8 @@ const aarch64 = struct {
1592 _ = it;1599 _ = it;
15931600
1594 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1601 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1602 const is_dyn_lib = elf_file.base.isDynLib();
1603
1595 switch (r_type) {1604 switch (r_type) {
1596 .ABS64 => {1605 .ABS64 => {
1597 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);1606 try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file);
...@@ -1620,6 +1629,35 @@ const aarch64 = struct {...@@ -1620,6 +1629,35 @@ const aarch64 = struct {
1620 }1629 }
1621 },1630 },
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
1623 .ADD_ABS_LO12_NC,1661 .ADD_ABS_LO12_NC,
1624 .ADR_PREL_LO21,1662 .ADR_PREL_LO21,
1625 .LDST8_ABS_LO12_NC,1663 .LDST8_ABS_LO12_NC,
...@@ -1627,6 +1665,8 @@ const aarch64 = struct {...@@ -1627,6 +1665,8 @@ const aarch64 = struct {
1627 .LDST32_ABS_LO12_NC,1665 .LDST32_ABS_LO12_NC,
1628 .LDST64_ABS_LO12_NC,1666 .LDST64_ABS_LO12_NC,
1629 .LDST128_ABS_LO12_NC,1667 .LDST128_ABS_LO12_NC,
1668 .PREL32,
1669 .PREL64,
1630 => {},1670 => {},
16311671
1632 else => try atom.reportUnhandledRelocError(rel, elf_file),1672 else => try atom.reportUnhandledRelocError(rel, elf_file),
...@@ -1640,7 +1680,7 @@ const aarch64 = struct {...@@ -1640,7 +1680,7 @@ const aarch64 = struct {
1640 target: *const Symbol,1680 target: *const Symbol,
1641 args: ResolveArgs,1681 args: ResolveArgs,
1642 it: *RelocsIterator,1682 it: *RelocsIterator,
1643 code: []u8,1683 code_buffer: []u8,
1644 stream: anytype,1684 stream: anytype,
1645 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {1685 ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void {
1646 _ = it;1686 _ = it;
...@@ -1648,9 +1688,10 @@ const aarch64 = struct {...@@ -1648,9 +1688,10 @@ const aarch64 = struct {
1648 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());1688 const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type());
1649 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;1689 const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow;
1650 const cwriter = stream.writer();1690 const cwriter = stream.writer();
1691 const code = code_buffer[r_offset..][0..4];
1692 const file_ptr = atom.file(elf_file).?;
16511693
1652 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;1694 const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args;
1653 _ = TP;
1654 _ = DTP;1695 _ = DTP;
1655 _ = ZIG_GOT;1696 _ = ZIG_GOT;
16561697
...@@ -1669,20 +1710,27 @@ const aarch64 = struct {...@@ -1669,20 +1710,27 @@ const aarch64 = struct {
1669 .CALL26,1710 .CALL26,
1670 .JUMP26,1711 .JUMP26,
1671 => {1712 => {
1672 // TODO: add thunk support1713 const disp: i28 = math.cast(i28, S + A - P) orelse blk: {
1673 const disp: i28 = math.cast(i28, S + A - P) orelse {1714 const th = atom.thunk(elf_file);
1674 var err = try elf_file.addErrorWithNotes(1);1715 const target_index = switch (file_ptr) {
1675 try err.addMsg(elf_file, "TODO: branch relocation target ({s}) exceeds max jump distance", .{1716 .zig_object => |x| x.symbol(rel.r_sym()),
1676 target.name(elf_file),1717 .object => |x| x.symbols.items[rel.r_sym()],
1677 });1718 else => unreachable,
1678 try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{1719 };
1679 atom.file(elf_file).?.fmtPath(),1720 const S_: i64 = @intCast(th.targetAddress(target_index, elf_file));
1680 atom.name(elf_file),1721 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
1681 r_offset,
1682 });
1683 return;
1684 };1722 };
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);
1686 },1734 },
16871735
1688 .ADR_PREL_PG_HI21 => {1736 .ADR_PREL_PG_HI21 => {
...@@ -1690,14 +1738,14 @@ const aarch64 = struct {...@@ -1690,14 +1738,14 @@ const aarch64 = struct {
1690 const saddr = @as(u64, @intCast(P));1738 const saddr = @as(u64, @intCast(P));
1691 const taddr = @as(u64, @intCast(S + A));1739 const taddr = @as(u64, @intCast(S + A));
1692 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1740 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);
1694 },1742 },
16951743
1696 .ADR_GOT_PAGE => if (target.flags.has_got) {1744 .ADR_GOT_PAGE => if (target.flags.has_got) {
1697 const saddr = @as(u64, @intCast(P));1745 const saddr = @as(u64, @intCast(P));
1698 const taddr = @as(u64, @intCast(G + GOT + A));1746 const taddr = @as(u64, @intCast(G + GOT + A));
1699 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1747 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);
1701 } else {1749 } else {
1702 // TODO: relax1750 // TODO: relax
1703 var err = try elf_file.addErrorWithNotes(1);1751 var err = try elf_file.addErrorWithNotes(1);
...@@ -1712,10 +1760,14 @@ const aarch64 = struct {...@@ -1712,10 +1760,14 @@ const aarch64 = struct {
1712 .LD64_GOT_LO12_NC => {1760 .LD64_GOT_LO12_NC => {
1713 assert(target.flags.has_got);1761 assert(target.flags.has_got);
1714 const taddr = @as(u64, @intCast(G + GOT + A));1762 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);
1716 },1769 },
17171770
1718 .ADD_ABS_LO12_NC,
1719 .LDST8_ABS_LO12_NC,1771 .LDST8_ABS_LO12_NC,
1720 .LDST16_ABS_LO12_NC,1772 .LDST16_ABS_LO12_NC,
1721 .LDST32_ABS_LO12_NC,1773 .LDST32_ABS_LO12_NC,
...@@ -1724,16 +1776,121 @@ const aarch64 = struct {...@@ -1724,16 +1776,121 @@ const aarch64 = struct {
1724 => {1776 => {
1725 // TODO: NC means no overflow check1777 // TODO: NC means no overflow check
1726 const taddr = @as(u64, @intCast(S + A));1778 const taddr = @as(u64, @intCast(S + A));
1727 const kind: aarch64_util.PageOffsetInstKind = switch (r_type) {1779 const offset: u12 = switch (r_type) {
1728 .ADD_ABS_LO12_NC => .arithmetic,1780 .LDST8_ABS_LO12_NC => @truncate(taddr),
1729 .LDST8_ABS_LO12_NC => .load_store_8,1781 .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2),
1730 .LDST16_ABS_LO12_NC => .load_store_16,1782 .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4),
1731 .LDST32_ABS_LO12_NC => .load_store_32,1783 .LDST64_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 8),
1732 .LDST64_ABS_LO12_NC => .load_store_64,1784 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
1733 .LDST128_ABS_LO12_NC => .load_store_128,
1734 else => unreachable,1785 else => unreachable,
1735 };1786 };
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);
1737 },1894 },
17381895
1739 else => try atom.reportUnhandledRelocError(rel, elf_file),1896 else => try atom.reportUnhandledRelocError(rel, elf_file),
...@@ -1768,6 +1925,8 @@ const aarch64 = struct {...@@ -1768,6 +1925,8 @@ const aarch64 = struct {
1768 }1925 }
17691926
1770 const aarch64_util = @import("../aarch64.zig");1927 const aarch64_util = @import("../aarch64.zig");
1928 const Instruction = aarch64_util.Instruction;
1929 const Register = aarch64_util.Register;
1771};1930};
17721931
1773const riscv = struct {1932const riscv = struct {
...@@ -2025,3 +2184,4 @@ const Fde = eh_frame.Fde;...@@ -2025,3 +2184,4 @@ const Fde = eh_frame.Fde;
2025const File = @import("file.zig").File;2184const File = @import("file.zig").File;
2026const Object = @import("Object.zig");2185const Object = @import("Object.zig");
2027const Symbol = @import("Symbol.zig");2186const Symbol = @import("Symbol.zig");
2187const Thunk = @import("thunks.zig").Thunk;
src/link/Elf/LdScript.zig+1
...@@ -139,6 +139,7 @@ const Parser = struct {...@@ -139,6 +139,7 @@ const Parser = struct {
139 } else return error.UnexpectedToken;139 } else return error.UnexpectedToken;
140 };140 };
141 if (std.mem.eql(u8, value, "elf64-x86-64")) return .x86_64;141 if (std.mem.eql(u8, value, "elf64-x86-64")) return .x86_64;
142 if (std.mem.eql(u8, value, "elf64-littleaarch64")) return .aarch64;
142 return error.UnknownCpuArch;143 return error.UnknownCpuArch;
143 }144 }
144145
src/link/Elf/Object.zig+5-6
...@@ -371,17 +371,16 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:...@@ -371,17 +371,16 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx:
371 const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {371 const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) {
372 elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)),372 elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)),
373 else => {},373 else => {},
374 } else {374 } else null;
375 // TODO: convert into an error
376 log.debug("{s}: missing reloc section for unwind info section", .{self.fmtPath()});
377 return;
378 };
379375
380 const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx);376 const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx);
381 defer allocator.free(raw);377 defer allocator.free(raw);
382 const data_start = @as(u32, @intCast(self.eh_frame_data.items.len));378 const data_start = @as(u32, @intCast(self.eh_frame_data.items.len));
383 try self.eh_frame_data.appendSlice(allocator, raw);379 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{};
385 defer allocator.free(relocs);384 defer allocator.free(relocs);
386 const rel_start = @as(u32, @intCast(self.relocs.items.len));385 const rel_start = @as(u32, @intCast(self.relocs.items.len));
387 try self.relocs.appendUnalignedSlice(allocator, relocs);386 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 {...@@ -139,14 +139,16 @@ 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 {
146 if (!symbol.flags.has_plt) return 0;147 if (!symbol.flags.has_plt) return 0;
147 const extras = symbol.extra(elf_file).?;148 const extras = symbol.extra(elf_file).?;
148 const shdr = elf_file.shdrs.items[elf_file.plt_section_index.?];149 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);
150}152}
151153
152pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) u64 {154pub 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 {...@@ -251,7 +253,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
251 break :blk 0;253 break :blk 0;
252 }254 }
253 if (st_shndx == elf.SHN_ABS or st_shndx == elf.SHN_COMMON) break :blk symbol.address(.{ .plt = false }, elf_file);255 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];
255 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)257 if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined)
256 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();258 break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress();
257 break :blk symbol.address(.{ .plt = false }, elf_file);259 break :blk symbol.address(.{ .plt = false }, elf_file);
...@@ -441,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;...@@ -441,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection;
441const LinkerDefined = @import("LinkerDefined.zig");443const LinkerDefined = @import("LinkerDefined.zig");
442const Object = @import("Object.zig");444const Object = @import("Object.zig");
443const PltSection = synthetic_sections.PltSection;445const PltSection = synthetic_sections.PltSection;
446const PltGotSection = synthetic_sections.PltGotSection;
444const SharedObject = @import("SharedObject.zig");447const SharedObject = @import("SharedObject.zig");
445const Symbol = @This();448const Symbol = @This();
446const ZigGotSection = synthetic_sections.ZigGotSection;449const ZigGotSection = synthetic_sections.ZigGotSection;
src/link/Elf/eh_frame.zig+1
...@@ -214,6 +214,7 @@ pub const Iterator = struct {...@@ -214,6 +214,7 @@ pub const Iterator = struct {
214 const reader = stream.reader();214 const reader = stream.reader();
215215
216 const size = try reader.readInt(u32, .little);216 const size = try reader.readInt(u32, .little);
217 if (size == 0) return null;
217 if (size == 0xFFFFFFFF) @panic("TODO");218 if (size == 0xFFFFFFFF) @panic("TODO");
218219
219 const id = try reader.readInt(u32, .little);220 const id = try reader.readInt(u32, .little);
src/link/Elf/synthetic_sections.zig+190-50
...@@ -634,8 +634,17 @@ pub const GotSection = struct {...@@ -634,8 +634,17 @@ pub const GotSection = struct {
634 }634 }
635 },635 },
636 .tlsdesc => {636 .tlsdesc => {
637 try writeInt(0, elf_file, writer);637 if (symbol.?.flags.import) {
638 try writeInt(0, elf_file, writer);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 }
639 },648 },
640 }649 }
641 }650 }
...@@ -738,8 +747,9 @@ pub const GotSection = struct {...@@ -738,8 +747,9 @@ pub const GotSection = struct {
738 const offset = symbol.?.tlsDescAddress(elf_file);747 const offset = symbol.?.tlsDescAddress(elf_file);
739 elf_file.addRelaDynAssumeCapacity(.{748 elf_file.addRelaDynAssumeCapacity(.{
740 .offset = offset,749 .offset = offset,
741 .sym = extra.?.dynamic,750 .sym = if (symbol.?.flags.import) extra.?.dynamic else 0,
742 .type = relocation.encode(.tlsdesc, cpu_arch),751 .type = relocation.encode(.tlsdesc, cpu_arch),
752 .addend = if (symbol.?.flags.import) 0 else @intCast(symbol.?.address(.{}, elf_file) - elf_file.tlsAddress()),
743 });753 });
744 },754 },
745 }755 }
...@@ -857,8 +867,6 @@ pub const PltSection = struct {...@@ -857,8 +867,6 @@ pub const PltSection = struct {
857 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},867 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
858 output_symtab_ctx: Elf.SymtabCtx = .{},868 output_symtab_ctx: Elf.SymtabCtx = .{},
859869
860 pub const preamble_size = 32;
861
862 pub fn deinit(plt: *PltSection, allocator: Allocator) void {870 pub fn deinit(plt: *PltSection, allocator: Allocator) void {
863 plt.symbols.deinit(allocator);871 plt.symbols.deinit(allocator);
864 }872 }
...@@ -877,39 +885,33 @@ pub const PltSection = struct {...@@ -877,39 +885,33 @@ pub const PltSection = struct {
877 try plt.symbols.append(gpa, sym_index);885 try plt.symbols.append(gpa, sym_index);
878 }886 }
879887
880 pub fn size(plt: PltSection) usize {888 pub fn size(plt: PltSection, elf_file: *Elf) usize {
881 return preamble_size + plt.symbols.items.len * 16;889 const cpu_arch = elf_file.getTarget().cpu.arch;
890 return preambleSize(cpu_arch) + plt.symbols.items.len * entrySize(cpu_arch);
882 }891 }
883892
884 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {893 pub fn preambleSize(cpu_arch: std.Target.Cpu.Arch) usize {
885 const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr;894 return switch (cpu_arch) {
886 const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr;895 .x86_64 => 32,
887 var preamble = [_]u8{896 .aarch64 => 8 * @sizeOf(u32),
888 0xf3, 0x0f, 0x1e, 0xfa, // endbr64897 else => @panic("TODO implement preambleSize for this cpu arch"),
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]
892 };898 };
893 var disp = @as(i64, @intCast(got_plt_addr + 8)) - @as(i64, @intCast(plt_addr + 8)) - 4;899 }
894 mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little);900
895 disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4;901 pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize {
896 mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little);902 return switch (cpu_arch) {
897 try writer.writeAll(&preamble);903 .x86_64 => 16,
898 try writer.writeByteNTimes(0xcc, preamble_size - preamble.len);904 .aarch64 => 4 * @sizeOf(u32),
899905 else => @panic("TODO implement entrySize for this cpu arch"),
900 for (plt.symbols.items, 0..) |sym_index, i| {906 };
901 const sym = elf_file.symbol(sym_index);907 }
902 const target_addr = sym.gotPltAddress(elf_file);908
903 const source_addr = sym.pltAddress(elf_file);909 pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
904 disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4;910 const cpu_arch = elf_file.getTarget().cpu.arch;
905 var entry = [_]u8{911 switch (cpu_arch) {
906 0xf3, 0x0f, 0x1e, 0xfa, // endbr64912 .x86_64 => try x86_64.write(plt, elf_file, writer),
907 0x41, 0xbb, 0x00, 0x00, 0x00, 0x00, // mov r11d, N913 .aarch64 => try aarch64.write(plt, elf_file, writer),
908 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[N]914 else => return error.UnsupportedCpuArch,
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);
913 }915 }
914 }916 }
915917
...@@ -946,6 +948,7 @@ pub const PltSection = struct {...@@ -946,6 +948,7 @@ pub const PltSection = struct {
946 }948 }
947949
948 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {950 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
951 const cpu_arch = elf_file.getTarget().cpu.arch;
949 for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| {952 for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| {
950 const sym = elf_file.symbol(sym_index);953 const sym = elf_file.symbol(sym_index);
951 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));954 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
...@@ -958,7 +961,7 @@ pub const PltSection = struct {...@@ -958,7 +961,7 @@ pub const PltSection = struct {
958 .st_other = 0,961 .st_other = 0,
959 .st_shndx = @intCast(elf_file.plt_section_index.?),962 .st_shndx = @intCast(elf_file.plt_section_index.?),
960 .st_value = sym.pltAddress(elf_file),963 .st_value = sym.pltAddress(elf_file),
961 .st_size = 16,964 .st_size = entrySize(cpu_arch),
962 };965 };
963 }966 }
964 }967 }
...@@ -992,6 +995,97 @@ pub const PltSection = struct {...@@ -992,6 +995,97 @@ pub const PltSection = struct {
992 });995 });
993 }996 }
994 }997 }
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 };
995};1089};
9961090
997pub const GotPltSection = struct {1091pub const GotPltSection = struct {
...@@ -1046,23 +1140,24 @@ pub const PltGotSection = struct {...@@ -1046,23 +1140,24 @@ pub const PltGotSection = struct {
1046 try plt_got.symbols.append(gpa, sym_index);1140 try plt_got.symbols.append(gpa, sym_index);
1047 }1141 }
10481142
1049 pub fn size(plt_got: PltGotSection) usize {1143 pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize {
1050 return plt_got.symbols.items.len * 16;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 };
1051 }1153 }
10521154
1053 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {1155 pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void {
1054 for (plt_got.symbols.items) |sym_index| {1156 const cpu_arch = elf_file.getTarget().cpu.arch;
1055 const sym = elf_file.symbol(sym_index);1157 switch (cpu_arch) {
1056 const target_addr = sym.gotAddress(elf_file);1158 .x86_64 => try x86_64.write(plt_got, elf_file, writer),
1057 const source_addr = sym.pltGotAddress(elf_file);1159 .aarch64 => try aarch64.write(plt_got, elf_file, writer),
1058 const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4;1160 else => return error.UnsupportedCpuArch,
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);
1066 }1161 }
1067 }1162 }
10681163
...@@ -1091,6 +1186,50 @@ pub const PltGotSection = struct {...@@ -1091,6 +1186,50 @@ pub const PltGotSection = struct {
1091 };1186 };
1092 }1187 }
1093 }1188 }
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 };
1094};1233};
10951234
1096pub const CopyRelSection = struct {1235pub const CopyRelSection = struct {
...@@ -1629,6 +1768,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {...@@ -1629,6 +1768,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
1629const assert = std.debug.assert;1768const assert = std.debug.assert;
1630const builtin = @import("builtin");1769const builtin = @import("builtin");
1631const elf = std.elf;1770const elf = std.elf;
1771const math = std.math;
1632const mem = std.mem;1772const mem = std.mem;
1633const log = std.log.scoped(.link);1773const log = std.log.scoped(.link);
1634const relocation = @import("relocation.zig");1774const 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(...@@ -700,7 +700,7 @@ fn resolveRelocInner(
700 const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));700 const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));
701 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;701 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
702 };702 };
703 try aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);703 aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);
704 },704 },
705 else => unreachable,705 else => unreachable,
706 }706 }
...@@ -771,7 +771,7 @@ fn resolveRelocInner(...@@ -771,7 +771,7 @@ fn resolveRelocInner(
771 break :target math.cast(u64, target) orelse return error.Overflow;771 break :target math.cast(u64, target) orelse return error.Overflow;
772 };772 };
773 const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target)));773 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]);
775 },775 },
776776
777 .pageoff => {777 .pageoff => {
...@@ -780,8 +780,26 @@ fn resolveRelocInner(...@@ -780,8 +780,26 @@ fn resolveRelocInner(
780 assert(!rel.meta.pcrel);780 assert(!rel.meta.pcrel);
781 const target = math.cast(u64, S + A) orelse return error.Overflow;781 const target = math.cast(u64, S + A) orelse return error.Overflow;
782 const inst_code = code[rel_offset..][0..4];782 const inst_code = code[rel_offset..][0..4];
783 const kind = aarch64.classifyInst(inst_code);783 if (aarch64.isArithmeticOp(inst_code)) {
784 try aarch64.writePageOffset(kind, target, 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 }
785 },803 },
786804
787 .got_load_pageoff => {805 .got_load_pageoff => {
...@@ -789,7 +807,7 @@ fn resolveRelocInner(...@@ -789,7 +807,7 @@ fn resolveRelocInner(
789 assert(rel.meta.length == 2);807 assert(rel.meta.length == 2);
790 assert(!rel.meta.pcrel);808 assert(!rel.meta.pcrel);
791 const target = math.cast(u64, G + A) orelse return error.Overflow;809 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]);
793 },811 },
794812
795 .tlvp_pageoff => {813 .tlvp_pageoff => {
...@@ -841,7 +859,7 @@ fn resolveRelocInner(...@@ -841,7 +859,7 @@ fn resolveRelocInner(
841 .load_store_register = .{859 .load_store_register = .{
842 .rt = reg_info.rd,860 .rt = reg_info.rd,
843 .rn = reg_info.rn,861 .rn = reg_info.rn,
844 .offset = try aarch64.calcPageOffset(.load_store_64, target),862 .offset = try math.divExact(u12, @truncate(target), 8),
845 .opc = 0b01,863 .opc = 0b01,
846 .op1 = 0b01,864 .op1 = 0b01,
847 .v = 0,865 .v = 0,
...@@ -851,7 +869,7 @@ fn resolveRelocInner(...@@ -851,7 +869,7 @@ fn resolveRelocInner(
851 .add_subtract_immediate = .{869 .add_subtract_immediate = .{
852 .rd = reg_info.rd,870 .rd = reg_info.rd,
853 .rn = reg_info.rn,871 .rn = reg_info.rn,
854 .imm12 = try aarch64.calcPageOffset(.arithmetic, target),872 .imm12 = @truncate(target),
855 .sh = 0,873 .sh = 0,
856 .s = 0,874 .s = 0,
857 .op = 0,875 .op = 0,
src/link/MachO/synthetic.zig+5-5
...@@ -269,7 +269,7 @@ pub const StubsSection = struct {...@@ -269,7 +269,7 @@ pub const StubsSection = struct {
269 // TODO relax if possible269 // TODO relax if possible
270 const pages = try aarch64.calcNumberOfPages(source, target);270 const pages = try aarch64.calcNumberOfPages(source, target);
271 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);271 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);
273 try writer.writeInt(273 try writer.writeInt(
274 u32,274 u32,
275 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),275 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
...@@ -413,7 +413,7 @@ pub const StubsHelperSection = struct {...@@ -413,7 +413,7 @@ pub const StubsHelperSection = struct {
413 // TODO relax if possible413 // TODO relax if possible
414 const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr);414 const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr);
415 try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);415 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);
417 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);417 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);
418 }418 }
419 try writer.writeInt(u32, aarch64.Instruction.stp(419 try writer.writeInt(u32, aarch64.Instruction.stp(
...@@ -426,7 +426,7 @@ pub const StubsHelperSection = struct {...@@ -426,7 +426,7 @@ pub const StubsHelperSection = struct {
426 // TODO relax if possible426 // TODO relax if possible
427 const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr);427 const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr);
428 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);428 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);
430 try writer.writeInt(u32, aarch64.Instruction.ldr(430 try writer.writeInt(u32, aarch64.Instruction.ldr(
431 .x16,431 .x16,
432 .x16,432 .x16,
...@@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct {...@@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct {
681 const source = addr;681 const source = addr;
682 const pages = try aarch64.calcNumberOfPages(source, target);682 const pages = try aarch64.calcNumberOfPages(source, target);
683 try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);683 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);
685 try writer.writeInt(685 try writer.writeInt(
686 u32,686 u32,
687 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),687 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
...@@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct {...@@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct {
694 const source = addr + 2 * @sizeOf(u32);694 const source = addr + 2 * @sizeOf(u32);
695 const pages = try aarch64.calcNumberOfPages(source, target);695 const pages = try aarch64.calcNumberOfPages(source, target);
696 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);696 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);
698 try writer.writeInt(698 try writer.writeInt(
699 u32,699 u32,
700 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),700 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 {...@@ -101,7 +101,7 @@ pub const Thunk = struct {
101 const taddr = sym.getAddress(.{}, macho_file);101 const taddr = sym.getAddress(.{}, macho_file);
102 const pages = try aarch64.calcNumberOfPages(saddr, taddr);102 const pages = try aarch64.calcNumberOfPages(saddr, taddr);
103 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);103 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);
105 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);105 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);
106 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);106 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
107 }107 }
src/link/aarch64.zig+16-56
...@@ -3,66 +3,26 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {...@@ -3,66 +3,26 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
3 return ((group_decode >> 2) == 4);3 return ((group_decode >> 2) == 4);
4}4}
55
6pub const PageOffsetInstKind = enum {6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
7 arithmetic,7 var inst = Instruction{
8 load_store_8,8 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
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(
19 Instruction,9 Instruction,
20 Instruction.load_store_register,10 Instruction.add_subtract_immediate,
21 ), code),11 ), code),
22 };12 };
23 return switch (inst.load_store_register.size) {13 inst.add_subtract_immediate.imm12 = value;
24 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8,14 mem.writeInt(u32, code, inst.toU32(), .little);
25 1 => .load_store_16,
26 2 => .load_store_32,
27 3 => .load_store_64,
28 };
29}15}
3016
31pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 {17pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {
32 const narrowed = @as(u12, @truncate(taddr));18 var inst: Instruction = .{
33 return switch (kind) {19 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
34 .arithmetic, .load_store_8 => narrowed,20 Instruction,
35 .load_store_16 => try math.divExact(u12, narrowed, 2),21 Instruction.load_store_register,
36 .load_store_32 => try math.divExact(u12, narrowed, 4),22 ), code),
37 .load_store_64 => try math.divExact(u12, narrowed, 8),
38 .load_store_128 => try math.divExact(u12, narrowed, 16),
39 };23 };
40}24 inst.load_store_register.offset = value;
4125 mem.writeInt(u32, code, inst.toU32(), .little);
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 }
66}26}
6727
68pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {28pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
...@@ -72,7 +32,7 @@ pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {...@@ -72,7 +32,7 @@ pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
72 return pages;32 return pages;
73}33}
7434
75pub fn writePages(pages: u21, code: *[4]u8) !void {35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
76 var inst = Instruction{36 var inst = Instruction{
77 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(37 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(
78 Instruction,38 Instruction,
...@@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void {...@@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void {
84 mem.writeInt(u32, code, inst.toU32(), .little);44 mem.writeInt(u32, code, inst.toU32(), .little);
85}45}
8646
87pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
88 var inst = Instruction{48 var inst = Instruction{
89 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(49 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(
90 Instruction,50 Instruction,
test/link/elf.zig+129-187
...@@ -20,30 +20,142 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -20,30 +20,142 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
20 .os_tag = .linux,20 .os_tag = .linux,
21 .abi = .gnu,21 .abi = .gnu,
22 });22 });
23 const aarch64_musl = b.resolveTargetQuery(.{23 // const aarch64_musl = b.resolveTargetQuery(.{
24 .cpu_arch = .aarch64,24 // .cpu_arch = .aarch64,
25 .os_tag = .linux,25 // .os_tag = .linux,
26 .abi = .musl,26 // .abi = .musl,
27 });27 // });
28 // const aarch64_gnu = b.resolveTargetQuery(.{
29 // .cpu_arch = .aarch64,
30 // .os_tag = .linux,
31 // .abi = .gnu,
32 // });
28 const riscv64_musl = b.resolveTargetQuery(.{33 const riscv64_musl = b.resolveTargetQuery(.{
29 .cpu_arch = .riscv64,34 .cpu_arch = .riscv64,
30 .os_tag = .linux,35 .os_tag = .linux,
31 .abi = .musl,36 .abi = .musl,
32 });37 });
3338
34 // x86_64 tests39 // Common tests
35 // Exercise linker in -r mode40 for (&[_]std.Target.Cpu.Arch{
36 elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl }));41 .x86_64,
37 elf_step.dependOn(testEmitRelocatable(b, .{ .target = x86_64_musl }));42 .aarch64,
38 elf_step.dependOn(testRelocatableArchive(b, .{ .target = x86_64_musl }));43 }) |cpu_arch| {
39 elf_step.dependOn(testRelocatableEhFrame(b, .{ .target = x86_64_musl }));44 const musl_target = b.resolveTargetQuery(.{
40 elf_step.dependOn(testRelocatableNoEhFrame(b, .{ .target = x86_64_musl }));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 mode55 // Exercise linker in -r mode
43 elf_step.dependOn(testEmitStaticLib(b, .{ .target = x86_64_musl }));56 elf_step.dependOn(testEmitRelocatable(b, .{ .target = musl_target }));
44 elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl }));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 }));
47 elf_step.dependOn(testGcSectionsZig(b, .{ .use_llvm = false, .target = default_target }));159 elf_step.dependOn(testGcSectionsZig(b, .{ .use_llvm = false, .target = default_target }));
48 elf_step.dependOn(testLinkingObj(b, .{ .use_llvm = false, .target = default_target }));160 elf_step.dependOn(testLinkingObj(b, .{ .use_llvm = false, .target = default_target }));
49 elf_step.dependOn(testLinkingStaticLib(b, .{ .use_llvm = false, .target = default_target }));161 elf_step.dependOn(testLinkingStaticLib(b, .{ .use_llvm = false, .target = default_target }));
...@@ -51,99 +163,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {...@@ -51,99 +163,7 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step {
51 elf_step.dependOn(testImportingDataDynamic(b, .{ .use_llvm = false, .target = x86_64_gnu }));163 elf_step.dependOn(testImportingDataDynamic(b, .{ .use_llvm = false, .target = x86_64_gnu }));
52 elf_step.dependOn(testImportingDataStatic(b, .{ .use_llvm = false, .target = x86_64_musl }));164 elf_step.dependOn(testImportingDataStatic(b, .{ .use_llvm = false, .target = x86_64_musl }));
53165
54 // Exercise linker with LLVM backend166 // riscv64 linker backend is currently not complete enough to support more
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
147 elf_step.dependOn(testLinkingC(b, .{ .target = riscv64_musl }));167 elf_step.dependOn(testLinkingC(b, .{ .target = riscv64_musl }));
148168
149 return elf_step;169 return elf_step;
...@@ -239,8 +259,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {...@@ -239,8 +259,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {
239 exe.addLibraryPath(libbaz.getEmittedBinDirectory());259 exe.addLibraryPath(libbaz.getEmittedBinDirectory());
240 exe.addRPath(libbaz.getEmittedBinDirectory());260 exe.addRPath(libbaz.getEmittedBinDirectory());
241 exe.linkLibC();261 exe.linkLibC();
242 // https://github.com/ziglang/zig/issues/17619
243 exe.pie = true;
244262
245 const run = addRunArtifact(exe);263 const run = addRunArtifact(exe);
246 run.expectStdOutEqual("42\n");264 run.expectStdOutEqual("42\n");
...@@ -269,8 +287,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {...@@ -269,8 +287,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step {
269 exe.addLibraryPath(libbaz.getEmittedBinDirectory());287 exe.addLibraryPath(libbaz.getEmittedBinDirectory());
270 exe.addRPath(libbaz.getEmittedBinDirectory());288 exe.addRPath(libbaz.getEmittedBinDirectory());
271 exe.linkLibC();289 exe.linkLibC();
272 // https://github.com/ziglang/zig/issues/17619
273 exe.pie = true;
274290
275 const run = addRunArtifact(exe);291 const run = addRunArtifact(exe);
276 run.expectStdOutEqual("42\n");292 run.expectStdOutEqual("42\n");
...@@ -489,8 +505,6 @@ fn testCopyrel(b: *Build, opts: Options) *Step {...@@ -489,8 +505,6 @@ fn testCopyrel(b: *Build, opts: Options) *Step {
489 });505 });
490 exe.linkLibrary(dso);506 exe.linkLibrary(dso);
491 exe.linkLibC();507 exe.linkLibC();
492 // https://github.com/ziglang/zig/issues/17619
493 exe.pie = true;
494508
495 const run = addRunArtifact(exe);509 const run = addRunArtifact(exe);
496 run.expectStdOutEqual("3 5\n");510 run.expectStdOutEqual("3 5\n");
...@@ -656,8 +670,6 @@ fn testDsoPlt(b: *Build, opts: Options) *Step {...@@ -656,8 +670,6 @@ fn testDsoPlt(b: *Build, opts: Options) *Step {
656 , &.{});670 , &.{});
657 exe.linkLibrary(dso);671 exe.linkLibrary(dso);
658 exe.linkLibC();672 exe.linkLibC();
659 // https://github.com/ziglang/zig/issues/17619
660 exe.pie = true;
661673
662 const run = addRunArtifact(exe);674 const run = addRunArtifact(exe);
663 run.expectStdOutEqual("Hello WORLD\n");675 run.expectStdOutEqual("Hello WORLD\n");
...@@ -695,8 +707,6 @@ fn testDsoUndef(b: *Build, opts: Options) *Step {...@@ -695,8 +707,6 @@ fn testDsoUndef(b: *Build, opts: Options) *Step {
695 \\}707 \\}
696 , &.{});708 , &.{});
697 exe.linkLibC();709 exe.linkLibC();
698 // https://github.com/ziglang/zig/issues/17619
699 exe.pie = true;
700710
701 const run = addRunArtifact(exe);711 const run = addRunArtifact(exe);
702 run.expectExitCode(0);712 run.expectExitCode(0);
...@@ -1280,8 +1290,6 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step {...@@ -1280,8 +1290,6 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step {
1280 , &.{});1290 , &.{});
1281 exe.root_module.pic = true;1291 exe.root_module.pic = true;
1282 exe.linkLibC();1292 exe.linkLibC();
1283 // https://github.com/ziglang/zig/issues/17619
1284 exe.pie = true;
12851293
1286 const run = addRunArtifact(exe);1294 const run = addRunArtifact(exe);
1287 run.expectExitCode(0);1295 run.expectExitCode(0);
...@@ -1396,8 +1404,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {...@@ -1396,8 +1404,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {
1396 addCSourceBytes(exe, main_c, &.{});1404 addCSourceBytes(exe, main_c, &.{});
1397 exe.linkLibC();1405 exe.linkLibC();
1398 exe.link_z_lazy = true;1406 exe.link_z_lazy = true;
1399 // https://github.com/ziglang/zig/issues/17619
1400 exe.pie = true;
14011407
1402 const run = addRunArtifact(exe);1408 const run = addRunArtifact(exe);
1403 run.expectStdOutEqual("Hello world\n");1409 run.expectStdOutEqual("Hello world\n");
...@@ -1407,8 +1413,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {...@@ -1407,8 +1413,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step {
1407 const exe = addExecutable(b, opts, .{ .name = "other" });1413 const exe = addExecutable(b, opts, .{ .name = "other" });
1408 addCSourceBytes(exe, main_c, &.{});1414 addCSourceBytes(exe, main_c, &.{});
1409 exe.linkLibC();1415 exe.linkLibC();
1410 // https://github.com/ziglang/zig/issues/17619
1411 exe.pie = true;
14121416
1413 const run = addRunArtifact(exe);1417 const run = addRunArtifact(exe);
1414 run.expectStdOutEqual("Hello world\n");1418 run.expectStdOutEqual("Hello world\n");
...@@ -1472,8 +1476,6 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step {...@@ -1472,8 +1476,6 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step {
1472 , &.{});1476 , &.{});
1473 exe.root_module.pic = true;1477 exe.root_module.pic = true;
1474 exe.linkLibC();1478 exe.linkLibC();
1475 // https://github.com/ziglang/zig/issues/17619
1476 exe.pie = true;
14771479
1478 const run = addRunArtifact(exe);1480 const run = addRunArtifact(exe);
1479 run.expectStdOutEqual("3\n");1481 run.expectStdOutEqual("3\n");
...@@ -1503,8 +1505,6 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step {...@@ -1503,8 +1505,6 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step {
1503 , &.{"-fno-plt"});1505 , &.{"-fno-plt"});
1504 exe.root_module.pic = true;1506 exe.root_module.pic = true;
1505 exe.linkLibC();1507 exe.linkLibC();
1506 // https://github.com/ziglang/zig/issues/17619
1507 exe.pie = true;
15081508
1509 const run = addRunArtifact(exe);1509 const run = addRunArtifact(exe);
1510 run.expectStdOutEqual("Hello world\n");1510 run.expectStdOutEqual("Hello world\n");
...@@ -1834,8 +1834,6 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step {...@@ -1834,8 +1834,6 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step {
1834 , &.{});1834 , &.{});
1835 exe.linkLibrary(dso);1835 exe.linkLibrary(dso);
1836 exe.linkLibC();1836 exe.linkLibC();
1837 // https://github.com/ziglang/zig/issues/17619
1838 exe.pie = true;
18391837
1840 const run = addRunArtifact(exe);1838 const run = addRunArtifact(exe);
1841 run.expectStdOutEqual("Hello world");1839 run.expectStdOutEqual("Hello world");
...@@ -1870,8 +1868,6 @@ fn testLargeAlignmentExe(b: *Build, opts: Options) *Step {...@@ -1870,8 +1868,6 @@ fn testLargeAlignmentExe(b: *Build, opts: Options) *Step {
1870 , &.{});1868 , &.{});
1871 exe.link_function_sections = true;1869 exe.link_function_sections = true;
1872 exe.linkLibC();1870 exe.linkLibC();
1873 // https://github.com/ziglang/zig/issues/17619
1874 exe.pie = true;
18751871
1876 const check = exe.checkObject();1872 const check = exe.checkObject();
1877 check.checkInSymtab();1873 check.checkInSymtab();
...@@ -1900,8 +1896,6 @@ fn testLargeBss(b: *Build, opts: Options) *Step {...@@ -1900,8 +1896,6 @@ fn testLargeBss(b: *Build, opts: Options) *Step {
1900 \\}1896 \\}
1901 , &.{});1897 , &.{});
1902 exe.linkLibC();1898 exe.linkLibC();
1903 // https://github.com/ziglang/zig/issues/17619
1904 exe.pie = true;
19051899
1906 const run = addRunArtifact(exe);1900 const run = addRunArtifact(exe);
1907 run.expectExitCode(0);1901 run.expectExitCode(0);
...@@ -1995,8 +1989,6 @@ fn testLdScript(b: *Build, opts: Options) *Step {...@@ -1995,8 +1989,6 @@ fn testLdScript(b: *Build, opts: Options) *Step {
1995 exe.addLibraryPath(dso.getEmittedBinDirectory());1989 exe.addLibraryPath(dso.getEmittedBinDirectory());
1996 exe.addRPath(dso.getEmittedBinDirectory());1990 exe.addRPath(dso.getEmittedBinDirectory());
1997 exe.linkLibC();1991 exe.linkLibC();
1998 // https://github.com/ziglang/zig/issues/17619
1999 exe.pie = true;
20001992
2001 const run = addRunArtifact(exe);1993 const run = addRunArtifact(exe);
2002 run.expectExitCode(0);1994 run.expectExitCode(0);
...@@ -2348,8 +2340,6 @@ fn testPltGot(b: *Build, opts: Options) *Step {...@@ -2348,8 +2340,6 @@ fn testPltGot(b: *Build, opts: Options) *Step {
2348 exe.linkLibrary(dso);2340 exe.linkLibrary(dso);
2349 exe.root_module.pic = true;2341 exe.root_module.pic = true;
2350 exe.linkLibC();2342 exe.linkLibC();
2351 // https://github.com/ziglang/zig/issues/17619
2352 exe.pie = true;
23532343
2354 const run = addRunArtifact(exe);2344 const run = addRunArtifact(exe);
2355 run.expectStdOutEqual("Hello world\n");2345 run.expectStdOutEqual("Hello world\n");
...@@ -2752,8 +2742,6 @@ fn testTlsDso(b: *Build, opts: Options) *Step {...@@ -2752,8 +2742,6 @@ fn testTlsDso(b: *Build, opts: Options) *Step {
2752 , &.{});2742 , &.{});
2753 exe.linkLibrary(dso);2743 exe.linkLibrary(dso);
2754 exe.linkLibC();2744 exe.linkLibC();
2755 // https://github.com/ziglang/zig/issues/17619
2756 exe.pie = true;
27572745
2758 const run = addRunArtifact(exe);2746 const run = addRunArtifact(exe);
2759 run.expectStdOutEqual("5 3 5 3 5 3\n");2747 run.expectStdOutEqual("5 3 5 3 5 3\n");
...@@ -2912,8 +2900,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {...@@ -2912,8 +2900,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {
2912 exe.linkLibrary(a_so);2900 exe.linkLibrary(a_so);
2913 exe.linkLibrary(b_so);2901 exe.linkLibrary(b_so);
2914 exe.linkLibC();2902 exe.linkLibC();
2915 // https://github.com/ziglang/zig/issues/17619
2916 exe.pie = true;
29172903
2918 const run = addRunArtifact(exe);2904 const run = addRunArtifact(exe);
2919 run.expectStdOutEqual("1 2 3 4 5 6\n");2905 run.expectStdOutEqual("1 2 3 4 5 6\n");
...@@ -2927,8 +2913,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {...@@ -2927,8 +2913,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step {
2927 exe.linkLibrary(b_so);2913 exe.linkLibrary(b_so);
2928 exe.linkLibC();2914 exe.linkLibC();
2929 // exe.link_relax = false; // TODO2915 // exe.link_relax = false; // TODO
2930 // https://github.com/ziglang/zig/issues/17619
2931 exe.pie = true;
29322916
2933 const run = addRunArtifact(exe);2917 const run = addRunArtifact(exe);
2934 run.expectStdOutEqual("1 2 3 4 5 6\n");2918 run.expectStdOutEqual("1 2 3 4 5 6\n");
...@@ -2976,8 +2960,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {...@@ -2976,8 +2960,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {
2976 exe.addObject(b_o);2960 exe.addObject(b_o);
2977 exe.linkLibrary(dso);2961 exe.linkLibrary(dso);
2978 exe.linkLibC();2962 exe.linkLibC();
2979 // https://github.com/ziglang/zig/issues/17619
2980 exe.pie = true;
29812963
2982 const run = addRunArtifact(exe);2964 const run = addRunArtifact(exe);
2983 run.expectStdOutEqual("1 2 3\n");2965 run.expectStdOutEqual("1 2 3\n");
...@@ -2993,8 +2975,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {...@@ -2993,8 +2975,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step {
2993 exe.addObject(b_o);2975 exe.addObject(b_o);
2994 exe.linkLibrary(dso);2976 exe.linkLibrary(dso);
2995 exe.linkLibC();2977 exe.linkLibC();
2996 // https://github.com/ziglang/zig/issues/17619
2997 exe.pie = true;
29982978
2999 const run = addRunArtifact(exe);2979 const run = addRunArtifact(exe);
3000 run.expectStdOutEqual("1 2 3\n");2980 run.expectStdOutEqual("1 2 3\n");
...@@ -3076,8 +3056,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {...@@ -3076,8 +3056,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {
3076 exe.addObject(main_o);3056 exe.addObject(main_o);
3077 exe.linkLibrary(dso);3057 exe.linkLibrary(dso);
3078 exe.linkLibC();3058 exe.linkLibC();
3079 // https://github.com/ziglang/zig/issues/17619
3080 exe.pie = true;
30813059
3082 const run = addRunArtifact(exe);3060 const run = addRunArtifact(exe);
3083 run.expectStdOutEqual(exp_stdout);3061 run.expectStdOutEqual(exp_stdout);
...@@ -3090,8 +3068,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {...@@ -3090,8 +3068,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step {
3090 exe.linkLibrary(dso);3068 exe.linkLibrary(dso);
3091 exe.linkLibC();3069 exe.linkLibC();
3092 // exe.link_relax = false; // TODO3070 // exe.link_relax = false; // TODO
3093 // https://github.com/ziglang/zig/issues/17619
3094 exe.pie = true;
30953071
3096 const run = addRunArtifact(exe);3072 const run = addRunArtifact(exe);
3097 run.expectStdOutEqual(exp_stdout);3073 run.expectStdOutEqual(exp_stdout);
...@@ -3147,8 +3123,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {...@@ -3147,8 +3123,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {
3147 exe.addObject(c_o);3123 exe.addObject(c_o);
3148 exe.linkLibrary(dso);3124 exe.linkLibrary(dso);
3149 exe.linkLibC();3125 exe.linkLibC();
3150 // https://github.com/ziglang/zig/issues/17619
3151 exe.pie = true;
31523126
3153 const run = addRunArtifact(exe);3127 const run = addRunArtifact(exe);
3154 run.expectStdOutEqual("42 1 2 3\n");3128 run.expectStdOutEqual("42 1 2 3\n");
...@@ -3161,8 +3135,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {...@@ -3161,8 +3135,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step {
3161 exe.addObject(b_o);3135 exe.addObject(b_o);
3162 exe.addObject(c_o);3136 exe.addObject(c_o);
3163 exe.linkLibC();3137 exe.linkLibC();
3164 // https://github.com/ziglang/zig/issues/17619
3165 exe.pie = true;
31663138
3167 const run = addRunArtifact(exe);3139 const run = addRunArtifact(exe);
3168 run.expectStdOutEqual("42 1 2 3\n");3140 run.expectStdOutEqual("42 1 2 3\n");
...@@ -3196,8 +3168,6 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step {...@@ -3196,8 +3168,6 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step {
3196 \\}3168 \\}
3197 , &.{});3169 , &.{});
3198 exe.linkLibC();3170 exe.linkLibC();
3199 // https://github.com/ziglang/zig/issues/17619
3200 exe.pie = true;
32013171
3202 const run = addRunArtifact(exe);3172 const run = addRunArtifact(exe);
3203 run.expectStdOutEqual("3 0 5 0 0 0\n");3173 run.expectStdOutEqual("3 0 5 0 0 0\n");
...@@ -3220,8 +3190,6 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step {...@@ -3220,8 +3190,6 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step {
3220 , &.{});3190 , &.{});
3221 exe.root_module.pic = true;3191 exe.root_module.pic = true;
3222 exe.linkLibC();3192 exe.linkLibC();
3223 // https://github.com/ziglang/zig/issues/17619
3224 exe.pie = true;
32253193
3226 const run = addRunArtifact(exe);3194 const run = addRunArtifact(exe);
3227 run.expectStdOutEqual("1 2 3 0 5\n");3195 run.expectStdOutEqual("1 2 3 0 5\n");
...@@ -3266,8 +3234,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {...@@ -3266,8 +3234,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {
3266 exe.addObject(main_o);3234 exe.addObject(main_o);
3267 exe.addObject(a_o);3235 exe.addObject(a_o);
3268 exe.linkLibC();3236 exe.linkLibC();
3269 // https://github.com/ziglang/zig/issues/17619
3270 exe.pie = true;
32713237
3272 const run = addRunArtifact(exe);3238 const run = addRunArtifact(exe);
3273 run.expectStdOutEqual(exp_stdout);3239 run.expectStdOutEqual(exp_stdout);
...@@ -3280,8 +3246,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {...@@ -3280,8 +3246,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step {
3280 exe.addObject(a_o);3246 exe.addObject(a_o);
3281 exe.linkLibC();3247 exe.linkLibC();
3282 // exe.link_relax = false; // TODO3248 // exe.link_relax = false; // TODO
3283 // https://github.com/ziglang/zig/issues/17619
3284 exe.pie = true;
32853249
3286 const run = addRunArtifact(exe);3250 const run = addRunArtifact(exe);
3287 run.expectStdOutEqual(exp_stdout);3251 run.expectStdOutEqual(exp_stdout);
...@@ -3315,8 +3279,6 @@ fn testTlsLdDso(b: *Build, opts: Options) *Step {...@@ -3315,8 +3279,6 @@ fn testTlsLdDso(b: *Build, opts: Options) *Step {
3315 , &.{});3279 , &.{});
3316 exe.linkLibrary(dso);3280 exe.linkLibrary(dso);
3317 exe.linkLibC();3281 exe.linkLibC();
3318 // https://github.com/ziglang/zig/issues/17619
3319 exe.pie = true;
33203282
3321 const run = addRunArtifact(exe);3283 const run = addRunArtifact(exe);
3322 run.expectStdOutEqual("1 2\n");3284 run.expectStdOutEqual("1 2\n");
...@@ -3360,8 +3322,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {...@@ -3360,8 +3322,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {
3360 exe.addObject(a_o);3322 exe.addObject(a_o);
3361 exe.addObject(b_o);3323 exe.addObject(b_o);
3362 exe.linkLibC();3324 exe.linkLibC();
3363 // https://github.com/ziglang/zig/issues/17619
3364 exe.pie = true;
33653325
3366 const run = addRunArtifact(exe);3326 const run = addRunArtifact(exe);
3367 run.expectStdOutEqual("3 5 3 5\n");3327 run.expectStdOutEqual("3 5 3 5\n");
...@@ -3374,8 +3334,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {...@@ -3374,8 +3334,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step {
3374 exe.addObject(b_o);3334 exe.addObject(b_o);
3375 exe.linkLibC();3335 exe.linkLibC();
3376 // exe.link_relax = false; // TODO3336 // exe.link_relax = false; // TODO
3377 // https://github.com/ziglang/zig/issues/17619
3378 exe.pie = true;
33793337
3380 const run = addRunArtifact(exe);3338 const run = addRunArtifact(exe);
3381 run.expectStdOutEqual("3 5 3 5\n");3339 run.expectStdOutEqual("3 5 3 5\n");
...@@ -3461,8 +3419,6 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step {...@@ -3461,8 +3419,6 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step {
3461 exe.addRPath(dso.getEmittedBinDirectory());3419 exe.addRPath(dso.getEmittedBinDirectory());
3462 exe.linkLibC();3420 exe.linkLibC();
3463 exe.root_module.pic = true;3421 exe.root_module.pic = true;
3464 // https://github.com/ziglang/zig/issues/17619
3465 exe.pie = true;
34663422
3467 const run = addRunArtifact(exe);3423 const run = addRunArtifact(exe);
3468 run.expectExitCode(0);3424 run.expectExitCode(0);
...@@ -3499,8 +3455,6 @@ fn testTlsPic(b: *Build, opts: Options) *Step {...@@ -3499,8 +3455,6 @@ fn testTlsPic(b: *Build, opts: Options) *Step {
3499 , &.{});3455 , &.{});
3500 exe.addObject(obj);3456 exe.addObject(obj);
3501 exe.linkLibC();3457 exe.linkLibC();
3502 // https://github.com/ziglang/zig/issues/17619
3503 exe.pie = true;
35043458
3505 const run = addRunArtifact(exe);3459 const run = addRunArtifact(exe);
3506 run.expectStdOutEqual("3 5 3 5\n");3460 run.expectStdOutEqual("3 5 3 5\n");
...@@ -3548,8 +3502,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {...@@ -3548,8 +3502,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {
3548 exe.addObject(b_o);3502 exe.addObject(b_o);
3549 exe.addObject(c_o);3503 exe.addObject(c_o);
3550 exe.linkLibC();3504 exe.linkLibC();
3551 // https://github.com/ziglang/zig/issues/17619
3552 exe.pie = true;
35533505
3554 const run = addRunArtifact(exe);3506 const run = addRunArtifact(exe);
3555 run.expectStdOutEqual("42\n");3507 run.expectStdOutEqual("42\n");
...@@ -3565,8 +3517,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {...@@ -3565,8 +3517,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step {
3565 exe.addObject(c_o);3517 exe.addObject(c_o);
3566 exe.linkLibrary(dso);3518 exe.linkLibrary(dso);
3567 exe.linkLibC();3519 exe.linkLibC();
3568 // https://github.com/ziglang/zig/issues/17619
3569 exe.pie = true;
35703520
3571 const run = addRunArtifact(exe);3521 const run = addRunArtifact(exe);
3572 run.expectStdOutEqual("42\n");3522 run.expectStdOutEqual("42\n");
...@@ -3717,8 +3667,6 @@ fn testWeakExports(b: *Build, opts: Options) *Step {...@@ -3717,8 +3667,6 @@ fn testWeakExports(b: *Build, opts: Options) *Step {
3717 const exe = addExecutable(b, opts, .{ .name = "main" });3667 const exe = addExecutable(b, opts, .{ .name = "main" });
3718 exe.addObject(obj);3668 exe.addObject(obj);
3719 exe.linkLibC();3669 exe.linkLibC();
3720 // https://github.com/ziglang/zig/issues/17619
3721 exe.pie = true;
37223670
3723 const check = exe.checkObject();3671 const check = exe.checkObject();
3724 check.checkInDynamicSymtab();3672 check.checkInDynamicSymtab();
...@@ -3751,8 +3699,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {...@@ -3751,8 +3699,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {
3751 , &.{});3699 , &.{});
3752 exe.linkLibrary(dso);3700 exe.linkLibrary(dso);
3753 exe.linkLibC();3701 exe.linkLibC();
3754 // https://github.com/ziglang/zig/issues/17619
3755 exe.pie = true;
37563702
3757 const run = addRunArtifact(exe);3703 const run = addRunArtifact(exe);
3758 run.expectStdOutEqual("bar=-1\n");3704 run.expectStdOutEqual("bar=-1\n");
...@@ -3769,8 +3715,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {...@@ -3769,8 +3715,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step {
3769 , &.{});3715 , &.{});
3770 exe.linkLibrary(dso);3716 exe.linkLibrary(dso);
3771 exe.linkLibC();3717 exe.linkLibC();
3772 // https://github.com/ziglang/zig/issues/17619
3773 exe.pie = true;
37743718
3775 const run = addRunArtifact(exe);3719 const run = addRunArtifact(exe);
3776 run.expectStdOutEqual("bar=5\n");3720 run.expectStdOutEqual("bar=5\n");
...@@ -3885,8 +3829,6 @@ fn testZText(b: *Build, opts: Options) *Step {...@@ -3885,8 +3829,6 @@ fn testZText(b: *Build, opts: Options) *Step {
3885 , &.{});3829 , &.{});
3886 exe.linkLibrary(dso);3830 exe.linkLibrary(dso);
3887 exe.linkLibC();3831 exe.linkLibC();
3888 // https://github.com/ziglang/zig/issues/17619
3889 exe.pie = true;
38903832
3891 const run = addRunArtifact(exe);3833 const run = addRunArtifact(exe);
3892 run.expectStdOutEqual("3\n");3834 run.expectStdOutEqual("3\n");