[llvm] 9573343 - [ExecutionEngine] Check for libunwind before calling __register_frame

Harald van Dijk via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 15 05:36:19 PDT 2021


Author: Harald van Dijk
Date: 2021-08-15T13:35:53+01:00
New Revision: 957334382cd12ec07b46c0ddfdcc220731f6d80f

URL: https://github.com/llvm/llvm-project/commit/957334382cd12ec07b46c0ddfdcc220731f6d80f
DIFF: https://github.com/llvm/llvm-project/commit/957334382cd12ec07b46c0ddfdcc220731f6d80f.diff

LOG: [ExecutionEngine] Check for libunwind before calling __register_frame

libgcc and libunwind have different flavours of __register_frame. Both
 flavours are already correctly handled, except that the code to handle
the libunwind flavour is guarded by __APPLE__. This change uses the
presence of __unw_add_dynamic_fde in libunwind instead to detect whether
libunwind is used, rather than hardcoding it as Apple vs. non-Apple.

Fixes PR44074.

Thanks to Albert Jin <albert.jin at gmail.com> and Chris Schafmeister
<chris.schaf at verizon.net> for identifying the problem.

Reviewed By: lhames

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

Added: 
    

Modified: 
    llvm/cmake/config-ix.cmake
    llvm/cmake/unwind.h
    llvm/include/llvm/Config/config.h.cmake
    llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
    llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake
index dd0aaadb47c72..6da2012728ad5 100644
--- a/llvm/cmake/config-ix.cmake
+++ b/llvm/cmake/config-ix.cmake
@@ -211,6 +211,7 @@ endif()
 # Determine whether we can register EH tables.
 check_symbol_exists(__register_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_REGISTER_FRAME)
 check_symbol_exists(__deregister_frame "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_DEREGISTER_FRAME)
+check_symbol_exists(__unw_add_dynamic_fde "${CMAKE_CURRENT_LIST_DIR}/unwind.h" HAVE_UNW_ADD_DYNAMIC_FDE)
 
 check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE__UNWIND_BACKTRACE)
 check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)

diff  --git a/llvm/cmake/unwind.h b/llvm/cmake/unwind.h
index e7f53465f9ce3..52243f2af787b 100644
--- a/llvm/cmake/unwind.h
+++ b/llvm/cmake/unwind.h
@@ -5,3 +5,4 @@
 // exist in the runtime.
 extern void __register_frame(const void *fde);   // NOLINT
 extern void __deregister_frame(const void *fde); // NOLINT
+extern void __unw_add_dynamic_fde();             // NOLINT

diff  --git a/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake
index 8d58ec9d665b3..d7cd44b5db36a 100644
--- a/llvm/include/llvm/Config/config.h.cmake
+++ b/llvm/include/llvm/Config/config.h.cmake
@@ -64,6 +64,9 @@
 /* Define to 1 if we can deregister EH frames on this platform. */
 #cmakedefine HAVE_DEREGISTER_FRAME ${HAVE_DEREGISTER_FRAME}
 
+/* Define if __unw_add_dynamic_fde() is available on this platform. */
+#cmakedefine HAVE_UNW_ADD_DYNAMIC_FDE ${HAVE_UNW_ADD_DYNAMIC_FDE}
+
 /* Define to 1 if you have the <errno.h> header file. */
 #cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H}
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
index db002a34b4445..6f891afabfdc3 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.cpp
@@ -85,11 +85,11 @@ static Error deregisterFrameWrapper(const void *P) {
 }
 #endif
 
-#ifdef __APPLE__
+#ifdef HAVE_UNW_ADD_DYNAMIC_FDE
 
 template <typename HandleFDEFn>
-Error walkAppleEHFrameSection(const char *const SectionStart,
-                              size_t SectionSize, HandleFDEFn HandleFDE) {
+Error walkLibunwindEHFrameSection(const char *const SectionStart,
+                                  size_t SectionSize, HandleFDEFn HandleFDE) {
   const char *CurCFIRecord = SectionStart;
   const char *End = SectionStart + SectionSize;
   uint64_t Size = *reinterpret_cast<const uint32_t *>(CurCFIRecord);
@@ -123,16 +123,19 @@ Error walkAppleEHFrameSection(const char *const SectionStart,
   return Error::success();
 }
 
-#endif // __APPLE__
+#endif // HAVE_UNW_ADD_DYNAMIC_FDE
 
 Error registerEHFrameSection(const void *EHFrameSectionAddr,
                              size_t EHFrameSectionSize) {
-#ifdef __APPLE__
-  // On Darwin __register_frame has to be called for each FDE entry.
-  return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
-                                 EHFrameSectionSize, registerFrameWrapper);
+  /* libgcc and libunwind __register_frame behave 
diff erently. We use the
+   * presence of __unw_add_dynamic_fde to detect libunwind. */
+#ifdef HAVE_UNW_ADD_DYNAMIC_FDE
+  // With libunwind, __register_frame has to be called for each FDE entry.
+  return walkLibunwindEHFrameSection(
+      static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
+      registerFrameWrapper);
 #else
-  // On Linux __register_frame takes a single argument:
+  // With libgcc, __register_frame takes a single argument:
   // a pointer to the start of the .eh_frame section.
 
   // How can it find the end? Because crtendS.o is linked
@@ -143,9 +146,10 @@ Error registerEHFrameSection(const void *EHFrameSectionAddr,
 
 Error deregisterEHFrameSection(const void *EHFrameSectionAddr,
                                size_t EHFrameSectionSize) {
-#ifdef __APPLE__
-  return walkAppleEHFrameSection(static_cast<const char *>(EHFrameSectionAddr),
-                                 EHFrameSectionSize, deregisterFrameWrapper);
+#ifdef HAVE_UNW_ADD_DYNAMIC_FDE
+  return walkLibunwindEHFrameSection(
+      static_cast<const char *>(EHFrameSectionAddr), EHFrameSectionSize,
+      deregisterFrameWrapper);
 #else
   return deregisterFrameWrapper(EHFrameSectionAddr);
 #endif

diff  --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
index b6ccd02405c10..252e20c3c38c9 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RTDyldMemoryManager.cpp
@@ -67,7 +67,9 @@ static void __deregister_frame(void *p) {
 }
 #endif
 
-#ifdef __APPLE__
+/* libgcc and libunwind __register_frame behave 
diff erently. We use the presence
+ * of __unw_add_dynamic_fde to detect libunwind. */
+#ifdef HAVE_UNW_ADD_DYNAMIC_FDE
 
 static const char *processFDE(const char *Entry, bool isDeregister) {
   const char *P = Entry;


        


More information about the llvm-commits mailing list