authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-07 00:52:02+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2024-10-26 22:00:49+02:00
log059f18855f18f9dd76f74031381e04dd131da528
tree991fdc0561ccf55da992a7bd8de5ee8c37eacd09
parent8818dc62131979cb29efe7a9f2a2ebd17583cd4a
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Target: Make DynamicLinker.standard() much stricter.

Its semantics are now documented in terms of DynamicLinker.kind(os.tag). The idea here is two-fold: * The term "standard" actually means something; we shouldn't return a valid dynamic linker path for a triple for which it hasn't *actually* been standardized. That's just incorrect. For example, previously, this function would happily return a path for x86_64-linux-androideabi, csky-macos-gnu, or aarch64-hurd-msvc, and other such obvious nonsense. * Callers that use the return value from this function to do host probing (such as std.zig.system.detectAbiAndDynamicLinker()) can now do so with greater confidence because DynamicLinker.standard() will eagerly reject nonsensical target triples.

1 files changed, 253 insertions(+), 173 deletions(-)

lib/std/Target.zig+253-173
...@@ -2054,209 +2054,237 @@ pub const DynamicLinker = struct {...@@ -2054,209 +2054,237 @@ pub const DynamicLinker = struct {
2054 };2054 };
2055 }2055 }
20562056
2057 /// The strictness of this function depends on the value of `kind(os.tag)`:
2058 ///
2059 /// * `.none`: Ignores all arguments and just returns `none`.
2060 /// * `.arch_os`: Ignores `abi` and returns the dynamic linker matching `cpu` and `os`.
2061 /// * `.arch_os_abi`: Returns the dynamic linker matching `cpu`, `os`, and `abi`.
2062 ///
2063 /// In the case of `.arch_os` in particular, callers should be aware that a valid dynamic linker
2064 /// being returned only means that the `cpu` + `os` combination represents a platform that
2065 /// actually exists and which has an established dynamic linker path that does not change with
2066 /// the ABI; it does not necessarily mean that `abi` makes any sense at all for that platform.
2067 /// The responsibility for determining whether `abi` is valid in this case rests with the
2068 /// caller. `Abi.default()` can be used to pick a best-effort default ABI for such platforms.
2057 pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {2069 pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {
2058 return switch (os.tag) {2070 return switch (os.tag) {
2059 .fuchsia => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.2071 .fuchsia => switch (cpu.arch) {
2072 .aarch64,
2073 .riscv64,
2074 .x86_64,
2075 => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.
2076 else => none,
2077 },
20602078
2061 .haiku => init("/system/runtime_loader"),2079 .haiku => switch (cpu.arch) {
2080 .arm,
2081 .thumb,
2082 .aarch64,
2083 .m68k,
2084 .powerpc,
2085 .riscv64,
2086 .sparc64,
2087 .x86,
2088 .x86_64,
2089 => init("/system/runtime_loader"),
2090 else => none,
2091 },
20622092
2063 .hurd => switch (cpu.arch) {2093 .hurd => switch (cpu.arch) {
2064 .aarch64,2094 .aarch64,
2065 .aarch64_be,2095 .aarch64_be,
2066 => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{2096 => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{
2067 @tagName(arch),2097 @tagName(arch),
2068 if (abi == .gnuilp32) "_ilp32" else "",2098 switch (abi) {
2099 .gnu => "",
2100 .gnuilp32 => "_ilp32",
2101 else => return none,
2102 },
2069 }),2103 }),
20702104
2071 .x86 => init("/lib/ld.so.1"),2105 .x86 => if (abi == .gnu) init("/lib/ld.so.1") else none,
2072 .x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}),2106 .x86_64 => initFmt("/lib/ld-{s}.so.1", .{switch (abi) {
2107 .gnu => "x86-64",
2108 .gnux32 => "x32",
2109 else => return none,
2110 }}),
20732111
2074 // These are unsupported by Hurd/glibc.2112 else => none,
2075 .amdgcn,
2076 .arc,
2077 .arm,
2078 .armeb,
2079 .thumb,
2080 .thumbeb,
2081 .avr,
2082 .bpfel,
2083 .bpfeb,
2084 .csky,
2085 .hexagon,
2086 .kalimba,
2087 .lanai,
2088 .loongarch32,
2089 .loongarch64,
2090 .m68k,
2091 .mips,
2092 .mipsel,
2093 .mips64,
2094 .mips64el,
2095 .msp430,
2096 .nvptx,
2097 .nvptx64,
2098 .powerpc,
2099 .powerpcle,
2100 .powerpc64,
2101 .powerpc64le,
2102 .propeller1,
2103 .propeller2,
2104 .riscv32,
2105 .riscv64,
2106 .s390x,
2107 .sparc,
2108 .sparc64,
2109 .spirv,
2110 .spirv32,
2111 .spirv64,
2112 .spu_2,
2113 .ve,
2114 .wasm32,
2115 .wasm64,
2116 .xcore,
2117 .xtensa,
2118 => none,
2119 },2113 },
21202114
2121 .linux => if (abi.isAndroid())2115 .linux => if (abi.isAndroid())
2122 initFmt("/system/bin/linker{s}", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""})2116 switch (cpu.arch) {
2117 .arm,
2118 .thumb,
2119 => if (abi == .androideabi) init("/system/bin/linker") else none,
2120
2121 .aarch64,
2122 .riscv64,
2123 .x86,
2124 .x86_64,
2125 => if (abi == .android) initFmt("/system/bin/linker{s}", .{
2126 if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
2127 }) else none,
2128
2129 else => none,
2130 }
2123 else if (abi.isMusl())2131 else if (abi.isMusl())
2124 switch (cpu.arch) {2132 switch (cpu.arch) {
2125 .arm,2133 .arm,
2126 .armeb,2134 .armeb,
2127 .thumb,2135 .thumb,
2128 .thumbeb,2136 .thumbeb,
2137 => |arch| initFmt("/lib/ld-musl-arm{s}{s}.so.1", .{
2138 if (arch == .armeb or arch == .thumbeb) "eb" else "",
2139 switch (abi) {
2140 .musleabi => "",
2141 .musleabihf => "hf",
2142 else => return none,
2143 },
2144 }),
2145
2129 .aarch64,2146 .aarch64,
2130 .aarch64_be,2147 .aarch64_be,
2131 .loongarch64,2148 .loongarch64, // TODO: `-sp` and `-sf` ABI support in LLVM 20.
2132 .m68k,2149 .m68k,
2133 .powerpc,
2134 .powerpc64,2150 .powerpc64,
2135 .powerpc64le,2151 .powerpc64le,
2136 .riscv32,
2137 .riscv64,
2138 .s390x,2152 .s390x,
2139 .x86,2153 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}.so.1", .{@tagName(arch)}) else none,
2140 .x86_64,
2141 => |arch| initFmt("/lib/ld-musl-{s}{s}.so.1", .{
2142 switch (arch) {
2143 .thumb => "arm",
2144 .thumbeb => "armeb",
2145 .x86 => "i386",
2146 .x86_64 => if (abi == .muslx32) "x32" else "x86_64",
2147 else => @tagName(arch),
2148 },
2149 switch (arch) {
2150 .arm, .armeb, .thumb, .thumbeb => if (abi.floatAbi() == .hard) "hf" else "",
2151 .aarch64, .aarch64_be => if (abi == .gnuilp32) "_ilp32" else "",
2152 .riscv32, .riscv64 => if (std.Target.riscv.featureSetHas(cpu.features, .d))
2153 ""
2154 else if (std.Target.riscv.featureSetHas(cpu.features, .f))
2155 "-sp"
2156 else
2157 "-sf",
2158 else => if (abi.floatAbi() == .soft) "-sf" else "",
2159 },
2160 }),
21612154
2162 // The naming scheme for MIPS is a bit irregular.
2163 .mips,2155 .mips,
2164 .mipsel,2156 .mipsel,
2157 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
2158 if (mips.featureSetHas(cpu.features, .mips32r6)) "r6" else "",
2159 if (arch == .mipsel) "el" else "",
2160 switch (abi) {
2161 .musleabi => "-sf",
2162 .musleabihf => "",
2163 else => return none,
2164 },
2165 }),
2166
2165 .mips64,2167 .mips64,
2166 .mips64el,2168 .mips64el,
2167 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{2169 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
2168 if (arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support in LLVM 20.2170 // TODO: `n32` ABI support in LLVM 20.
2169 if (mips.featureSetHas(cpu.features, if (arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "",2171 switch (abi) {
2170 if (arch.endian() == .little) "el" else "",2172 .musl => "64",
2171 if (abi.floatAbi() == .soft) "-sf" else "",2173 else => return none,
2174 },
2175 if (mips.featureSetHas(cpu.features, .mips64r6)) "r6" else "",
2176 if (arch == .mips64el) "el" else "",
2172 }),2177 }),
21732178
2174 // These are unsupported by musl.2179 .powerpc => initFmt("/lib/ld-musl-powerpc{s}.so.1", .{switch (abi) {
2175 .amdgcn,2180 .musleabi => "-sf",
2176 .arc,2181 .musleabihf => "",
2177 .avr,2182 else => return none,
2178 .csky,2183 }}),
2179 .bpfel,2184
2180 .bpfeb,2185 .riscv32,
2181 .hexagon,2186 .riscv64,
2182 .kalimba,2187 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{
2183 .lanai,2188 @tagName(arch),
2184 .loongarch32,2189 if (riscv.featureSetHas(cpu.features, .d))
2185 .msp430,2190 ""
2186 .nvptx,2191 else if (riscv.featureSetHas(cpu.features, .f))
2187 .nvptx64,2192 "-sp"
2188 .powerpcle,2193 else
2189 .propeller1,2194 "-sf",
2190 .propeller2,2195 }) else none,
2191 .sparc,2196
2192 .sparc64,2197 .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none,
2193 .spirv,2198 .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) {
2194 .spirv32,2199 .musl => "x86_64",
2195 .spirv64,2200 .muslx32 => "x32",
2196 .spu_2,2201 else => return none,
2197 .ve,2202 }}),
2198 .wasm32,2203
2199 .wasm64,2204 else => none,
2200 .xcore,
2201 .xtensa,
2202 => none,
2203 }2205 }
2204 else if (abi.isGnu())2206 else if (abi.isGnu())
2205 switch (cpu.arch) {2207 switch (cpu.arch) {
2206 // TODO: `eb` architecture support.2208 // TODO: `eb` architecture support.
2207 // TODO: `700` ABI support.2209 // TODO: `700` ABI support.
2208 .arc => init("/lib/ld-linux-arc.so.2"),2210 .arc => if (abi == .gnu) init("/lib/ld-linux-arc.so.2") else none,
22092211
2210 // TODO: OABI support (`/lib/ld-linux.so.2`).2212 // TODO: OABI support (`/lib/ld-linux.so.2`).
2211 .arm,2213 .arm,
2212 .armeb,2214 .armeb,
2213 .thumb,2215 .thumb,
2214 .thumbeb,2216 .thumbeb,
2215 => initFmt("/lib/ld-linux{s}.so.3", .{if (abi.floatAbi() == .hard) "-armhf" else ""}),2217 => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi) {
2218 .gnueabi => "",
2219 .gnueabihf => "-armhf",
2220 else => return none,
2221 }}),
22162222
2217 .aarch64,2223 .aarch64,
2218 .aarch64_be,2224 .aarch64_be,
2219 => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{2225 => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{
2220 @tagName(arch),2226 @tagName(arch),
2221 if (abi == .gnuilp32) "_ilp32" else "",2227 switch (abi) {
2228 .gnu => "",
2229 .gnuilp32 => "_ilp32",
2230 else => return none,
2231 },
2222 }),2232 }),
22232233
2224 // TODO: `-be` architecture support.2234 // TODO: `-be` architecture support.
2225 .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}),2235 .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{switch (abi) {
2236 .gnueabi => "",
2237 .gnueabihf => "-hf",
2238 else => return none,
2239 }}),
22262240
2227 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {2241 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
2242 .gnu => "lp64d",
2228 .gnuf32 => "lp64f",2243 .gnuf32 => "lp64f",
2229 .gnusf => "lp64s",2244 .gnusf => "lp64s",
2230 else => "lp64d",2245 else => return none,
2231 }}),2246 }}),
22322247
2233 .m68k => init("/lib/ld.so.1"),2248 .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none,
22342249
2235 .mips,2250 .mips,
2236 .mipsel,2251 .mipsel,
2252 => switch (abi) {
2253 .gnueabi,
2254 .gnueabihf,
2255 => initFmt("/lib/ld{s}.so.1", .{
2256 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
2257 }),
2258 else => none,
2259 },
2260
2237 .mips64,2261 .mips64,
2238 .mips64el,2262 .mips64el,
2239 => initFmt("/lib{s}/ld{s}.so.1", .{2263 => initFmt("/lib{s}/ld{s}.so.1", .{
2240 switch (abi) {2264 switch (abi) {
2241 .gnuabin32 => "32",
2242 .gnuabi64 => "64",2265 .gnuabi64 => "64",
2243 else => "",2266 .gnuabin32 => "32",
2267 else => return none,
2244 },2268 },
2245 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",2269 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
2246 }),2270 }),
22472271
2248 .powerpc => init("/lib/ld.so.1"),2272 .powerpc => switch (abi) {
2249 // TODO: ELFv2 ABI opt-in support.2273 .gnueabi,
2250 .powerpc64 => init("/lib64/ld64.so.1"),2274 .gnueabihf,
2251 .powerpc64le => init("/lib64/ld64.so.2"),2275 => init("/lib/ld.so.1"),
2276 else => none,
2277 },
2278 // TODO: ELFv2 ABI (`/lib64/ld64.so.2`) opt-in support.
2279 .powerpc64 => if (abi == .gnu) init("/lib64/ld64.so.1") else none,
2280 .powerpc64le => if (abi == .gnu) init("/lib64/ld64.so.2") else none,
22522281
2253 .riscv32,2282 .riscv32,
2254 .riscv64,2283 .riscv64,
2255 => |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{2284 => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{s}{s}.so.1", .{
2256 @tagName(arch),
2257 switch (arch) {2285 switch (arch) {
2258 .riscv32 => "ilp32",2286 .riscv32 => "riscv32-ilp32",
2259 .riscv64 => "lp64",2287 .riscv64 => "riscv64-lp64",
2260 else => unreachable,2288 else => unreachable,
2261 },2289 },
2262 if (riscv.featureSetHas(cpu.features, .d))2290 if (riscv.featureSetHas(cpu.features, .d))
...@@ -2265,78 +2293,130 @@ pub const DynamicLinker = struct {...@@ -2265,78 +2293,130 @@ pub const DynamicLinker = struct {
2265 "f"2293 "f"
2266 else2294 else
2267 "",2295 "",
2268 }),2296 }) else none,
22692297
2270 .s390x => init("/lib/ld64.so.1"),2298 .s390x => if (abi == .gnu) init("/lib/ld64.so.1") else none,
22712299
2272 .sparc => init("/lib/ld-linux.so.2"),2300 .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
2273 .sparc64 => init("/lib64/ld-linux.so.2"),2301 .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none,
22742302
2275 .x86 => init("/lib/ld-linux.so.2"),2303 .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
2276 .x86_64 => init(if (abi == .gnux32) "/libx32/ld-linux-x32.so.2" else "/lib64/ld-linux-x86-64.so.2"),2304 .x86_64 => switch (abi) {
2305 .gnu => init("/lib64/ld-linux-x86-64.so.2"),
2306 .gnux32 => init("/libx32/ld-linux-x32.so.2"),
2307 else => none,
2308 },
22772309
2278 .xtensa => init("/lib/ld.so.1"),2310 .xtensa => if (abi == .gnu) init("/lib/ld.so.1") else none,
22792311
2280 // These are unsupported by glibc.2312 else => none,
2281 .amdgcn,
2282 .avr,
2283 .bpfeb,
2284 .bpfel,
2285 .hexagon,
2286 .kalimba,
2287 .lanai,
2288 .loongarch32,
2289 .msp430,
2290 .nvptx,
2291 .nvptx64,
2292 .powerpcle,
2293 .propeller1,
2294 .propeller2,
2295 .spirv,
2296 .spirv32,
2297 .spirv64,
2298 .spu_2,
2299 .ve,
2300 .wasm32,
2301 .wasm64,
2302 .xcore,
2303 => none,
2304 }2313 }
2305 else2314 else
2306 none, // Not a known Linux libc.2315 none, // Not a known Linux libc.
23072316
2308 .serenity => init("/usr/lib/Loader.so"),2317 .serenity => switch (cpu.arch) {
2318 .aarch64,
2319 .riscv64,
2320 .x86_64,
2321 => init("/usr/lib/Loader.so"),
2322 else => none,
2323 },
23092324
2310 .dragonfly => initFmt("{s}/libexec/ld-elf.so.2", .{2325 .dragonfly => if (cpu.arch == .x86_64) initFmt("{s}/libexec/ld-elf.so.2", .{
2311 if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)2326 if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)
2312 ""2327 ""
2313 else2328 else
2314 "/usr",2329 "/usr",
2315 }),2330 }) else none,
23162331
2317 .freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{2332 .freebsd => switch (cpu.arch) {
2318 if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)2333 .arm,
2319 ""2334 .armeb,
2320 else2335 .thumb,
2321 "/usr",2336 .thumbeb,
2322 }),2337 .aarch64,
2338 .mips,
2339 .mipsel,
2340 .mips64,
2341 .mips64el,
2342 .powerpc,
2343 .powerpc64,
2344 .powerpc64le,
2345 .riscv64,
2346 .sparc64,
2347 .x86,
2348 .x86_64,
2349 => initFmt("{s}/libexec/ld-elf.so.1", .{
2350 if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
2351 ""
2352 else
2353 "/usr",
2354 }),
2355 else => none,
2356 },
23232357
2324 .netbsd => init("/libexec/ld.elf_so"),2358 .netbsd => switch (cpu.arch) {
2359 .arm,
2360 .armeb,
2361 .thumb,
2362 .thumbeb,
2363 .aarch64,
2364 .aarch64_be,
2365 .m68k,
2366 .mips,
2367 .mipsel,
2368 .mips64,
2369 .mips64el,
2370 .powerpc,
2371 .riscv64,
2372 .sparc,
2373 .sparc64,
2374 .x86,
2375 .x86_64,
2376 => init("/libexec/ld.elf_so"),
2377 else => none,
2378 },
23252379
2326 .openbsd => init("/usr/libexec/ld.so"),2380 .openbsd => switch (cpu.arch) {
2381 .arm,
2382 .thumb,
2383 .aarch64,
2384 .mips64,
2385 .mips64el,
2386 .powerpc,
2387 .powerpc64,
2388 .riscv64,
2389 .sparc64,
2390 .x86,
2391 .x86_64,
2392 => init("/usr/libexec/ld.so"),
2393 else => none,
2394 },
23272395
2328 .bridgeos,2396 .bridgeos => if (cpu.arch == .aarch64) init("/usr/lib/dyld") else none,
2329 .driverkit,2397 .driverkit,
2330 .ios,2398 .ios,
2331 .macos,2399 .macos,
2332 .tvos,2400 .tvos,
2333 .visionos,2401 .visionos,
2334 .watchos,2402 .watchos,
2335 => init("/usr/lib/dyld"),2403 => switch (cpu.arch) {
2404 .aarch64,
2405 .x86_64,
2406 => init("/usr/lib/dyld"),
2407 else => none,
2408 },
23362409
2337 .illumos,2410 .illumos,
2338 .solaris,2411 .solaris,
2339 => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64/" else ""}),2412 => switch (cpu.arch) {
2413 .sparc,
2414 .sparc64,
2415 .x86,
2416 .x86_64,
2417 => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, .none) == 64) "64/" else ""}),
2418 else => none,
2419 },
23402420
2341 // Operating systems in this list have been verified as not having a standard2421 // Operating systems in this list have been verified as not having a standard
2342 // dynamic linker path.2422 // dynamic linker path.