Commit 28c708e9 authored by Brad King's avatar Brad King Committed by Code Review
Browse files

Merge topic 'update-kwsys' into master

9cd1b1a9 Merge branch 'upstream-kwsys' into update-kwsys
d485fcc6 KWSys 2013-10-15 (f67bb2ba)
parents 063fb585 9cd1b1a9
......@@ -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)
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()
ENDIF(KWSYS_USE_SystemInformation AND WIN32)
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()
# Apply user-defined target properties to the library.
IF(KWSYS_PROPERTIES_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.
......@@ -84,6 +88,15 @@ typedef int siginfo_t;
# include <ifaddrs.h>
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# 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
#if defined(__OpenBSD__) || defined(__NetBSD__)
......@@ -114,8 +127,15 @@ typedef int siginfo_t;
# define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
# endif
# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 >= 1050
# if defined(KWSYS_SYSTEMINFORMATION_HAS_BACKTRACE)
# include <execinfo.h>
# 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
# endif
#endif
......@@ -130,10 +150,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 +380,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 +839,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 +940,12 @@ int LoadLines(
}
continue;
}
char *pBuf=buf;
while(*pBuf)
{
if (*pBuf=='\n') *pBuf='\0';
pBuf+=1;
}
lines.push_back(buf);
++nRead;
}
......@@ -1046,12 +1084,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 +1154,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 +1175,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 +1189,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 +1218,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 +1276,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
<< "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 +1294,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,12 +1743,12 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
{
char host[NI_MAXHOST]={'\0'};
socklen_t addrlen
const size_t addrlen
= (fam==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6));
ierr=getnameinfo(
ifa->ifa_addr,
addrlen,
static_cast<socklen_t>(addrlen),
host,
NI_MAXHOST,
NULL,
......@@ -3335,6 +3607,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<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.
*/
......@@ -3342,6 +3662,7 @@ 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 +3670,11 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
static struct sigaction saBUSOrig;