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
This commit is contained in:
parent
1aec14edf4
commit
a97d6b0e1c
@ -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)
|
|||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
"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 @@
|
|||||||
/* 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,
|
|||||||
|
|
||||||
_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);
|
|||||||
// 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() {
|
|||||||
#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) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__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) {
|
|||||||
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 @@
|
|||||||
# 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 @@
|
|||||||
// 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.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user