diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 6f0281d12..0f2783689 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -649,6 +649,68 @@ IF(KWSYS_USE_SystemInformation) SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) ENDIF() + IF(UNIX) + INCLUDE(CheckIncludeFileCXX) + # check for simple stack trace + # usually it's in libc but on FreeBSD + # it's in libexecinfo + FIND_LIBRARY(EXECINFO_LIB "execinfo") + IF (NOT EXECINFO_LIB) + SET(EXECINFO_LIB "") + ENDIF() + CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH) + IF (KWSYS_CXX_HAS_EXECINFOH) + # we have the backtrace header check if it + # can be used with this compiler + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB}) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE + "Checking whether backtrace works with this C++ compiler" DIRECT) + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + IF (KWSYS_CXX_HAS_BACKTRACE) + # backtrace is supported by this system and compiler. + # now check for the more advanced capabilities. + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE=1) + # check for symbol lookup using dladdr + CHECK_INCLUDE_FILE_CXX("dlfcn.h" KWSYS_CXX_HAS_DLFCNH) + IF (KWSYS_CXX_HAS_DLFCNH) + # we have symbol lookup libraries and headers + # check if they can be used with this compiler + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${CMAKE_DL_LIBS}) + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_DLADDR + "Checking whether dladdr works with this C++ compiler" DIRECT) + SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES) + IF (KWSYS_CXX_HAS_DLADDR) + # symbol lookup is supported by this system + # and compiler. + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP=1) + ENDIF() + ENDIF() + # c++ demangling support + # check for cxxabi headers + CHECK_INCLUDE_FILE_CXX("cxxabi.h" KWSYS_CXX_HAS_CXXABIH) + IF (KWSYS_CXX_HAS_CXXABIH) + # check if cxxabi can be used with this + # system and compiler. + KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_CXXABI + "Checking whether cxxabi works with this C++ compiler" DIRECT) + IF (KWSYS_CXX_HAS_CXXABI) + # c++ demangle using cxxabi is supported with + # this system and compiler + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE=1) + ENDIF() + ENDIF() + # basic backtrace works better with release build + # don't bother with advanced features for release + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS_DEBUG KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) + SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY + COMPILE_DEFINITIONS_RELWITHDEBINFO KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD=1) + ENDIF() + ENDIF() + ENDIF() IF(BORLAND) KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM "Checking whether Borland CXX compiler supports assembler instructions" DIRECT) @@ -913,12 +975,23 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS) ENDIF(UNIX) ENDIF(KWSYS_USE_DynamicLoader) - IF(KWSYS_USE_SystemInformation AND WIN32) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32) - IF(KWSYS_SYS_HAS_PSAPI) - TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi) + IF(KWSYS_USE_SystemInformation) + IF(WIN32) + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ws2_32) + IF(KWSYS_SYS_HAS_PSAPI) + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} Psapi) + ENDIF() + ELSEIF(UNIX) + IF (EXECINFO_LIB AND KWSYS_CXX_HAS_BACKTRACE) + # backtrace on FreeBSD is not in libc + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${EXECINFO_LIB}) + ENDIF() + IF (KWSYS_CXX_HAS_DLADDR) + # for symbol lookup using dladdr + TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE} ${CMAKE_DL_LIBS}) + ENDIF() ENDIF() - ENDIF(KWSYS_USE_SystemInformation AND WIN32) + ENDIF() # Apply user-defined target properties to the library. IF(KWSYS_PROPERTIES_CXX) diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 9db1dee38..beefd7d73 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -18,6 +18,10 @@ # include // WSADATA, include before sys/types.h #endif +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif + // TODO: // We need an alternative implementation for many functions in this file // when USE_ASM_INSTRUCTIONS gets defined as 0. @@ -114,8 +118,15 @@ typedef int siginfo_t; # define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN # endif # if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050 -# include -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) +# include +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include +# endif +# endif # endif #endif @@ -130,10 +141,13 @@ typedef int siginfo_t; # define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN # endif # endif -# if defined(__GNUC__) +# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) # include -# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41) -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include # endif # endif # if defined(KWSYS_CXX_HAS_RLIMIT64) @@ -357,6 +371,10 @@ public: static void SetStackTraceOnError(int enable); + // get current stack + static + kwsys_stl::string GetProgramStack(int firstFrame, int wholePath); + /** Run the different checks */ void RunCPUCheck(); void RunOSCheck(); @@ -812,6 +830,11 @@ void SystemInformation::SetStackTraceOnError(int enable) SystemInformationImplementation::SetStackTraceOnError(enable); } +kwsys_stl::string SystemInformation::GetProgramStack(int firstFrame, int wholePath) +{ + return SystemInformationImplementation::GetProgramStack(firstFrame, wholePath); +} + /** Run the different checks */ void SystemInformation::RunCPUCheck() { @@ -908,6 +931,12 @@ int LoadLines( } continue; } + char *pBuf=buf; + while(*pBuf) + { + if (*pBuf=='\n') *pBuf='\0'; + pBuf+=1; + } lines.push_back(buf); ++nRead; } @@ -1046,12 +1075,29 @@ void StacktraceSignalHandler( #if defined(__linux) || defined(__APPLE__) kwsys_ios::ostringstream oss; oss + << kwsys_ios::endl << "=========================================================" << kwsys_ios::endl << "Process id " << getpid() << " "; switch (sigNo) { + case SIGINT: + oss << "Caught SIGINT"; + break; + + case SIGTERM: + oss << "Caught SIGTERM"; + break; + + case SIGABRT: + oss << "Caught SIGABRT"; + break; + case SIGFPE: - oss << "Caught SIGFPE "; + oss + << "Caught SIGFPE at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { # if defined(FPE_INTDIV) @@ -1099,7 +1145,11 @@ void StacktraceSignalHandler( break; case SIGSEGV: - oss << "Caught SIGSEGV "; + oss + << "Caught SIGSEGV at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case SEGV_MAPERR: @@ -1116,16 +1166,12 @@ void StacktraceSignalHandler( } break; - case SIGINT: - oss << "Caught SIGTERM"; - break; - - case SIGTERM: - oss << "Caught SIGTERM"; - break; - case SIGBUS: - oss << "Caught SIGBUS type "; + oss + << "Caught SIGBUS at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case BUS_ADRALN: @@ -1134,13 +1180,25 @@ void StacktraceSignalHandler( # if defined(BUS_ADRERR) case BUS_ADRERR: - oss << "non-exestent physical address"; + oss << "nonexistent physical address"; break; # endif # if defined(BUS_OBJERR) case BUS_OBJERR: - oss << "object specific hardware error"; + oss << "object-specific hardware error"; + break; +# endif + +# if defined(BUS_MCEERR_AR) + case BUS_MCEERR_AR: + oss << "Hardware memory error consumed on a machine check; action required."; + break; +# endif + +# if defined(BUS_MCEERR_AO) + case BUS_MCEERR_AO: + oss << "Hardware memory error detected in process but not consumed; action optional."; break; # endif @@ -1151,7 +1209,11 @@ void StacktraceSignalHandler( break; case SIGILL: - oss << "Caught SIGILL "; + oss + << "Caught SIGILL at " + << (sigInfo->si_addr==0?"0x":"") + << sigInfo->si_addr + << " "; switch (sigInfo->si_code) { case ILL_ILLOPC: @@ -1205,20 +1267,16 @@ void StacktraceSignalHandler( oss << "Caught " << sigNo << " code " << sigInfo->si_code; break; } - oss << kwsys_ios::endl; -#if defined(KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE) - oss << "Program Stack:" << kwsys_ios::endl; - void *stackSymbols[128]; - int n=backtrace(stackSymbols,128); - char **stackText=backtrace_symbols(stackSymbols,n); - for (int i=0; iAddress; } + + // Description: + // If not set paths will be removed. eg, from a binary + // or source file. + void SetReportPath(int rp){ this->ReportPath=rp; } + + // Description: + // Set/Get the name of the binary file that the symbol + // is found in. + void SetBinary(const char *binary) + { this->Binary=safes(binary); } + + kwsys_stl::string GetBinary() const; + + // Description: + // Set the name of the function that the symbol is found in. + // If c++ demangling is supported it will be demangled. + void SetFunction(const char *function) + { this->Function=this->Demangle(function); } + + kwsys_stl::string GetFunction() const + { return this->Function; } + + // Description: + // Set/Get the name of the source file where the symbol + // is defined. + void SetSourceFile(const char *sourcefile) + { this->SourceFile=safes(sourcefile); } + + kwsys_stl::string GetSourceFile() const + { return this->GetFileName(this->SourceFile); } + + // Description: + // Set/Get the line number where the symbol is defined + void SetLineNumber(long linenumber){ this->LineNumber=linenumber; } + long GetLineNumber() const { return this->LineNumber; } + + // Description: + // Set the address where the biinary image is mapped + // into memory. + void SetBinaryBaseAddress(void *address) + { this->BinaryBaseAddress=address; } + +private: + void *GetRealAddress() const + { return (void*)((char*)this->Address-(char*)this->BinaryBaseAddress); } + + kwsys_stl::string GetFileName(const kwsys_stl::string &path) const; + kwsys_stl::string Demangle(const char *symbol) const; + +private: + kwsys_stl::string Binary; + void *BinaryBaseAddress; + void *Address; + kwsys_stl::string SourceFile; + kwsys_stl::string Function; + long LineNumber; + int ReportPath; +}; + +// -------------------------------------------------------------------------- +kwsys_ios::ostream &operator<<( + kwsys_ios::ostream &os, + const SymbolProperties &sp) +{ +#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + os + << kwsys_ios::hex << sp.GetAddress() << " : " + << sp.GetFunction() + << " [(" << sp.GetBinary() << ") " + << sp.GetSourceFile() << ":" + << kwsys_ios::dec << sp.GetLineNumber() << "]"; +#elif defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + void *addr = sp.GetAddress(); + char **syminfo = backtrace_symbols(&addr,1); + os << safes(syminfo[0]); + free(syminfo); +#else + (void)os; + (void)sp; +#endif + return os; +} + +// -------------------------------------------------------------------------- +SymbolProperties::SymbolProperties() +{ + // not using an initializer list + // to avoid some PGI compiler warnings + this->SetBinary("???"); + this->SetBinaryBaseAddress(NULL); + this->Address = NULL; + this->SetSourceFile("???"); + this->SetFunction("???"); + this->SetLineNumber(-1); + this->SetReportPath(0); + // avoid PGI compiler warnings + this->GetRealAddress(); + this->GetFunction(); + this->GetSourceFile(); + this->GetLineNumber(); +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::GetFileName(const kwsys_stl::string &path) const +{ + kwsys_stl::string file(path); + if (!this->ReportPath) + { + size_t at = file.rfind("/"); + if (at!=kwsys_stl::string::npos) + { + file = file.substr(at+1,kwsys_stl::string::npos); + } + } + return file; +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::GetBinary() const +{ +// only linux has proc fs +#if defined(__linux__) + if (this->Binary=="/proc/self/exe") + { + kwsys_stl::string binary; + char buf[1024]={'\0'}; + ssize_t ll=0; + if ((ll=readlink("/proc/self/exe",buf,1024))>0) + { + buf[ll]='\0'; + binary=buf; + } + else + { + binary="/proc/self/exe"; + } + return this->GetFileName(binary); + } +#endif + return this->GetFileName(this->Binary); +} + +// -------------------------------------------------------------------------- +kwsys_stl::string SymbolProperties::Demangle(const char *symbol) const +{ + kwsys_stl::string result = safes(symbol); +#if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) + int status = 0; + size_t bufferLen = 1024; + char *buffer = (char*)malloc(1024); + char *demangledSymbol = + abi::__cxa_demangle(symbol, buffer, &bufferLen, &status); + if (!status) + { + result = demangledSymbol; + } + free(buffer); +#else + (void)symbol; +#endif + return result; +} + +// -------------------------------------------------------------------------- +void SymbolProperties::Initialize(void *address) +{ + this->Address = address; +#if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + // first fallback option can demangle c++ functions + Dl_info info; + int ierr=dladdr(this->Address,&info); + if (ierr && info.dli_sname && info.dli_saddr) + { + this->SetBinary(info.dli_fname); + this->SetFunction(info.dli_sname); + } +#else + // second fallback use builtin backtrace_symbols + // to decode the bactrace. +#endif +} +#endif // don't define this class if we're not using it + } // anonymous namespace + SystemInformationImplementation::SystemInformationImplementation() { this->TotalVirtualMemory = 0; @@ -3335,6 +3598,54 @@ SystemInformationImplementation::GetProcessId() #endif } +/** +return current program stack in a string +demangle cxx symbols if possible. +*/ +kwsys_stl::string SystemInformationImplementation::GetProgramStack( + int firstFrame, + int wholePath) +{ + kwsys_stl::string programStack = "" +#if !defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + "WARNING: The stack could not be examined " + "because backtrace is not supported.\n" +#elif !defined(KWSYS_SYSTEMINFORMATION_HAS_DEBUG_BUILD) + "WARNING: The stack trace will not use advanced " + "capabilities because this is a release build.\n" +#else +# if !defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) + "WARNING: Function names will not be demangled because " + "dladdr is not available.\n" +# endif +# if !defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) + "WARNING: Function names will not be demangled " + "because cxxabi is not available.\n" +# endif +#endif + ; + + kwsys_ios::ostringstream oss; +#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) + void *stackSymbols[256]; + int nFrames=backtrace(stackSymbols,256); + for (int i=firstFrame; i& subkeys, + KeyWOW64 view) +{ + HKEY primaryKey = HKEY_CURRENT_USER; + kwsys_stl::string second; + kwsys_stl::string valuename; + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) + { + return false; + } + + HKEY hKey; + if(RegOpenKeyEx(primaryKey, + second.c_str(), + 0, + SystemToolsMakeRegistryMode(KEY_READ, view), + &hKey) != ERROR_SUCCESS) + { + return false; + } + else + { + char name[1024]; + DWORD dwNameSize = sizeof(name)/sizeof(name[0]); + + DWORD i = 0; + while (RegEnumKey(hKey, i, name, dwNameSize) == ERROR_SUCCESS) + { + subkeys.push_back(name); + ++i; + } + + RegCloseKey(hKey); + } + + return true; +} +#else +bool SystemTools::GetRegistrySubKeys(const char *, + kwsys_stl::vector&, + KeyWOW64) +{ + return false; +} +#endif + // Read a registry value. // Example : // HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath @@ -730,47 +825,14 @@ bool SystemTools::ReadRegistryValue(const char *key, kwsys_stl::string &value, KeyWOW64 view) { bool valueset = false; - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; if(RegOpenKeyEx(primaryKey, second.c_str(), @@ -834,47 +896,14 @@ bool SystemTools::ReadRegistryValue(const char *, kwsys_stl::string &, bool SystemTools::WriteRegistryValue(const char *key, const char *value, KeyWOW64 view) { - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; DWORD dwDummy; char lpClass[] = ""; @@ -919,47 +948,14 @@ bool SystemTools::WriteRegistryValue(const char *, const char *, KeyWOW64) #if defined(_WIN32) && !defined(__CYGWIN__) bool SystemTools::DeleteRegistryValue(const char *key, KeyWOW64 view) { - kwsys_stl::string primary = key; + HKEY primaryKey = HKEY_CURRENT_USER; kwsys_stl::string second; kwsys_stl::string valuename; - - size_t start = primary.find("\\"); - if (start == kwsys_stl::string::npos) + if (!SystemToolsParseRegistryKey(key, primaryKey, second, valuename)) { return false; } - size_t valuenamepos = primary.find(";"); - if (valuenamepos != kwsys_stl::string::npos) - { - valuename = primary.substr(valuenamepos+1); - } - - second = primary.substr(start+1, valuenamepos-start-1); - primary = primary.substr(0, start); - - HKEY primaryKey = HKEY_CURRENT_USER; - if (primary == "HKEY_CURRENT_USER") - { - primaryKey = HKEY_CURRENT_USER; - } - if (primary == "HKEY_CURRENT_CONFIG") - { - primaryKey = HKEY_CURRENT_CONFIG; - } - if (primary == "HKEY_CLASSES_ROOT") - { - primaryKey = HKEY_CLASSES_ROOT; - } - if (primary == "HKEY_LOCAL_MACHINE") - { - primaryKey = HKEY_LOCAL_MACHINE; - } - if (primary == "HKEY_USERS") - { - primaryKey = HKEY_USERS; - } - HKEY hKey; if(RegOpenKeyEx(primaryKey, second.c_str(), @@ -4869,7 +4865,8 @@ static int SystemToolsDebugReport(int, char* message, int*) void SystemTools::EnableMSVCDebugHook() { - if (getenv("DART_TEST_FROM_DART")) + if (getenv("DART_TEST_FROM_DART") || + getenv("DASHBOARD_TEST_FROM_CTEST")) { _CrtSetReportHook(SystemToolsDebugReport); } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index e55d4319f..d6dae3986 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -715,6 +715,13 @@ public: */ enum KeyWOW64 { KeyWOW64_Default, KeyWOW64_32, KeyWOW64_64 }; + /** + * Get a list of subkeys. + */ + static bool GetRegistrySubKeys(const char *key, + kwsys_stl::vector& subkeys, + KeyWOW64 view = KeyWOW64_Default); + /** * Read a registry value */ diff --git a/Source/kwsys/auto_ptr.hxx.in b/Source/kwsys/auto_ptr.hxx.in index 857b1db3c..ad9654cb4 100644 --- a/Source/kwsys/auto_ptr.hxx.in +++ b/Source/kwsys/auto_ptr.hxx.in @@ -31,6 +31,17 @@ # define @KWSYS_NAMESPACE@_AUTO_PTR_CAST(a) a #endif +// In C++11, clang will warn about using dynamic exception specifications +// as they are deprecated. But as this class is trying to faithfully +// mimic std::auto_ptr, we want to keep the 'throw()' decorations below. +// So we suppress the warning. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" +# endif +#endif + namespace @KWSYS_NAMESPACE@ { @@ -198,4 +209,11 @@ public: } // namespace @KWSYS_NAMESPACE@ +// Undo warning suppression. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic pop +# endif +#endif + #endif diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in index c83550304..651de82bf 100644 --- a/Source/kwsys/hashtable.hxx.in +++ b/Source/kwsys/hashtable.hxx.in @@ -62,6 +62,17 @@ # pragma set woff 3970 /* pointer to int conversion */ 3321 3968 #endif +// In C++11, clang will warn about using dynamic exception specifications +// as they are deprecated. But as this class is trying to faithfully +// mimic unordered_set and unordered_map, we want to keep the 'throw()' +// decorations below. So we suppress the warning. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated" +# endif +#endif + #if @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_TEMPLATE # define @KWSYS_NAMESPACE@_HASH_DEFAULT_ALLOCATOR(T) @KWSYS_NAMESPACE@_stl::allocator< T > #elif @KWSYS_NAMESPACE@_STL_HAS_ALLOCATOR_NONTEMPLATE @@ -1268,6 +1279,13 @@ using @KWSYS_NAMESPACE@::operator==; using @KWSYS_NAMESPACE@::operator!=; #endif +// Undo warning suppression. +#if defined(__clang__) && defined(__has_warning) +# if __has_warning("-Wdeprecated") +# pragma clang diagnostic pop +# endif +#endif + #if defined(_MSC_VER) # pragma warning (pop) #endif diff --git a/Source/kwsys/kwsysPlatformTests.cmake b/Source/kwsys/kwsysPlatformTests.cmake index d042450ee..f9ee254f0 100644 --- a/Source/kwsys/kwsysPlatformTests.cmake +++ b/Source/kwsys/kwsysPlatformTests.cmake @@ -19,6 +19,7 @@ MACRO(KWSYS_PLATFORM_TEST lang var description invert) ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/${KWSYS_PLATFORM_TEST_FILE_${lang}} COMPILE_DEFINITIONS -DTEST_${var} ${KWSYS_PLATFORM_TEST_DEFINES} ${KWSYS_PLATFORM_TEST_EXTRA_FLAGS} + CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${KWSYS_PLATFORM_TEST_LINK_LIBRARIES}" OUTPUT_VARIABLE OUTPUT) IF(${var}_COMPILED) FILE(APPEND @@ -150,9 +151,11 @@ ENDMACRO(KWSYS_PLATFORM_C_TEST_RUN) MACRO(KWSYS_PLATFORM_CXX_TEST var description invert) SET(KWSYS_PLATFORM_TEST_DEFINES ${KWSYS_PLATFORM_CXX_TEST_DEFINES}) SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS ${KWSYS_PLATFORM_CXX_TEST_EXTRA_FLAGS}) + SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES ${KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES}) KWSYS_PLATFORM_TEST(CXX "${var}" "${description}" "${invert}") SET(KWSYS_PLATFORM_TEST_DEFINES) SET(KWSYS_PLATFORM_TEST_EXTRA_FLAGS) + SET(KWSYS_PLATFORM_TEST_LINK_LIBRARIES) ENDMACRO(KWSYS_PLATFORM_CXX_TEST) MACRO(KWSYS_PLATFORM_CXX_TEST_RUN var description invert) diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index a7e3b50c0..be7a09ee2 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -513,6 +513,54 @@ int main() } #endif +#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE +#if defined(__PATHSCALE__) || defined(__PATHCC__) \ + || (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41)) +backtrace doesnt work with this compiler or os +#endif +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include +int main() +{ + void *stackSymbols[256]; + backtrace(stackSymbols,256); + backtrace_symbols(&stackSymbols[0],1); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_DLADDR +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include +int main() +{ + Dl_info info; + int ierr=dladdr((void*)main,&info); + return 0; +} +#endif + +#ifdef TEST_KWSYS_CXX_HAS_CXXABI +#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif +#include +int main() +{ + int status = 0; + size_t bufferLen = 512; + char buffer[512] = {'\0'}; + const char *function="_ZN5kwsys17SystemInformation15GetProgramStackEii"; + char *demangledFunction = + abi::__cxa_demangle(function, buffer, &bufferLen, &status); + return status; +} +#endif + #ifdef TEST_KWSYS_CXX_TYPE_INFO /* Collect fundamental type information and save it to a CMake script. */ diff --git a/Source/kwsys/testSystemInformation.cxx b/Source/kwsys/testSystemInformation.cxx index 738043f77..53d51ac40 100644 --- a/Source/kwsys/testSystemInformation.cxx +++ b/Source/kwsys/testSystemInformation.cxx @@ -95,7 +95,24 @@ int testSystemInformation(int, char*[]) kwsys_ios::cout << "CPU feature " << i << "\n"; } } - //int GetProcessorCacheXSize(long int); -// bool DoesCPUSupportFeature(long int); + + /* test stack trace + */ + kwsys_ios::cout + << "Program Stack:" << kwsys_ios::endl + << kwsys::SystemInformation::GetProgramStack(0,0) << kwsys_ios::endl + << kwsys_ios::endl; + + /* test segv handler + info.SetStackTraceOnError(1); + double *d = (double*)100; + *d=0; + */ + + /* test abort handler + info.SetStackTraceOnError(1); + abort(); + */ + return 0; }