Unverified Commit a97d6b0e authored by Sergiu Deitsch's avatar Sergiu Deitsch Committed by GitHub

Symbolizer support for mingw and cygwin (#208)

* added dbghelp symbolizer support for mingw and cygwin
* fixed compiler errors in case <stdint.h> is not available
* cmake: check whether SymFromAddr actually works
parent 1aec14ed
...@@ -26,6 +26,7 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) ...@@ -26,6 +26,7 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include (CheckCSourceCompiles) include (CheckCSourceCompiles)
include (CheckCXXCompilerFlag) include (CheckCXXCompilerFlag)
include (CheckCXXSourceCompiles) include (CheckCXXSourceCompiles)
include (CheckCXXSourceRuns)
include (CheckFunctionExists) include (CheckFunctionExists)
include (CheckIncludeFile) include (CheckIncludeFile)
include (CheckIncludeFileCXX) include (CheckIncludeFileCXX)
...@@ -34,6 +35,7 @@ include (CheckStructHasMember) ...@@ -34,6 +35,7 @@ include (CheckStructHasMember)
include (CheckSymbolExists) include (CheckSymbolExists)
include (CheckTypeSize) include (CheckTypeSize)
include (CMakePackageConfigHelpers) include (CMakePackageConfigHelpers)
include (CMakePushCheckState)
include (CPack) include (CPack)
include (CTest) include (CTest)
include (DetermineGflagsNamespace) include (DetermineGflagsNamespace)
...@@ -112,6 +114,7 @@ check_cxx_compiler_flag (-Wunnamed-type-template-args ...@@ -112,6 +114,7 @@ check_cxx_compiler_flag (-Wunnamed-type-template-args
check_symbol_exists (snprintf stdio.h HAVE_SNPRINTF) check_symbol_exists (snprintf stdio.h HAVE_SNPRINTF)
check_library_exists (unwind get_static_proc_name "" HAVE_LIB_UNWIND) 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") find_library (UNWIND_LIBRARY NAMES unwind DOC "unwind library")
mark_as_advanced (UNWIND_LIBRARY) mark_as_advanced (UNWIND_LIBRARY)
...@@ -339,6 +342,49 @@ else (HAVE_USING_OPERATOR) ...@@ -339,6 +342,49 @@ else (HAVE_USING_OPERATOR)
set (ac_cv_cxx_using_operator 0) set (ac_cv_cxx_using_operator 0)
endif (HAVE_USING_OPERATOR) 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}) set (SIZEOF_VOID_P ${CMAKE_SIZEOF_VOID_P})
if (WITH_THREADS AND Threads_FOUND) if (WITH_THREADS AND Threads_FOUND)
...@@ -408,6 +454,10 @@ if (UNWIND_LIBRARY) ...@@ -408,6 +454,10 @@ if (UNWIND_LIBRARY)
target_link_libraries (glog PUBLIC ${UNWIND_LIBRARY}) target_link_libraries (glog PUBLIC ${UNWIND_LIBRARY})
endif (UNWIND_LIBRARY) endif (UNWIND_LIBRARY)
if (HAVE_DBGHELP)
target_link_libraries (glog PUBLIC DbgHelp)
endif (HAVE_DBGHELP)
if (HAVE_PTHREAD) if (HAVE_PTHREAD)
target_link_libraries (glog PUBLIC ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries (glog PUBLIC ${CMAKE_THREAD_LIBS_INIT})
endif (HAVE_PTHREAD) endif (HAVE_PTHREAD)
...@@ -476,19 +526,6 @@ else (NOT BUILD_SHARED_LIBS) ...@@ -476,19 +526,6 @@ else (NOT BUILD_SHARED_LIBS)
"GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=${_IMPORT}") "GOOGLE_GLOG_DLL_DECL_FOR_UNITTESTS=${_IMPORT}")
endif (NOT BUILD_SHARED_LIBS) 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 # Unit testing
if (BUILD_TESTING) if (BUILD_TESTING)
......
...@@ -130,6 +130,9 @@ ...@@ -130,6 +130,9 @@
/* define if your compiler has __sync_val_compare_and_swap */ /* define if your compiler has __sync_val_compare_and_swap */
#cmakedefine HAVE___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. /* Define to the sub-directory in which libtool stores uninstalled libraries.
*/ */
#cmakedefine LT_OBJDIR #cmakedefine LT_OBJDIR
......
...@@ -844,18 +844,22 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out, ...@@ -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_ _START_GOOGLE_NAMESPACE_
class SymInitializer { class SymInitializer {
public: public:
HANDLE process = NULL; HANDLE process;
bool ready = false; bool ready;
SymInitializer() { SymInitializer() : process(NULL), ready(false) {
// Initialize the symbol handler. // Initialize the symbol handler.
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680344(v=vs.85).aspx
process = GetCurrentProcess(); process = GetCurrentProcess();
......
...@@ -130,9 +130,9 @@ void InstallSymbolizeCallback(SymbolizeCallback callback); ...@@ -130,9 +130,9 @@ void InstallSymbolizeCallback(SymbolizeCallback callback);
// file is opened successfully, returns the file descriptor. Otherwise, // file is opened successfully, returns the file descriptor. Otherwise,
// returns -1. |out_file_name_size| is the size of the file name buffer // returns -1. |out_file_name_size| is the size of the file name buffer
// (including the null-terminator). // (including the null-terminator).
typedef int (*SymbolizeOpenObjectFileCallback)(uint64_t pc, typedef int (*SymbolizeOpenObjectFileCallback)(uint64 pc,
uint64_t &start_address, uint64 &start_address,
uint64_t &base_address, uint64 &base_address,
char *out_file_name, char *out_file_name,
int out_file_name_size); int out_file_name_size);
void InstallSymbolizeOpenObjectFileCallback( void InstallSymbolizeOpenObjectFileCallback(
......
...@@ -357,10 +357,12 @@ void ATTRIBUTE_NOINLINE TestWithReturnAddress() { ...@@ -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> #include <intrin.h>
#pragma intrinsic(_ReturnAddress) #pragma intrinsic(_ReturnAddress)
#endif
struct Foo { struct Foo {
static void func(int x); static void func(int x);
...@@ -378,7 +380,13 @@ TEST(Symbolize, SymbolizeWithDemangling) { ...@@ -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); const char *symbol = TrySymbolize(return_address);
CHECK(symbol != NULL); CHECK(symbol != NULL);
CHECK_STREQ(symbol, "main"); CHECK_STREQ(symbol, "main");
...@@ -401,7 +409,7 @@ int main(int argc, char **argv) { ...@@ -401,7 +409,7 @@ int main(int argc, char **argv) {
TestWithPCInsideNonInlineFunction(); TestWithPCInsideNonInlineFunction();
TestWithReturnAddress(); TestWithReturnAddress();
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
# elif defined(OS_WINDOWS) # elif defined(OS_WINDOWS) || defined(OS_CYGWIN)
TestWithReturnAddress(); TestWithReturnAddress();
return RUN_ALL_TESTS(); return RUN_ALL_TESTS();
# else // OS_WINDOWS # else // OS_WINDOWS
......
...@@ -127,6 +127,7 @@ ...@@ -127,6 +127,7 @@
# define HAVE_STACKTRACE # define HAVE_STACKTRACE
#endif #endif
#ifndef HAVE_SYMBOLIZE
// defined by gcc // defined by gcc
#if defined(__ELF__) && defined(OS_LINUX) #if defined(__ELF__) && defined(OS_LINUX)
# define HAVE_SYMBOLIZE # define HAVE_SYMBOLIZE
...@@ -137,6 +138,7 @@ ...@@ -137,6 +138,7 @@
// Use DbgHelp to symbolize // Use DbgHelp to symbolize
# define HAVE_SYMBOLIZE # define HAVE_SYMBOLIZE
#endif #endif
#endif // !defined(HAVE_SYMBOLIZE)
#ifndef ARRAYSIZE #ifndef ARRAYSIZE
// There is a better way, but this is good enough for our purpose. // There is a better way, but this is good enough for our purpose.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment