mgorny created this revision.
mgorny added a reviewer: EricWF.
mgorny added a subscriber: cfe-commits.
Herald added subscribers: mgorny, beanz.

Include an appropriate unwinder library (-lunwind or -lgcc_s) when constructing 
a linker script for libc++. This is necessary since otherwise clang++ set for 
pure LLVM stack (compiler-rt + libc++) does not link against -lgcc_s and 
linking any C++ program fails due to missing unwinder symbols.

In order to handle additional libraries, the linker script generator has been 
modified to accept any number of libraries as the second argument. The ABI 
library name check has been removed as it is redundant to the checks done in 
CMake, and additional check for empty SCRIPT_ABI_LIBNAME has been added in 
CMake (the empty value resulted in wrong usage error in the script before).

The change has been tested with all four C++ ABI library variants. In each 
case, clang++ failed to link a simple "Hello world" program without either of 
the unwinder libraries.


https://reviews.llvm.org/D25008

Files:
  lib/CMakeLists.txt
  utils/gen_link_script/gen_link_script.py

Index: utils/gen_link_script/gen_link_script.py
===================================================================
--- utils/gen_link_script/gen_link_script.py
+++ utils/gen_link_script/gen_link_script.py
@@ -16,23 +16,24 @@
     sys.exit(1)
 
 def usage_and_exit():
-    print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] 
<path/to/libcxx.so> <abi_libname>")
+    print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] 
<path/to/libcxx.so> <libs>")
 
 def help_and_exit():
     help_msg = \
 """Usage
 
-  gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <abi_libname>
+  gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <libs>
 
-  Generate a linker script that links libc++ to the proper ABI library.
+  Generate a linker script that links libc++ to the proper ABI library
+  (and other dependant libraries).
   The script replaces the specified libc++ symlink.
   An example script for c++abi would look like "INPUT(libc++.so.1 -lc++abi)".
 
 Arguments
   <path/to/libcxx.so> - The top level symlink to the versioned libc++ shared
                         library. This file is replaced with a linker script.
-  <abi_libname>       - The name of the ABI library to use in the linker 
script.
-                        The name must be one of [c++abi, stdc++, supc++, 
cxxrt].
+  <libs>              - The list of libraries (-l flags) to use in the linker
+                        script.
 
 Exit Status:
   0 if OK,
@@ -53,28 +54,22 @@
     if len(args) != 2:
         usage_and_exit()
     symlink_file = args[0]
-    abi_libname = args[1]
-    return dryrun, symlink_file, abi_libname
+    abi_libs = args[1]
+    return dryrun, symlink_file, abi_libs
 
 def main():
-    dryrun, symlink_file, abi_libname = parse_args()
+    dryrun, symlink_file, abi_libs = parse_args()
 
     # Check that the given libc++.so file is a valid symlink.
     if not os.path.islink(symlink_file):
         print_and_exit("symlink file %s is not a symlink" % symlink_file)
 
     # Read the symlink so we know what libc++ to link to in the linker script.
     linked_libcxx = os.readlink(symlink_file)
 
-    # Check that the abi_libname is one of the supported values.
-    supported_abi_list = ['c++abi', 'stdc++', 'supc++', 'cxxrt']
-    if abi_libname not in supported_abi_list:
-        print_and_exit("abi name '%s' is not supported: Use one of %r" %
-                        (abi_libname, supported_abi_list))
-
     # Generate the linker script contents and print the script and destination
     # information.
-    contents = "INPUT(%s -l%s)" % (linked_libcxx, abi_libname)
+    contents = "INPUT(%s %s)" % (linked_libcxx, abi_libs)
     print("GENERATING SCRIPT: '%s' as file %s" % (contents, symlink_file))
 
     # Remove the existing libc++ symlink and replace it with the script.
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt
+++ lib/CMakeLists.txt
@@ -230,15 +230,26 @@
   set(SCRIPT_ABI_LIBNAME "${LIBCXX_CXX_ABI_LIBRARY}")
   if (SCRIPT_ABI_LIBNAME STREQUAL "cxxabi_shared")
     set(SCRIPT_ABI_LIBNAME "c++abi")
+  elseif(SCRIPT_ABI_LIBNAME STREQUAL "")
+    message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT can not find an ABI 
library")
   endif()
+
+  # Prepare a complete list of dependant libraries for linking.
+  set(SCRIPT_LINKED_LIBS "-l${SCRIPT_ABI_LIBNAME}")
+  if (LIBCXXABI_USE_LLVM_UNWINDER)
+    set(SCRIPT_LINKED_LIBS "${SCRIPT_LINKED_LIBS} -lunwind")
+  elseif (LIBCXX_HAS_GCC_S_LIB)
+    set(SCRIPT_LINKED_LIBS "${SCRIPT_LINKED_LIBS} -lgcc_s")
+  endif()
+
   # Generate a linker script inplace of a libc++.so symlink. Rerun this command
   # after cxx builds.
   add_custom_command(TARGET cxx_shared POST_BUILD
     COMMAND
       ${PYTHON_EXECUTABLE} 
${LIBCXX_SOURCE_DIR}/utils/gen_link_script/gen_link_script.py
     ARGS
       "$<TARGET_LINKER_FILE:cxx_shared>"
-      "${SCRIPT_ABI_LIBNAME}"
+      "${SCRIPT_LINKED_LIBS}"
     WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
   )
 endif()


Index: utils/gen_link_script/gen_link_script.py
===================================================================
--- utils/gen_link_script/gen_link_script.py
+++ utils/gen_link_script/gen_link_script.py
@@ -16,23 +16,24 @@
     sys.exit(1)
 
 def usage_and_exit():
-    print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <abi_libname>")
+    print_and_exit("Usage: ./gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <libs>")
 
 def help_and_exit():
     help_msg = \
 """Usage
 
