authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-11-02 10:29:41+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-11-02 10:29:41+01:00
loge27b4647d86e3bdaf2c4fd95db2e7d359afd7fc4
treea979dd3e143102fea636ae9c5dc7fc61a81aa8b5
parent8abbdb56a4fce176cb8ec24e5d4724ac16196a0b
parent059f18855f18f9dd76f74031381e04dd131da528
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21617 from alexrp/target-dyld-stuff

Improve the `DynamicLinker` API and fix `detectAbiAndDynamicLinker()` for non-Linux/Hurd ELF hosts

3 files changed, 357 insertions(+), 217 deletions(-)

lib/std/Target.zig+322-197
...@@ -2059,30 +2059,6 @@ pub inline fn floatAbi(target: Target) FloatAbi {...@@ -2059,30 +2059,6 @@ pub inline fn floatAbi(target: Target) FloatAbi {
2059 return target.abi.floatAbi();2059 return target.abi.floatAbi();
2060}2060}
20612061
2062pub inline fn hasDynamicLinker(target: Target) bool {
2063 if (target.cpu.arch.isWasm()) {
2064 return false;
2065 }
2066 switch (target.os.tag) {
2067 .freestanding,
2068 .ios,
2069 .tvos,
2070 .watchos,
2071 .macos,
2072 .visionos,
2073 .uefi,
2074 .windows,
2075 .emscripten,
2076 .opencl,
2077 .opengl,
2078 .vulkan,
2079 .plan9,
2080 .other,
2081 => return false,
2082 else => return true,
2083 }
2084}
2085
2086pub const DynamicLinker = struct {2062pub const DynamicLinker = struct {
2087 /// Contains the memory used to store the dynamic linker path. This field2063 /// Contains the memory used to store the dynamic linker path. This field
2088 /// should not be used directly. See `get` and `set`. This field exists so2064 /// should not be used directly. See `get` and `set`. This field exists so
...@@ -2129,209 +2105,306 @@ pub const DynamicLinker = struct {...@@ -2129,209 +2105,306 @@ pub const DynamicLinker = struct {
2129 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);2105 return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
2130 }2106 }
21312107
2108 pub const Kind = enum {
2109 /// No dynamic linker.
2110 none,
2111 /// Dynamic linker path is determined by the arch/OS components.
2112 arch_os,
2113 /// Dynamic linker path is determined by the arch/OS/ABI components.
2114 arch_os_abi,
2115 };
2116
2117 pub fn kind(os: Os.Tag) Kind {
2118 return switch (os) {
2119 .fuchsia,
2120
2121 .haiku,
2122 .serenity,
2123
2124 .dragonfly,
2125 .freebsd,
2126 .netbsd,
2127 .openbsd,
2128
2129 .bridgeos,
2130 .driverkit,
2131 .ios,
2132 .macos,
2133 .tvos,
2134 .visionos,
2135 .watchos,
2136
2137 .illumos,
2138 .solaris,
2139 => .arch_os,
2140 .hurd,
2141 .linux,
2142 => .arch_os_abi,
2143 .freestanding,
2144 .other,
2145
2146 .contiki,
2147 .elfiamcu,
2148 .hermit,
2149
2150 .aix,
2151 .plan9,
2152 .rtems,
2153 .zos,
2154
2155 .uefi,
2156 .windows,
2157
2158 .emscripten,
2159 .wasi,
2160
2161 .amdhsa,
2162 .amdpal,
2163 .cuda,
2164 .mesa3d,
2165 .nvcl,
2166 .opencl,
2167 .opengl,
2168 .vulkan,
2169
2170 .ps3,
2171 .ps4,
2172 .ps5,
2173 => .none,
2174 };
2175 }
2176
2177 /// The strictness of this function depends on the value of `kind(os.tag)`:
2178 ///
2179 /// * `.none`: Ignores all arguments and just returns `none`.
2180 /// * `.arch_os`: Ignores `abi` and returns the dynamic linker matching `cpu` and `os`.
2181 /// * `.arch_os_abi`: Returns the dynamic linker matching `cpu`, `os`, and `abi`.
2182 ///
2183 /// In the case of `.arch_os` in particular, callers should be aware that a valid dynamic linker
2184 /// being returned only means that the `cpu` + `os` combination represents a platform that
2185 /// actually exists and which has an established dynamic linker path that does not change with
2186 /// the ABI; it does not necessarily mean that `abi` makes any sense at all for that platform.
2187 /// The responsibility for determining whether `abi` is valid in this case rests with the
2188 /// caller. `Abi.default()` can be used to pick a best-effort default ABI for such platforms.
2132 pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {2189 pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {
2133 return switch (os.tag) {2190 return switch (os.tag) {
2134 .fuchsia => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.2191 .fuchsia => switch (cpu.arch) {
2192 .aarch64,
2193 .riscv64,
2194 .x86_64,
2195 => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.
2196 else => none,
2197 },
21352198
2136 .haiku => init("/system/runtime_loader"),2199 .haiku => switch (cpu.arch) {
2200 .arm,
2201 .thumb,
2202 .aarch64,
2203 .m68k,
2204 .powerpc,
2205 .riscv64,
2206 .sparc64,
2207 .x86,
2208 .x86_64,
2209 => init("/system/runtime_loader"),
2210 else => none,
2211 },
21372212
2138 .hurd => switch (cpu.arch) {2213 .hurd => switch (cpu.arch) {
2139 .aarch64,2214 .aarch64,
2140 .aarch64_be,2215 .aarch64_be,
2141 => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{2216 => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{
2142 @tagName(arch),2217 @tagName(arch),
2143 if (abi == .gnuilp32) "_ilp32" else "",2218 switch (abi) {
2219 .gnu => "",
2220 .gnuilp32 => "_ilp32",
2221 else => return none,
2222 },
2144 }),2223 }),
21452224
2146 .x86 => init("/lib/ld.so.1"),2225 .x86 => if (abi == .gnu) init("/lib/ld.so.1") else none,
2147 .x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}),2226 .x86_64 => initFmt("/lib/ld-{s}.so.1", .{switch (abi) {
2227 .gnu => "x86-64",
2228 .gnux32 => "x32",
2229 else => return none,
2230 }}),
21482231
2149 // These are unsupported by Hurd/glibc.2232 else => none,
2150 .amdgcn,
2151 .arc,
2152 .arm,
2153 .armeb,
2154 .thumb,
2155 .thumbeb,
2156 .avr,
2157 .bpfel,
2158 .bpfeb,
2159 .csky,
2160 .hexagon,
2161 .kalimba,
2162 .lanai,
2163 .loongarch32,
2164 .loongarch64,
2165 .m68k,
2166 .mips,
2167 .mipsel,
2168 .mips64,
2169 .mips64el,
2170 .msp430,
2171 .nvptx,
2172 .nvptx64,
2173 .powerpc,
2174 .powerpcle,
2175 .powerpc64,
2176 .powerpc64le,
2177 .propeller1,
2178 .propeller2,
2179 .riscv32,
2180 .riscv64,
2181 .s390x,
2182 .sparc,
2183 .sparc64,
2184 .spirv,
2185 .spirv32,
2186 .spirv64,
2187 .spu_2,
2188 .ve,
2189 .wasm32,
2190 .wasm64,
2191 .xcore,
2192 .xtensa,
2193 => none,
2194 },2233 },
21952234
2196 .linux => if (abi.isAndroid())2235 .linux => if (abi.isAndroid())
2197 initFmt("/system/bin/linker{s}", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""})2236 switch (cpu.arch) {
2237 .arm,
2238 .thumb,
2239 => if (abi == .androideabi) init("/system/bin/linker") else none,
2240
2241 .aarch64,
2242 .riscv64,
2243 .x86,
2244 .x86_64,
2245 => if (abi == .android) initFmt("/system/bin/linker{s}", .{
2246 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
2247 }) else none,
2248
2249 else => none,
2250 }
2198 else if (abi.isMusl())2251 else if (abi.isMusl())
2199 switch (cpu.arch) {2252 switch (cpu.arch) {
2200 .arm,2253 .arm,
2201 .armeb,2254 .armeb,
2202 .thumb,2255 .thumb,
2203 .thumbeb,2256 .thumbeb,
2257 => |arch| initFmt("/lib/ld-musl-arm{s}{s}.so.1", .{
2258 if (arch == .armeb or arch == .thumbeb) "eb" else "",
2259 switch (abi) {
2260 .musleabi => "",
2261 .musleabihf => "hf",
2262 else => return none,
2263 },
2264 }),
2265
2204 .aarch64,2266 .aarch64,
2205 .aarch64_be,2267 .aarch64_be,
2206 .loongarch64,2268 .loongarch64, // TODO: `-sp` and `-sf` ABI support in LLVM 20.
2207 .m68k,2269 .m68k,
2208 .powerpc,
2209 .powerpc64,2270 .powerpc64,
2210 .powerpc64le,2271 .powerpc64le,
2211 .riscv32,
2212 .riscv64,
2213 .s390x,2272 .s390x,
2214 .x86,2273 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}.so.1", .{@tagName(arch)}) else none,
2215 .x86_64,
2216 => |arch| initFmt("/lib/ld-musl-{s}{s}.so.1", .{
2217 switch (arch) {
2218 .thumb => "arm",
2219 .thumbeb => "armeb",
2220 .x86 => "i386",
2221 .x86_64 => if (abi == .muslx32) "x32" else "x86_64",
2222 else => @tagName(arch),
2223 },
2224 switch (arch) {
2225 .arm, .armeb, .thumb, .thumbeb => if (abi.floatAbi() == .hard) "hf" else "",
2226 .aarch64, .aarch64_be => if (abi == .gnuilp32) "_ilp32" else "",
2227 .riscv32, .riscv64 => if (std.Target.riscv.featureSetHas(cpu.features, .d))
2228 ""
2229 else if (std.Target.riscv.featureSetHas(cpu.features, .f))
2230 "-sp"
2231 else
2232 "-sf",
2233 else => if (abi.floatAbi() == .soft) "-sf" else "",
2234 },
2235 }),
22362274
2237 // The naming scheme for MIPS is a bit irregular.
2238 .mips,2275 .mips,
2239 .mipsel,2276 .mipsel,
2277 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
2278 if (mips.featureSetHas(cpu.features, .mips32r6)) "r6" else "",
2279 if (arch == .mipsel) "el" else "",
2280 switch (abi) {
2281 .musleabi => "-sf",
2282 .musleabihf => "",
2283 else => return none,
2284 },
2285 }),
2286
2240 .mips64,2287 .mips64,
2241 .mips64el,2288 .mips64el,
2242 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{2289 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
2243 if (arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support in LLVM 20.2290 // TODO: `n32` ABI support in LLVM 20.
2244 if (mips.featureSetHas(cpu.features, if (arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "",2291 switch (abi) {
2245 if (arch.endian() == .little) "el" else "",2292 .musl => "64",
2246 if (abi.floatAbi() == .soft) "-sf" else "",2293 else => return none,
2294 },
2295 if (mips.featureSetHas(cpu.features, .mips64r6)) "r6" else "",
2296 if (arch == .mips64el) "el" else "",
2247 }),2297 }),
22482298
2249 // These are unsupported by musl.2299 .powerpc => initFmt("/lib/ld-musl-powerpc{s}.so.1", .{switch (abi) {
2250 .amdgcn,2300 .musleabi => "-sf",
2251 .arc,2301 .musleabihf => "",
2252 .avr,2302 else => return none,
2253 .csky,2303 }}),
2254 .bpfel,2304
2255 .bpfeb,2305 .riscv32,
2256 .hexagon,2306 .riscv64,
2257 .kalimba,2307 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{
2258 .lanai,2308 @tagName(arch),
2259 .loongarch32,2309 if (riscv.featureSetHas(cpu.features, .d))
2260 .msp430,2310 ""
2261 .nvptx,2311 else if (riscv.featureSetHas(cpu.features, .f))
2262 .nvptx64,2312 "-sp"
2263 .powerpcle,2313 else
2264 .propeller1,2314 "-sf",
2265 .propeller2,2315 }) else none,
2266 .sparc,2316
2267 .sparc64,2317 .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none,
2268 .spirv,2318 .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) {
2269 .spirv32,2319 .musl => "x86_64",
2270 .spirv64,2320 .muslx32 => "x32",
2271 .spu_2,2321 else => return none,
2272 .ve,2322 }}),
2273 .wasm32,2323
2274 .wasm64,2324 else => none,
2275 .xcore,
2276 .xtensa,
2277 => none,
2278 }2325 }
2279 else if (abi.isGnu())2326 else if (abi.isGnu())
2280 switch (cpu.arch) {2327 switch (cpu.arch) {
2281 // TODO: `eb` architecture support.2328 // TODO: `eb` architecture support.
2282 // TODO: `700` ABI support.2329 // TODO: `700` ABI support.
2283 .arc => init("/lib/ld-linux-arc.so.2"),2330 .arc => if (abi == .gnu) init("/lib/ld-linux-arc.so.2") else none,
22842331
2285 // TODO: OABI support (`/lib/ld-linux.so.2`).2332 // TODO: OABI support (`/lib/ld-linux.so.2`).
2286 .arm,2333 .arm,
2287 .armeb,2334 .armeb,
2288 .thumb,2335 .thumb,
2289 .thumbeb,2336 .thumbeb,
2290 => initFmt("/lib/ld-linux{s}.so.3", .{if (abi.floatAbi() == .hard) "-armhf" else ""}),2337 => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi) {
2338 .gnueabi => "",
2339 .gnueabihf => "-armhf",
2340 else => return none,
2341 }}),
22912342
2292 .aarch64,2343 .aarch64,
2293 .aarch64_be,2344 .aarch64_be,
2294 => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{2345 => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{
2295 @tagName(arch),2346 @tagName(arch),
2296 if (abi == .gnuilp32) "_ilp32" else "",2347 switch (abi) {
2348 .gnu => "",
2349 .gnuilp32 => "_ilp32",
2350 else => return none,
2351 },
2297 }),2352 }),
22982353
2299 // TODO: `-be` architecture support.2354 // TODO: `-be` architecture support.
2300 .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}),2355 .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{switch (abi) {
2356 .gnueabi => "",
2357 .gnueabihf => "-hf",
2358 else => return none,
2359 }}),
23012360
2302 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {2361 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
2362 .gnu => "lp64d",
2303 .gnuf32 => "lp64f",2363 .gnuf32 => "lp64f",
2304 .gnusf => "lp64s",2364 .gnusf => "lp64s",
2305 else => "lp64d",2365 else => return none,
2306 }}),2366 }}),
23072367
2308 .m68k => init("/lib/ld.so.1"),2368 .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none,
23092369
2310 .mips,2370 .mips,
2311 .mipsel,2371 .mipsel,
2372 => switch (abi) {
2373 .gnueabi,
2374 .gnueabihf,
2375 => initFmt("/lib/ld{s}.so.1", .{
2376 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
2377 }),
2378 else => none,
2379 },
2380
2312 .mips64,2381 .mips64,
2313 .mips64el,2382 .mips64el,
2314 => initFmt("/lib{s}/ld{s}.so.1", .{2383 => initFmt("/lib{s}/ld{s}.so.1", .{
2315 switch (abi) {2384 switch (abi) {
2316 .gnuabin32 => "32",
2317 .gnuabi64 => "64",2385 .gnuabi64 => "64",
2318 else => "",2386 .gnuabin32 => "32",
2387 else => return none,
2319 },2388 },
2320 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",2389 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
2321 }),2390 }),
23222391
2323 .powerpc => init("/lib/ld.so.1"),2392 .powerpc => switch (abi) {
2324 // TODO: ELFv2 ABI opt-in support.2393 .gnueabi,
2325 .powerpc64 => init("/lib64/ld64.so.1"),2394 .gnueabihf,
2326 .powerpc64le => init("/lib64/ld64.so.2"),2395 => init("/lib/ld.so.1"),
2396 else => none,
2397 },
2398 // TODO: ELFv2 ABI (`/lib64/ld64.so.2`) opt-in support.
2399 .powerpc64 => if (abi == .gnu) init("/lib64/ld64.so.1") else none,
2400 .powerpc64le => if (abi == .gnu) init("/lib64/ld64.so.2") else none,
23272401
2328 .riscv32,2402 .riscv32,
2329 .riscv64,2403 .riscv64,
2330 => |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{2404 => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{s}{s}.so.1", .{
2331 @tagName(arch),
2332 switch (arch) {2405 switch (arch) {
2333 .riscv32 => "ilp32",2406 .riscv32 => "riscv32-ilp32",
2334 .riscv64 => "lp64",2407 .riscv64 => "riscv64-lp64",
2335 else => unreachable,2408 else => unreachable,
2336 },2409 },
2337 if (riscv.featureSetHas(cpu.features, .d))2410 if (riscv.featureSetHas(cpu.features, .d))
...@@ -2340,78 +2413,130 @@ pub const DynamicLinker = struct {...@@ -2340,78 +2413,130 @@ pub const DynamicLinker = struct {
2340 "f"2413 "f"
2341 else2414 else
2342 "",2415 "",
2343 }),2416 }) else none,
23442417
2345 .s390x => init("/lib/ld64.so.1"),2418 .s390x => if (abi == .gnu) init("/lib/ld64.so.1") else none,
23462419
2347 .sparc => init("/lib/ld-linux.so.2"),2420 .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
2348 .sparc64 => init("/lib64/ld-linux.so.2"),2421 .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none,
23492422
2350 .x86 => init("/lib/ld-linux.so.2"),2423 .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
2351 .x86_64 => init(if (abi == .gnux32) "/libx32/ld-linux-x32.so.2" else "/lib64/ld-linux-x86-64.so.2"),2424 .x86_64 => switch (abi) {
2425 .gnu => init("/lib64/ld-linux-x86-64.so.2"),
2426 .gnux32 => init("/libx32/ld-linux-x32.so.2"),
2427 else => none,
2428 },
23522429
2353 .xtensa => init("/lib/ld.so.1"),2430 .xtensa => if (abi == .gnu) init("/lib/ld.so.1") else none,
23542431
2355 // These are unsupported by glibc.2432 else => none,
2356 .amdgcn,
2357 .avr,
2358 .bpfeb,
2359 .bpfel,
2360 .hexagon,
2361 .kalimba,
2362 .lanai,
2363 .loongarch32,
2364 .msp430,
2365 .nvptx,
2366 .nvptx64,
2367 .powerpcle,
2368 .propeller1,
2369 .propeller2,
2370 .spirv,
2371 .spirv32,
2372 .spirv64,
2373 .spu_2,
2374 .ve,
2375 .wasm32,
2376 .wasm64,
2377 .xcore,
2378 => none,
2379 }2433 }
2380 else2434 else
2381 none, // Not a known Linux libc.2435 none, // Not a known Linux libc.
23822436
2383 .serenity => init("/usr/lib/Loader.so"),2437 .serenity => switch (cpu.arch) {
2438 .aarch64,
2439 .riscv64,
2440 .x86_64,
2441 => init("/usr/lib/Loader.so"),
2442 else => none,
2443 },
23842444
2385 .dragonfly => initFmt("{s}/libexec/ld-elf.so.2", .{2445 .dragonfly => if (cpu.arch == .x86_64) initFmt("{s}/libexec/ld-elf.so.2", .{
2386 if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)2446 if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)
2387 ""2447 ""
2388 else2448 else
2389 "/usr",2449 "/usr",
2390 }),2450 }) else none,
23912451
2392 .freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{2452 .freebsd => switch (cpu.arch) {
2393 if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)2453 .arm,
2394 ""2454 .armeb,
2395 else2455 .thumb,
2396 "/usr",2456 .thumbeb,
2397 }),2457 .aarch64,
2458 .mips,
2459 .mipsel,
2460 .mips64,
2461 .mips64el,
2462 .powerpc,
2463 .powerpc64,
2464 .powerpc64le,
2465 .riscv64,
2466 .sparc64,
2467 .x86,
2468 .x86_64,
2469 => initFmt("{s}/libexec/ld-elf.so.1", .{
2470 if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
2471 ""
2472 else
2473 "/usr",
2474 }),
2475 else => none,
2476 },
23982477
2399 .netbsd => init("/libexec/ld.elf_so"),2478 .netbsd => switch (cpu.arch) {
2479 .arm,
2480 .armeb,
2481 .thumb,
2482 .thumbeb,
2483 .aarch64,
2484 .aarch64_be,
2485 .m68k,
2486 .mips,
2487 .mipsel,
2488 .mips64,
2489 .mips64el,
2490 .powerpc,
2491 .riscv64,
2492 .sparc,
2493 .sparc64,
2494 .x86,
2495 .x86_64,
2496 => init("/libexec/ld.elf_so"),
2497 else => none,
2498 },
24002499
2401 .openbsd => init("/usr/libexec/ld.so"),2500 .openbsd => switch (cpu.arch) {
2501 .arm,
2502 .thumb,
2503 .aarch64,
2504 .mips64,
2505 .mips64el,
2506 .powerpc,
2507 .powerpc64,
2508 .riscv64,
2509 .sparc64,
2510 .x86,
2511 .x86_64,
2512 => init("/usr/libexec/ld.so"),
2513 else => none,
2514 },
24022515
2403 .bridgeos,2516 .bridgeos => if (cpu.arch == .aarch64) init("/usr/lib/dyld") else none,
2404 .driverkit,2517 .driverkit,
2405 .ios,2518 .ios,
2406 .macos,2519 .macos,
2407 .tvos,2520 .tvos,
2408 .visionos,2521 .visionos,
2409 .watchos,2522 .watchos,
2410 => init("/usr/lib/dyld"),2523 => switch (cpu.arch) {
2524 .aarch64,
2525 .x86_64,
2526 => init("/usr/lib/dyld"),
2527 else => none,
2528 },
24112529
2412 .illumos,2530 .illumos,
2413 .solaris,2531 .solaris,
2414 => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64/" else ""}),2532 => switch (cpu.arch) {
2533 .sparc,
2534 .sparc64,
2535 .x86,
2536 .x86_64,
2537 => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, .none) == 64) "64/" else ""}),
2538 else => none,
2539 },
24152540
2416 // Operating systems in this list have been verified as not having a standard2541 // Operating systems in this list have been verified as not having a standard
2417 // dynamic linker path.2542 // dynamic linker path.
lib/std/zig/system.zig+28-20
...@@ -967,14 +967,15 @@ fn detectAbiAndDynamicLinker(...@@ -967,14 +967,15 @@ fn detectAbiAndDynamicLinker(
967 os: Target.Os,967 os: Target.Os,
968 query: Target.Query,968 query: Target.Query,
969) DetectError!Target {969) DetectError!Target {
970 const native_target_has_ld = comptime builtin.target.hasDynamicLinker();970 const native_target_has_ld = comptime Target.DynamicLinker.kind(builtin.os.tag) != .none;
971 const is_linux = builtin.target.os.tag == .linux;971 const is_linux = builtin.target.os.tag == .linux;
972 const is_solarish = builtin.target.os.tag.isSolarish();972 const is_solarish = builtin.target.os.tag.isSolarish();
973 const is_darwin = builtin.target.os.tag.isDarwin();
973 const have_all_info = query.dynamic_linker.get() != null and974 const have_all_info = query.dynamic_linker.get() != null and
974 query.abi != null and (!is_linux or query.abi.?.isGnu());975 query.abi != null and (!is_linux or query.abi.?.isGnu());
975 const os_is_non_native = query.os_tag != null;976 const os_is_non_native = query.os_tag != null;
976 // The Solaris/illumos environment is always the same.977 // The Solaris/illumos environment is always the same.
977 if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish) {978 if (!native_target_has_ld or have_all_info or os_is_non_native or is_solarish or is_darwin) {
978 return defaultAbiAndDynamicLinker(cpu, os, query);979 return defaultAbiAndDynamicLinker(cpu, os, query);
979 }980 }
980 if (query.abi) |abi| {981 if (query.abi) |abi| {
...@@ -999,26 +1000,33 @@ fn detectAbiAndDynamicLinker(...@@ -999,26 +1000,33 @@ fn detectAbiAndDynamicLinker(
999 };1000 };
1000 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;1001 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
1001 var ld_info_list_len: usize = 0;1002 var ld_info_list_len: usize = 0;
1002 const ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch);
1003
1004 for (all_abis) |abi| {
1005 // This may be a nonsensical parameter. We detect this with
1006 // error.UnknownDynamicLinkerPath and skip adding it to `ld_info_list`.
1007 const target: Target = .{
1008 .cpu = cpu,
1009 .os = os,
1010 .abi = abi,
1011 .ofmt = ofmt,
1012 };
1013 const ld = target.standardDynamicLinkerPath();
1014 if (ld.get() == null) continue;
10151003
1016 ld_info_list_buffer[ld_info_list_len] = .{1004 switch (Target.DynamicLinker.kind(os.tag)) {
1017 .ld = ld,1005 // The OS has no dynamic linker. Leave the list empty and rely on `Abi.default()` to pick
1018 .abi = abi,1006 // something sensible in `abiAndDynamicLinkerFromFile()`.
1019 };1007 .none => {},
1020 ld_info_list_len += 1;1008 // The OS has a system-wide dynamic linker. Unfortunately, this implies that there's no
1009 // useful ABI information that we can glean from it merely being present. That means the
1010 // best we can do for this case (for now) is also `Abi.default()`.
1011 .arch_os => {},
1012 // The OS can have different dynamic linker paths depending on libc/ABI. In this case, we
1013 // need to gather all the valid arch/OS/ABI combinations. `abiAndDynamicLinkerFromFile()`
1014 // will then look for a dynamic linker with a matching path on the system and pick the ABI
1015 // we associated it with here.
1016 .arch_os_abi => for (all_abis) |abi| {
1017 const ld = Target.DynamicLinker.standard(cpu, os, abi);
1018
1019 // Does the generated target triple actually have a standard dynamic linker path?
1020 if (ld.get() == null) continue;
1021
1022 ld_info_list_buffer[ld_info_list_len] = .{
1023 .ld = ld,
1024 .abi = abi,
1025 };
1026 ld_info_list_len += 1;
1027 },
1021 }1028 }
1029
1022 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];1030 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
10231031
1024 // Best case scenario: the executable is dynamically linked, and we can iterate1032 // Best case scenario: the executable is dynamically linked, and we can iterate
test/llvm_targets.zig+7
...@@ -249,10 +249,12 @@ const targets = [_]std.Target.Query{...@@ -249,10 +249,12 @@ const targets = [_]std.Target.Query{
249 .{ .cpu_arch = .s390x, .os_tag = .zos, .abi = .none },249 .{ .cpu_arch = .s390x, .os_tag = .zos, .abi = .none },
250250
251 .{ .cpu_arch = .sparc, .os_tag = .freestanding, .abi = .none },251 .{ .cpu_arch = .sparc, .os_tag = .freestanding, .abi = .none },
252 .{ .cpu_arch = .sparc, .os_tag = .illumos, .abi = .none },
252 .{ .cpu_arch = .sparc, .os_tag = .linux, .abi = .gnu },253 .{ .cpu_arch = .sparc, .os_tag = .linux, .abi = .gnu },
253 .{ .cpu_arch = .sparc, .os_tag = .linux, .abi = .none },254 .{ .cpu_arch = .sparc, .os_tag = .linux, .abi = .none },
254 .{ .cpu_arch = .sparc, .os_tag = .netbsd, .abi = .none },255 .{ .cpu_arch = .sparc, .os_tag = .netbsd, .abi = .none },
255 .{ .cpu_arch = .sparc, .os_tag = .rtems, .abi = .none },256 .{ .cpu_arch = .sparc, .os_tag = .rtems, .abi = .none },
257 .{ .cpu_arch = .sparc, .os_tag = .solaris, .abi = .none },
256258
257 .{ .cpu_arch = .sparc64, .os_tag = .freebsd, .abi = .none },259 .{ .cpu_arch = .sparc64, .os_tag = .freebsd, .abi = .none },
258 .{ .cpu_arch = .sparc64, .os_tag = .freestanding, .abi = .none },260 .{ .cpu_arch = .sparc64, .os_tag = .freestanding, .abi = .none },
...@@ -269,6 +271,9 @@ const targets = [_]std.Target.Query{...@@ -269,6 +271,9 @@ const targets = [_]std.Target.Query{
269 .{ .cpu_arch = .thumb, .os_tag = .freebsd, .abi = .eabihf },271 .{ .cpu_arch = .thumb, .os_tag = .freebsd, .abi = .eabihf },
270 .{ .cpu_arch = .thumb, .os_tag = .freestanding, .abi = .eabi },272 .{ .cpu_arch = .thumb, .os_tag = .freestanding, .abi = .eabi },
271 .{ .cpu_arch = .thumb, .os_tag = .freestanding, .abi = .eabihf },273 .{ .cpu_arch = .thumb, .os_tag = .freestanding, .abi = .eabihf },
274 .{ .cpu_arch = .thumb, .os_tag = .haiku, .abi = .eabi },
275 .{ .cpu_arch = .thumb, .os_tag = .haiku, .abi = .eabihf },
276 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .androideabi },
272 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .eabi },277 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .eabi },
273 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .eabihf },278 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .eabihf },
274 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .musleabi },279 .{ .cpu_arch = .thumb, .os_tag = .linux, .abi = .musleabi },
...@@ -314,6 +319,7 @@ const targets = [_]std.Target.Query{...@@ -314,6 +319,7 @@ const targets = [_]std.Target.Query{
314 .{ .cpu_arch = .x86, .os_tag = .freestanding, .abi = .none },319 .{ .cpu_arch = .x86, .os_tag = .freestanding, .abi = .none },
315 .{ .cpu_arch = .x86, .os_tag = .haiku, .abi = .none },320 .{ .cpu_arch = .x86, .os_tag = .haiku, .abi = .none },
316 .{ .cpu_arch = .x86, .os_tag = .hurd, .abi = .gnu },321 .{ .cpu_arch = .x86, .os_tag = .hurd, .abi = .gnu },
322 .{ .cpu_arch = .x86, .os_tag = .illumos, .abi = .none },
317 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .android },323 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .android },
318 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .gnu },324 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .gnu },
319 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .musl },325 .{ .cpu_arch = .x86, .os_tag = .linux, .abi = .musl },
...@@ -322,6 +328,7 @@ const targets = [_]std.Target.Query{...@@ -322,6 +328,7 @@ const targets = [_]std.Target.Query{
322 .{ .cpu_arch = .x86, .os_tag = .netbsd, .abi = .none },328 .{ .cpu_arch = .x86, .os_tag = .netbsd, .abi = .none },
323 .{ .cpu_arch = .x86, .os_tag = .openbsd, .abi = .none },329 .{ .cpu_arch = .x86, .os_tag = .openbsd, .abi = .none },
324 .{ .cpu_arch = .x86, .os_tag = .rtems, .abi = .none },330 .{ .cpu_arch = .x86, .os_tag = .rtems, .abi = .none },
331 .{ .cpu_arch = .x86, .os_tag = .solaris, .abi = .none },
325 .{ .cpu_arch = .x86, .os_tag = .uefi, .abi = .none },332 .{ .cpu_arch = .x86, .os_tag = .uefi, .abi = .none },
326 .{ .cpu_arch = .x86, .os_tag = .windows, .abi = .gnu },333 .{ .cpu_arch = .x86, .os_tag = .windows, .abi = .gnu },
327 .{ .cpu_arch = .x86, .os_tag = .windows, .abi = .itanium },334 .{ .cpu_arch = .x86, .os_tag = .windows, .abi = .itanium },