diff options
author | KWSys Robot <kwrobot@kitware.com> | 2013-08-06 13:10:11 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2013-08-07 12:18:29 (GMT) |
commit | ce6eac8b58b0230cd1d8ee100a27973e5354a5c4 (patch) | |
tree | 3e190e65b187a9c70ac89786eee80259f0ae8d76 /SystemInformation.cxx | |
parent | 0a44fa4c6c87c76d2adfa1edf68b9f2cfe2096cb (diff) | |
download | CMake-ce6eac8b58b0230cd1d8ee100a27973e5354a5c4.zip CMake-ce6eac8b58b0230cd1d8ee100a27973e5354a5c4.tar.gz CMake-ce6eac8b58b0230cd1d8ee100a27973e5354a5c4.tar.bz2 |
KWSys 2013-08-06 (deec6b8a)
Extract upstream KWSys using the following shell commands.
$ git archive --prefix=upstream-kwsys/ deec6b8a | tar x
$ git shortlog --no-merges --abbrev=8 --format='%h %s' beef6819..deec6b8a
Brad King (1):
e39f85e0 SystemTools: Activate EnableMSVCDebugHook under CTest
Burlen Loring (1):
1d882d4c SystemInformation : Better stack trace
Patrick Gansterer (2):
89e42c36 SystemTools: Remove duplicate code for parsing Windows registry keys
deec6b8a SystemTools: Add a function to get subkeys of a Windows registry key
Sean McBride (1):
4c4f8a9e Supress clang warnings about dynamic exception specifications
Change-Id: I37367dc5db58818d5954735e00c6d523a1dd1411
Diffstat (limited to 'SystemInformation.cxx')
-rw-r--r-- | SystemInformation.cxx | 380 |
1 files changed, 348 insertions, 32 deletions
diff --git a/SystemInformation.cxx b/SystemInformation.cxx index 9db1dee..beefd7d 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -18,6 +18,10 @@ # include <winsock.h> // 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 <execinfo.h> -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) +# include <execinfo.h> +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include <cxxabi.h> +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include <dlfcn.h> +# 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 <execinfo.h> -# if !(defined(__LSB_VERSION__) && __LSB_VERSION__ < 41) -# define KWSYS_SYSTEMINFORMATION_HAVE_BACKTRACE +# if defined(KWSYS_SYSTEMINFORMATION_HAS_CPP_DEMANGLE) +# include <cxxabi.h> +# endif +# if defined(KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP) +# include <dlfcn.h> # 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; i<n; ++i) - { - oss << " " << stackText[i] << kwsys_ios::endl; - } -#endif oss - << "=========================================================" << kwsys_ios::endl; + << kwsys_ios::endl + << "Program Stack:" << kwsys_ios::endl + << SystemInformationImplementation::GetProgramStack(2,0) + << "=========================================================" << kwsys_ios::endl; kwsys_ios::cerr << oss.str() << kwsys_ios::endl; + + // restore the previously registered handlers + // and abort + SystemInformationImplementation::SetStackTraceOnError(0); abort(); #else // avoid warning C4100 @@ -1227,8 +1285,213 @@ void StacktraceSignalHandler( #endif } #endif + +#if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE) +#define safes(_arg)((_arg)?(_arg):"???") + +// Description: +// A container for symbol properties. Each instance +// must be Initialized. +class SymbolProperties +{ +public: + SymbolProperties(); + + // Description: + // The SymbolProperties instance must be initialized by + // passing a stack address. + void Initialize(void *address); + + // Description: + // Get the symbol's stack address. + void *GetAddress() const { return this->Address; } + + // 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; @@ -3336,12 +3599,61 @@ SystemInformationImplementation::GetProcessId() } /** +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<nFrames; ++i) + { + SymbolProperties symProps; + symProps.SetReportPath(wholePath); + symProps.Initialize(stackSymbols[i]); + oss << symProps << kwsys_ios::endl; + } +#else + (void)firstFrame; + (void)wholePath; +#endif + programStack += oss.str(); + + return programStack; +} + + +/** when set print stack trace in response to common signals. */ void SystemInformationImplementation::SetStackTraceOnError(int enable) { #if !defined(_WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) static int saOrigValid=0; + static struct sigaction saABRTOrig; static struct sigaction saSEGVOrig; static struct sigaction saTERMOrig; static struct sigaction saINTOrig; @@ -3349,9 +3661,11 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) static struct sigaction saBUSOrig; static struct sigaction saFPEOrig; + if (enable && !saOrigValid) { // save the current actions + sigaction(SIGABRT,0,&saABRTOrig); sigaction(SIGSEGV,0,&saSEGVOrig); sigaction(SIGTERM,0,&saTERMOrig); sigaction(SIGINT,0,&saINTOrig); @@ -3365,9 +3679,10 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) // install ours struct sigaction sa; sa.sa_sigaction=(SigAction)StacktraceSignalHandler; - sa.sa_flags=SA_SIGINFO|SA_RESTART; + sa.sa_flags=SA_SIGINFO|SA_RESTART|SA_RESETHAND; sigemptyset(&sa.sa_mask); + sigaction(SIGABRT,&sa,0); sigaction(SIGSEGV,&sa,0); sigaction(SIGTERM,&sa,0); sigaction(SIGINT,&sa,0); @@ -3379,6 +3694,7 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable) if (!enable && saOrigValid) { // restore previous actions + sigaction(SIGABRT,&saABRTOrig,0); sigaction(SIGSEGV,&saSEGVOrig,0); sigaction(SIGTERM,&saTERMOrig,0); sigaction(SIGINT,&saINTOrig,0); |