-  gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <abi_libname>
+  gen_link_script.py [--help] [--dryrun] <path/to/libcxx.so> <libs>
 
-  Generate a linker script that links libc++ to the proper ABI library.
+  Generate a linker script that links libc++ to the proper ABI library
+  (and other dependant libraries).
   The script replaces the specified libc++ symlink.
   An example script for c++abi would look like "INPUT(libc++.so.1 -lc++abi)".
 
 Arguments
   <path/to/libcxx.so> - The top level symlink to the versioned libc++ shared
                         library. This file is replaced with a linker script.
-  <abi_libname>       - The name of the ABI library to use in the linker script.
-                        The name must be one of [c++abi, stdc++, supc++, cxxrt].
+  <libs>              - The list of libraries (-l flags) to use in the linker
+                        script.
 
 Exit Status:
   0 if OK,
@@ -53,28 +54,22 @@
     if len(args) != 2:
         usage_and_exit()
     symlink_file = args[0]
-    abi_libname = args[1]
-    return dryrun, symlink_file, abi_libname
+    abi_libs = args[1]
+    return dryrun, symlink_file, abi_libs
 
 def main():
-    dryrun, symlink_file, abi_libname = parse_args()
+    dryrun, symlink_file, abi_libs = parse_args()
 
     # Check that the given libc++.so file is a valid symlink.
     if not os.path.islink(symlink_file):
         print_and_exit("symlink file %s is not a symlink" % symlink_file)
 
     # Read the symlink so we know what libc++ to link to in the linker script.
     linked_libcxx = os.readlink(symlink_file)
 
-    # Check that the abi_libname is one of the supported values.
-    supported_abi_list = ['c++abi', 'stdc++', 'supc++', 'cxxrt']
-    if abi_libname not in supported_abi_list:
-        print_and_exit("abi name '%s' is not supported: Use one of %r" %
-                        (abi_libname, supported_abi_list))
-
     # Generate the linker script contents and print the script and destination
     # information.
-    contents = "INPUT(%s -l%s)" % (linked_libcxx, abi_libname)
+    contents = "INPUT(%s %s)" % (linked_libcxx, abi_libs)
     print("GENERATING SCRIPT: '%s' as file %s" % (contents, symlink_file))
 
     # Remove the existing libc++ symlink and replace it with the script.
Index: lib/CMakeLists.txt
===================================================================
--- lib/CMakeLists.txt
+++ lib/CMakeLists.txt
@@ -230,15 +230,26 @@
   set(SCRIPT_ABI_LIBNAME "${LIBCXX_CXX_ABI_LIBRARY}")
   if (SCRIPT_ABI_LIBNAME STREQUAL "cxxabi_shared")
     set(SCRIPT_ABI_LIBNAME "c++abi")
+  elseif(SCRIPT_ABI_LIBNAME STREQUAL "")
+    message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT can not find an ABI library")
   endif()
+
+  # Prepare a complete list of dependant libraries for linking.
+  set(SCRIPT_LINKED_LIBS "-l${SCRIPT_ABI_LIBNAME}")
+  if (LIBCXXABI_USE_LLVM_UNWINDER)
+    set(SCRIPT_LINKED_LIBS "${SCRIPT_LINKED_LIBS} -lunwind")
+  elseif (LIBCXX_HAS_GCC_S_LIB)
+    set(SCRIPT_LINKED_LIBS "${SCRIPT_LINKED_LIBS} -lgcc_s")
+  endif()
+
   # Generate a linker script inplace of a libc++.so symlink. Rerun this command
   # after cxx builds.
   add_custom_command(TARGET cxx_shared POST_BUILD
     COMMAND
       ${PYTHON_EXECUTABLE} ${LIBCXX_SOURCE_DIR}/utils/gen_link_script/gen_link_script.py
     ARGS
       "$<TARGET_LINKER_FILE:cxx_shared>"
-      "${SCRIPT_ABI_LIBNAME}"
+      "${SCRIPT_LINKED_LIBS}"
     WORKING_DIRECTORY ${LIBCXX_BUILD_DIR}
   )
 endif()
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to