Merge pull request #21037 from alexrp/target-dyld

`std.Target`: Rewrite DynamicLinker.standard() and fill in some missing details.
This commit is contained in:
Alex Rønne Petersen
2024-10-06 09:17:57 +02:00
committed by GitHub
2 changed files with 277 additions and 101 deletions

View File

@@ -1768,156 +1768,332 @@ pub const DynamicLinker = struct {
return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]);
}
pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker {
return if (abi.isAndroid()) initFmt("/system/bin/linker{s}", .{
if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "",
}) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{
@tagName(switch (cpu.arch) {
.thumb => .arm,
.thumbeb => .armeb,
else => cpu.arch,
}),
if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "",
}) catch unreachable else switch (os_tag) {
.freebsd => init("/libexec/ld-elf.so.1"),
.netbsd => init("/libexec/ld.elf_so"),
.openbsd => init("/usr/libexec/ld.so"),
.dragonfly => init("/libexec/ld-elf.so.2"),
.solaris, .illumos => init("/lib/64/ld.so.1"),
.linux => switch (cpu.arch) {
.x86,
.sparc,
=> init("/lib/ld-linux.so.2"),
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.
.aarch64 => init("/lib/ld-linux-aarch64.so.1"),
.aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
.haiku => init("/system/runtime_loader"),
.hurd => switch (cpu.arch) {
.aarch64,
.aarch64_be,
=> |arch| initFmt("/lib/ld-{s}{s}.so.1", .{
@tagName(arch),
if (abi == .gnuilp32) "_ilp32" else "",
}),
.x86 => init("/lib/ld.so.1"),
.x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}),
// These are unsupported by Hurd/glibc.
.amdgcn,
.arc,
.arm,
.armeb,
.thumb,
.thumbeb,
=> initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) {
.hard => "-armhf",
else => "",
}}) catch unreachable,
.loongarch64 => init("/lib64/ld-linux-loongarch-lp64d.so.1"),
.avr,
.bpfel,
.bpfeb,
.csky,
.hexagon,
.kalimba,
.lanai,
.loongarch32,
.loongarch64,
.m68k,
.mips,
.mipsel,
.mips64,
.mips64el,
=> initFmt("/lib{s}/{s}", .{
switch (abi) {
.gnuabin32, .gnux32 => "32",
.gnuabi64 => "64",
else => "",
},
if (mips.featureSetHas(cpu.features, .nan2008))
"ld-linux-mipsn8.so.1"
else
"ld.so.1",
}) catch unreachable,
.powerpc, .powerpcle => init("/lib/ld.so.1"),
.powerpc64, .powerpc64le => init("/lib64/ld64.so.2"),
.s390x => init("/lib64/ld64.so.1"),
.sparc64 => init("/lib64/ld-linux.so.2"),
.x86_64 => init(switch (abi) {
.gnux32 => "/libx32/ld-linux-x32.so.2",
else => "/lib64/ld-linux-x86-64.so.2",
}),
.riscv32 => init("/lib/ld-linux-riscv32-ilp32d.so.1"),
.riscv64 => init("/lib/ld-linux-riscv64-lp64d.so.1"),
// Architectures in this list have been verified as not having a standard
// dynamic linker path.
.wasm32,
.wasm64,
.bpfel,
.bpfeb,
.msp430,
.nvptx,
.nvptx64,
.spu_2,
.avr,
.powerpc,
.powerpcle,
.powerpc64,
.powerpc64le,
.propeller1,
.propeller2,
.riscv32,
.riscv64,
.s390x,
.sparc,
.sparc64,
.spirv,
.spirv32,
.spirv64,
.propeller1,
.propeller2,
=> none,
// TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it.
.arc,
.csky,
.hexagon,
.m68k,
.msp430,
.amdgcn,
.xcore,
.kalimba,
.lanai,
.spu_2,
.ve,
.loongarch32,
.wasm32,
.wasm64,
.xcore,
.xtensa,
=> none,
},
.linux => if (abi.isAndroid())
initFmt("/system/bin/linker{s}", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""})
else if (abi.isMusl())
switch (cpu.arch) {
.arm,
.armeb,
.thumb,
.thumbeb,
.aarch64,
.aarch64_be,
.loongarch64,
.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 "",
},
}),
// The naming scheme for MIPS is a bit irregular.
.mips,
.mipsel,
.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 "",
}),
// 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,
}
else if (abi.isGnu())
switch (cpu.arch) {
// TODO: `eb` architecture support.
// TODO: `700` ABI support.
.arc => init("/lib/ld-linux-arc.so.2"),
// 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 ""}),
.aarch64,
.aarch64_be,
=> |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{
@tagName(arch),
if (abi == .gnuilp32) "_ilp32" else "",
}),
// TODO: `-be` architecture support.
.csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}),
.loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) {
.gnuf32 => "lp64f",
.gnusf => "lp64s",
else => "lp64d",
}}),
.m68k => init("/lib/ld.so.1"),
.mips,
.mipsel,
.mips64,
.mips64el,
=> initFmt("/lib{s}/ld{s}.so.1", .{
switch (abi) {
.gnuabin32 => "32",
.gnuabi64 => "64",
else => "",
},
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"),
.riscv32,
.riscv64,
=> |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{
@tagName(arch),
switch (arch) {
.riscv32 => "ilp32",
.riscv64 => "lp64",
else => unreachable,
},
if (riscv.featureSetHas(cpu.features, .d))
"d"
else if (riscv.featureSetHas(cpu.features, .f))
"f"
else
"",
}),
.s390x => init("/lib/ld64.so.1"),
.sparc => init("/lib/ld-linux.so.2"),
.sparc64 => init("/lib64/ld-linux.so.2"),
.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"),
.xtensa => init("/lib/ld.so.1"),
// 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, // Not a known Linux libc.
.serenity => init("/usr/lib/Loader.so"),
.dragonfly => initFmt("{s}/libexec/ld-elf.so.2", .{
if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false)
""
else
"/usr",
}),
.freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{
if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false)
""
else
"/usr",
}),
.netbsd => init("/libexec/ld.elf_so"),
.openbsd => init("/usr/libexec/ld.so"),
.bridgeos,
.driverkit,
.ios,
.tvos,
.watchos,
.macos,
.tvos,
.visionos,
.watchos,
=> init("/usr/lib/dyld"),
.serenity => init("/usr/lib/Loader.so"),
.illumos,
.solaris,
=> initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64/" else ""}),
// Operating systems in this list have been verified as not having a standard
// dynamic linker path.
.freestanding,
.other,
.contiki,
.elfiamcu,
.hermit,
.aix,
.plan9,
.rtems,
.zos,
.uefi,
.windows,
.emscripten,
.wasi,
.amdhsa,
.amdpal,
.cuda,
.mesa3d,
.nvcl,
.opencl,
.opengl,
.vulkan,
.other,
.plan9,
=> none,
// TODO revisit when multi-arch for Haiku is available
.haiku => init("/system/runtime_loader"),
// TODO go over each item in this list and either move it to the above list, or
// implement the standard dynamic linker path code for it.
.fuchsia,
.ps3,
.zos,
.rtems,
.aix,
.cuda,
.nvcl,
.amdhsa,
.ps4,
.ps5,
.elfiamcu,
.mesa3d,
.contiki,
.amdpal,
.hermit,
.hurd,
=> none,
};
} catch unreachable;
}
};
pub fn standardDynamicLinkerPath(target: Target) DynamicLinker {
return DynamicLinker.standard(target.cpu, target.os.tag, target.abi);
return DynamicLinker.standard(target.cpu, target.os, target.abi);
}
pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {

View File

@@ -1152,7 +1152,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer
.abi = abi,
.ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch),
.dynamic_linker = if (query.dynamic_linker.get() == null)
Target.DynamicLinker.standard(cpu, os.tag, abi)
Target.DynamicLinker.standard(cpu, os, abi)
else
query.dynamic_linker,
};