Symbolizer support for mingw and cygwin (#208) master
authorSergiu Deitsch <sergiud@users.noreply.github.com>
Tue, 27 Feb 2018 20:03:20 +0000 (21:03 +0100)
committerGitHub <noreply@github.com>
Tue, 27 Feb 2018 20:03:20 +0000 (21:03 +0100)
* added dbghelp symbolizer support for mingw and cygwin
* fixed compiler errors in case <stdint.h> is not available
* cmake: check whether SymFromAddr actually works

CMakeLists.txt
src/config.h.cmake.in
src/symbolize.cc
src/symbolize.h
src/symbolize_unittest.cc
src/utilities.h

index 8b491db..f27f00d 100644 (file)
@@ -26,6 +26,7 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
 include (CheckCSourceCompiles)
 include (CheckCXXCompilerFlag)
 include (CheckCXXSourceCompiles)
 include (CheckCSourceCompiles)
 include (CheckCXXCompilerFlag)
 include (CheckCXXSourceCompiles)
+include (CheckCXXSourceRuns)
 include (CheckFunctionExists)
 include (CheckIncludeFile)
 include (CheckIncludeFileCXX)
 include (CheckFunctionExists)
 include (CheckIncludeFile)
 include (CheckIncludeFileCXX)
@@ -34,6 +35,7 @@ include (CheckStructHasMember)
 include (CheckSymbolExists)
 include (CheckTypeSize)
 include (CMakePackageConfigHelpers)
 include (CheckSymbolExists)
 include (CheckTypeSize)
 include (CMakePackageConfigHelpers)
+include (CMakePushCheckState)
 include (CPack)
 include (CTest)
 include (DetermineGflagsNamespace)
 include (CPack)
 include (CTest)
 include (DetermineGflagsNamespace)
@@ -112,6 +114,7 @@ check_cxx_compiler_flag (-Wunnamed-type-template-args
 check_symbol_exists (snprintf stdio.h HAVE_SNPRINTF)
 
 check_library_exists (unwind get_static_proc_name "" HAVE_LIB_UNWIND)
 check_symbol_exists (snprintf stdio.h HAVE_SNPRINTF)
 
 check_library_exists (unwind get_static_proc_name "" HAVE_LIB_UNWIND)
+check_library_exists (DbgHelp UnDecorateSymbolName "" HAVE_DBGHELP)
 
 find_library (UNWIND_LIBRARY NAMES unwind DOC "unwind library")
 mark_as_advanced (UNWIND_LIBRARY)
 
 find_library (UNWIND_LIBRARY NAMES unwind DOC "unwind library")
 mark_as_advanced (UNWIND_LIBRARY)
@@ -339,6 +342,49 @@ else (HAVE_USING_OPERATOR)
   set (ac_cv_cxx_using_operator 0)
 endif (HAVE_USING_OPERATOR)
 
   set (ac_cv_cxx_using_operator 0)
 endif (HAVE_USING_OPERATOR)
 
+if (HAVE_EXECINFO_H)
+  set (HAVE_STACKTRACE 1)
+endif (HAVE_EXECINFO_H)
+
+if (WIN32 OR CYGWIN)
+  cmake_push_check_state (RESET)
+  set (CMAKE_REQUIRED_LIBRARIES DbgHelp)
+
+  check_cxx_source_runs ([=[
+  #include <windows.h>
+  #include <dbghelp.h>
+  #include <cstdlib>
+
+  void foobar() { }
+
+  int main()
+  {
+      HANDLE process = GetCurrentProcess();
+
+      if (!SymInitialize(process, NULL, TRUE))
+          return EXIT_FAILURE;
+
+      char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
+      SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(buf);
+      symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+      symbol->MaxNameLen = MAX_SYM_NAME;
+
+      void* const pc = reinterpret_cast<void*>(&foobar);
+      BOOL ret = SymFromAddr(process, reinterpret_cast<DWORD64>(pc), 0, symbol);
+
+      return ret ? EXIT_SUCCESS : EXIT_FAILURE;
+  }
+  ]=] HAVE_SYMBOLIZE)
+
+  cmake_pop_check_state ()
+
+  if (HAVE_SYMBOLIZE)
+    set (HAVE_STACKTRACE 1)
+  endif (HAVE_SYMBOLIZE)
+elseif (UNIX OR (APPLE AND HAVE_DLADDR))
+  set (HAVE_SYMBOLIZE 1)
+endif (WIN32 OR CYGWIN)
+
 set (SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
 
 if (WITH_THREADS AND Threads_FOUND)
 set (SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
 
 if (WITH_THREADS AND Threads_FOUND)
@@ -408,6 +454,10 @@ if (UNWIND_LIBRARY)
   target_link_libraries (glog PUBLIC ${UNWIND_LIBRARY})
 endif (UNWIND_LIBRARY)
 
   target_link_libraries (glog PUBLIC ${UNWIND_LIBRARY})
 endif (UNWIND_LIBRARY)
 
+if (HAVE_DBGHELP)
+   target_link_libraries (glog PUBLIC DbgHelp)
+endif (HAVE_DBGHELP)
+
 if (HAVE_PTHREAD)
   target_link_libraries (glog PUBLIC ${CMAKE_THREAD_LIBS_INIT})
 endif (HAVE_PTHREAD)
 if (HAVE_PTHREAD)
   target_link_libraries (glog PUBLIC ${CMAKE_THREAD_LIBS_INIT})
 endif (HAVE_PTHREAD)
@@ -476,19 +526,6 @@ else (NOT BUILD_SHARED_LIBS)
     "GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=${_IMPORT}")
 endif (NOT BUILD_SHARED_LIBS)
 
     "GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=${_IMPORT}")
 endif (NOT BUILD_SHARED_LIBS)
 
-if (HAVE_EXECINFO_H)
-  set (HAVE_STACKTRACE 1)
-endif (HAVE_EXECINFO_H)
-
-if (WIN32)
-  set (HAVE_STACKTRACE 1)
-  set (HAVE_SYMBOLIZE 1)
-endif (WIN32)
-
-if (UNIX OR (APPLE AND HAVE_DLADDR))
-  set (HAVE_SYMBOLIZE 1)
-endif (UNIX OR (APPLE AND HAVE_DLADDR))
-
 # Unit testing
 
 if (BUILD_TESTING)
 # Unit testing
 
 if (BUILD_TESTING)
index 9d87d37..e15c737 100644 (file)
 /* define if your compiler has __sync_val_compare_and_swap */
 #cmakedefine HAVE___SYNC_VAL_COMPARE_AND_SWAP
 
 /* define if your compiler has __sync_val_compare_and_swap */
 #cmakedefine HAVE___SYNC_VAL_COMPARE_AND_SWAP
 
+/* define if symbolize support is available */
+#cmakedefine HAVE_SYMBOLIZE
+
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #cmakedefine LT_OBJDIR
 /* Define to the sub-directory in which libtool stores uninstalled libraries.
    */
 #cmakedefine LT_OBJDIR
index 98a754f..61fe2ff 100644 (file)
@@ -844,18 +844,22 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
 
 _END_GOOGLE_NAMESPACE_
 
 
 _END_GOOGLE_NAMESPACE_
 
-#elif defined(OS_WINDOWS)
+#elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
 
 
+#include <windows.h>
 #include <DbgHelp.h>
 #include <DbgHelp.h>
+
+#ifdef _MSC_VER
 #pragma comment(lib, "DbgHelp")
 #pragma comment(lib, "DbgHelp")
+#endif
 
 _START_GOOGLE_NAMESPACE_
 
 class SymInitializer {
 public:
 
 _START_GOOGLE_NAMESPACE_
 
 class SymInitializer {
 public:
-  HANDLE process = NULL;
-  bool ready = false;
-  SymInitializer() {
+  HANDLE process;
+  bool ready;
+  SymInitializer() : process(NULL), ready(false) {
     // Initialize the symbol handler.
     // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
     process = GetCurrentProcess();
     // Initialize the symbol handler.
     // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
     process = GetCurrentProcess();
index 86f0c79..9ff16c1 100644 (file)
@@ -130,9 +130,9 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
 // file is opened successfully, returns the file descriptor.  Otherwise,
 // returns -1.  |out_file_name_size| is the size of the file name buffer
 // (including the null-terminator).
 // file is opened successfully, returns the file descriptor.  Otherwise,
 // returns -1.  |out_file_name_size| is the size of the file name buffer
 // (including the null-terminator).
-typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc,
-                                               uint64_t &start_address,
-                                               uint64_t &base_address,
+typedef int (*SymbolizeOpenObjectFileCallback)(uint64 pc,
+                                               uint64 &start_address,
+                                               uint64 &base_address,
                                                char *out_file_name,
                                                int out_file_name_size);
 void InstallSymbolizeOpenObjectFileCallback(
                                                char *out_file_name,
                                                int out_file_name_size);
 void InstallSymbolizeOpenObjectFileCallback(
index a0a9737..413161b 100644 (file)
@@ -357,10 +357,12 @@ void ATTRIBUTE_NOINLINE TestWithReturnAddress() {
 #endif
 }
 
 #endif
 }
 
-# elif defined(OS_WINDOWS)
+# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
 
 
+#ifdef _MSC_VER
 #include <intrin.h>
 #pragma intrinsic(_ReturnAddress)
 #include <intrin.h>
 #pragma intrinsic(_ReturnAddress)
+#endif
 
 struct Foo {
   static void func(int x);
 
 struct Foo {
   static void func(int x);
@@ -378,7 +380,13 @@ TEST(Symbolize, SymbolizeWithDemangling) {
 }
 
 __declspec(noinline) void TestWithReturnAddress() {
 }
 
 __declspec(noinline) void TestWithReturnAddress() {
-  void *return_address = _ReturnAddress();
+  void *return_address =
+#ifdef __GNUC__ // Cygwin and MinGW support
+         __builtin_return_address(0)
+#else
+         _ReturnAddress()
+#endif
+         ;
   const char *symbol = TrySymbolize(return_address);
   CHECK(symbol != NULL);
   CHECK_STREQ(symbol, "main");
   const char *symbol = TrySymbolize(return_address);
   CHECK(symbol != NULL);
   CHECK_STREQ(symbol, "main");
@@ -401,7 +409,7 @@ int main(int argc, char **argv) {
   TestWithPCInsideNonInlineFunction();
   TestWithReturnAddress();
   return RUN_ALL_TESTS();
   TestWithPCInsideNonInlineFunction();
   TestWithReturnAddress();
   return RUN_ALL_TESTS();
-# elif defined(OS_WINDOWS)
+# elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
   TestWithReturnAddress();
   return RUN_ALL_TESTS();
 # else  // OS_WINDOWS
   TestWithReturnAddress();
   return RUN_ALL_TESTS();
 # else  // OS_WINDOWS
index be2cff4..ca21cfb 100644 (file)
 # define HAVE_STACKTRACE
 #endif
 
 # define HAVE_STACKTRACE
 #endif
 
+#ifndef HAVE_SYMBOLIZE
 // defined by gcc
 #if defined(__ELF__) && defined(OS_LINUX)
 # define HAVE_SYMBOLIZE
 // defined by gcc
 #if defined(__ELF__) && defined(OS_LINUX)
 # define HAVE_SYMBOLIZE
 // Use DbgHelp to symbolize
 # define HAVE_SYMBOLIZE
 #endif
 // Use DbgHelp to symbolize
 # define HAVE_SYMBOLIZE
 #endif
+#endif // !defined(HAVE_SYMBOLIZE)
 
 #ifndef ARRAYSIZE
 // There is a better way, but this is good enough for our purpose.
 
 #ifndef ARRAYSIZE
 // There is a better way, but this is good enough for our purpose.