| author | |
| committer | |
| log | c1bda06c14250f6751b834331a0f9c40f409c7d1 |
| tree | d43996ee94cd2ae88ee32966064a08520755609d |
| parent | 4ba4f94c93d5eb1945f1b2c8c53a45cbee609d3b |
| parent | 1a6b2e84ac5d88f00bfb281c8101f2b69a962b67 |
| signature |
elf: port aarch64 support from zld14 files changed, 902 insertions(+), 366 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -598,6 +598,7 @@ set(ZIG_STAGE2_SOURCES |
| 598 | 598 | "${CMAKE_SOURCE_DIR}/src/link/Elf/relocatable.zig" |
| 599 | 599 | "${CMAKE_SOURCE_DIR}/src/link/Elf/relocation.zig" |
| 600 | 600 | "${CMAKE_SOURCE_DIR}/src/link/Elf/synthetic_sections.zig" |
| 601 | "${CMAKE_SOURCE_DIR}/src/link/Elf/thunks.zig" | |
| 601 | 602 | "${CMAKE_SOURCE_DIR}/src/link/MachO.zig" |
| 602 | 603 | "${CMAKE_SOURCE_DIR}/src/link/MachO/Archive.zig" |
| 603 | 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 | 206 | /// List of atoms that are owned directly by the linker. |
| 207 | 207 | atoms: std.ArrayListUnmanaged(Atom) = .{}, |
| 208 | 208 | |
| 209 | /// List of range extension thunks. | |
| 210 | thunks: std.ArrayListUnmanaged(Thunk) = .{}, | |
| 211 | ||
| 209 | 212 | /// Table of last atom index in a section and matching atom free list if any. |
| 210 | 213 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 211 | 214 | |
| ... | ... | @@ -255,7 +258,7 @@ pub fn createEmpty( |
| 255 | 258 | }; |
| 256 | 259 | |
| 257 | 260 | const page_size: u32 = switch (target.cpu.arch) { |
| 258 | .powerpc64le => 0x10000, | |
| 261 | .aarch64, .powerpc64le => 0x10000, | |
| 259 | 262 | .sparc64 => 0x2000, |
| 260 | 263 | else => 0x1000, |
| 261 | 264 | }; |
| ... | ... | @@ -488,6 +491,7 @@ pub fn deinit(self: *Elf) void { |
| 488 | 491 | self.start_stop_indexes.deinit(gpa); |
| 489 | 492 | |
| 490 | 493 | self.atoms.deinit(gpa); |
| 494 | self.thunks.deinit(gpa); | |
| 491 | 495 | for (self.last_atom_and_free_list_table.values()) |*value| { |
| 492 | 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 | 1377 | try self.writePhdrTable(); |
| 1374 | 1378 | try self.writeShdrTable(); |
| 1375 | 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 | }; | |
| 1377 | 1388 | |
| 1378 | 1389 | if (self.entry_index == null and self.base.isExe()) { |
| 1379 | 1390 | log.debug("flushing. no_entry_point_found = true", .{}); |
| ... | ... | @@ -2098,7 +2109,6 @@ fn scanRelocs(self: *Elf) !void { |
| 2098 | 2109 | } |
| 2099 | 2110 | if (sym.flags.needs_tlsdesc) { |
| 2100 | 2111 | log.debug("'{s}' needs TLSDESC", .{sym.name(self)}); |
| 2101 | try self.dynsym.addSymbol(index, self); | |
| 2102 | 2112 | try self.got.addTlsDescSymbol(index, self); |
| 2103 | 2113 | } |
| 2104 | 2114 | } |
| ... | ... | @@ -3164,11 +3174,20 @@ fn allocateLinkerDefinedSymbols(self: *Elf) void { |
| 3164 | 3174 | } |
| 3165 | 3175 | |
| 3166 | 3176 | // _GLOBAL_OFFSET_TABLE_ |
| 3167 | if (self.got_plt_section_index) |shndx| { | |
| 3168 | const shdr = &self.shdrs.items[shndx]; | |
| 3169 | const symbol_ptr = self.symbol(self.got_index.?); | |
| 3170 | symbol_ptr.value = shdr.sh_addr; | |
| 3171 | symbol_ptr.output_section_index = shndx; | |
| 3177 | if (self.getTarget().cpu.arch == .x86_64) { | |
| 3178 | if (self.got_plt_section_index) |shndx| { | |
| 3179 | const shdr = self.shdrs.items[shndx]; | |
| 3180 | const sym = self.symbol(self.got_index.?); | |
| 3181 | sym.value = shdr.sh_addr; | |
| 3182 | sym.output_section_index = shndx; | |
| 3183 | } | |
| 3184 | } else { | |
| 3185 | if (self.got_section_index) |shndx| { | |
| 3186 | const shdr = self.shdrs.items[shndx]; | |
| 3187 | const sym = self.symbol(self.got_index.?); | |
| 3188 | sym.value = shdr.sh_addr; | |
| 3189 | sym.output_section_index = shndx; | |
| 3190 | } | |
| 3172 | 3191 | } |
| 3173 | 3192 | |
| 3174 | 3193 | // _PROCEDURE_LINKAGE_TABLE_ |
| ... | ... | @@ -3578,7 +3597,7 @@ fn sortInitFini(self: *Elf) !void { |
| 3578 | 3597 | } |
| 3579 | 3598 | }; |
| 3580 | 3599 | |
| 3581 | for (self.shdrs.items, 0..) |*shdr, shndx| { | |
| 3600 | for (self.shdrs.items, 0..) |shdr, shndx| { | |
| 3582 | 3601 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3583 | 3602 | |
| 3584 | 3603 | var is_init_fini = false; |
| ... | ... | @@ -4023,6 +4042,8 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4023 | 4042 | const target = self.base.comp.root_mod.resolved_target.result; |
| 4024 | 4043 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { |
| 4025 | 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 | 4047 | for (atom_list.items) |atom_index| { |
| 4027 | 4048 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 4028 | 4049 | if (!atom_ptr.flags.alive) continue; |
| ... | ... | @@ -4034,6 +4055,17 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4034 | 4055 | } |
| 4035 | 4056 | } |
| 4036 | 4057 | |
| 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 | 4069 | if (self.eh_frame_section_index) |index| { |
| 4038 | 4070 | self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self); |
| 4039 | 4071 | } |
| ... | ... | @@ -4047,7 +4079,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4047 | 4079 | } |
| 4048 | 4080 | |
| 4049 | 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 | } |
| 4052 | 4084 | |
| 4053 | 4085 | if (self.got_plt_section_index) |index| { |
| ... | ... | @@ -4055,7 +4087,7 @@ fn updateSectionSizes(self: *Elf) !void { |
| 4055 | 4087 | } |
| 4056 | 4088 | |
| 4057 | 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 | } |
| 4060 | 4092 | |
| 4061 | 4093 | if (self.rela_dyn_section_index) |shndx| { |
| ... | ... | @@ -4490,7 +4522,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4490 | 4522 | const buffer = try gpa.alloc(u8, sh_size); |
| 4491 | 4523 | defer gpa.free(buffer); |
| 4492 | 4524 | 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 | 4526 | 0xcc // int3 |
| 4495 | 4527 | else |
| 4496 | 4528 | 0; |
| ... | ... | @@ -4561,6 +4593,13 @@ pub fn updateSymtabSize(self: *Elf) !void { |
| 4561 | 4593 | nlocals += 1; |
| 4562 | 4594 | } |
| 4563 | 4595 | |
| 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 | 4603 | for (files.items) |index| { |
| 4565 | 4604 | const file_ptr = self.file(index).?; |
| 4566 | 4605 | const ctx = switch (file_ptr) { |
| ... | ... | @@ -4692,14 +4731,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4692 | 4731 | const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; |
| 4693 | 4732 | var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); |
| 4694 | 4733 | defer buffer.deinit(); |
| 4695 | eh_frame.writeEhFrame(self, buffer.writer()) catch |err| switch (err) { | |
| 4696 | error.RelocFailure => return error.FlushFailure, | |
| 4697 | error.UnsupportedCpuArch => { | |
| 4698 | try self.reportUnsupportedCpuArch(); | |
| 4699 | return error.FlushFailure; | |
| 4700 | }, | |
| 4701 | else => |e| return e, | |
| 4702 | }; | |
| 4734 | try eh_frame.writeEhFrame(self, buffer.writer()); | |
| 4703 | 4735 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| 4704 | 4736 | } |
| 4705 | 4737 | |
| ... | ... | @@ -4731,7 +4763,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4731 | 4763 | |
| 4732 | 4764 | if (self.plt_section_index) |shndx| { |
| 4733 | 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 | 4767 | defer buffer.deinit(); |
| 4736 | 4768 | try self.plt.write(self, buffer.writer()); |
| 4737 | 4769 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| ... | ... | @@ -4747,7 +4779,7 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4747 | 4779 | |
| 4748 | 4780 | if (self.plt_got_section_index) |shndx| { |
| 4749 | 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 | 4783 | defer buffer.deinit(); |
| 4752 | 4784 | try self.plt_got.write(self, buffer.writer()); |
| 4753 | 4785 | try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); |
| ... | ... | @@ -4798,6 +4830,10 @@ pub fn writeSymtab(self: *Elf) !void { |
| 4798 | 4830 | |
| 4799 | 4831 | self.writeSectionSymbols(); |
| 4800 | 4832 | |
| 4833 | for (self.thunks.items) |th| { | |
| 4834 | th.writeSymtab(self); | |
| 4835 | } | |
| 4836 | ||
| 4801 | 4837 | if (self.zigObjectPtr()) |zig_object| { |
| 4802 | 4838 | zig_object.asFile().writeSymtab(self); |
| 4803 | 4839 | } |
| ... | ... | @@ -5393,6 +5429,18 @@ pub fn addAtom(self: *Elf) !Atom.Index { |
| 5393 | 5429 | return index; |
| 5394 | 5430 | } |
| 5395 | 5431 | |
| 5432 | pub 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 | ||
| 5439 | pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk { | |
| 5440 | assert(index < self.thunks.items.len); | |
| 5441 | return &self.thunks.items[index]; | |
| 5442 | } | |
| 5443 | ||
| 5396 | 5444 | pub fn file(self: *Elf, index: File.Index) ?File { |
| 5397 | 5445 | const tag = self.files.items(.tags)[index]; |
| 5398 | 5446 | return switch (tag) { |
| ... | ... | @@ -5572,11 +5620,17 @@ pub fn gotAddress(self: *Elf) u64 { |
| 5572 | 5620 | pub fn tpAddress(self: *Elf) u64 { |
| 5573 | 5621 | const index = self.phdr_tls_index orelse return 0; |
| 5574 | 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 | } |
| 5577 | 5629 | |
| 5578 | 5630 | pub 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 | } |
| 5581 | 5635 | |
| 5582 | 5636 | pub fn tlsAddress(self: *Elf) u64 { |
| ... | ... | @@ -5943,6 +5997,10 @@ fn fmtDumpState( |
| 5943 | 5997 | try writer.print("linker_defined({d}) : (linker defined)\n", .{index}); |
| 5944 | 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 | 6004 | try writer.print("{}\n", .{self.zig_got.fmt(self)}); |
| 5947 | 6005 | try writer.print("{}\n", .{self.got.fmt(self)}); |
| 5948 | 6006 | try writer.print("{}\n", .{self.plt.fmt(self)}); |
| ... | ... | @@ -6010,6 +6068,14 @@ pub fn getTarget(self: Elf) std.Target { |
| 6010 | 6068 | return self.base.comp.root_mod.resolved_target.result; |
| 6011 | 6069 | } |
| 6012 | 6070 | |
| 6071 | fn 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 | 6079 | /// The following three values are only observed at compile-time and used to emit a compile error |
| 6014 | 6080 | /// to remind the programmer to update expected maximum numbers of different program header types |
| 6015 | 6081 | /// so that we reserve enough space for the program header table up-front. |
| ... | ... | @@ -6140,6 +6206,7 @@ const musl = @import("../musl.zig"); |
| 6140 | 6206 | const relocatable = @import("Elf/relocatable.zig"); |
| 6141 | 6207 | const relocation = @import("Elf/relocation.zig"); |
| 6142 | 6208 | const target_util = @import("../target.zig"); |
| 6209 | const thunks = @import("Elf/thunks.zig"); | |
| 6143 | 6210 | const trace = @import("../tracy.zig").trace; |
| 6144 | 6211 | const synthetic_sections = @import("Elf/synthetic_sections.zig"); |
| 6145 | 6212 | |
| ... | ... | @@ -6172,6 +6239,7 @@ const PltGotSection = synthetic_sections.PltGotSection; |
| 6172 | 6239 | const SharedObject = @import("Elf/SharedObject.zig"); |
| 6173 | 6240 | const Symbol = @import("Elf/Symbol.zig"); |
| 6174 | 6241 | const StringTable = @import("StringTable.zig"); |
| 6242 | const Thunk = thunks.Thunk; | |
| 6175 | 6243 | const TypedValue = @import("../TypedValue.zig"); |
| 6176 | 6244 | const VerneedSection = synthetic_sections.VerneedSection; |
| 6177 | 6245 | const ZigGotSection = synthetic_sections.ZigGotSection; |
src/link/Elf/Atom.zig+187-27| ... | ... | @@ -31,6 +31,9 @@ rel_num: u32 = 0, |
| 31 | 31 | /// Index of this atom in the linker's atoms table. |
| 32 | 32 | atom_index: Index = 0, |
| 33 | 33 | |
| 34 | /// Index of the thunk for this atom. | |
| 35 | thunk_index: Thunk.Index = 0, | |
| 36 | ||
| 34 | 37 | /// Flags we use for state tracking. |
| 35 | 38 | flags: Flags = .{}, |
| 36 | 39 | |
| ... | ... | @@ -64,6 +67,10 @@ pub fn file(self: Atom, elf_file: *Elf) ?File { |
| 64 | 67 | return elf_file.file(self.file_index); |
| 65 | 68 | } |
| 66 | 69 | |
| 70 | pub fn thunk(self: Atom, elf_file: *Elf) *Thunk { | |
| 71 | return elf_file.thunk(self.thunk_index); | |
| 72 | } | |
| 73 | ||
| 67 | 74 | pub fn inputShdr(self: Atom, elf_file: *Elf) elf.Elf64_Shdr { |
| 68 | 75 | return switch (self.file(elf_file).?) { |
| 69 | 76 | .object => |x| x.shdrs.items[self.input_section_index], |
| ... | ... | @@ -1592,6 +1599,8 @@ const aarch64 = struct { |
| 1592 | 1599 | _ = it; |
| 1593 | 1600 | |
| 1594 | 1601 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1602 | const is_dyn_lib = elf_file.base.isDynLib(); | |
| 1603 | ||
| 1595 | 1604 | switch (r_type) { |
| 1596 | 1605 | .ABS64 => { |
| 1597 | 1606 | try atom.scanReloc(symbol, rel, dynAbsRelocAction(symbol, elf_file), elf_file); |
| ... | ... | @@ -1620,6 +1629,35 @@ const aarch64 = struct { |
| 1620 | 1629 | } |
| 1621 | 1630 | }, |
| 1622 | 1631 | |
| 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 | 1661 | .ADD_ABS_LO12_NC, |
| 1624 | 1662 | .ADR_PREL_LO21, |
| 1625 | 1663 | .LDST8_ABS_LO12_NC, |
| ... | ... | @@ -1627,6 +1665,8 @@ const aarch64 = struct { |
| 1627 | 1665 | .LDST32_ABS_LO12_NC, |
| 1628 | 1666 | .LDST64_ABS_LO12_NC, |
| 1629 | 1667 | .LDST128_ABS_LO12_NC, |
| 1668 | .PREL32, | |
| 1669 | .PREL64, | |
| 1630 | 1670 | => {}, |
| 1631 | 1671 | |
| 1632 | 1672 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| ... | ... | @@ -1640,7 +1680,7 @@ const aarch64 = struct { |
| 1640 | 1680 | target: *const Symbol, |
| 1641 | 1681 | args: ResolveArgs, |
| 1642 | 1682 | it: *RelocsIterator, |
| 1643 | code: []u8, | |
| 1683 | code_buffer: []u8, | |
| 1644 | 1684 | stream: anytype, |
| 1645 | 1685 | ) (error{ UnexpectedRemainder, DivisionByZero } || RelocError)!void { |
| 1646 | 1686 | _ = it; |
| ... | ... | @@ -1648,9 +1688,10 @@ const aarch64 = struct { |
| 1648 | 1688 | const r_type: elf.R_AARCH64 = @enumFromInt(rel.r_type()); |
| 1649 | 1689 | const r_offset = std.math.cast(usize, rel.r_offset) orelse return error.Overflow; |
| 1650 | 1690 | const cwriter = stream.writer(); |
| 1691 | const code = code_buffer[r_offset..][0..4]; | |
| 1692 | const file_ptr = atom.file(elf_file).?; | |
| 1651 | 1693 | |
| 1652 | 1694 | const P, const A, const S, const GOT, const G, const TP, const DTP, const ZIG_GOT = args; |
| 1653 | _ = TP; | |
| 1654 | 1695 | _ = DTP; |
| 1655 | 1696 | _ = ZIG_GOT; |
| 1656 | 1697 | |
| ... | ... | @@ -1669,20 +1710,27 @@ const aarch64 = struct { |
| 1669 | 1710 | .CALL26, |
| 1670 | 1711 | .JUMP26, |
| 1671 | 1712 | => { |
| 1672 | // TODO: add thunk support | |
| 1673 | const disp: i28 = math.cast(i28, S + A - P) orelse { | |
| 1674 | var err = try elf_file.addErrorWithNotes(1); | |
| 1675 | try err.addMsg(elf_file, "TODO: branch relocation target ({s}) exceeds max jump distance", .{ | |
| 1676 | target.name(elf_file), | |
| 1677 | }); | |
| 1678 | try err.addNote(elf_file, "in {}:{s} at offset 0x{x}", .{ | |
| 1679 | atom.file(elf_file).?.fmtPath(), | |
| 1680 | atom.name(elf_file), | |
| 1681 | r_offset, | |
| 1682 | }); | |
| 1683 | return; | |
| 1713 | const disp: i28 = math.cast(i28, S + A - P) orelse blk: { | |
| 1714 | const th = atom.thunk(elf_file); | |
| 1715 | const target_index = switch (file_ptr) { | |
| 1716 | .zig_object => |x| x.symbol(rel.r_sym()), | |
| 1717 | .object => |x| x.symbols.items[rel.r_sym()], | |
| 1718 | else => unreachable, | |
| 1719 | }; | |
| 1720 | const S_: i64 = @intCast(th.targetAddress(target_index, elf_file)); | |
| 1721 | break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow; | |
| 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 | }, |
| 1687 | 1735 | |
| 1688 | 1736 | .ADR_PREL_PG_HI21 => { |
| ... | ... | @@ -1690,14 +1738,14 @@ const aarch64 = struct { |
| 1690 | 1738 | const saddr = @as(u64, @intCast(P)); |
| 1691 | 1739 | const taddr = @as(u64, @intCast(S + A)); |
| 1692 | 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 | }, |
| 1695 | 1743 | |
| 1696 | 1744 | .ADR_GOT_PAGE => if (target.flags.has_got) { |
| 1697 | 1745 | const saddr = @as(u64, @intCast(P)); |
| 1698 | 1746 | const taddr = @as(u64, @intCast(G + GOT + A)); |
| 1699 | 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 | 1749 | } else { |
| 1702 | 1750 | // TODO: relax |
| 1703 | 1751 | var err = try elf_file.addErrorWithNotes(1); |
| ... | ... | @@ -1712,10 +1760,14 @@ const aarch64 = struct { |
| 1712 | 1760 | .LD64_GOT_LO12_NC => { |
| 1713 | 1761 | assert(target.flags.has_got); |
| 1714 | 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 | }, |
| 1717 | 1770 | |
| 1718 | .ADD_ABS_LO12_NC, | |
| 1719 | 1771 | .LDST8_ABS_LO12_NC, |
| 1720 | 1772 | .LDST16_ABS_LO12_NC, |
| 1721 | 1773 | .LDST32_ABS_LO12_NC, |
| ... | ... | @@ -1724,16 +1776,121 @@ const aarch64 = struct { |
| 1724 | 1776 | => { |
| 1725 | 1777 | // TODO: NC means no overflow check |
| 1726 | 1778 | const taddr = @as(u64, @intCast(S + A)); |
| 1727 | const kind: aarch64_util.PageOffsetInstKind = switch (r_type) { | |
| 1728 | .ADD_ABS_LO12_NC => .arithmetic, | |
| 1729 | .LDST8_ABS_LO12_NC => .load_store_8, | |
| 1730 | .LDST16_ABS_LO12_NC => .load_store_16, | |
| 1731 | .LDST32_ABS_LO12_NC => .load_store_32, | |
| 1732 | .LDST64_ABS_LO12_NC => .load_store_64, | |
| 1733 | .LDST128_ABS_LO12_NC => .load_store_128, | |
| 1779 | const offset: u12 = switch (r_type) { | |
| 1780 | .LDST8_ABS_LO12_NC => @truncate(taddr), | |
| 1781 | .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2), | |
| 1782 | .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4), | |
| 1783 | .LDST64_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 8), | |
| 1784 | .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16), | |
| 1734 | 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 | }, |
| 1738 | 1895 | |
| 1739 | 1896 | else => try atom.reportUnhandledRelocError(rel, elf_file), |
| ... | ... | @@ -1768,6 +1925,8 @@ const aarch64 = struct { |
| 1768 | 1925 | } |
| 1769 | 1926 | |
| 1770 | 1927 | const aarch64_util = @import("../aarch64.zig"); |
| 1928 | const Instruction = aarch64_util.Instruction; | |
| 1929 | const Register = aarch64_util.Register; | |
| 1771 | 1930 | }; |
| 1772 | 1931 | |
| 1773 | 1932 | const riscv = struct { |
| ... | ... | @@ -2025,3 +2184,4 @@ const Fde = eh_frame.Fde; |
| 2025 | 2184 | const File = @import("file.zig").File; |
| 2026 | 2185 | const Object = @import("Object.zig"); |
| 2027 | 2186 | const Symbol = @import("Symbol.zig"); |
| 2187 | const Thunk = @import("thunks.zig").Thunk; |
src/link/Elf/LdScript.zig+1| ... | ... | @@ -139,6 +139,7 @@ const Parser = struct { |
| 139 | 139 | } else return error.UnexpectedToken; |
| 140 | 140 | }; |
| 141 | 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 | 143 | return error.UnknownCpuArch; |
| 143 | 144 | } |
| 144 | 145 |
src/link/Elf/Object.zig+5-6| ... | ... | @@ -371,17 +371,16 @@ fn parseEhFrame(self: *Object, allocator: Allocator, handle: std.fs.File, shndx: |
| 371 | 371 | const relocs_shndx = for (self.shdrs.items, 0..) |shdr, i| switch (shdr.sh_type) { |
| 372 | 372 | elf.SHT_RELA => if (shdr.sh_info == shndx) break @as(u32, @intCast(i)), |
| 373 | 373 | else => {}, |
| 374 | } else { | |
| 375 | // TODO: convert into an error | |
| 376 | log.debug("{s}: missing reloc section for unwind info section", .{self.fmtPath()}); | |
| 377 | return; | |
| 378 | }; | |
| 374 | } else null; | |
| 379 | 375 | |
| 380 | 376 | const raw = try self.preadShdrContentsAlloc(allocator, handle, shndx); |
| 381 | 377 | defer allocator.free(raw); |
| 382 | 378 | const data_start = @as(u32, @intCast(self.eh_frame_data.items.len)); |
| 383 | 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 | 384 | defer allocator.free(relocs); |
| 386 | 385 | const rel_start = @as(u32, @intCast(self.relocs.items.len)); |
| 387 | 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 | 139 | if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0; |
| 140 | 140 | const extras = symbol.extra(elf_file).?; |
| 141 | 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 | } |
| 144 | 145 | |
| 145 | 146 | pub fn pltAddress(symbol: Symbol, elf_file: *Elf) u64 { |
| 146 | 147 | if (!symbol.flags.has_plt) return 0; |
| 147 | 148 | const extras = symbol.extra(elf_file).?; |
| 148 | 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 | } |
| 151 | 153 | |
| 152 | 154 | pub 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 | 253 | break :blk 0; |
| 252 | 254 | } |
| 253 | 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 | 257 | if (shdr.sh_flags & elf.SHF_TLS != 0 and file_ptr != .linker_defined) |
| 256 | 258 | break :blk symbol.address(.{ .plt = false }, elf_file) - elf_file.tlsAddress(); |
| 257 | 259 | break :blk symbol.address(.{ .plt = false }, elf_file); |
| ... | ... | @@ -441,6 +443,7 @@ const GotPltSection = synthetic_sections.GotPltSection; |
| 441 | 443 | const LinkerDefined = @import("LinkerDefined.zig"); |
| 442 | 444 | const Object = @import("Object.zig"); |
| 443 | 445 | const PltSection = synthetic_sections.PltSection; |
| 446 | const PltGotSection = synthetic_sections.PltGotSection; | |
| 444 | 447 | const SharedObject = @import("SharedObject.zig"); |
| 445 | 448 | const Symbol = @This(); |
| 446 | 449 | const ZigGotSection = synthetic_sections.ZigGotSection; |
src/link/Elf/eh_frame.zig+1| ... | ... | @@ -214,6 +214,7 @@ pub const Iterator = struct { |
| 214 | 214 | const reader = stream.reader(); |
| 215 | 215 | |
| 216 | 216 | const size = try reader.readInt(u32, .little); |
| 217 | if (size == 0) return null; | |
| 217 | 218 | if (size == 0xFFFFFFFF) @panic("TODO"); |
| 218 | 219 | |
| 219 | 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 | 634 | } |
| 635 | 635 | }, |
| 636 | 636 | .tlsdesc => { |
| 637 | try writeInt(0, elf_file, writer); | |
| 638 | try writeInt(0, elf_file, writer); | |
| 637 | if (symbol.?.flags.import) { | |
| 638 | try writeInt(0, elf_file, writer); | |
| 639 | try writeInt(0, elf_file, writer); | |
| 640 | } else { | |
| 641 | try writeInt(0, elf_file, writer); | |
| 642 | const offset = if (apply_relocs) | |
| 643 | @as(i64, @intCast(symbol.?.address(.{}, elf_file))) - @as(i64, @intCast(elf_file.tlsAddress())) | |
| 644 | else | |
| 645 | 0; | |
| 646 | try writeInt(offset, elf_file, writer); | |
| 647 | } | |
| 639 | 648 | }, |
| 640 | 649 | } |
| 641 | 650 | } |
| ... | ... | @@ -738,8 +747,9 @@ pub const GotSection = struct { |
| 738 | 747 | const offset = symbol.?.tlsDescAddress(elf_file); |
| 739 | 748 | elf_file.addRelaDynAssumeCapacity(.{ |
| 740 | 749 | .offset = offset, |
| 741 | .sym = extra.?.dynamic, | |
| 750 | .sym = if (symbol.?.flags.import) extra.?.dynamic else 0, | |
| 742 | 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 | 867 | symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 858 | 868 | output_symtab_ctx: Elf.SymtabCtx = .{}, |
| 859 | 869 | |
| 860 | pub const preamble_size = 32; | |
| 861 | ||
| 862 | 870 | pub fn deinit(plt: *PltSection, allocator: Allocator) void { |
| 863 | 871 | plt.symbols.deinit(allocator); |
| 864 | 872 | } |
| ... | ... | @@ -877,39 +885,33 @@ pub const PltSection = struct { |
| 877 | 885 | try plt.symbols.append(gpa, sym_index); |
| 878 | 886 | } |
| 879 | 887 | |
| 880 | pub fn size(plt: PltSection) usize { | |
| 881 | return preamble_size + plt.symbols.items.len * 16; | |
| 888 | pub fn size(plt: PltSection, elf_file: *Elf) usize { | |
| 889 | const cpu_arch = elf_file.getTarget().cpu.arch; | |
| 890 | return preambleSize(cpu_arch) + plt.symbols.items.len * entrySize(cpu_arch); | |
| 882 | 891 | } |
| 883 | 892 | |
| 884 | pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | |
| 885 | const plt_addr = elf_file.shdrs.items[elf_file.plt_section_index.?].sh_addr; | |
| 886 | const got_plt_addr = elf_file.shdrs.items[elf_file.got_plt_section_index.?].sh_addr; | |
| 887 | var preamble = [_]u8{ | |
| 888 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 | |
| 889 | 0x41, 0x53, // push r11 | |
| 890 | 0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // push qword ptr [rip] -> .got.plt[1] | |
| 891 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[2] | |
| 893 | pub fn preambleSize(cpu_arch: std.Target.Cpu.Arch) usize { | |
| 894 | return switch (cpu_arch) { | |
| 895 | .x86_64 => 32, | |
| 896 | .aarch64 => 8 * @sizeOf(u32), | |
| 897 | else => @panic("TODO implement preambleSize for this cpu arch"), | |
| 892 | 898 | }; |
| 893 | var disp = @as(i64, @intCast(got_plt_addr + 8)) - @as(i64, @intCast(plt_addr + 8)) - 4; | |
| 894 | mem.writeInt(i32, preamble[8..][0..4], @as(i32, @intCast(disp)), .little); | |
| 895 | disp = @as(i64, @intCast(got_plt_addr + 16)) - @as(i64, @intCast(plt_addr + 14)) - 4; | |
| 896 | mem.writeInt(i32, preamble[14..][0..4], @as(i32, @intCast(disp)), .little); | |
| 897 | try writer.writeAll(&preamble); | |
| 898 | try writer.writeByteNTimes(0xcc, preamble_size - preamble.len); | |
| 899 | ||
| 900 | for (plt.symbols.items, 0..) |sym_index, i| { | |
| 901 | const sym = elf_file.symbol(sym_index); | |
| 902 | const target_addr = sym.gotPltAddress(elf_file); | |
| 903 | const source_addr = sym.pltAddress(elf_file); | |
| 904 | disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 12)) - 4; | |
| 905 | var entry = [_]u8{ | |
| 906 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 | |
| 907 | 0x41, 0xbb, 0x00, 0x00, 0x00, 0x00, // mov r11d, N | |
| 908 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got.plt[N] | |
| 909 | }; | |
| 910 | mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(i)), .little); | |
| 911 | mem.writeInt(i32, entry[12..][0..4], @as(i32, @intCast(disp)), .little); | |
| 912 | try writer.writeAll(&entry); | |
| 899 | } | |
| 900 | ||
| 901 | pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize { | |
| 902 | return switch (cpu_arch) { | |
| 903 | .x86_64 => 16, | |
| 904 | .aarch64 => 4 * @sizeOf(u32), | |
| 905 | else => @panic("TODO implement entrySize for this cpu arch"), | |
| 906 | }; | |
| 907 | } | |
| 908 | ||
| 909 | pub fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { | |
| 910 | const cpu_arch = elf_file.getTarget().cpu.arch; | |
| 911 | switch (cpu_arch) { | |
| 912 | .x86_64 => try x86_64.write(plt, elf_file, writer), | |
| 913 | .aarch64 => try aarch64.write(plt, elf_file, writer), | |
| 914 | else => return error.UnsupportedCpuArch, | |
| 913 | 915 | } |
| 914 | 916 | } |
| 915 | 917 | |
| ... | ... | @@ -946,6 +948,7 @@ pub const PltSection = struct { |
| 946 | 948 | } |
| 947 | 949 | |
| 948 | 950 | pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void { |
| 951 | const cpu_arch = elf_file.getTarget().cpu.arch; | |
| 949 | 952 | for (plt.symbols.items, plt.output_symtab_ctx.ilocal..) |sym_index, ilocal| { |
| 950 | 953 | const sym = elf_file.symbol(sym_index); |
| 951 | 954 | const st_name = @as(u32, @intCast(elf_file.strtab.items.len)); |
| ... | ... | @@ -958,7 +961,7 @@ pub const PltSection = struct { |
| 958 | 961 | .st_other = 0, |
| 959 | 962 | .st_shndx = @intCast(elf_file.plt_section_index.?), |
| 960 | 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 | 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 | }; |
| 996 | 1090 | |
| 997 | 1091 | pub const GotPltSection = struct { |
| ... | ... | @@ -1046,23 +1140,24 @@ pub const PltGotSection = struct { |
| 1046 | 1140 | try plt_got.symbols.append(gpa, sym_index); |
| 1047 | 1141 | } |
| 1048 | 1142 | |
| 1049 | pub fn size(plt_got: PltGotSection) usize { | |
| 1050 | return plt_got.symbols.items.len * 16; | |
| 1143 | pub fn size(plt_got: PltGotSection, elf_file: *Elf) usize { | |
| 1144 | return plt_got.symbols.items.len * entrySize(elf_file.getTarget().cpu.arch); | |
| 1145 | } | |
| 1146 | ||
| 1147 | pub fn entrySize(cpu_arch: std.Target.Cpu.Arch) usize { | |
| 1148 | return switch (cpu_arch) { | |
| 1149 | .x86_64 => 16, | |
| 1150 | .aarch64 => 4 * @sizeOf(u32), | |
| 1151 | else => @panic("TODO implement PltGotSection.entrySize for this arch"), | |
| 1152 | }; | |
| 1051 | 1153 | } |
| 1052 | 1154 | |
| 1053 | 1155 | pub fn write(plt_got: PltGotSection, elf_file: *Elf, writer: anytype) !void { |
| 1054 | for (plt_got.symbols.items) |sym_index| { | |
| 1055 | const sym = elf_file.symbol(sym_index); | |
| 1056 | const target_addr = sym.gotAddress(elf_file); | |
| 1057 | const source_addr = sym.pltGotAddress(elf_file); | |
| 1058 | const disp = @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr + 6)) - 4; | |
| 1059 | var entry = [_]u8{ | |
| 1060 | 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 | |
| 1061 | 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] -> .got[N] | |
| 1062 | 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, | |
| 1063 | }; | |
| 1064 | mem.writeInt(i32, entry[6..][0..4], @as(i32, @intCast(disp)), .little); | |
| 1065 | try writer.writeAll(&entry); | |
| 1156 | const cpu_arch = elf_file.getTarget().cpu.arch; | |
| 1157 | switch (cpu_arch) { | |
| 1158 | .x86_64 => try x86_64.write(plt_got, elf_file, writer), | |
| 1159 | .aarch64 => try aarch64.write(plt_got, elf_file, writer), | |
| 1160 | else => return error.UnsupportedCpuArch, | |
| 1066 | 1161 | } |
| 1067 | 1162 | } |
| 1068 | 1163 | |
| ... | ... | @@ -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 | }; |
| 1095 | 1234 | |
| 1096 | 1235 | pub const CopyRelSection = struct { |
| ... | ... | @@ -1629,6 +1768,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void { |
| 1629 | 1768 | const assert = std.debug.assert; |
| 1630 | 1769 | const builtin = @import("builtin"); |
| 1631 | 1770 | const elf = std.elf; |
| 1771 | const math = std.math; | |
| 1632 | 1772 | const mem = std.mem; |
| 1633 | 1773 | const log = std.log.scoped(.link); |
| 1634 | 1774 | const relocation = @import("relocation.zig"); |
src/link/Elf/thunks.zig created+243| ... | ... | @@ -0,0 +1,243 @@ |
| 1 | pub 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 | ||
| 62 | fn 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. | |
| 72 | fn 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 | ||
| 80 | pub 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 | ||
| 193 | const 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 | ||
| 233 | const assert = std.debug.assert; | |
| 234 | const elf = std.elf; | |
| 235 | const log = std.log.scoped(.link); | |
| 236 | const math = std.math; | |
| 237 | const mem = std.mem; | |
| 238 | const std = @import("std"); | |
| 239 | ||
| 240 | const Allocator = mem.Allocator; | |
| 241 | const Atom = @import("Atom.zig"); | |
| 242 | const Elf = @import("../Elf.zig"); | |
| 243 | const Symbol = @import("Symbol.zig"); |
src/link/MachO/Atom.zig+25-7| ... | ... | @@ -700,7 +700,7 @@ fn resolveRelocInner( |
| 700 | 700 | const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file)); |
| 701 | 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 | 705 | else => unreachable, |
| 706 | 706 | } |
| ... | ... | @@ -771,7 +771,7 @@ fn resolveRelocInner( |
| 771 | 771 | break :target math.cast(u64, target) orelse return error.Overflow; |
| 772 | 772 | }; |
| 773 | 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 | }, |
| 776 | 776 | |
| 777 | 777 | .pageoff => { |
| ... | ... | @@ -780,8 +780,26 @@ fn resolveRelocInner( |
| 780 | 780 | assert(!rel.meta.pcrel); |
| 781 | 781 | const target = math.cast(u64, S + A) orelse return error.Overflow; |
| 782 | 782 | const inst_code = code[rel_offset..][0..4]; |
| 783 | const kind = aarch64.classifyInst(inst_code); | |
| 784 | try aarch64.writePageOffset(kind, target, inst_code); | |
| 783 | if (aarch64.isArithmeticOp(inst_code)) { | |
| 784 | aarch64.writeAddImmInst(@truncate(target), inst_code); | |
| 785 | } else { | |
| 786 | var inst = aarch64.Instruction{ | |
| 787 | .load_store_register = mem.bytesToValue(std.meta.TagPayload( | |
| 788 | aarch64.Instruction, | |
| 789 | aarch64.Instruction.load_store_register, | |
| 790 | ), inst_code), | |
| 791 | }; | |
| 792 | inst.load_store_register.offset = switch (inst.load_store_register.size) { | |
| 793 | 0 => if (inst.load_store_register.v == 1) | |
| 794 | try math.divExact(u12, @truncate(target), 16) | |
| 795 | else | |
| 796 | @truncate(target), | |
| 797 | 1 => try math.divExact(u12, @truncate(target), 2), | |
| 798 | 2 => try math.divExact(u12, @truncate(target), 4), | |
| 799 | 3 => try math.divExact(u12, @truncate(target), 8), | |
| 800 | }; | |
| 801 | try writer.writeInt(u32, inst.toU32(), .little); | |
| 802 | } | |
| 785 | 803 | }, |
| 786 | 804 | |
| 787 | 805 | .got_load_pageoff => { |
| ... | ... | @@ -789,7 +807,7 @@ fn resolveRelocInner( |
| 789 | 807 | assert(rel.meta.length == 2); |
| 790 | 808 | assert(!rel.meta.pcrel); |
| 791 | 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 | }, |
| 794 | 812 | |
| 795 | 813 | .tlvp_pageoff => { |
| ... | ... | @@ -841,7 +859,7 @@ fn resolveRelocInner( |
| 841 | 859 | .load_store_register = .{ |
| 842 | 860 | .rt = reg_info.rd, |
| 843 | 861 | .rn = reg_info.rn, |
| 844 | .offset = try aarch64.calcPageOffset(.load_store_64, target), | |
| 862 | .offset = try math.divExact(u12, @truncate(target), 8), | |
| 845 | 863 | .opc = 0b01, |
| 846 | 864 | .op1 = 0b01, |
| 847 | 865 | .v = 0, |
| ... | ... | @@ -851,7 +869,7 @@ fn resolveRelocInner( |
| 851 | 869 | .add_subtract_immediate = .{ |
| 852 | 870 | .rd = reg_info.rd, |
| 853 | 871 | .rn = reg_info.rn, |
| 854 | .imm12 = try aarch64.calcPageOffset(.arithmetic, target), | |
| 872 | .imm12 = @truncate(target), | |
| 855 | 873 | .sh = 0, |
| 856 | 874 | .s = 0, |
| 857 | 875 | .op = 0, |
src/link/MachO/synthetic.zig+5-5| ... | ... | @@ -269,7 +269,7 @@ pub const StubsSection = struct { |
| 269 | 269 | // TODO relax if possible |
| 270 | 270 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 271 | 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 | 273 | try writer.writeInt( |
| 274 | 274 | u32, |
| 275 | 275 | aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), |
| ... | ... | @@ -413,7 +413,7 @@ pub const StubsHelperSection = struct { |
| 413 | 413 | // TODO relax if possible |
| 414 | 414 | const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr); |
| 415 | 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 | 417 | try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little); |
| 418 | 418 | } |
| 419 | 419 | try writer.writeInt(u32, aarch64.Instruction.stp( |
| ... | ... | @@ -426,7 +426,7 @@ pub const StubsHelperSection = struct { |
| 426 | 426 | // TODO relax if possible |
| 427 | 427 | const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr); |
| 428 | 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 | 430 | try writer.writeInt(u32, aarch64.Instruction.ldr( |
| 431 | 431 | .x16, |
| 432 | 432 | .x16, |
| ... | ... | @@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct { |
| 681 | 681 | const source = addr; |
| 682 | 682 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 683 | 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 | 685 | try writer.writeInt( |
| 686 | 686 | u32, |
| 687 | 687 | aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(), |
| ... | ... | @@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct { |
| 694 | 694 | const source = addr + 2 * @sizeOf(u32); |
| 695 | 695 | const pages = try aarch64.calcNumberOfPages(source, target); |
| 696 | 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 | 698 | try writer.writeInt( |
| 699 | 699 | u32, |
| 700 | 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 | 101 | const taddr = sym.getAddress(.{}, macho_file); |
| 102 | 102 | const pages = try aarch64.calcNumberOfPages(saddr, taddr); |
| 103 | 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 | 105 | try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little); |
| 106 | 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 | 3 | return ((group_decode >> 2) == 4); |
| 4 | 4 | } |
| 5 | 5 | |
| 6 | pub const PageOffsetInstKind = enum { | |
| 7 | arithmetic, | |
| 8 | load_store_8, | |
| 9 | load_store_16, | |
| 10 | load_store_32, | |
| 11 | load_store_64, | |
| 12 | load_store_128, | |
| 13 | }; | |
| 14 | ||
| 15 | pub 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( | |
| 6 | pub fn writeAddImmInst(value: u12, code: *[4]u8) void { | |
| 7 | var inst = Instruction{ | |
| 8 | .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( | |
| 19 | 9 | Instruction, |
| 20 | Instruction.load_store_register, | |
| 10 | Instruction.add_subtract_immediate, | |
| 21 | 11 | ), code), |
| 22 | 12 | }; |
| 23 | return switch (inst.load_store_register.size) { | |
| 24 | 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8, | |
| 25 | 1 => .load_store_16, | |
| 26 | 2 => .load_store_32, | |
| 27 | 3 => .load_store_64, | |
| 28 | }; | |
| 13 | inst.add_subtract_immediate.imm12 = value; | |
| 14 | mem.writeInt(u32, code, inst.toU32(), .little); | |
| 29 | 15 | } |
| 30 | 16 | |
| 31 | pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 { | |
| 32 | const narrowed = @as(u12, @truncate(taddr)); | |
| 33 | return switch (kind) { | |
| 34 | .arithmetic, .load_store_8 => narrowed, | |
| 35 | .load_store_16 => try math.divExact(u12, narrowed, 2), | |
| 36 | .load_store_32 => try math.divExact(u12, narrowed, 4), | |
| 37 | .load_store_64 => try math.divExact(u12, narrowed, 8), | |
| 38 | .load_store_128 => try math.divExact(u12, narrowed, 16), | |
| 17 | pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void { | |
| 18 | var inst: Instruction = .{ | |
| 19 | .load_store_register = mem.bytesToValue(std.meta.TagPayload( | |
| 20 | Instruction, | |
| 21 | Instruction.load_store_register, | |
| 22 | ), code), | |
| 39 | 23 | }; |
| 40 | } | |
| 41 | ||
| 42 | pub fn writePageOffset(kind: PageOffsetInstKind, taddr: u64, code: *[4]u8) !void { | |
| 43 | const value = try calcPageOffset(kind, taddr); | |
| 44 | switch (kind) { | |
| 45 | .arithmetic => { | |
| 46 | var inst = Instruction{ | |
| 47 | .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( | |
| 48 | Instruction, | |
| 49 | Instruction.add_subtract_immediate, | |
| 50 | ), code), | |
| 51 | }; | |
| 52 | inst.add_subtract_immediate.imm12 = value; | |
| 53 | mem.writeInt(u32, code, inst.toU32(), .little); | |
| 54 | }, | |
| 55 | else => { | |
| 56 | var inst: Instruction = .{ | |
| 57 | .load_store_register = mem.bytesToValue(std.meta.TagPayload( | |
| 58 | Instruction, | |
| 59 | Instruction.load_store_register, | |
| 60 | ), code), | |
| 61 | }; | |
| 62 | inst.load_store_register.offset = value; | |
| 63 | mem.writeInt(u32, code, inst.toU32(), .little); | |
| 64 | }, | |
| 65 | } | |
| 24 | inst.load_store_register.offset = value; | |
| 25 | mem.writeInt(u32, code, inst.toU32(), .little); | |
| 66 | 26 | } |
| 67 | 27 | |
| 68 | 28 | 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 | 32 | return pages; |
| 73 | 33 | } |
| 74 | 34 | |
| 75 | pub fn writePages(pages: u21, code: *[4]u8) !void { | |
| 35 | pub fn writeAdrpInst(pages: u21, code: *[4]u8) void { | |
| 76 | 36 | var inst = Instruction{ |
| 77 | 37 | .pc_relative_address = mem.bytesToValue(std.meta.TagPayload( |
| 78 | 38 | Instruction, |
| ... | ... | @@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void { |
| 84 | 44 | mem.writeInt(u32, code, inst.toU32(), .little); |
| 85 | 45 | } |
| 86 | 46 | |
| 87 | pub fn writeBranchImm(disp: i28, code: *[4]u8) !void { | |
| 47 | pub fn writeBranchImm(disp: i28, code: *[4]u8) void { | |
| 88 | 48 | var inst = Instruction{ |
| 89 | 49 | .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload( |
| 90 | 50 | Instruction, |
test/link/elf.zig+129-187| ... | ... | @@ -20,30 +20,142 @@ pub fn testAll(b: *Build, build_opts: BuildOptions) *Step { |
| 20 | 20 | .os_tag = .linux, |
| 21 | 21 | .abi = .gnu, |
| 22 | 22 | }); |
| 23 | const aarch64_musl = b.resolveTargetQuery(.{ | |
| 24 | .cpu_arch = .aarch64, | |
| 25 | .os_tag = .linux, | |
| 26 | .abi = .musl, | |
| 27 | }); | |
| 23 | // const aarch64_musl = b.resolveTargetQuery(.{ | |
| 24 | // .cpu_arch = .aarch64, | |
| 25 | // .os_tag = .linux, | |
| 26 | // .abi = .musl, | |
| 27 | // }); | |
| 28 | // const aarch64_gnu = b.resolveTargetQuery(.{ | |
| 29 | // .cpu_arch = .aarch64, | |
| 30 | // .os_tag = .linux, | |
| 31 | // .abi = .gnu, | |
| 32 | // }); | |
| 28 | 33 | const riscv64_musl = b.resolveTargetQuery(.{ |
| 29 | 34 | .cpu_arch = .riscv64, |
| 30 | 35 | .os_tag = .linux, |
| 31 | 36 | .abi = .musl, |
| 32 | 37 | }); |
| 33 | 38 | |
| 34 | // x86_64 tests | |
| 35 | // Exercise linker in -r mode | |
| 36 | elf_step.dependOn(testEmitRelocatable(b, .{ .use_llvm = false, .target = x86_64_musl })); | |
| 37 | elf_step.dependOn(testEmitRelocatable(b, .{ .target = x86_64_musl })); | |
| 38 | elf_step.dependOn(testRelocatableArchive(b, .{ .target = x86_64_musl })); | |
| 39 | elf_step.dependOn(testRelocatableEhFrame(b, .{ .target = x86_64_musl })); | |
| 40 | elf_step.dependOn(testRelocatableNoEhFrame(b, .{ .target = x86_64_musl })); | |
| 39 | // Common tests | |
| 40 | for (&[_]std.Target.Cpu.Arch{ | |
| 41 | .x86_64, | |
| 42 | .aarch64, | |
| 43 | }) |cpu_arch| { | |
| 44 | const musl_target = b.resolveTargetQuery(.{ | |
| 45 | .cpu_arch = cpu_arch, | |
| 46 | .os_tag = .linux, | |
| 47 | .abi = .musl, | |
| 48 | }); | |
| 49 | const gnu_target = b.resolveTargetQuery(.{ | |
| 50 | .cpu_arch = cpu_arch, | |
| 51 | .os_tag = .linux, | |
| 52 | .abi = .gnu, | |
| 53 | }); | |
| 41 | 54 | |
| 42 | // Exercise linker in ar mode | |
| 43 | elf_step.dependOn(testEmitStaticLib(b, .{ .target = x86_64_musl })); | |
| 44 | elf_step.dependOn(testEmitStaticLibZig(b, .{ .use_llvm = false, .target = x86_64_musl })); | |
| 55 | // Exercise linker in -r mode | |
| 56 | elf_step.dependOn(testEmitRelocatable(b, .{ .target = musl_target })); | |
| 57 | elf_step.dependOn(testRelocatableArchive(b, .{ .target = musl_target })); | |
| 58 | elf_step.dependOn(testRelocatableEhFrame(b, .{ .target = musl_target })); | |
| 59 | elf_step.dependOn(testRelocatableNoEhFrame(b, .{ .target = musl_target })); | |
| 60 | ||
| 61 | // Exercise linker in ar mode | |
| 62 | elf_step.dependOn(testEmitStaticLib(b, .{ .target = musl_target })); | |
| 63 | ||
| 64 | // Exercise linker with LLVM backend | |
| 65 | // musl tests | |
| 66 | elf_step.dependOn(testAbsSymbols(b, .{ .target = musl_target })); | |
| 67 | elf_step.dependOn(testCommonSymbols(b, .{ .target = musl_target })); | |
| 68 | elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = musl_target })); | |
| 69 | elf_step.dependOn(testEmptyObject(b, .{ .target = musl_target })); | |
| 70 | elf_step.dependOn(testEntryPoint(b, .{ .target = musl_target })); | |
| 71 | elf_step.dependOn(testGcSections(b, .{ .target = musl_target })); | |
| 72 | elf_step.dependOn(testImageBase(b, .{ .target = musl_target })); | |
| 73 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = musl_target })); | |
| 74 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = musl_target })); | |
| 75 | // https://github.com/ziglang/zig/issues/17449 | |
| 76 | // elf_step.dependOn(testLargeBss(b, .{ .target = musl_target })); | |
| 77 | elf_step.dependOn(testLinkingC(b, .{ .target = musl_target })); | |
| 78 | elf_step.dependOn(testLinkingCpp(b, .{ .target = musl_target })); | |
| 79 | elf_step.dependOn(testLinkingZig(b, .{ .target = musl_target })); | |
| 80 | // https://github.com/ziglang/zig/issues/17451 | |
| 81 | // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = musl_target })); | |
| 82 | elf_step.dependOn(testTlsStatic(b, .{ .target = musl_target })); | |
| 83 | elf_step.dependOn(testStrip(b, .{ .target = musl_target })); | |
| 84 | ||
| 85 | // glibc tests | |
| 86 | elf_step.dependOn(testAsNeeded(b, .{ .target = gnu_target })); | |
| 87 | // https://github.com/ziglang/zig/issues/17430 | |
| 88 | // elf_step.dependOn(testCanonicalPlt(b, .{ .target = gnu_target })); | |
| 89 | elf_step.dependOn(testCopyrel(b, .{ .target = gnu_target })); | |
| 90 | // https://github.com/ziglang/zig/issues/17430 | |
| 91 | // elf_step.dependOn(testCopyrelAlias(b, .{ .target = gnu_target })); | |
| 92 | // https://github.com/ziglang/zig/issues/17430 | |
| 93 | // elf_step.dependOn(testCopyrelAlignment(b, .{ .target = gnu_target })); | |
| 94 | elf_step.dependOn(testDsoPlt(b, .{ .target = gnu_target })); | |
| 95 | elf_step.dependOn(testDsoUndef(b, .{ .target = gnu_target })); | |
| 96 | elf_step.dependOn(testExportDynamic(b, .{ .target = gnu_target })); | |
| 97 | elf_step.dependOn(testExportSymbolsFromExe(b, .{ .target = gnu_target })); | |
| 98 | // https://github.com/ziglang/zig/issues/17430 | |
| 99 | // elf_step.dependOn(testFuncAddress(b, .{ .target = gnu_target })); | |
| 100 | elf_step.dependOn(testHiddenWeakUndef(b, .{ .target = gnu_target })); | |
| 101 | elf_step.dependOn(testIFuncAlias(b, .{ .target = gnu_target })); | |
| 102 | // https://github.com/ziglang/zig/issues/17430 | |
| 103 | // elf_step.dependOn(testIFuncDlopen(b, .{ .target = gnu_target })); | |
| 104 | elf_step.dependOn(testIFuncDso(b, .{ .target = gnu_target })); | |
| 105 | elf_step.dependOn(testIFuncDynamic(b, .{ .target = gnu_target })); | |
| 106 | elf_step.dependOn(testIFuncExport(b, .{ .target = gnu_target })); | |
| 107 | elf_step.dependOn(testIFuncFuncPtr(b, .{ .target = gnu_target })); | |
| 108 | elf_step.dependOn(testIFuncNoPlt(b, .{ .target = gnu_target })); | |
| 109 | // https://github.com/ziglang/zig/issues/17430 ?? | |
| 110 | // elf_step.dependOn(testIFuncStatic(b, .{ .target = gnu_target })); | |
| 111 | // elf_step.dependOn(testIFuncStaticPie(b, .{ .target = gnu_target })); | |
| 112 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = gnu_target })); | |
| 113 | elf_step.dependOn(testLargeAlignmentDso(b, .{ .target = gnu_target })); | |
| 114 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = gnu_target })); | |
| 115 | elf_step.dependOn(testLargeBss(b, .{ .target = gnu_target })); | |
| 116 | elf_step.dependOn(testLinkOrder(b, .{ .target = gnu_target })); | |
| 117 | elf_step.dependOn(testLdScript(b, .{ .target = gnu_target })); | |
| 118 | elf_step.dependOn(testLdScriptPathError(b, .{ .target = gnu_target })); | |
| 119 | elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true })); | |
| 120 | elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = gnu_target, .use_lld = true })); | |
| 121 | // https://github.com/ziglang/zig/issues/17451 | |
| 122 | // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = gnu_target })); | |
| 123 | elf_step.dependOn(testPie(b, .{ .target = gnu_target })); | |
| 124 | elf_step.dependOn(testPltGot(b, .{ .target = gnu_target })); | |
| 125 | elf_step.dependOn(testPreinitArray(b, .{ .target = gnu_target })); | |
| 126 | elf_step.dependOn(testSharedAbsSymbol(b, .{ .target = gnu_target })); | |
| 127 | elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = gnu_target })); | |
| 128 | elf_step.dependOn(testTlsDso(b, .{ .target = gnu_target })); | |
| 129 | elf_step.dependOn(testTlsGd(b, .{ .target = gnu_target })); | |
| 130 | elf_step.dependOn(testTlsGdNoPlt(b, .{ .target = gnu_target })); | |
| 131 | elf_step.dependOn(testTlsGdToIe(b, .{ .target = gnu_target })); | |
| 132 | elf_step.dependOn(testTlsIe(b, .{ .target = gnu_target })); | |
| 133 | elf_step.dependOn(testTlsLargeAlignment(b, .{ .target = gnu_target })); | |
| 134 | elf_step.dependOn(testTlsLargeTbss(b, .{ .target = gnu_target })); | |
| 135 | elf_step.dependOn(testTlsLargeStaticImage(b, .{ .target = gnu_target })); | |
| 136 | elf_step.dependOn(testTlsLd(b, .{ .target = gnu_target })); | |
| 137 | elf_step.dependOn(testTlsLdDso(b, .{ .target = gnu_target })); | |
| 138 | elf_step.dependOn(testTlsLdNoPlt(b, .{ .target = gnu_target })); | |
| 139 | // https://github.com/ziglang/zig/issues/17430 | |
| 140 | // elf_step.dependOn(testTlsNoPic(b, .{ .target = gnu_target })); | |
| 141 | elf_step.dependOn(testTlsOffsetAlignment(b, .{ .target = gnu_target })); | |
| 142 | elf_step.dependOn(testTlsPic(b, .{ .target = gnu_target })); | |
| 143 | elf_step.dependOn(testTlsSmallAlignment(b, .{ .target = gnu_target })); | |
| 144 | elf_step.dependOn(testUnknownFileTypeError(b, .{ .target = gnu_target })); | |
| 145 | elf_step.dependOn(testUnresolvedError(b, .{ .target = gnu_target })); | |
| 146 | elf_step.dependOn(testWeakExports(b, .{ .target = gnu_target })); | |
| 147 | elf_step.dependOn(testWeakUndefsDso(b, .{ .target = gnu_target })); | |
| 148 | elf_step.dependOn(testZNow(b, .{ .target = gnu_target })); | |
| 149 | elf_step.dependOn(testZStackSize(b, .{ .target = gnu_target })); | |
| 150 | } | |
| 45 | 151 | |
| 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 | 159 | elf_step.dependOn(testGcSectionsZig(b, .{ .use_llvm = false, .target = default_target })); |
| 48 | 160 | elf_step.dependOn(testLinkingObj(b, .{ .use_llvm = false, .target = default_target })); |
| 49 | 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 | 163 | elf_step.dependOn(testImportingDataDynamic(b, .{ .use_llvm = false, .target = x86_64_gnu })); |
| 52 | 164 | elf_step.dependOn(testImportingDataStatic(b, .{ .use_llvm = false, .target = x86_64_musl })); |
| 53 | 165 | |
| 54 | // Exercise linker with LLVM backend | |
| 55 | // musl tests | |
| 56 | elf_step.dependOn(testAbsSymbols(b, .{ .target = x86_64_musl })); | |
| 57 | elf_step.dependOn(testCommonSymbols(b, .{ .target = x86_64_musl })); | |
| 58 | elf_step.dependOn(testCommonSymbolsInArchive(b, .{ .target = x86_64_musl })); | |
| 59 | elf_step.dependOn(testEmptyObject(b, .{ .target = x86_64_musl })); | |
| 60 | elf_step.dependOn(testEntryPoint(b, .{ .target = x86_64_musl })); | |
| 61 | elf_step.dependOn(testGcSections(b, .{ .target = x86_64_musl })); | |
| 62 | elf_step.dependOn(testImageBase(b, .{ .target = x86_64_musl })); | |
| 63 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = x86_64_musl })); | |
| 64 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = x86_64_musl })); | |
| 65 | // https://github.com/ziglang/zig/issues/17449 | |
| 66 | // elf_step.dependOn(testLargeBss(b, .{ .target = x86_64_musl })); | |
| 67 | elf_step.dependOn(testLinkingC(b, .{ .target = x86_64_musl })); | |
| 68 | elf_step.dependOn(testLinkingCpp(b, .{ .target = x86_64_musl })); | |
| 69 | elf_step.dependOn(testLinkingZig(b, .{ .target = x86_64_musl })); | |
| 70 | // https://github.com/ziglang/zig/issues/17451 | |
| 71 | // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = x86_64_musl })); | |
| 72 | elf_step.dependOn(testTlsStatic(b, .{ .target = x86_64_musl })); | |
| 73 | elf_step.dependOn(testStrip(b, .{ .target = x86_64_musl })); | |
| 74 | ||
| 75 | // glibc tests | |
| 76 | elf_step.dependOn(testAsNeeded(b, .{ .target = x86_64_gnu })); | |
| 77 | // https://github.com/ziglang/zig/issues/17430 | |
| 78 | // elf_step.dependOn(testCanonicalPlt(b, .{ .target = x86_64_gnu })); | |
| 79 | elf_step.dependOn(testCopyrel(b, .{ .target = x86_64_gnu })); | |
| 80 | // https://github.com/ziglang/zig/issues/17430 | |
| 81 | // elf_step.dependOn(testCopyrelAlias(b, .{ .target = x86_64_gnu })); | |
| 82 | // https://github.com/ziglang/zig/issues/17430 | |
| 83 | // elf_step.dependOn(testCopyrelAlignment(b, .{ .target = x86_64_gnu })); | |
| 84 | elf_step.dependOn(testDsoPlt(b, .{ .target = x86_64_gnu })); | |
| 85 | elf_step.dependOn(testDsoUndef(b, .{ .target = x86_64_gnu })); | |
| 86 | elf_step.dependOn(testExportDynamic(b, .{ .target = x86_64_gnu })); | |
| 87 | elf_step.dependOn(testExportSymbolsFromExe(b, .{ .target = x86_64_gnu })); | |
| 88 | // https://github.com/ziglang/zig/issues/17430 | |
| 89 | // elf_step.dependOn(testFuncAddress(b, .{ .target = x86_64_gnu })); | |
| 90 | elf_step.dependOn(testHiddenWeakUndef(b, .{ .target = x86_64_gnu })); | |
| 91 | elf_step.dependOn(testIFuncAlias(b, .{ .target = x86_64_gnu })); | |
| 92 | // https://github.com/ziglang/zig/issues/17430 | |
| 93 | // elf_step.dependOn(testIFuncDlopen(b, .{ .target = x86_64_gnu })); | |
| 94 | elf_step.dependOn(testIFuncDso(b, .{ .target = x86_64_gnu })); | |
| 95 | elf_step.dependOn(testIFuncDynamic(b, .{ .target = x86_64_gnu })); | |
| 96 | elf_step.dependOn(testIFuncExport(b, .{ .target = x86_64_gnu })); | |
| 97 | elf_step.dependOn(testIFuncFuncPtr(b, .{ .target = x86_64_gnu })); | |
| 98 | elf_step.dependOn(testIFuncNoPlt(b, .{ .target = x86_64_gnu })); | |
| 99 | // https://github.com/ziglang/zig/issues/17430 ?? | |
| 100 | // elf_step.dependOn(testIFuncStatic(b, .{ .target = x86_64_gnu })); | |
| 101 | // elf_step.dependOn(testIFuncStaticPie(b, .{ .target = x86_64_gnu })); | |
| 102 | elf_step.dependOn(testInitArrayOrder(b, .{ .target = x86_64_gnu })); | |
| 103 | elf_step.dependOn(testLargeAlignmentDso(b, .{ .target = x86_64_gnu })); | |
| 104 | elf_step.dependOn(testLargeAlignmentExe(b, .{ .target = x86_64_gnu })); | |
| 105 | elf_step.dependOn(testLargeBss(b, .{ .target = x86_64_gnu })); | |
| 106 | elf_step.dependOn(testLinkOrder(b, .{ .target = x86_64_gnu })); | |
| 107 | elf_step.dependOn(testLdScript(b, .{ .target = x86_64_gnu })); | |
| 108 | elf_step.dependOn(testLdScriptPathError(b, .{ .target = x86_64_gnu })); | |
| 109 | elf_step.dependOn(testLdScriptAllowUndefinedVersion(b, .{ .target = x86_64_gnu, .use_lld = true })); | |
| 110 | elf_step.dependOn(testLdScriptDisallowUndefinedVersion(b, .{ .target = x86_64_gnu, .use_lld = true })); | |
| 111 | elf_step.dependOn(testMismatchedCpuArchitectureError(b, .{ .target = x86_64_gnu })); | |
| 112 | // https://github.com/ziglang/zig/issues/17451 | |
| 113 | // elf_step.dependOn(testNoEhFrameHdr(b, .{ .target = x86_64_gnu })); | |
| 114 | elf_step.dependOn(testPie(b, .{ .target = x86_64_gnu })); | |
| 115 | elf_step.dependOn(testPltGot(b, .{ .target = x86_64_gnu })); | |
| 116 | elf_step.dependOn(testPreinitArray(b, .{ .target = x86_64_gnu })); | |
| 117 | elf_step.dependOn(testSharedAbsSymbol(b, .{ .target = x86_64_gnu })); | |
| 118 | elf_step.dependOn(testTlsDfStaticTls(b, .{ .target = x86_64_gnu })); | |
| 119 | elf_step.dependOn(testTlsDso(b, .{ .target = x86_64_gnu })); | |
| 120 | elf_step.dependOn(testTlsGd(b, .{ .target = x86_64_gnu })); | |
| 121 | elf_step.dependOn(testTlsGdNoPlt(b, .{ .target = x86_64_gnu })); | |
| 122 | elf_step.dependOn(testTlsGdToIe(b, .{ .target = x86_64_gnu })); | |
| 123 | elf_step.dependOn(testTlsIe(b, .{ .target = x86_64_gnu })); | |
| 124 | elf_step.dependOn(testTlsLargeAlignment(b, .{ .target = x86_64_gnu })); | |
| 125 | elf_step.dependOn(testTlsLargeTbss(b, .{ .target = x86_64_gnu })); | |
| 126 | elf_step.dependOn(testTlsLargeStaticImage(b, .{ .target = x86_64_gnu })); | |
| 127 | elf_step.dependOn(testTlsLd(b, .{ .target = x86_64_gnu })); | |
| 128 | elf_step.dependOn(testTlsLdDso(b, .{ .target = x86_64_gnu })); | |
| 129 | elf_step.dependOn(testTlsLdNoPlt(b, .{ .target = x86_64_gnu })); | |
| 130 | // https://github.com/ziglang/zig/issues/17430 | |
| 131 | // elf_step.dependOn(testTlsNoPic(b, .{ .target = x86_64_gnu })); | |
| 132 | elf_step.dependOn(testTlsOffsetAlignment(b, .{ .target = x86_64_gnu })); | |
| 133 | elf_step.dependOn(testTlsPic(b, .{ .target = x86_64_gnu })); | |
| 134 | elf_step.dependOn(testTlsSmallAlignment(b, .{ .target = x86_64_gnu })); | |
| 135 | elf_step.dependOn(testUnknownFileTypeError(b, .{ .target = x86_64_gnu })); | |
| 136 | elf_step.dependOn(testUnresolvedError(b, .{ .target = x86_64_gnu })); | |
| 137 | elf_step.dependOn(testWeakExports(b, .{ .target = x86_64_gnu })); | |
| 138 | elf_step.dependOn(testWeakUndefsDso(b, .{ .target = x86_64_gnu })); | |
| 139 | elf_step.dependOn(testZNow(b, .{ .target = x86_64_gnu })); | |
| 140 | elf_step.dependOn(testZStackSize(b, .{ .target = x86_64_gnu })); | |
| 141 | elf_step.dependOn(testZText(b, .{ .target = x86_64_gnu })); | |
| 142 | ||
| 143 | // aarch64 tests | |
| 144 | elf_step.dependOn(testLinkingC(b, .{ .target = aarch64_musl })); | |
| 145 | ||
| 146 | // riscv64 tests | |
| 166 | // riscv64 linker backend is currently not complete enough to support more | |
| 147 | 167 | elf_step.dependOn(testLinkingC(b, .{ .target = riscv64_musl })); |
| 148 | 168 | |
| 149 | 169 | return elf_step; |
| ... | ... | @@ -239,8 +259,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { |
| 239 | 259 | exe.addLibraryPath(libbaz.getEmittedBinDirectory()); |
| 240 | 260 | exe.addRPath(libbaz.getEmittedBinDirectory()); |
| 241 | 261 | exe.linkLibC(); |
| 242 | // https://github.com/ziglang/zig/issues/17619 | |
| 243 | exe.pie = true; | |
| 244 | 262 | |
| 245 | 263 | const run = addRunArtifact(exe); |
| 246 | 264 | run.expectStdOutEqual("42\n"); |
| ... | ... | @@ -269,8 +287,6 @@ fn testAsNeeded(b: *Build, opts: Options) *Step { |
| 269 | 287 | exe.addLibraryPath(libbaz.getEmittedBinDirectory()); |
| 270 | 288 | exe.addRPath(libbaz.getEmittedBinDirectory()); |
| 271 | 289 | exe.linkLibC(); |
| 272 | // https://github.com/ziglang/zig/issues/17619 | |
| 273 | exe.pie = true; | |
| 274 | 290 | |
| 275 | 291 | const run = addRunArtifact(exe); |
| 276 | 292 | run.expectStdOutEqual("42\n"); |
| ... | ... | @@ -489,8 +505,6 @@ fn testCopyrel(b: *Build, opts: Options) *Step { |
| 489 | 505 | }); |
| 490 | 506 | exe.linkLibrary(dso); |
| 491 | 507 | exe.linkLibC(); |
| 492 | // https://github.com/ziglang/zig/issues/17619 | |
| 493 | exe.pie = true; | |
| 494 | 508 | |
| 495 | 509 | const run = addRunArtifact(exe); |
| 496 | 510 | run.expectStdOutEqual("3 5\n"); |
| ... | ... | @@ -656,8 +670,6 @@ fn testDsoPlt(b: *Build, opts: Options) *Step { |
| 656 | 670 | , &.{}); |
| 657 | 671 | exe.linkLibrary(dso); |
| 658 | 672 | exe.linkLibC(); |
| 659 | // https://github.com/ziglang/zig/issues/17619 | |
| 660 | exe.pie = true; | |
| 661 | 673 | |
| 662 | 674 | const run = addRunArtifact(exe); |
| 663 | 675 | run.expectStdOutEqual("Hello WORLD\n"); |
| ... | ... | @@ -695,8 +707,6 @@ fn testDsoUndef(b: *Build, opts: Options) *Step { |
| 695 | 707 | \\} |
| 696 | 708 | , &.{}); |
| 697 | 709 | exe.linkLibC(); |
| 698 | // https://github.com/ziglang/zig/issues/17619 | |
| 699 | exe.pie = true; | |
| 700 | 710 | |
| 701 | 711 | const run = addRunArtifact(exe); |
| 702 | 712 | run.expectExitCode(0); |
| ... | ... | @@ -1280,8 +1290,6 @@ fn testIFuncAlias(b: *Build, opts: Options) *Step { |
| 1280 | 1290 | , &.{}); |
| 1281 | 1291 | exe.root_module.pic = true; |
| 1282 | 1292 | exe.linkLibC(); |
| 1283 | // https://github.com/ziglang/zig/issues/17619 | |
| 1284 | exe.pie = true; | |
| 1285 | 1293 | |
| 1286 | 1294 | const run = addRunArtifact(exe); |
| 1287 | 1295 | run.expectExitCode(0); |
| ... | ... | @@ -1396,8 +1404,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step { |
| 1396 | 1404 | addCSourceBytes(exe, main_c, &.{}); |
| 1397 | 1405 | exe.linkLibC(); |
| 1398 | 1406 | exe.link_z_lazy = true; |
| 1399 | // https://github.com/ziglang/zig/issues/17619 | |
| 1400 | exe.pie = true; | |
| 1401 | 1407 | |
| 1402 | 1408 | const run = addRunArtifact(exe); |
| 1403 | 1409 | run.expectStdOutEqual("Hello world\n"); |
| ... | ... | @@ -1407,8 +1413,6 @@ fn testIFuncDynamic(b: *Build, opts: Options) *Step { |
| 1407 | 1413 | const exe = addExecutable(b, opts, .{ .name = "other" }); |
| 1408 | 1414 | addCSourceBytes(exe, main_c, &.{}); |
| 1409 | 1415 | exe.linkLibC(); |
| 1410 | // https://github.com/ziglang/zig/issues/17619 | |
| 1411 | exe.pie = true; | |
| 1412 | 1416 | |
| 1413 | 1417 | const run = addRunArtifact(exe); |
| 1414 | 1418 | run.expectStdOutEqual("Hello world\n"); |
| ... | ... | @@ -1472,8 +1476,6 @@ fn testIFuncFuncPtr(b: *Build, opts: Options) *Step { |
| 1472 | 1476 | , &.{}); |
| 1473 | 1477 | exe.root_module.pic = true; |
| 1474 | 1478 | exe.linkLibC(); |
| 1475 | // https://github.com/ziglang/zig/issues/17619 | |
| 1476 | exe.pie = true; | |
| 1477 | 1479 | |
| 1478 | 1480 | const run = addRunArtifact(exe); |
| 1479 | 1481 | run.expectStdOutEqual("3\n"); |
| ... | ... | @@ -1503,8 +1505,6 @@ fn testIFuncNoPlt(b: *Build, opts: Options) *Step { |
| 1503 | 1505 | , &.{"-fno-plt"}); |
| 1504 | 1506 | exe.root_module.pic = true; |
| 1505 | 1507 | exe.linkLibC(); |
| 1506 | // https://github.com/ziglang/zig/issues/17619 | |
| 1507 | exe.pie = true; | |
| 1508 | 1508 | |
| 1509 | 1509 | const run = addRunArtifact(exe); |
| 1510 | 1510 | run.expectStdOutEqual("Hello world\n"); |
| ... | ... | @@ -1834,8 +1834,6 @@ fn testLargeAlignmentDso(b: *Build, opts: Options) *Step { |
| 1834 | 1834 | , &.{}); |
| 1835 | 1835 | exe.linkLibrary(dso); |
| 1836 | 1836 | exe.linkLibC(); |
| 1837 | // https://github.com/ziglang/zig/issues/17619 | |
| 1838 | exe.pie = true; | |
| 1839 | 1837 | |
| 1840 | 1838 | const run = addRunArtifact(exe); |
| 1841 | 1839 | run.expectStdOutEqual("Hello world"); |
| ... | ... | @@ -1870,8 +1868,6 @@ fn testLargeAlignmentExe(b: *Build, opts: Options) *Step { |
| 1870 | 1868 | , &.{}); |
| 1871 | 1869 | exe.link_function_sections = true; |
| 1872 | 1870 | exe.linkLibC(); |
| 1873 | // https://github.com/ziglang/zig/issues/17619 | |
| 1874 | exe.pie = true; | |
| 1875 | 1871 | |
| 1876 | 1872 | const check = exe.checkObject(); |
| 1877 | 1873 | check.checkInSymtab(); |
| ... | ... | @@ -1900,8 +1896,6 @@ fn testLargeBss(b: *Build, opts: Options) *Step { |
| 1900 | 1896 | \\} |
| 1901 | 1897 | , &.{}); |
| 1902 | 1898 | exe.linkLibC(); |
| 1903 | // https://github.com/ziglang/zig/issues/17619 | |
| 1904 | exe.pie = true; | |
| 1905 | 1899 | |
| 1906 | 1900 | const run = addRunArtifact(exe); |
| 1907 | 1901 | run.expectExitCode(0); |
| ... | ... | @@ -1995,8 +1989,6 @@ fn testLdScript(b: *Build, opts: Options) *Step { |
| 1995 | 1989 | exe.addLibraryPath(dso.getEmittedBinDirectory()); |
| 1996 | 1990 | exe.addRPath(dso.getEmittedBinDirectory()); |
| 1997 | 1991 | exe.linkLibC(); |
| 1998 | // https://github.com/ziglang/zig/issues/17619 | |
| 1999 | exe.pie = true; | |
| 2000 | 1992 | |
| 2001 | 1993 | const run = addRunArtifact(exe); |
| 2002 | 1994 | run.expectExitCode(0); |
| ... | ... | @@ -2348,8 +2340,6 @@ fn testPltGot(b: *Build, opts: Options) *Step { |
| 2348 | 2340 | exe.linkLibrary(dso); |
| 2349 | 2341 | exe.root_module.pic = true; |
| 2350 | 2342 | exe.linkLibC(); |
| 2351 | // https://github.com/ziglang/zig/issues/17619 | |
| 2352 | exe.pie = true; | |
| 2353 | 2343 | |
| 2354 | 2344 | const run = addRunArtifact(exe); |
| 2355 | 2345 | run.expectStdOutEqual("Hello world\n"); |
| ... | ... | @@ -2752,8 +2742,6 @@ fn testTlsDso(b: *Build, opts: Options) *Step { |
| 2752 | 2742 | , &.{}); |
| 2753 | 2743 | exe.linkLibrary(dso); |
| 2754 | 2744 | exe.linkLibC(); |
| 2755 | // https://github.com/ziglang/zig/issues/17619 | |
| 2756 | exe.pie = true; | |
| 2757 | 2745 | |
| 2758 | 2746 | const run = addRunArtifact(exe); |
| 2759 | 2747 | run.expectStdOutEqual("5 3 5 3 5 3\n"); |
| ... | ... | @@ -2912,8 +2900,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { |
| 2912 | 2900 | exe.linkLibrary(a_so); |
| 2913 | 2901 | exe.linkLibrary(b_so); |
| 2914 | 2902 | exe.linkLibC(); |
| 2915 | // https://github.com/ziglang/zig/issues/17619 | |
| 2916 | exe.pie = true; | |
| 2917 | 2903 | |
| 2918 | 2904 | const run = addRunArtifact(exe); |
| 2919 | 2905 | run.expectStdOutEqual("1 2 3 4 5 6\n"); |
| ... | ... | @@ -2927,8 +2913,6 @@ fn testTlsGdNoPlt(b: *Build, opts: Options) *Step { |
| 2927 | 2913 | exe.linkLibrary(b_so); |
| 2928 | 2914 | exe.linkLibC(); |
| 2929 | 2915 | // exe.link_relax = false; // TODO |
| 2930 | // https://github.com/ziglang/zig/issues/17619 | |
| 2931 | exe.pie = true; | |
| 2932 | 2916 | |
| 2933 | 2917 | const run = addRunArtifact(exe); |
| 2934 | 2918 | run.expectStdOutEqual("1 2 3 4 5 6\n"); |
| ... | ... | @@ -2976,8 +2960,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { |
| 2976 | 2960 | exe.addObject(b_o); |
| 2977 | 2961 | exe.linkLibrary(dso); |
| 2978 | 2962 | exe.linkLibC(); |
| 2979 | // https://github.com/ziglang/zig/issues/17619 | |
| 2980 | exe.pie = true; | |
| 2981 | 2963 | |
| 2982 | 2964 | const run = addRunArtifact(exe); |
| 2983 | 2965 | run.expectStdOutEqual("1 2 3\n"); |
| ... | ... | @@ -2993,8 +2975,6 @@ fn testTlsGdToIe(b: *Build, opts: Options) *Step { |
| 2993 | 2975 | exe.addObject(b_o); |
| 2994 | 2976 | exe.linkLibrary(dso); |
| 2995 | 2977 | exe.linkLibC(); |
| 2996 | // https://github.com/ziglang/zig/issues/17619 | |
| 2997 | exe.pie = true; | |
| 2998 | 2978 | |
| 2999 | 2979 | const run = addRunArtifact(exe); |
| 3000 | 2980 | run.expectStdOutEqual("1 2 3\n"); |
| ... | ... | @@ -3076,8 +3056,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step { |
| 3076 | 3056 | exe.addObject(main_o); |
| 3077 | 3057 | exe.linkLibrary(dso); |
| 3078 | 3058 | exe.linkLibC(); |
| 3079 | // https://github.com/ziglang/zig/issues/17619 | |
| 3080 | exe.pie = true; | |
| 3081 | 3059 | |
| 3082 | 3060 | const run = addRunArtifact(exe); |
| 3083 | 3061 | run.expectStdOutEqual(exp_stdout); |
| ... | ... | @@ -3090,8 +3068,6 @@ fn testTlsIe(b: *Build, opts: Options) *Step { |
| 3090 | 3068 | exe.linkLibrary(dso); |
| 3091 | 3069 | exe.linkLibC(); |
| 3092 | 3070 | // exe.link_relax = false; // TODO |
| 3093 | // https://github.com/ziglang/zig/issues/17619 | |
| 3094 | exe.pie = true; | |
| 3095 | 3071 | |
| 3096 | 3072 | const run = addRunArtifact(exe); |
| 3097 | 3073 | run.expectStdOutEqual(exp_stdout); |
| ... | ... | @@ -3147,8 +3123,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step { |
| 3147 | 3123 | exe.addObject(c_o); |
| 3148 | 3124 | exe.linkLibrary(dso); |
| 3149 | 3125 | exe.linkLibC(); |
| 3150 | // https://github.com/ziglang/zig/issues/17619 | |
| 3151 | exe.pie = true; | |
| 3152 | 3126 | |
| 3153 | 3127 | const run = addRunArtifact(exe); |
| 3154 | 3128 | run.expectStdOutEqual("42 1 2 3\n"); |
| ... | ... | @@ -3161,8 +3135,6 @@ fn testTlsLargeAlignment(b: *Build, opts: Options) *Step { |
| 3161 | 3135 | exe.addObject(b_o); |
| 3162 | 3136 | exe.addObject(c_o); |
| 3163 | 3137 | exe.linkLibC(); |
| 3164 | // https://github.com/ziglang/zig/issues/17619 | |
| 3165 | exe.pie = true; | |
| 3166 | 3138 | |
| 3167 | 3139 | const run = addRunArtifact(exe); |
| 3168 | 3140 | run.expectStdOutEqual("42 1 2 3\n"); |
| ... | ... | @@ -3196,8 +3168,6 @@ fn testTlsLargeTbss(b: *Build, opts: Options) *Step { |
| 3196 | 3168 | \\} |
| 3197 | 3169 | , &.{}); |
| 3198 | 3170 | exe.linkLibC(); |
| 3199 | // https://github.com/ziglang/zig/issues/17619 | |
| 3200 | exe.pie = true; | |
| 3201 | 3171 | |
| 3202 | 3172 | const run = addRunArtifact(exe); |
| 3203 | 3173 | run.expectStdOutEqual("3 0 5 0 0 0\n"); |
| ... | ... | @@ -3220,8 +3190,6 @@ fn testTlsLargeStaticImage(b: *Build, opts: Options) *Step { |
| 3220 | 3190 | , &.{}); |
| 3221 | 3191 | exe.root_module.pic = true; |
| 3222 | 3192 | exe.linkLibC(); |
| 3223 | // https://github.com/ziglang/zig/issues/17619 | |
| 3224 | exe.pie = true; | |
| 3225 | 3193 | |
| 3226 | 3194 | const run = addRunArtifact(exe); |
| 3227 | 3195 | run.expectStdOutEqual("1 2 3 0 5\n"); |
| ... | ... | @@ -3266,8 +3234,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step { |
| 3266 | 3234 | exe.addObject(main_o); |
| 3267 | 3235 | exe.addObject(a_o); |
| 3268 | 3236 | exe.linkLibC(); |
| 3269 | // https://github.com/ziglang/zig/issues/17619 | |
| 3270 | exe.pie = true; | |
| 3271 | 3237 | |
| 3272 | 3238 | const run = addRunArtifact(exe); |
| 3273 | 3239 | run.expectStdOutEqual(exp_stdout); |
| ... | ... | @@ -3280,8 +3246,6 @@ fn testTlsLd(b: *Build, opts: Options) *Step { |
| 3280 | 3246 | exe.addObject(a_o); |
| 3281 | 3247 | exe.linkLibC(); |
| 3282 | 3248 | // exe.link_relax = false; // TODO |
| 3283 | // https://github.com/ziglang/zig/issues/17619 | |
| 3284 | exe.pie = true; | |
| 3285 | 3249 | |
| 3286 | 3250 | const run = addRunArtifact(exe); |
| 3287 | 3251 | run.expectStdOutEqual(exp_stdout); |
| ... | ... | @@ -3315,8 +3279,6 @@ fn testTlsLdDso(b: *Build, opts: Options) *Step { |
| 3315 | 3279 | , &.{}); |
| 3316 | 3280 | exe.linkLibrary(dso); |
| 3317 | 3281 | exe.linkLibC(); |
| 3318 | // https://github.com/ziglang/zig/issues/17619 | |
| 3319 | exe.pie = true; | |
| 3320 | 3282 | |
| 3321 | 3283 | const run = addRunArtifact(exe); |
| 3322 | 3284 | run.expectStdOutEqual("1 2\n"); |
| ... | ... | @@ -3360,8 +3322,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { |
| 3360 | 3322 | exe.addObject(a_o); |
| 3361 | 3323 | exe.addObject(b_o); |
| 3362 | 3324 | exe.linkLibC(); |
| 3363 | // https://github.com/ziglang/zig/issues/17619 | |
| 3364 | exe.pie = true; | |
| 3365 | 3325 | |
| 3366 | 3326 | const run = addRunArtifact(exe); |
| 3367 | 3327 | run.expectStdOutEqual("3 5 3 5\n"); |
| ... | ... | @@ -3374,8 +3334,6 @@ fn testTlsLdNoPlt(b: *Build, opts: Options) *Step { |
| 3374 | 3334 | exe.addObject(b_o); |
| 3375 | 3335 | exe.linkLibC(); |
| 3376 | 3336 | // exe.link_relax = false; // TODO |
| 3377 | // https://github.com/ziglang/zig/issues/17619 | |
| 3378 | exe.pie = true; | |
| 3379 | 3337 | |
| 3380 | 3338 | const run = addRunArtifact(exe); |
| 3381 | 3339 | run.expectStdOutEqual("3 5 3 5\n"); |
| ... | ... | @@ -3461,8 +3419,6 @@ fn testTlsOffsetAlignment(b: *Build, opts: Options) *Step { |
| 3461 | 3419 | exe.addRPath(dso.getEmittedBinDirectory()); |
| 3462 | 3420 | exe.linkLibC(); |
| 3463 | 3421 | exe.root_module.pic = true; |
| 3464 | // https://github.com/ziglang/zig/issues/17619 | |
| 3465 | exe.pie = true; | |
| 3466 | 3422 | |
| 3467 | 3423 | const run = addRunArtifact(exe); |
| 3468 | 3424 | run.expectExitCode(0); |
| ... | ... | @@ -3499,8 +3455,6 @@ fn testTlsPic(b: *Build, opts: Options) *Step { |
| 3499 | 3455 | , &.{}); |
| 3500 | 3456 | exe.addObject(obj); |
| 3501 | 3457 | exe.linkLibC(); |
| 3502 | // https://github.com/ziglang/zig/issues/17619 | |
| 3503 | exe.pie = true; | |
| 3504 | 3458 | |
| 3505 | 3459 | const run = addRunArtifact(exe); |
| 3506 | 3460 | run.expectStdOutEqual("3 5 3 5\n"); |
| ... | ... | @@ -3548,8 +3502,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step { |
| 3548 | 3502 | exe.addObject(b_o); |
| 3549 | 3503 | exe.addObject(c_o); |
| 3550 | 3504 | exe.linkLibC(); |
| 3551 | // https://github.com/ziglang/zig/issues/17619 | |
| 3552 | exe.pie = true; | |
| 3553 | 3505 | |
| 3554 | 3506 | const run = addRunArtifact(exe); |
| 3555 | 3507 | run.expectStdOutEqual("42\n"); |
| ... | ... | @@ -3565,8 +3517,6 @@ fn testTlsSmallAlignment(b: *Build, opts: Options) *Step { |
| 3565 | 3517 | exe.addObject(c_o); |
| 3566 | 3518 | exe.linkLibrary(dso); |
| 3567 | 3519 | exe.linkLibC(); |
| 3568 | // https://github.com/ziglang/zig/issues/17619 | |
| 3569 | exe.pie = true; | |
| 3570 | 3520 | |
| 3571 | 3521 | const run = addRunArtifact(exe); |
| 3572 | 3522 | run.expectStdOutEqual("42\n"); |
| ... | ... | @@ -3717,8 +3667,6 @@ fn testWeakExports(b: *Build, opts: Options) *Step { |
| 3717 | 3667 | const exe = addExecutable(b, opts, .{ .name = "main" }); |
| 3718 | 3668 | exe.addObject(obj); |
| 3719 | 3669 | exe.linkLibC(); |
| 3720 | // https://github.com/ziglang/zig/issues/17619 | |
| 3721 | exe.pie = true; | |
| 3722 | 3670 | |
| 3723 | 3671 | const check = exe.checkObject(); |
| 3724 | 3672 | check.checkInDynamicSymtab(); |
| ... | ... | @@ -3751,8 +3699,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step { |
| 3751 | 3699 | , &.{}); |
| 3752 | 3700 | exe.linkLibrary(dso); |
| 3753 | 3701 | exe.linkLibC(); |
| 3754 | // https://github.com/ziglang/zig/issues/17619 | |
| 3755 | exe.pie = true; | |
| 3756 | 3702 | |
| 3757 | 3703 | const run = addRunArtifact(exe); |
| 3758 | 3704 | run.expectStdOutEqual("bar=-1\n"); |
| ... | ... | @@ -3769,8 +3715,6 @@ fn testWeakUndefsDso(b: *Build, opts: Options) *Step { |
| 3769 | 3715 | , &.{}); |
| 3770 | 3716 | exe.linkLibrary(dso); |
| 3771 | 3717 | exe.linkLibC(); |
| 3772 | // https://github.com/ziglang/zig/issues/17619 | |
| 3773 | exe.pie = true; | |
| 3774 | 3718 | |
| 3775 | 3719 | const run = addRunArtifact(exe); |
| 3776 | 3720 | run.expectStdOutEqual("bar=5\n"); |
| ... | ... | @@ -3885,8 +3829,6 @@ fn testZText(b: *Build, opts: Options) *Step { |
| 3885 | 3829 | , &.{}); |
| 3886 | 3830 | exe.linkLibrary(dso); |
| 3887 | 3831 | exe.linkLibC(); |
| 3888 | // https://github.com/ziglang/zig/issues/17619 | |
| 3889 | exe.pie = true; | |
| 3890 | 3832 | |
| 3891 | 3833 | const run = addRunArtifact(exe); |
| 3892 | 3834 | run.expectStdOutEqual("3\n"); |