From 4060ae93fb14b333166ff9d8ba880ff128989d31 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 26 Nov 2015 23:38:26 -0700 Subject: call ld with correct -dynamic-linker argument It looks like Debian/Ubuntu are doing it correctly. See https://sourceware.org/glibc/wiki/ABIList NixOS has a clang patch which disables adding the -dynamic-linker argument to ld in order to ensure "purity" - that is - that all paths are in /nix/store/*. See https://github.com/NixOS/nixpkgs/blob/6b1651928e943bdb0d69a20764fdaae294e92dc1/pkgs/development/compilers/llvm/3.7/clang/purity.patch So, I changed the environment variable to ZIG_NATIVE_DYNAMIC_LINKER and allow it to be set to blank. And it only matters when building for the native target, since you might want to build for other targets without modifying your environment. closes #1 --- src/codegen.cpp | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 132 insertions(+), 3 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 26c189a4e9..0cf60fe66b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include struct FnTableEntry { LLVMValueRef fn_value; @@ -66,6 +68,7 @@ struct CodeGen { bool strip_debug_symbols; CodeGenBuildType build_type; LLVMTargetMachineRef target_machine; + bool is_native_target; Buf in_file; Buf in_dir; ZigList block_scopes; @@ -423,6 +426,7 @@ void semantic_analyze(CodeGen *g) { LLVMInitializeAllAsmParsers(); LLVMInitializeNativeTarget(); + g->is_native_target = true; char *native_triple = LLVMGetDefaultTargetTriple(); LLVMTargetRef target_ref; @@ -699,6 +703,121 @@ ZigList *codegen_error_messages(CodeGen *g) { return &g->errors; } +enum FloatAbi { + FloatAbiHard, + FloatAbiSoft, + FloatAbiSoftFp, +}; + + +static int get_arm_sub_arch_version(const llvm::Triple &triple) { + return llvm::ARMTargetParser::parseArchVersion(triple.getArchName()); +} + +static FloatAbi get_float_abi(const llvm::Triple &triple) { + switch (triple.getOS()) { + case llvm::Triple::Darwin: + case llvm::Triple::MacOSX: + case llvm::Triple::IOS: + if (get_arm_sub_arch_version(triple) == 6 || + get_arm_sub_arch_version(triple) == 7) + { + return FloatAbiSoftFp; + } else { + return FloatAbiSoft; + } + case llvm::Triple::Win32: + return FloatAbiHard; + case llvm::Triple::FreeBSD: + switch (triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + return FloatAbiHard; + default: + return FloatAbiSoft; + } + default: + switch (triple.getEnvironment()) { + case llvm::Triple::GNUEABIHF: + return FloatAbiHard; + case llvm::Triple::GNUEABI: + return FloatAbiSoftFp; + case llvm::Triple::EABIHF: + return FloatAbiHard; + case llvm::Triple::EABI: + return FloatAbiSoftFp; + case llvm::Triple::Android: + if (get_arm_sub_arch_version(triple) == 7) { + return FloatAbiSoftFp; + } else { + return FloatAbiSoft; + } + default: + return FloatAbiSoft; + } + } +} + +static Buf *get_dynamic_linker(CodeGen *g) { + llvm::TargetMachine *target_machine = reinterpret_cast(g->target_machine); + const llvm::Triple &triple = target_machine->getTargetTriple(); + + const llvm::Triple::ArchType arch = triple.getArch(); + + if (triple.getEnvironment() == llvm::Triple::Android) { + if (triple.isArch64Bit()) { + return buf_create_from_str("/system/bin/linker64"); + } else { + return buf_create_from_str("/system/bin/linker"); + } + } else if (arch == llvm::Triple::x86 || + arch == llvm::Triple::sparc || + arch == llvm::Triple::sparcel) + { + return buf_create_from_str("/lib/ld-linux.so.2"); + } else if (arch == llvm::Triple::aarch64) { + return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); + } else if (arch == llvm::Triple::aarch64_be) { + return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); + } else if (arch == llvm::Triple::arm || arch == llvm::Triple::thumb) { + if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || + get_float_abi(triple) == FloatAbiHard) + { + return buf_create_from_str("/lib/ld-linux-armhf.so.3"); + } else { + return buf_create_from_str("/lib/ld-linux.so.3"); + } + } else if (arch == llvm::Triple::armeb || arch == llvm::Triple::thumbeb) { + if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || + get_float_abi(triple) == FloatAbiHard) + { + return buf_create_from_str("/lib/ld-linux-armhf.so.3"); + } else { + return buf_create_from_str("/lib/ld-linux.so.3"); + } + } else if (arch == llvm::Triple::mips || arch == llvm::Triple::mipsel || + arch == llvm::Triple::mips64 || arch == llvm::Triple::mips64el) + { + // when you want to solve this TODO, grep clang codebase for + // getLinuxDynamicLinker + zig_panic("TODO figure out MIPS dynamic linker name"); + } else if (arch == llvm::Triple::ppc) { + return buf_create_from_str("/lib/ld.so.1"); + } else if (arch == llvm::Triple::ppc64) { + return buf_create_from_str("/lib64/ld64.so.2"); + } else if (arch == llvm::Triple::ppc64le) { + return buf_create_from_str("/lib64/ld64.so.2"); + } else if (arch == llvm::Triple::systemz) { + return buf_create_from_str("/lib64/ld64.so.1"); + } else if (arch == llvm::Triple::sparcv9) { + return buf_create_from_str("/lib64/ld-linux.so.2"); + } else if (arch == llvm::Triple::x86_64 && + triple.getEnvironment() == llvm::Triple::GNUX32) + { + return buf_create_from_str("/libx32/ld-linux-x32.so.2"); + } else { + return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); + } +} void code_gen_link(CodeGen *g, const char *out_file) { LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry(); @@ -721,13 +840,21 @@ void code_gen_link(CodeGen *g, const char *out_file) { if (g->is_static) { args.append("-static"); } - if (getenv("ZIG_DEBIAN_HACK") != nullptr) { - // XXX: hack. see https://github.com/andrewrk/zig/issues/1 + + char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER"); + if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) { + if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) { + args.append("-dynamic-linker"); + args.append(ZIG_NATIVE_DYNAMIC_LINKER); + } + } else { args.append("-dynamic-linker"); - args.append("/lib64/ld-linux-x86-64.so.2"); + args.append(buf_ptr(get_dynamic_linker(g))); } + args.append("-o"); args.append(out_file); + args.append((const char *)buf_ptr(&out_file_o)); auto it = g->link_table.entry_iterator(); @@ -742,3 +869,5 @@ void code_gen_link(CodeGen *g, const char *out_file) { os_spawn_process("ld", args, false); } + + -- cgit v1.2.3