Skip to content

Commit

Permalink
std.Target: Rewrite DynamicLinker.standard() and fill in some missing…
Browse files Browse the repository at this point in the history
… details.
  • Loading branch information
alexrp committed Aug 13, 2024
1 parent b00f586 commit 4d9fc0a
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 102 deletions.
344 changes: 243 additions & 101 deletions lib/std/Target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1706,155 +1706,297 @@ 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 == .android) 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.

.haiku => init("/system/runtime_loader"),

.hurd => switch (cpu.arch) {
.aarch64,
.aarch64_be,
=> |t| initFmt("/lib/ld-{s}{s}.so.1", .{ @tagName(t), if (abi == .gnuilp32) "_ilp32" else "" }),

.aarch64 => init("/lib/ld-linux-aarch64.so.1"),
.aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"),
.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,
.dxil,
.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,
.riscv32,
.riscv64,
.s390x,
.sparc,
.sparc64,
.spirv,
.spirv32,
.spirv64,
=> 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,
.dxil,
.loongarch32,
.wasm32,
.wasm64,
.xcore,
.xtensa,
=> none,
},

.linux => if (abi == .android)
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,
=> initFmt("/lib/ld-musl-{s}{s}.so.1", .{
switch (cpu.arch) {
.thumb => "arm",
.thumbeb => "armeb",
.x86 => "i386",
.x86_64 => if (abi == .muslx32) "x32" else "x86_64",
else => |a| @tagName(a),
},
// TODO: `_ilp32` ABI support for AArch64.
// TODO: `-sp` ABI support for LoongArch/RISC-V.
switch (cpu.arch) {
.arm, .armeb, .thumb, .thumbeb => if (abi.floatAbi() == .hard) "hf" else "",
else => if (abi.floatAbi() == .soft) "-sf" else "",
},
}),

// The naming scheme for MIPS is a bit irregular.
.mips,
.mipsel,
.mips64,
.mips64el,
=> initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{
if (cpu.arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support.
if (mips.featureSetHas(cpu.features, if (cpu.arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "",
if (cpu.arch.endian() == .little) "el" else "",
if (abi.floatAbi() == .soft) "-sf" else "",
}),

// These are unsupported by musl.
.amdgcn,
.arc,
.avr,
.csky,
.bpfel,
.bpfeb,
.dxil,
.hexagon,
.kalimba,
.lanai,
.loongarch32,
.msp430,
.nvptx,
.nvptx64,
.powerpcle,
.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,
=> |t| initFmt("/lib/ld-linux-{s}{s}.so.1", .{ @tagName(t), if (abi == .gnuilp32) "_ilp32" else "" }),

// TODO: `-be` architecture support.
.csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}),

// TODO: `-lp64s` and `-lp64f` ABI support.
.loongarch64 => init("/lib64/ld-linux-loongarch-lp64d.so.1"),

.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"),

// TODO: `-ilp32`, `-ilp32f`, and `ilp32e` ABI support.
.riscv32 => init("/lib/ld-linux-riscv32-ilp32d.so.1"),
// TODO: `-lp64`, `-lp64f`, and `-lp64e` ABI support.
.riscv64 => init("/lib/ld-linux-riscv64-lp64d.so.1"),

.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,
.bpfel,
.bpfeb,
.dxil,
.hexagon,
.kalimba,
.lanai,
.loongarch32,
.msp430,
.nvptx,
.nvptx64,
.powerpcle,
.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.includesVersion(.{ .major = 3, .minor = 8, .patch = 0 })) "" else "/usr",
}),

.freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{
if (os.version_range.semver.includesVersion(.{ .major = 6, .minor = 0, .patch = 0 })) "" else "/usr",
}),

.netbsd => init("/libexec/ld.elf_so"),

.openbsd => init("/usr/libexec/ld.so"),

.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,
.shadermodel,
.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,
.driverkit,
.shadermodel,
=> 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 {
Expand Down
Loading

0 comments on commit 4d9fc0a

Please sign in to comment.