summaryrefslogtreecommitdiff
path: root/Source/kwsys/SystemInformation.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/kwsys/SystemInformation.cxx')
-rw-r--r--Source/kwsys/SystemInformation.cxx384
1 files changed, 350 insertions, 34 deletions
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 9e2a93d7c..beefd7d73 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/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;
@@ -1471,7 +1734,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
{
char host[NI_MAXHOST]={'\0'};
- int addrlen
+ socklen_t addrlen
= (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
ierr=getnameinfo(
@@ -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);
@@ -3487,7 +3803,7 @@ bool SystemInformationImplementation::QueryLinuxMemory()
bool have[6] = { false, false, false, false, false, false };
unsigned long value[6];
int count = 0;
- while(fgets(buffer, sizeof(buffer), fd))
+ while(fgets(buffer, static_cast<int>(sizeof(buffer)), fd))
{
for(int i=0; i < 6; ++i)
{