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 {
20542054 };
20552055 }
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.
20572069 pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {
20582070 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
20632093 .hurd => switch (cpu.arch) {
20642094 .aarch64,
20652095 .aarch64_be,
20662096 => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{
20672097 @tagName(arch),
2068 if (abi == .gnuilp32) "_ilp32" else "",
2098 switch (abi) {
2099 .gnu => "",
2100 .gnuilp32 => "_ilp32",
2101 else => return none,
2102 },
20692103 }),
20702104
2071 .x86 => init("/lib/ld.so.1"),
2072 .x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}),
2105 .x86 => if (abi == .gnu) init("/lib/ld.so.1") else none,
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.
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,
2112 else => none,
21192113 },
21202114
21212115 .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 }
21232131 else if (abi.isMusl())
21242132 switch (cpu.arch) {
21252133 .arm,
21262134 .armeb,
21272135 .thumb,
21282136 .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
21292146 .aarch64,
21302147 .aarch64_be,
2131 .loongarch64,
2148 .loongarch64, // TODO: `-sp` and `-sf` ABI support in LLVM 20.
21322149 .m68k,
2133 .powerpc,
21342150 .powerpc64,
21352151 .powerpc64le,
2136 .riscv32,
2137 .riscv64,
21382152 .s390x,
2139 .x86,
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 }),
2153 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}.so.1", .{@tagName(arch)}) else none,
21612154
2162 // The naming scheme for MIPS is a bit irregular.
21632155 .mips,
21642156 .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
21652167 .mips64,
21662168 .mips64el,
2167 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{
2168 if (arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support in LLVM 20.
2169 if (mips.featureSetHas(cpu.features, if (arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "",
2170 if (arch.endian() == .little) "el" else "",
2171 if (abi.floatAbi() == .soft) "-sf" else "",
2169 => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
2170 // TODO: `n32` ABI support in LLVM 20.
2171 switch (abi) {
2172 .musl => "64",
2173 else => return none,
2174 },
2175 if (mips.featureSetHas(cpu.features, .mips64r6)) "r6" else "",
2176 if (arch == .mips64el) "el" else "",
21722177 }),
21732178
2174 // These are unsupported by musl.
2175 .amdgcn,
2176 .arc,
2177 .avr,
2178 .csky,
2179 .bpfel,
2180 .bpfeb,
2181 .hexagon,
2182 .kalimba,
2183 .lanai,
2184 .loongarch32,
2185 .msp430,
2186 .nvptx,
2187 .nvptx64,
2188 .powerpcle,
2189 .propeller1,
2190 .propeller2,
2191 .sparc,
2192 .sparc64,
2193 .spirv,
2194 .spirv32,
2195 .spirv64,
2196 .spu_2,
2197 .ve,
2198 .wasm32,
2199 .wasm64,
2200 .xcore,
2201 .xtensa,
2202 => none,
2179 .powerpc => initFmt("/lib/ld-musl-powerpc{s}.so.1", .{switch (abi) {
2180 .musleabi => "-sf",
2181 .musleabihf => "",
2182 else => return none,
2183 }}),
2184
2185 .riscv32,
2186 .riscv64,
2187 => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{
2188 @tagName(arch),
2189 if (riscv.featureSetHas(cpu.features, .d))
2190 ""
2191 else if (riscv.featureSetHas(cpu.features, .f))
2192 "-sp"
2193 else
2194 "-sf",
2195 }) else none,
2196
2197 .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none,
2198 .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) {
2199 .musl => "x86_64",
2200 .muslx32 => "x32",
2201 else => return none,
2202 }}),
2203
2204 else => none,
22032205 }
22042206 else if (abi.isGnu())
22052207 switch (cpu.arch) {
22062208 // TODO: `eb` architecture support.
22072209 // 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
22102212 // TODO: OABI support (`/lib/ld-linux.so.2`).
22112213 .arm,
22122214 .armeb,
22132215 .thumb,
22142216 .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
22172223 .aarch64,
22182224 .aarch64_be,
22192225 => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{
22202226 @tagName(arch),
2221 if (abi == .gnuilp32) "_ilp32" else "",
2227 switch (abi) {
2228 .gnu => "",
2229 .gnuilp32 => "_ilp32",
2230 else => return none,
2231 },
22222232 }),
22232233
22242234 // 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
22272241 .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
2242 .gnu => "lp64d",
22282243 .gnuf32 => "lp64f",
22292244 .gnusf => "lp64s",
2230 else => "lp64d",
2245 else => return none,
22312246 }}),
22322247
2233 .m68k => init("/lib/ld.so.1"),
2248 .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none,
22342249
22352250 .mips,
22362251 .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
22372261 .mips64,
22382262 .mips64el,
22392263 => initFmt("/lib{s}/ld{s}.so.1", .{
22402264 switch (abi) {
2241 .gnuabin32 => "32",
22422265 .gnuabi64 => "64",
2243 else => "",
2266 .gnuabin32 => "32",
2267 else => return none,
22442268 },
22452269 if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
22462270 }),
22472271
2248 .powerpc => init("/lib/ld.so.1"),
2249 // TODO: ELFv2 ABI opt-in support.
2250 .powerpc64 => init("/lib64/ld64.so.1"),
2251 .powerpc64le => init("/lib64/ld64.so.2"),
2272 .powerpc => switch (abi) {
2273 .gnueabi,
2274 .gnueabihf,
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
22532282 .riscv32,
22542283 .riscv64,
2255 => |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{
2256 @tagName(arch),
2284 => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{s}{s}.so.1", .{
22572285 switch (arch) {
2258 .riscv32 => "ilp32",
2259 .riscv64 => "lp64",
2286 .riscv32 => "riscv32-ilp32",
2287 .riscv64 => "riscv64-lp64",
22602288 else => unreachable,
22612289 },
22622290 if (riscv.featureSetHas(cpu.features, .d))
......@@ -2265,78 +2293,130 @@ pub const DynamicLinker = struct {
22652293 "f"
22662294 else
22672295 "",
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"),
2273 .sparc64 => init("/lib64/ld-linux.so.2"),
2300 .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
2301 .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none,
22742302
2275 .x86 => init("/lib/ld-linux.so.2"),
2276 .x86_64 => init(if (abi == .gnux32) "/libx32/ld-linux-x32.so.2" else "/lib64/ld-linux-x86-64.so.2"),
2303 .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
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.
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,
2312 else => none,
23042313 }
23052314 else
23062315 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", .{
23112326 if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)
23122327 ""
23132328 else
23142329 "/usr",
2315 }),
2330 }) else none,
23162331
2317 .freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{
2318 if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
2319 ""
2320 else
2321 "/usr",
2322 }),
2332 .freebsd => switch (cpu.arch) {
2333 .arm,
2334 .armeb,
2335 .thumb,
2336 .thumbeb,
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,
23292397 .driverkit,
23302398 .ios,
23312399 .macos,
23322400 .tvos,
23332401 .visionos,
23342402 .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
23372410 .illumos,
23382411 .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
23412421 // Operating systems in this list have been verified as not having a standard
23422422 // dynamic linker path.