authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-26 23:38:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2015-11-26 23:43:29-07:00
log4060ae93fb14b333166ff9d8ba880ff128989d31
tree747e54aadebde32d3824dd9604ff1d036612429c
parentbd5cb3e50e9f9a887cd23a24f8c766914a5c4496

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

2 files changed, 135 insertions(+), 6 deletions(-)

src/codegen.cpp+132-3
......@@ -17,6 +17,8 @@
1717#include <llvm/IR/DIBuilder.h>
1818#include <llvm/IR/DiagnosticInfo.h>
1919#include <llvm/IR/DiagnosticPrinter.h>
20#include <llvm/Target/TargetMachine.h>
21#include <llvm/Support/TargetParser.h>
2022
2123struct FnTableEntry {
2224 LLVMValueRef fn_value;
......@@ -66,6 +68,7 @@ struct CodeGen {
6668 bool strip_debug_symbols;
6769 CodeGenBuildType build_type;
6870 LLVMTargetMachineRef target_machine;
71 bool is_native_target;
6972 Buf in_file;
7073 Buf in_dir;
7174 ZigList<llvm::DIScope *> block_scopes;
......@@ -423,6 +426,7 @@ void semantic_analyze(CodeGen *g) {
423426 LLVMInitializeAllAsmParsers();
424427 LLVMInitializeNativeTarget();
425428
429 g->is_native_target = true;
426430 char *native_triple = LLVMGetDefaultTargetTriple();
427431
428432 LLVMTargetRef target_ref;
......@@ -699,6 +703,121 @@ ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) {
699703 return &g->errors;
700704}
701705
706enum FloatAbi {
707 FloatAbiHard,
708 FloatAbiSoft,
709 FloatAbiSoftFp,
710};
711
712
713static int get_arm_sub_arch_version(const llvm::Triple &triple) {
714 return llvm::ARMTargetParser::parseArchVersion(triple.getArchName());
715}
716
717static FloatAbi get_float_abi(const llvm::Triple &triple) {
718 switch (triple.getOS()) {
719 case llvm::Triple::Darwin:
720 case llvm::Triple::MacOSX:
721 case llvm::Triple::IOS:
722 if (get_arm_sub_arch_version(triple) == 6 ||
723 get_arm_sub_arch_version(triple) == 7)
724 {
725 return FloatAbiSoftFp;
726 } else {
727 return FloatAbiSoft;
728 }
729 case llvm::Triple::Win32:
730 return FloatAbiHard;
731 case llvm::Triple::FreeBSD:
732 switch (triple.getEnvironment()) {
733 case llvm::Triple::GNUEABIHF:
734 return FloatAbiHard;
735 default:
736 return FloatAbiSoft;
737 }
738 default:
739 switch (triple.getEnvironment()) {
740 case llvm::Triple::GNUEABIHF:
741 return FloatAbiHard;
742 case llvm::Triple::GNUEABI:
743 return FloatAbiSoftFp;
744 case llvm::Triple::EABIHF:
745 return FloatAbiHard;
746 case llvm::Triple::EABI:
747 return FloatAbiSoftFp;
748 case llvm::Triple::Android:
749 if (get_arm_sub_arch_version(triple) == 7) {
750 return FloatAbiSoftFp;
751 } else {
752 return FloatAbiSoft;
753 }
754 default:
755 return FloatAbiSoft;
756 }
757 }
758}
759
760static Buf *get_dynamic_linker(CodeGen *g) {
761 llvm::TargetMachine *target_machine = reinterpret_cast<llvm::TargetMachine*>(g->target_machine);
762 const llvm::Triple &triple = target_machine->getTargetTriple();
763
764 const llvm::Triple::ArchType arch = triple.getArch();
765
766 if (triple.getEnvironment() == llvm::Triple::Android) {
767 if (triple.isArch64Bit()) {
768 return buf_create_from_str("/system/bin/linker64");
769 } else {
770 return buf_create_from_str("/system/bin/linker");
771 }
772 } else if (arch == llvm::Triple::x86 ||
773 arch == llvm::Triple::sparc ||
774 arch == llvm::Triple::sparcel)
775 {
776 return buf_create_from_str("/lib/ld-linux.so.2");
777 } else if (arch == llvm::Triple::aarch64) {
778 return buf_create_from_str("/lib/ld-linux-aarch64.so.1");
779 } else if (arch == llvm::Triple::aarch64_be) {
780 return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1");
781 } else if (arch == llvm::Triple::arm || arch == llvm::Triple::thumb) {
782 if (triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
783 get_float_abi(triple) == FloatAbiHard)
784 {
785 return buf_create_from_str("/lib/ld-linux-armhf.so.3");
786 } else {
787 return buf_create_from_str("/lib/ld-linux.so.3");
788 }
789 } else if (arch == llvm::Triple::armeb || arch == llvm::Triple::thumbeb) {
790 if (triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
791 get_float_abi(triple) == FloatAbiHard)
792 {
793 return buf_create_from_str("/lib/ld-linux-armhf.so.3");
794 } else {
795 return buf_create_from_str("/lib/ld-linux.so.3");
796 }
797 } else if (arch == llvm::Triple::mips || arch == llvm::Triple::mipsel ||
798 arch == llvm::Triple::mips64 || arch == llvm::Triple::mips64el)
799 {
800 // when you want to solve this TODO, grep clang codebase for
801 // getLinuxDynamicLinker
802 zig_panic("TODO figure out MIPS dynamic linker name");
803 } else if (arch == llvm::Triple::ppc) {
804 return buf_create_from_str("/lib/ld.so.1");
805 } else if (arch == llvm::Triple::ppc64) {
806 return buf_create_from_str("/lib64/ld64.so.2");
807 } else if (arch == llvm::Triple::ppc64le) {
808 return buf_create_from_str("/lib64/ld64.so.2");
809 } else if (arch == llvm::Triple::systemz) {
810 return buf_create_from_str("/lib64/ld64.so.1");
811 } else if (arch == llvm::Triple::sparcv9) {
812 return buf_create_from_str("/lib64/ld-linux.so.2");
813 } else if (arch == llvm::Triple::x86_64 &&
814 triple.getEnvironment() == llvm::Triple::GNUX32)
815 {
816 return buf_create_from_str("/libx32/ld-linux-x32.so.2");
817 } else {
818 return buf_create_from_str("/lib64/ld-linux-x86-64.so.2");
819 }
820}
702821
703822void code_gen_link(CodeGen *g, const char *out_file) {
704823 LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry();
......@@ -721,13 +840,21 @@ void code_gen_link(CodeGen *g, const char *out_file) {
721840 if (g->is_static) {
722841 args.append("-static");
723842 }
724 if (getenv("ZIG_DEBIAN_HACK") != nullptr) {
725 // XXX: hack. see https://github.com/andrewrk/zig/issues/1
843
844 char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");
845 if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) {
846 if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) {
847 args.append("-dynamic-linker");
848 args.append(ZIG_NATIVE_DYNAMIC_LINKER);
849 }
850 } else {
726851 args.append("-dynamic-linker");
727 args.append("/lib64/ld-linux-x86-64.so.2");
852 args.append(buf_ptr(get_dynamic_linker(g)));
728853 }
854
729855 args.append("-o");
730856 args.append(out_file);
857
731858 args.append((const char *)buf_ptr(&out_file_o));
732859
733860 auto it = g->link_table.entry_iterator();
......@@ -742,3 +869,5 @@ void code_gen_link(CodeGen *g, const char *out_file) {
742869
743870 os_spawn_process("ld", args, false);
744871}
872
873
test/standalone.cpp+3-3
......@@ -102,9 +102,9 @@ static void run_test(TestCase *test_case) {
102102
103103 if (return_code != 0) {
104104 printf("\nProgram exited with return code %d:\n", return_code);
105 printf("zig");
106 for (int i = 0; i < test_case->compiler_args.length; i += 1) {
107 printf(" %s", test_case->compiler_args.at(i));
105 printf("%s", tmp_exe_path);
106 for (int i = 0; i < test_case->program_args.length; i += 1) {
107 printf(" %s", test_case->program_args.at(i));
108108 }
109109 printf("\n");
110110 printf("%s\n", buf_ptr(&program_stderr));