]> granicus.if.org Git - llvm/commitdiff
[cmake] Pass -Wl,-z,nodelete on Linux to prevent unloading
authorMichal Gorny <mgorny@gentoo.org>
Mon, 27 Nov 2017 22:23:09 +0000 (22:23 +0000)
committerMichal Gorny <mgorny@gentoo.org>
Mon, 27 Nov 2017 22:23:09 +0000 (22:23 +0000)
Prevent unloading shared libraries on Linux when dlclose() is called.
This is necessary since command-line option parsing API relies on
registering the global option instances in the option parser instance
which can be loaded in a different shared library.

Given that we can't reliably remove those options when a library is
unloaded, the parser ends up containing dangling references. Since glibc
has relatively complex library unloading rules, some of the LLVM
libraries can be unloaded while others (including the Support library)
stay loaded causing quite a mayhem. To reliably prevent that, just
forbid unloading all libraries -- it's a very bad idea anyway.

While the issue arguably happens only with BUILD_SHARED_LIBS, it may
affect any library reusing llvm::cl interface.

Based on patch provided Ross Hayward on https://bugs.gentoo.org/617154.
Previously hit by Fedora back in Feb 2016:
https://lists.freedesktop.org/archives/mesa-dev/2016-February/107242.html

Differential Revision: https://reviews.llvm.org/D40459

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@319105 91177308-0d34-0410-b5e6-96231b3b80d8

cmake/modules/HandleLLVMOptions.cmake
unittests/Support/DynamicLibrary/CMakeLists.txt

index c5390371845e1c574eaca76f665a67e103b6fa04..b5059a8a60e72a982753e8430d653fba199fb80e 100644 (file)
@@ -151,6 +151,14 @@ if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
 endif()
 
+# Pass -Wl,-z,nodelete. This makes sure our shared libraries are not unloaded
+# by dlclose(). We need that since the CLI API relies on cross-references
+# between global objects which became horribly broken when one of the libraries
+# is unloaded.
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+  set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,nodelete")
+endif()
+
 
 function(append value)
   foreach(variable ${ARGN})
index 9355979221aae12e26f92c7f9e9fc199f549a4e7..c6201b1ad319df4f3d03e9d281af9f7ee62600a4 100644 (file)
@@ -24,5 +24,12 @@ function(dynlib_add_module NAME)
   add_dependencies(DynamicLibraryTests ${NAME})
 endfunction(dynlib_add_module)
 
+# Revert -Wl,-z,nodelete on this test since it relies on the file
+# being unloaded.
+if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+  string(REPLACE "-Wl,-z,nodelete" "" CMAKE_SHARED_LINKER_FLAGS
+    ${CMAKE_SHARED_LINKER_FLAGS})
+endif()
+
 dynlib_add_module(PipSqueak)
 dynlib_add_module(SecondLib)