Commit 059f18855f
Changed files (1)
lib
std
lib/std/Target.zig
@@ -2054,209 +2054,237 @@ pub const DynamicLinker = struct {
};
}
+ /// The strictness of this function depends on the value of `kind(os.tag)`:
+ ///
+ /// * `.none`: Ignores all arguments and just returns `none`.
+ /// * `.arch_os`: Ignores `abi` and returns the dynamic linker matching `cpu` and `os`.
+ /// * `.arch_os_abi`: Returns the dynamic linker matching `cpu`, `os`, and `abi`.
+ ///
+ /// In the case of `.arch_os` in particular, callers should be aware that a valid dynamic linker
+ /// being returned only means that the `cpu` + `os` combination represents a platform that
+ /// actually exists and which has an established dynamic linker path that does not change with
+ /// the ABI; it does not necessarily mean that `abi` makes any sense at all for that platform.
+ /// The responsibility for determining whether `abi` is valid in this case rests with the
+ /// caller. `Abi.default()` can be used to pick a best-effort default ABI for such platforms.
pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker {
return switch (os.tag) {
- .fuchsia => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.
+ .fuchsia => switch (cpu.arch) {
+ .aarch64,
+ .riscv64,
+ .x86_64,
+ => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename.
+ else => none,
+ },
- .haiku => init("/system/runtime_loader"),
+ .haiku => switch (cpu.arch) {
+ .arm,
+ .thumb,
+ .aarch64,
+ .m68k,
+ .powerpc,
+ .riscv64,
+ .sparc64,
+ .x86,
+ .x86_64,
+ => init("/system/runtime_loader"),
+ else => none,
+ },
.hurd => switch (cpu.arch) {
.aarch64,
.aarch64_be,
=> |arch| initFmt("/lib/ld-{s}{s}.so.1", .{
@tagName(arch),
- if (abi == .gnuilp32) "_ilp32" else "",
+ switch (abi) {
+ .gnu => "",
+ .gnuilp32 => "_ilp32",
+ else => return none,
+ },
}),
- .x86 => init("/lib/ld.so.1"),
- .x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}),
+ .x86 => if (abi == .gnu) init("/lib/ld.so.1") else none,
+ .x86_64 => initFmt("/lib/ld-{s}.so.1", .{switch (abi) {
+ .gnu => "x86-64",
+ .gnux32 => "x32",
+ else => return none,
+ }}),
- // These are unsupported by Hurd/glibc.
- .amdgcn,
- .arc,
- .arm,
- .armeb,
- .thumb,
- .thumbeb,
- .avr,
- .bpfel,
- .bpfeb,
- .csky,
- .hexagon,
- .kalimba,
- .lanai,
- .loongarch32,
- .loongarch64,
- .m68k,
- .mips,
- .mipsel,
- .mips64,
- .mips64el,
- .msp430,
- .nvptx,
- .nvptx64,
- .powerpc,
- .powerpcle,
- .powerpc64,
- .powerpc64le,
- .propeller1,
- .propeller2,
- .riscv32,
- .riscv64,
- .s390x,
- .sparc,
- .sparc64,
- .spirv,
- .spirv32,
- .spirv64,
- .spu_2,
- .ve,
- .wasm32,
- .wasm64,
- .xcore,
- .xtensa,
- => none,
+ else => none,
},
.linux => if (abi.isAndroid())
- initFmt("/system/bin/linker{s}", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""})
+ switch (cpu.arch) {
+ .arm,
+ .thumb,
+ => if (abi == .androideabi) init("/system/bin/linker") else none,
+
+ .aarch64,
+ .riscv64,
+ .x86,
+ .x86_64,
+ => if (abi == .android) initFmt("/system/bin/linker{s}", .{
+ if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
+ }) else none,
+
+ else => none,
+ }
else if (abi.isMusl())
switch (cpu.arch) {
.arm,
.armeb,
.thumb,
.thumbeb,
+ => |arch| initFmt("/lib/ld-musl-arm{s}{s}.so.1", .{
+ if (arch == .armeb or arch == .thumbeb) "eb" else "",
+ switch (abi) {
+ .musleabi => "",
+ .musleabihf => "hf",
+ else => return none,
+ },
+ }),
+
.aarch64,
.aarch64_be,
- .loongarch64,
+ .loongarch64, // TODO: `-sp` and `-sf` ABI support in LLVM 20.
.m68k,
- .powerpc,
.powerpc64,
.powerpc64le,
- .riscv32,
- .riscv64,
.s390x,
- .x86,
- .x86_64,
- => |arch| initFmt("/lib/ld-musl-{s}{s}.so.1", .{
- switch (arch) {
- .thumb => "arm",
- .thumbeb => "armeb",
- .x86 => "i386",
- .x86_64 => if (abi == .muslx32) "x32" else "x86_64",
- else => @tagName(arch),
- },
- switch (arch) {
- .arm, .armeb, .thumb, .thumbeb => if (abi.floatAbi() == .hard) "hf" else "",
- .aarch64, .aarch64_be => if (abi == .gnuilp32) "_ilp32" else "",
- .riscv32, .riscv64 => if (std.Target.riscv.featureSetHas(cpu.features, .d))
- ""
- else if (std.Target.riscv.featureSetHas(cpu.features, .f))
- "-sp"
- else
- "-sf",
- else => if (abi.floatAbi() == .soft) "-sf" else "",
- },
- }),
+ => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}.so.1", .{@tagName(arch)}) else none,
- // The naming scheme for MIPS is a bit irregular.
.mips,
.mipsel,
+ => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
+ if (mips.featureSetHas(cpu.features, .mips32r6)) "r6" else "",
+ if (arch == .mipsel) "el" else "",
+ switch (abi) {
+ .musleabi => "-sf",
+ .musleabihf => "",
+ else => return none,
+ },
+ }),
+
.mips64,
.mips64el,
- => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{
- if (arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support in LLVM 20.
- if (mips.featureSetHas(cpu.features, if (arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "",
- if (arch.endian() == .little) "el" else "",
- if (abi.floatAbi() == .soft) "-sf" else "",
+ => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}.so.1", .{
+ // TODO: `n32` ABI support in LLVM 20.
+ switch (abi) {
+ .musl => "64",
+ else => return none,
+ },
+ if (mips.featureSetHas(cpu.features, .mips64r6)) "r6" else "",
+ if (arch == .mips64el) "el" else "",
}),
- // These are unsupported by musl.
- .amdgcn,
- .arc,
- .avr,
- .csky,
- .bpfel,
- .bpfeb,
- .hexagon,
- .kalimba,
- .lanai,
- .loongarch32,
- .msp430,
- .nvptx,
- .nvptx64,
- .powerpcle,
- .propeller1,
- .propeller2,
- .sparc,
- .sparc64,
- .spirv,
- .spirv32,
- .spirv64,
- .spu_2,
- .ve,
- .wasm32,
- .wasm64,
- .xcore,
- .xtensa,
- => none,
+ .powerpc => initFmt("/lib/ld-musl-powerpc{s}.so.1", .{switch (abi) {
+ .musleabi => "-sf",
+ .musleabihf => "",
+ else => return none,
+ }}),
+
+ .riscv32,
+ .riscv64,
+ => |arch| if (abi == .musl) initFmt("/lib/ld-musl-{s}{s}.so.1", .{
+ @tagName(arch),
+ if (riscv.featureSetHas(cpu.features, .d))
+ ""
+ else if (riscv.featureSetHas(cpu.features, .f))
+ "-sp"
+ else
+ "-sf",
+ }) else none,
+
+ .x86 => if (abi == .musl) init("/lib/ld-musl-i386.so.1") else none,
+ .x86_64 => initFmt("/lib/ld-musl-{s}.so.1", .{switch (abi) {
+ .musl => "x86_64",
+ .muslx32 => "x32",
+ else => return none,
+ }}),
+
+ else => none,
}
else if (abi.isGnu())
switch (cpu.arch) {
// TODO: `eb` architecture support.
// TODO: `700` ABI support.
- .arc => init("/lib/ld-linux-arc.so.2"),
+ .arc => if (abi == .gnu) init("/lib/ld-linux-arc.so.2") else none,
// TODO: OABI support (`/lib/ld-linux.so.2`).
.arm,
.armeb,
.thumb,
.thumbeb,
- => initFmt("/lib/ld-linux{s}.so.3", .{if (abi.floatAbi() == .hard) "-armhf" else ""}),
+ => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi) {
+ .gnueabi => "",
+ .gnueabihf => "-armhf",
+ else => return none,
+ }}),
.aarch64,
.aarch64_be,
=> |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{
@tagName(arch),
- if (abi == .gnuilp32) "_ilp32" else "",
+ switch (abi) {
+ .gnu => "",
+ .gnuilp32 => "_ilp32",
+ else => return none,
+ },
}),
// TODO: `-be` architecture support.
- .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}),
+ .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{switch (abi) {
+ .gnueabi => "",
+ .gnueabihf => "-hf",
+ else => return none,
+ }}),
.loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
+ .gnu => "lp64d",
.gnuf32 => "lp64f",
.gnusf => "lp64s",
- else => "lp64d",
+ else => return none,
}}),
- .m68k => init("/lib/ld.so.1"),
+ .m68k => if (abi == .gnu) init("/lib/ld.so.1") else none,
.mips,
.mipsel,
+ => switch (abi) {
+ .gnueabi,
+ .gnueabihf,
+ => initFmt("/lib/ld{s}.so.1", .{
+ if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
+ }),
+ else => none,
+ },
+
.mips64,
.mips64el,
=> initFmt("/lib{s}/ld{s}.so.1", .{
switch (abi) {
- .gnuabin32 => "32",
.gnuabi64 => "64",
- else => "",
+ .gnuabin32 => "32",
+ else => return none,
},
if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "",
}),
- .powerpc => init("/lib/ld.so.1"),
- // TODO: ELFv2 ABI opt-in support.
- .powerpc64 => init("/lib64/ld64.so.1"),
- .powerpc64le => init("/lib64/ld64.so.2"),
+ .powerpc => switch (abi) {
+ .gnueabi,
+ .gnueabihf,
+ => init("/lib/ld.so.1"),
+ else => none,
+ },
+ // TODO: ELFv2 ABI (`/lib64/ld64.so.2`) opt-in support.
+ .powerpc64 => if (abi == .gnu) init("/lib64/ld64.so.1") else none,
+ .powerpc64le => if (abi == .gnu) init("/lib64/ld64.so.2") else none,
.riscv32,
.riscv64,
- => |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{
- @tagName(arch),
+ => |arch| if (abi == .gnu) initFmt("/lib/ld-linux-{s}{s}.so.1", .{
switch (arch) {
- .riscv32 => "ilp32",
- .riscv64 => "lp64",
+ .riscv32 => "riscv32-ilp32",
+ .riscv64 => "riscv64-lp64",
else => unreachable,
},
if (riscv.featureSetHas(cpu.features, .d))
@@ -2265,78 +2293,130 @@ pub const DynamicLinker = struct {
"f"
else
"",
- }),
+ }) else none,
- .s390x => init("/lib/ld64.so.1"),
+ .s390x => if (abi == .gnu) init("/lib/ld64.so.1") else none,
- .sparc => init("/lib/ld-linux.so.2"),
- .sparc64 => init("/lib64/ld-linux.so.2"),
+ .sparc => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
+ .sparc64 => if (abi == .gnu) init("/lib64/ld-linux.so.2") else none,
- .x86 => init("/lib/ld-linux.so.2"),
- .x86_64 => init(if (abi == .gnux32) "/libx32/ld-linux-x32.so.2" else "/lib64/ld-linux-x86-64.so.2"),
+ .x86 => if (abi == .gnu) init("/lib/ld-linux.so.2") else none,
+ .x86_64 => switch (abi) {
+ .gnu => init("/lib64/ld-linux-x86-64.so.2"),
+ .gnux32 => init("/libx32/ld-linux-x32.so.2"),
+ else => none,
+ },
- .xtensa => init("/lib/ld.so.1"),
+ .xtensa => if (abi == .gnu) init("/lib/ld.so.1") else none,
- // These are unsupported by glibc.
- .amdgcn,
- .avr,
- .bpfeb,
- .bpfel,
- .hexagon,
- .kalimba,
- .lanai,
- .loongarch32,
- .msp430,
- .nvptx,
- .nvptx64,
- .powerpcle,
- .propeller1,
- .propeller2,
- .spirv,
- .spirv32,
- .spirv64,
- .spu_2,
- .ve,
- .wasm32,
- .wasm64,
- .xcore,
- => none,
+ else => none,
}
else
none, // Not a known Linux libc.
- .serenity => init("/usr/lib/Loader.so"),
+ .serenity => switch (cpu.arch) {
+ .aarch64,
+ .riscv64,
+ .x86_64,
+ => init("/usr/lib/Loader.so"),
+ else => none,
+ },
- .dragonfly => initFmt("{s}/libexec/ld-elf.so.2", .{
+ .dragonfly => if (cpu.arch == .x86_64) initFmt("{s}/libexec/ld-elf.so.2", .{
if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)
""
else
"/usr",
- }),
+ }) else none,
- .freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{
- if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
- ""
- else
- "/usr",
- }),
+ .freebsd => switch (cpu.arch) {
+ .arm,
+ .armeb,
+ .thumb,
+ .thumbeb,
+ .aarch64,
+ .mips,
+ .mipsel,
+ .mips64,
+ .mips64el,
+ .powerpc,
+ .powerpc64,
+ .powerpc64le,
+ .riscv64,
+ .sparc64,
+ .x86,
+ .x86_64,
+ => initFmt("{s}/libexec/ld-elf.so.1", .{
+ if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
+ ""
+ else
+ "/usr",
+ }),
+ else => none,
+ },
- .netbsd => init("/libexec/ld.elf_so"),
+ .netbsd => switch (cpu.arch) {
+ .arm,
+ .armeb,
+ .thumb,
+ .thumbeb,
+ .aarch64,
+ .aarch64_be,
+ .m68k,
+ .mips,
+ .mipsel,
+ .mips64,
+ .mips64el,
+ .powerpc,
+ .riscv64,
+ .sparc,
+ .sparc64,
+ .x86,
+ .x86_64,
+ => init("/libexec/ld.elf_so"),
+ else => none,
+ },
- .openbsd => init("/usr/libexec/ld.so"),
+ .openbsd => switch (cpu.arch) {
+ .arm,
+ .thumb,
+ .aarch64,
+ .mips64,
+ .mips64el,
+ .powerpc,
+ .powerpc64,
+ .riscv64,
+ .sparc64,
+ .x86,
+ .x86_64,
+ => init("/usr/libexec/ld.so"),
+ else => none,
+ },
- .bridgeos,
+ .bridgeos => if (cpu.arch == .aarch64) init("/usr/lib/dyld") else none,
.driverkit,
.ios,
.macos,
.tvos,
.visionos,
.watchos,
- => init("/usr/lib/dyld"),
+ => switch (cpu.arch) {
+ .aarch64,
+ .x86_64,
+ => init("/usr/lib/dyld"),
+ else => none,
+ },
.illumos,
.solaris,
- => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64/" else ""}),
+ => switch (cpu.arch) {
+ .sparc,
+ .sparc64,
+ .x86,
+ .x86_64,
+ => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, .none) == 64) "64/" else ""}),
+ else => none,
+ },
// Operating systems in this list have been verified as not having a standard
// dynamic linker path.