| ... | ... | @@ -28,8 +28,10 @@ shdrs: std.ArrayList(Section), |
| 28 | 28 | phdrs: std.ArrayList(MappedFile.Node.Index), |
| 29 | 29 | shndx: struct { |
| 30 | 30 | got: Section.Index, |
| 31 | /// Always `.UNDEF` on some targets (e.g. SPARC). |
| 31 | 32 | got_plt: Section.Index, |
| 32 | 33 | plt: Section.Index, |
| 34 | /// Only created for x86 targets; `.UNDEF` everywhere else. |
| 33 | 35 | plt_sec: Section.Index, |
| 34 | 36 | dynsym: Section.Index, |
| 35 | 37 | dynstr: Section.Index, |
| ... | ... | @@ -897,11 +899,12 @@ const GotReloc = struct { |
| 897 | 899 | }; |
| 898 | 900 | |
| 899 | 901 | pub const MachineRelocType = union { |
| 900 | | X86_64: std.elf.R_X86_64, |
| 901 | 902 | AARCH64: std.elf.R_AARCH64, |
| 902 | 903 | LOONGARCH: std.elf.R_LARCH, |
| 903 | | RISCV: std.elf.R_RISCV, |
| 904 | 904 | PPC64: std.elf.R_PPC64, |
| 905 | RISCV: std.elf.R_RISCV, |
| 906 | SPARC: std.elf.R_SPARC, |
| 907 | X86_64: std.elf.R_X86_64, |
| 905 | 908 | |
| 906 | 909 | pub fn none(elf: *Elf) MachineRelocType { |
| 907 | 910 | return switch (elf.ehdrField(.machine)) { |
| ... | ... | @@ -910,6 +913,7 @@ pub const MachineRelocType = union { |
| 910 | 913 | .LOONGARCH => .{ .LOONGARCH = .NONE }, |
| 911 | 914 | .PPC64 => .{ .PPC64 = .NONE }, |
| 912 | 915 | .RISCV => .{ .RISCV = .NONE }, |
| 916 | .SPARCV9 => .{ .SPARC = .NONE }, |
| 913 | 917 | .X86_64 => .{ .X86_64 = .NONE }, |
| 914 | 918 | }; |
| 915 | 919 | } |
| ... | ... | @@ -920,6 +924,7 @@ pub const MachineRelocType = union { |
| 920 | 924 | .LOONGARCH => .{ .LOONGARCH = .COPY }, |
| 921 | 925 | .PPC64 => .{ .PPC64 = .COPY }, |
| 922 | 926 | .RISCV => .{ .RISCV = .COPY }, |
| 927 | .SPARCV9 => .{ .SPARC = .COPY }, |
| 923 | 928 | .X86_64 => .{ .X86_64 = .COPY }, |
| 924 | 929 | }; |
| 925 | 930 | } |
| ... | ... | @@ -930,43 +935,57 @@ pub const MachineRelocType = union { |
| 930 | 935 | .LOONGARCH => .{ .LOONGARCH = .RELATIVE }, |
| 931 | 936 | .PPC64 => .{ .PPC64 = .RELATIVE }, |
| 932 | 937 | .RISCV => .{ .RISCV = .RELATIVE }, |
| 938 | .SPARCV9 => .{ .SPARC = .RELATIVE }, |
| 933 | 939 | .X86_64 => .{ .X86_64 = .RELATIVE }, |
| 934 | 940 | }; |
| 935 | 941 | } |
| 936 | 942 | pub fn jumpSlot(elf: *Elf) MachineRelocType { |
| 937 | 943 | return switch (elf.ehdrField(.machine)) { |
| 938 | 944 | else => unreachable, |
| 939 | | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, |
| 945 | .AARCH64 => .{ .AARCH64 = .JUMP_SLOT }, |
| 940 | 946 | .LOONGARCH => .{ .LOONGARCH = .JUMP_SLOT }, |
| 947 | .PPC64 => .{ .PPC64 = .JMP_SLOT }, |
| 948 | .RISCV => .{ .RISCV = .JUMP_SLOT }, |
| 949 | .SPARCV9 => .{ .SPARC = .JMP_SLOT }, |
| 950 | .X86_64 => .{ .X86_64 = .JUMP_SLOT }, |
| 941 | 951 | }; |
| 942 | 952 | } |
| 943 | 953 | pub fn globDat(elf: *Elf) MachineRelocType { |
| 944 | 954 | return switch (elf.ehdrField(.machine)) { |
| 945 | 955 | else => unreachable, |
| 946 | | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 956 | .AARCH64 => .{ .AARCH64 = .GLOB_DAT }, |
| 947 | 957 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 958 | .PPC64 => .{ .PPC64 = .GLOB_DAT }, |
| 959 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 960 | .SPARCV9 => .{ .SPARC = .GLOB_DAT }, |
| 961 | .X86_64 => .{ .X86_64 = .GLOB_DAT }, |
| 948 | 962 | }; |
| 949 | 963 | } |
| 950 | 964 | pub fn dtpOffAddr(elf: *Elf) MachineRelocType { |
| 951 | 965 | return switch (elf.ehdrField(.machine)) { |
| 952 | 966 | else => unreachable, |
| 953 | | .X86_64 => .{ .X86_64 = .DTPOFF64 }, |
| 954 | 967 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| 968 | .PPC64 => .{ .PPC64 = .DTPREL64 }, |
| 969 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .TLS_DTPREL64 else .TLS_DTPREL32 }, |
| 970 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .TLS_DTPOFF64 else .TLS_DTPOFF32 }, |
| 971 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .DTPOFF64 else .DTPOFF32 }, |
| 955 | 972 | }; |
| 956 | 973 | } |
| 957 | 974 | pub fn absAddr(elf: *Elf) MachineRelocType { |
| 958 | 975 | return switch (elf.ehdrField(.machine)) { |
| 959 | 976 | else => unreachable, |
| 960 | | .AARCH64 => .{ .AARCH64 = .ABS64 }, |
| 977 | .AARCH64 => .{ .AARCH64 = if (elf.identClass() == .@"64") .ABS64 else .P32_ABS32 }, |
| 961 | 978 | .LOONGARCH => .{ .LOONGARCH = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 962 | 979 | .PPC64 => .{ .PPC64 = .ADDR64 }, |
| 963 | | .RISCV => .{ .RISCV = .@"64" }, |
| 964 | | .X86_64 => .{ .X86_64 = .@"64" }, |
| 980 | .RISCV => .{ .RISCV = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 981 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 982 | .X86_64 => .{ .X86_64 = if (elf.identClass() == .@"64") .@"64" else .@"32" }, |
| 965 | 983 | }; |
| 966 | 984 | } |
| 967 | 985 | pub fn sizeAddr(elf: *Elf) MachineRelocType { |
| 968 | 986 | return switch (elf.ehdrField(.machine)) { |
| 969 | 987 | else => unreachable, |
| 988 | .SPARCV9 => .{ .SPARC = if (elf.identClass() == .@"64") .SIZE64 else .SIZE32 }, |
| 970 | 989 | .X86_64 => .{ .X86_64 = .SIZE64 }, |
| 971 | 990 | }; |
| 972 | 991 | } |
| ... | ... | @@ -974,6 +993,7 @@ pub const MachineRelocType = union { |
| 974 | 993 | pub fn wrap(int: u32, elf: *Elf) MachineRelocType { |
| 975 | 994 | return switch (elf.ehdrField(.machine)) { |
| 976 | 995 | else => unreachable, |
| 996 | .SPARCV9 => .{ .SPARC = @enumFromInt(int) }, |
| 977 | 997 | inline .AARCH64, |
| 978 | 998 | .LOONGARCH, |
| 979 | 999 | .PPC64, |
| ... | ... | @@ -985,6 +1005,7 @@ pub const MachineRelocType = union { |
| 985 | 1005 | pub fn unwrap(rt: MachineRelocType, elf: *Elf) u32 { |
| 986 | 1006 | return switch (elf.ehdrField(.machine)) { |
| 987 | 1007 | else => unreachable, |
| 1008 | .SPARCV9 => @intFromEnum(rt.SPARC), |
| 988 | 1009 | inline .AARCH64, |
| 989 | 1010 | .LOONGARCH, |
| 990 | 1011 | .PPC64, |
| ... | ... | @@ -1448,10 +1469,7 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1448 | 1469 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1449 | 1470 | |
| 1450 | 1471 | // Ensure the `.got.plt` section's node is big enough |
| 1451 | | const got_plt_need_size: usize = switch (elf.identClass()) { |
| 1452 | | .NONE, _ => unreachable, |
| 1453 | | inline else => |class| @sizeOf(class.ElfN().Addr) * (3 + need_plt_capacity), |
| 1454 | | }; |
| 1472 | const got_plt_need_size: usize = elf.targetPtrSize() * (3 + need_plt_capacity); |
| 1455 | 1473 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1456 | 1474 | |
| 1457 | 1475 | // Ensure the `.plt.sec` section's node is big enough |
| ... | ... | @@ -1460,16 +1478,18 @@ fn ensureUnusedPltCapacity(elf: *Elf, len: u32) Error!void { |
| 1460 | 1478 | }, |
| 1461 | 1479 | .LOONGARCH => { |
| 1462 | 1480 | // Ensure the `.plt` section's node is big enough |
| 1463 | | const plt_need_size: usize = 32 + 16 * need_plt_capacity; |
| 1481 | const plt_need_size: usize = 16 * (2 + need_plt_capacity); |
| 1464 | 1482 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1465 | 1483 | |
| 1466 | 1484 | // Ensure the `.got.plt` section's node is big enough |
| 1467 | | const got_plt_need_size: usize = switch (elf.identClass()) { |
| 1468 | | .NONE, _ => unreachable, |
| 1469 | | inline else => |class| @sizeOf(class.ElfN().Addr) * (2 + need_plt_capacity), |
| 1470 | | }; |
| 1485 | const got_plt_need_size: usize = elf.targetPtrSize() * (2 + need_plt_capacity); |
| 1471 | 1486 | try elf.ensureNodeSize(elf.shndx.got_plt.get(elf).ni, got_plt_need_size); |
| 1472 | 1487 | }, |
| 1488 | .SPARCV9 => { |
| 1489 | // Ensure the `.plt` section's node is big enough |
| 1490 | const plt_need_size: usize = 32 * (4 + need_plt_capacity); |
| 1491 | try elf.ensureNodeSize(elf.shndx.plt.get(elf).ni, plt_need_size); |
| 1492 | }, |
| 1473 | 1493 | } |
| 1474 | 1494 | } |
| 1475 | 1495 | /// Given an index into the PLT, returns whether that PLT entry is dead, meaning it may be reused at |
| ... | ... | @@ -2090,23 +2110,17 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2090 | 2110 | .addend = 0, |
| 2091 | 2111 | })); |
| 2092 | 2112 | |
| 2093 | | const reserved_got_plt_entries: u32 = switch (elf.ehdrField(.machine)) { |
| 2113 | // Note that some architectures don't have .got.plt (e.g. SPARC), and so |
| 2114 | // these values actually refer to .plt. |
| 2115 | const got_plt_section, const got_plt_offset = switch (elf.ehdrField(.machine)) { |
| 2094 | 2116 | else => |machine| @panic(@tagName(machine)), |
| 2095 | | .X86_64 => 3, |
| 2096 | | .LOONGARCH => 2, |
| 2117 | .LOONGARCH => .{ elf.shndx.got_plt, elf.targetPtrSize() * (2 + plt_index) }, |
| 2118 | .SPARCV9 => .{ elf.shndx.plt, 32 * (4 + plt_index) }, |
| 2119 | .X86_64 => .{ elf.shndx.got_plt, elf.targetPtrSize() * (3 + plt_index) }, |
| 2097 | 2120 | }; |
| 2098 | 2121 | |
| 2099 | 2122 | // Now that we know the index, we can set the relocation's offset. |
| 2100 | | const got_plt_addr = switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2101 | | inline else => |shdr, class| got_plt_addr: { |
| 2102 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2103 | | assert(elf.targetLoad(&shdr.entsize) == ent_size); |
| 2104 | | const offset = ent_size * @as(u64, reserved_got_plt_entries + plt_index); |
| 2105 | | assert(offset <= elf.targetLoad(&shdr.size)); |
| 2106 | | break :got_plt_addr elf.targetLoad(&shdr.addr) + offset; |
| 2107 | | }, |
| 2108 | | }; |
| 2109 | | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_addr); |
| 2123 | elf.shndx.rela_plt.relaSetOffset(elf, @enumFromInt(plt_index), got_plt_section.vaddr(elf) + got_plt_offset); |
| 2110 | 2124 | |
| 2111 | 2125 | if (plt_index < elf.plt.count()) { |
| 2112 | 2126 | // We reused a free entry, so we're already done! |
| ... | ... | @@ -2148,13 +2162,11 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2148 | 2162 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2149 | 2163 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2150 | 2164 | inline else => |shdr, class| { |
| 2151 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2152 | | const old_size = ent_size * (3 + plt_index); |
| 2153 | | assert(elf.targetLoad(&shdr.size) == old_size); |
| 2154 | | elf.targetStore(&shdr.size, old_size + ent_size); |
| 2165 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2166 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(shdr.ElfN().Addr)); |
| 2155 | 2167 | std.mem.writeInt( |
| 2156 | 2168 | class.ElfN().Addr, |
| 2157 | | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], |
| 2169 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(shdr.ElfN().Addr)], |
| 2158 | 2170 | @intCast(plt_addr), |
| 2159 | 2171 | target_endian, |
| 2160 | 2172 | ); |
| ... | ... | @@ -2176,7 +2188,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2176 | 2188 | i32, |
| 2177 | 2189 | plt_sec_slice[6..][0..4], |
| 2178 | 2190 | @intCast(@as(i64, @bitCast( |
| 2179 | | got_plt_addr -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| 2191 | (got_plt_section.vaddr(elf) + got_plt_offset) -% (elf.targetLoad(&shdr.addr) + old_size + 10), |
| 2180 | 2192 | ))), |
| 2181 | 2193 | target_endian, |
| 2182 | 2194 | ); |
| ... | ... | @@ -2212,26 +2224,54 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 2212 | 2224 | const got_plt_ni = elf.shndx.got_plt.get(elf).ni; |
| 2213 | 2225 | switch (elf.shdrPtr(elf.shndx.got_plt)) { |
| 2214 | 2226 | inline else => |shdr, class| { |
| 2215 | | const ent_size = @sizeOf(class.ElfN().Addr); |
| 2216 | | const old_size = ent_size * (2 + plt_index); |
| 2217 | | assert(elf.targetLoad(&shdr.size) == old_size); |
| 2218 | | elf.targetStore(&shdr.size, old_size + ent_size); |
| 2227 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2228 | elf.targetStore(&shdr.size, got_plt_offset + @sizeOf(shdr.ElfN().Addr)); |
| 2219 | 2229 | std.mem.writeInt( |
| 2220 | 2230 | class.ElfN().Addr, |
| 2221 | | got_plt_ni.slice(&elf.mf)[old_size..][0..ent_size], |
| 2231 | got_plt_ni.slice(&elf.mf)[got_plt_offset..][0..@sizeOf(shdr.ElfN().Addr)], |
| 2222 | 2232 | @intCast(plt_addr), |
| 2223 | 2233 | target_endian, |
| 2224 | 2234 | ); |
| 2225 | | assert(got_plt_addr == (elf.targetLoad(&shdr.addr) + old_size)); |
| 2226 | 2235 | }, |
| 2227 | 2236 | } |
| 2228 | 2237 | |
| 2229 | 2238 | // relocate the PLT entry to point to the .GOT.PLT entry |
| 2230 | | const got_plt_abs: u64 = @as(u64, got_plt_addr); |
| 2239 | const got_plt_abs = got_plt_section.vaddr(elf) + got_plt_offset; |
| 2231 | 2240 | // TODO: handle overflow gracefully |
| 2232 | 2241 | link.loongarch.writeJ20(plt_slice[0..4], link.loongarch.toPcalaHi20(got_plt_abs, plt_addr)); |
| 2233 | 2242 | link.loongarch.writeK12(plt_slice[4..8], @truncate(got_plt_abs)); |
| 2234 | 2243 | }, |
| 2244 | .SPARCV9 => { |
| 2245 | // add a .PLT entry, writing the template |
| 2246 | const plt_ni = elf.shndx.plt.get(elf).ni; |
| 2247 | switch (elf.shdrPtr(elf.shndx.plt)) { |
| 2248 | inline else => |shdr| { |
| 2249 | assert(elf.targetLoad(&shdr.size) == got_plt_offset); |
| 2250 | elf.targetStore(&shdr.size, got_plt_offset + 32); |
| 2251 | const plt_slice: []u32 = @ptrCast(@alignCast(plt_ni.slice(&elf.mf)[got_plt_offset..][0..32])); |
| 2252 | // sethi (. - .plt[0]), %g1 |
| 2253 | // ba,a %xcc, .plt[1] |
| 2254 | // nop |
| 2255 | // nop |
| 2256 | // nop |
| 2257 | // nop |
| 2258 | // nop |
| 2259 | // nop |
| 2260 | @memcpy(plt_slice, &([2]u32{ |
| 2261 | // TODO: handle overflow gracefully |
| 2262 | @bitCast(link.sparc.reloc.Imm22{ |
| 2263 | .imm22 = @truncate(got_plt_offset), |
| 2264 | .b22_31 = 0b0000000011, |
| 2265 | }), |
| 2266 | @bitCast(link.sparc.reloc.Disp19{ |
| 2267 | .disp19 = @truncate((got_plt_offset + 4 - 32) >> 2), |
| 2268 | .b19_31 = 0b1100001101000, |
| 2269 | }), |
| 2270 | } ++ @as([6]u32, @splat(0x01000000)))); |
| 2271 | if (elf.targetEndian() != native_endian) std.mem.byteSwapAllElements(u32, plt_slice); |
| 2272 | }, |
| 2273 | } |
| 2274 | }, |
| 2235 | 2275 | } |
| 2236 | 2276 | } |
| 2237 | 2277 | |
| ... | ... | @@ -3084,11 +3124,12 @@ fn initHeaders( |
| 3084 | 3124 | .@"64" => .@"8", |
| 3085 | 3125 | }; |
| 3086 | 3126 | |
| 3087 | | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const plt_sec = |
| 3127 | const init_plt_size: std.elf.Xword, const plt_align: std.mem.Alignment, const got_plt, const plt_sec = |
| 3088 | 3128 | switch (machine) { |
| 3089 | 3129 | else => @panic(@tagName(machine)), |
| 3090 | | .X86_64 => .{ 16, .@"16", true }, |
| 3091 | | .LOONGARCH => .{ 32, .@"4", false }, |
| 3130 | .LOONGARCH => .{ 16 * 2, .@"4", true, false }, |
| 3131 | .SPARCV9 => .{ 32 * 4, .fromByteUnits(256), false, false }, |
| 3132 | .X86_64 => .{ 16, .@"16", true, true }, |
| 3092 | 3133 | }; |
| 3093 | 3134 | |
| 3094 | 3135 | const shnum: u32 = shnum: { |
| ... | ... | @@ -3111,7 +3152,7 @@ fn initHeaders( |
| 3111 | 3152 | } |
| 3112 | 3153 | if (@"type" != .REL) { |
| 3113 | 3154 | shnum += 1; // .got |
| 3114 | | shnum += 1; // .got.plt |
| 3155 | shnum += @intFromBool(got_plt); // .got.plt |
| 3115 | 3156 | shnum += 1; // .plt |
| 3116 | 3157 | shnum += @intFromBool(plt_sec); // .plt_sec |
| 3117 | 3158 | } |
| ... | ... | @@ -3212,7 +3253,6 @@ fn initHeaders( |
| 3212 | 3253 | ehdr.phoff = 0; |
| 3213 | 3254 | ehdr.shoff = 0; |
| 3214 | 3255 | ehdr.flags = switch (machine) { |
| 3215 | | .X86_64 => 0, |
| 3216 | 3256 | .LOONGARCH => e_flags: { |
| 3217 | 3257 | const target_cpu = &elf.base.comp.getTarget().cpu; |
| 3218 | 3258 | const e_flags: std.elf.loongarch.EFlags = .{ |
| ... | ... | @@ -3227,6 +3267,20 @@ fn initHeaders( |
| 3227 | 3267 | }; |
| 3228 | 3268 | break :e_flags @bitCast(e_flags); |
| 3229 | 3269 | }, |
| 3270 | .SPARCV9 => e_flags: { |
| 3271 | const e_flags: std.elf.sparc.EFlags = .{ |
| 3272 | .mm = .rmo, |
| 3273 | .ext = .{ |
| 3274 | .@"32plus" = false, |
| 3275 | .sun_us1 = false, |
| 3276 | .hal_r1 = false, |
| 3277 | .sun_us3 = false, |
| 3278 | .le_data = false, |
| 3279 | }, |
| 3280 | }; |
| 3281 | break :e_flags @bitCast(e_flags); |
| 3282 | }, |
| 3283 | .X86_64 => 0, |
| 3230 | 3284 | else => @panic(@tagName(machine)), |
| 3231 | 3285 | }; |
| 3232 | 3286 | ehdr.ehsize = @sizeOf(ElfN.Ehdr); |
| ... | ... | @@ -3324,8 +3378,8 @@ fn initHeaders( |
| 3324 | 3378 | .@"386" => 0x400000, |
| 3325 | 3379 | .AARCH64, .X86_64 => 0x200000, |
| 3326 | 3380 | .PPC, .PPC64 => 0x10000000, |
| 3327 | | .S390, .S390_OLD => 0x1000000, |
| 3328 | | .OLD_SPARCV9, .SPARCV9 => 0x100000, |
| 3381 | .S390 => 0x1000000, |
| 3382 | .SPARCV9 => 0x100000, |
| 3329 | 3383 | else => 0x10000, |
| 3330 | 3384 | }, |
| 3331 | 3385 | }; |
| ... | ... | @@ -3561,14 +3615,16 @@ fn initHeaders( |
| 3561 | 3615 | // Reserve space for the reserved words, populated later. |
| 3562 | 3616 | .size = switch (machine) { |
| 3563 | 3617 | else => @panic(@tagName(machine)), |
| 3564 | | .X86_64 => 3 * 8, |
| 3565 | | .LOONGARCH => if (elf.identClass() == .@"64") 8 else 4, |
| 3618 | .X86_64 => 3 * elf.targetPtrSize(), |
| 3619 | .LOONGARCH, |
| 3620 | .SPARCV9, |
| 3621 | => elf.targetPtrSize(), |
| 3566 | 3622 | }, |
| 3567 | 3623 | .flags = .{ .WRITE = true, .ALLOC = true }, |
| 3568 | 3624 | .addralign = addr_align, |
| 3569 | 3625 | .entsize = @intCast(addr_align.toByteUnits()), |
| 3570 | 3626 | }); |
| 3571 | | elf.shndx.got_plt = try elf.addSection( |
| 3627 | if (got_plt) elf.shndx.got_plt = try elf.addSection( |
| 3572 | 3628 | if (elf.options.z_now) elf.ni.data_rel_ro else elf.ni.data, |
| 3573 | 3629 | .{ |
| 3574 | 3630 | .name = ".got.plt", |
| ... | ... | @@ -3578,7 +3634,7 @@ fn initHeaders( |
| 3578 | 3634 | else => @panic(@tagName(machine)), |
| 3579 | 3635 | .@"386" => 3 * 4, |
| 3580 | 3636 | .X86_64 => 3 * 8, |
| 3581 | | .LOONGARCH => if (elf.identClass() == .@"64") 2 * 8 else 2 * 4, |
| 3637 | .LOONGARCH => 2 * elf.targetPtrSize(), |
| 3582 | 3638 | }, |
| 3583 | 3639 | .addralign = addr_align, |
| 3584 | 3640 | .entsize = @intCast(addr_align.toByteUnits()), |
| ... | ... | @@ -3587,7 +3643,14 @@ fn initHeaders( |
| 3587 | 3643 | elf.shndx.plt = try elf.addSection(elf.ni.text, .{ |
| 3588 | 3644 | .name = ".plt", |
| 3589 | 3645 | .type = .PROGBITS, |
| 3590 | | .flags = .{ .ALLOC = true, .EXECINSTR = true }, |
| 3646 | .flags = .{ |
| 3647 | .ALLOC = true, |
| 3648 | .EXECINSTR = true, |
| 3649 | .WRITE = switch (machine) { |
| 3650 | .SPARCV9 => true, |
| 3651 | else => false, |
| 3652 | }, |
| 3653 | }, |
| 3591 | 3654 | .size = init_plt_size, |
| 3592 | 3655 | .addralign = plt_align, |
| 3593 | 3656 | .node_align = elf.mf.flags.block_size, |
| ... | ... | @@ -3686,7 +3749,7 @@ fn initHeaders( |
| 3686 | 3749 | .type = .RELA, |
| 3687 | 3750 | .flags = .{ .ALLOC = true, .INFO_LINK = true }, |
| 3688 | 3751 | .link = elf.shndx.dynsym.toSection().?, |
| 3689 | | .info = elf.shndx.got_plt.toSection().?, |
| 3752 | .info = (if (got_plt) elf.shndx.got_plt else elf.shndx.plt).toSection().?, |
| 3690 | 3753 | .addralign = addr_align, |
| 3691 | 3754 | .entsize = rela_size, |
| 3692 | 3755 | .node_align = elf.mf.flags.block_size, |
| ... | ... | @@ -3758,6 +3821,7 @@ fn initHeaders( |
| 3758 | 3821 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 8, got_plt_sym, 0, .abs32_lo12); |
| 3759 | 3822 | try elf.addSymbolRelocAssumeCapacity(plt_ni, 16, got_plt_sym, 0, .abs32_lo12); |
| 3760 | 3823 | }, |
| 3824 | .SPARCV9 => {}, |
| 3761 | 3825 | } |
| 3762 | 3826 | } |
| 3763 | 3827 | if (comp.config.any_non_single_threaded) { |
| ... | ... | @@ -3782,7 +3846,9 @@ fn initHeaders( |
| 3782 | 3846 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 1 }, .none); |
| 3783 | 3847 | elf.got.putAssumeCapacityNoClobber(.{ .reserved = 2 }, .none); |
| 3784 | 3848 | }, |
| 3785 | | .LOONGARCH => { |
| 3849 | .LOONGARCH, |
| 3850 | .SPARCV9, |
| 3851 | => { |
| 3786 | 3852 | try elf.got.ensureUnusedCapacity(gpa, 1); |
| 3787 | 3853 | elf.got.putAssumeCapacityNoClobber(switch (have_dynamic_section) { |
| 3788 | 3854 | true => .{ .symbol = .local(elf.shndx.dynamic.get(elf).lsi) }, |
| ... | ... | @@ -4100,12 +4166,11 @@ fn identData(elf: *const Elf) std.elf.DATA { |
| 4100 | 4166 | return @enumFromInt(elf.mf.memory_map.memory[std.elf.EI.DATA]); |
| 4101 | 4167 | } |
| 4102 | 4168 | |
| 4169 | fn targetPtrSize(elf: *const Elf) u32 { |
| 4170 | return elf.identClass().size(); |
| 4171 | } |
| 4103 | 4172 | fn targetEndian(elf: *const Elf) std.lang.Endian { |
| 4104 | | return switch (elf.identData()) { |
| 4105 | | .NONE, _ => unreachable, |
| 4106 | | .@"2LSB" => .little, |
| 4107 | | .@"2MSB" => .big, |
| 4108 | | }; |
| 4173 | return elf.identData().endian(); |
| 4109 | 4174 | } |
| 4110 | 4175 | fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.child { |
| 4111 | 4176 | const pointer_ty = @typeInfo(@TypeOf(ptr)).pointer; |
| ... | ... | @@ -5462,6 +5527,11 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5462 | 5527 | }; |
| 5463 | 5528 | } |
| 5464 | 5529 | |
| 5530 | const got_plt = switch (elf.ehdrField(.machine)) { |
| 5531 | .SPARCV9 => false, |
| 5532 | else => true, |
| 5533 | }; |
| 5534 | |
| 5465 | 5535 | if (elf.shndx.dynamic != .UNDEF) switch (elf.identClass()) { |
| 5466 | 5536 | .NONE, _ => unreachable, |
| 5467 | 5537 | inline else => |ct_class| { |
| ... | ... | @@ -5645,7 +5715,7 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5645 | 5715 | if (dynamic_indices.pltgot) |index| try elf.addSymbolRelocAssumeCapacity( |
| 5646 | 5716 | dynamic_ni, |
| 5647 | 5717 | @sizeOf(ElfN.Addr) * (2 * index + 1), |
| 5648 | | .local(elf.shndx.got_plt.get(elf).lsi), |
| 5718 | .local((if (got_plt) elf.shndx.got_plt else elf.shndx.plt).get(elf).lsi), |
| 5649 | 5719 | 0, |
| 5650 | 5720 | dsorel, |
| 5651 | 5721 | ); |
| ... | ... | @@ -7370,6 +7440,17 @@ fn flushMovedPltSection(elf: *Elf, which: enum { plt, plt_sec, got_plt }, old_ad |
| 7370 | 7440 | }, |
| 7371 | 7441 | } |
| 7372 | 7442 | }, |
| 7443 | .SPARCV9 => switch (which) { |
| 7444 | .plt => { |
| 7445 | // Update the offsets of the relocation entries in `.rela.plt`. |
| 7446 | const rela_plt_shndx = elf.shndx.rela_plt; |
| 7447 | for (0..elf.plt.count()) |plt_index| { |
| 7448 | if (elf.pltEntryIsDead(plt_index)) continue; |
| 7449 | rela_plt_shndx.relaAdjustOffset(elf, @enumFromInt(plt_index), old_addr, addr); |
| 7450 | } |
| 7451 | }, |
| 7452 | .plt_sec, .got_plt => unreachable, |
| 7453 | }, |
| 7373 | 7454 | } |
| 7374 | 7455 | } |
| 7375 | 7456 | |