From 6215e47e9dad67bcf0f09d0a27a42650b4861e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Sat, 10 Aug 2024 18:00:36 +0200 Subject: [PATCH] std.Target: Rewrite DynamicLinker.standard() and fill in some missing details. --- lib/std/Target.zig | 352 +++++++++++++++++++++++++++++------------ lib/std/zig/system.zig | 2 +- 2 files changed, 255 insertions(+), 99 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index a231892e6e31..99f295e2e22a 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1719,155 +1719,311 @@ 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, }, .driverkit, .ios, + .macos, .tvos, + .visionos, .watchos, + => init("/usr/lib/dyld"), + + .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.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"), + + .driverkit, + .ios, .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, - .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 { diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 92058fbf3b7f..21d9d04cec51 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -1140,7 +1140,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, };