gollvm: add GOLLVM_DEFAULT_LINKER cmake option

Currently gold is the default linker if -fuse-ld option isn't specified.
But gold on linux arm64 has a problem, which makes gollvm can not be used
for static compilation. This CL works around this issue by adding the option
--eh-frame-hdr to the linker when linking statically.

This CL also added a cmake option GOLLVM_DEFAULT_LINKER, which can be used
to configure the default linker.

Change-Id: I79609efb015d94ab34e7b3f4b6fbd03bdf7ed757
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/232957
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/cmake/modules/AddGollvm.cmake b/cmake/modules/AddGollvm.cmake
index 6b4bb96..f5dd868 100644
--- a/cmake/modules/AddGollvm.cmake
+++ b/cmake/modules/AddGollvm.cmake
@@ -20,6 +20,7 @@
 set(GOLLVM_LIBVERSION "${libversion}")
 set(GOLLVM_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
 set(GOLLVM_INSTALL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${libsubdir}")
+set(GOLLVM_DEFAULT_LINKER "${LLVM_USE_LINKER}")
 
 # Check to see whether the build compiler supports -fcf-protection=branch
 set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
diff --git a/driver/GnuTools.cpp b/driver/GnuTools.cpp
index 8719a4a..2fb63a1 100644
--- a/driver/GnuTools.cpp
+++ b/driver/GnuTools.cpp
@@ -229,8 +229,14 @@
 {
   llvm::opt::ArgList &args = toolchain().driver().args();
 
+  // Currently ld.gold will not automatically add this option when linking
+  // staticly on arm64, resulting in the binary crash. The issue
+  // (https://sourceware.org/bugzilla/show_bug.cgi?id=25903) has not been
+  // fixed yet, for older versions of gold, add this option no matter static
+  // or dynamic link mode.
+  cmdArgs.push_back("--eh-frame-hdr");
+
   if (!args.hasArg(gollvm::options::OPT_static)) {
-    cmdArgs.push_back("--eh-frame-hdr");
     if (!args.hasArg(gollvm::options::OPT_shared)) {
       // NB: no support for --dyld-prefix= option
       const std::string Loader = toolchain().getDynamicLinker(args);
@@ -333,7 +339,11 @@
   // will always look for "ld.ABC" on the path. With clang, however,
   // you can supply a full path (e.g. "-fuse-ld=/my/path/to/ld"). This
   // code is intended to be consistent with clang.
+#ifdef GOLLVM_DEFAULT_LINKER
+  const char *variant = GOLLVM_DEFAULT_LINKER;
+#else
   const char *variant = "gold";
+#endif
   const char *linker = nullptr;
   llvm::opt::Arg *ldarg = args.getLastArg(gollvm::options::OPT_fuse_ld_EQ);
   const char *executable = nullptr;
diff --git a/driver/GollvmConfig.h.cmake b/driver/GollvmConfig.h.cmake
index debf707..b22caca 100644
--- a/driver/GollvmConfig.h.cmake
+++ b/driver/GollvmConfig.h.cmake
@@ -21,4 +21,7 @@
 // Compiler version. Same as library version currently.
 #define GOLLVM_COMPILERVERSION GOLLVM_LIBVERSION
 
+// Gollvm default linker
+#cmakedefine GOLLVM_DEFAULT_LINKER "@GOLLVM_DEFAULT_LINKER@"
+
 #endif // GOLLVM_CONFIG_H