|
|
|
@ -28,7 +28,7 @@
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if NV_OS_LINUX && defined(HAVE_EXECINFO_H)
|
|
|
|
|
# include <execinfo.h>
|
|
|
|
|
# include <execinfo.h> // backtrace
|
|
|
|
|
# if NV_CC_GNUC // defined(HAVE_CXXABI_H)
|
|
|
|
|
# include <cxxabi.h>
|
|
|
|
|
# endif
|
|
|
|
@ -39,6 +39,13 @@
|
|
|
|
|
# include <sys/types.h>
|
|
|
|
|
# include <sys/sysctl.h> // sysctl
|
|
|
|
|
# include <ucontext.h>
|
|
|
|
|
# undef HAVE_EXECINFO_H
|
|
|
|
|
# if defined(HAVE_EXECINFO_H) // only after OSX 10.5
|
|
|
|
|
# include <execinfo.h> // backtrace
|
|
|
|
|
# if NV_CC_GNUC // defined(HAVE_CXXABI_H)
|
|
|
|
|
# include <cxxabi.h>
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <stdexcept> // std::runtime_error
|
|
|
|
@ -128,6 +135,10 @@ namespace
|
|
|
|
|
|
|
|
|
|
#if defined(HAVE_EXECINFO_H) // NV_OS_LINUX
|
|
|
|
|
|
|
|
|
|
static bool nvHasStackTrace() {
|
|
|
|
|
return backtrace != NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void nvPrintStackTrace(void * trace[], int size, int start=0) {
|
|
|
|
|
char ** string_array = backtrace_symbols(trace, size);
|
|
|
|
|
|
|
|
|
@ -166,24 +177,36 @@ namespace
|
|
|
|
|
|
|
|
|
|
static void * callerAddress(void * secret)
|
|
|
|
|
{
|
|
|
|
|
# if NV_OS_DARWIN && NV_CPU_PPC
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->ss.srr0;
|
|
|
|
|
# elif NV_OS_DARWIN && NV_CPU_X86
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->ss.eip;
|
|
|
|
|
# elif NV_CPU_X86_64
|
|
|
|
|
// #define REG_RIP REG_INDEX(rip) // seems to be 16
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *)ucp->uc_mcontext.gregs[REG_RIP];
|
|
|
|
|
# elif NV_CPU_X86
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *)ucp->uc_mcontext.gregs[14/*REG_EIP*/];
|
|
|
|
|
# elif NV_CPU_PPC
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext.regs->nip;
|
|
|
|
|
# if NV_OS_DARWIN
|
|
|
|
|
# if defined(_STRUCT_MCONTEXT)
|
|
|
|
|
# if NV_CPU_PPC
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->__ss.__srr0;
|
|
|
|
|
# elif NV_CPU_X86
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->__ss.__eip;
|
|
|
|
|
# endif
|
|
|
|
|
# else
|
|
|
|
|
# if NV_CPU_PPC
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->ss.srr0;
|
|
|
|
|
# elif NV_CPU_X86
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext->ss.eip;
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
# else
|
|
|
|
|
return NULL;
|
|
|
|
|
# if NV_CPU_X86_64
|
|
|
|
|
// #define REG_RIP REG_INDEX(rip) // seems to be 16
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *)ucp->uc_mcontext.gregs[REG_RIP];
|
|
|
|
|
# elif NV_CPU_X86
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *)ucp->uc_mcontext.gregs[14/*REG_EIP*/];
|
|
|
|
|
# elif NV_CPU_PPC
|
|
|
|
|
ucontext_t * ucp = (ucontext_t *)secret;
|
|
|
|
|
return (void *) ucp->uc_mcontext.regs->nip;
|
|
|
|
|
# endif
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
// How to obtain the instruction pointers in different platforms, from mlton's source code.
|
|
|
|
@ -228,17 +251,18 @@ namespace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# if defined(HAVE_EXECINFO_H)
|
|
|
|
|
if (nvHasStackTrace()) // in case of weak linking
|
|
|
|
|
{
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
|
|
|
|
|
if (pnt != NULL) {
|
|
|
|
|
// Overwrite sigaction with caller's address.
|
|
|
|
|
trace[1] = pnt;
|
|
|
|
|
if (pnt != NULL) {
|
|
|
|
|
// Overwrite sigaction with caller's address.
|
|
|
|
|
trace[1] = pnt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvPrintStackTrace(trace, size, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nvPrintStackTrace(trace, size, 1);
|
|
|
|
|
|
|
|
|
|
# endif // defined(HAVE_EXECINFO_H)
|
|
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
@ -373,9 +397,12 @@ namespace
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
# if defined(HAVE_EXECINFO_H)
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
nvPrintStackTrace(trace, size, 3);
|
|
|
|
|
if (nvHasStackTrace())
|
|
|
|
|
{
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
nvPrintStackTrace(trace, size, 3);
|
|
|
|
|
}
|
|
|
|
|
# endif
|
|
|
|
|
|
|
|
|
|
// Exit cleanly.
|
|
|
|
@ -422,9 +449,12 @@ void NV_CDECL nvDebug(const char *msg, ...)
|
|
|
|
|
void debug::dumpInfo()
|
|
|
|
|
{
|
|
|
|
|
#if !NV_OS_WIN32 && defined(HAVE_SIGNAL_H) && defined(HAVE_EXECINFO_H)
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
nvPrintStackTrace(trace, size, 1);
|
|
|
|
|
if (nvHasStackTrace())
|
|
|
|
|
{
|
|
|
|
|
void * trace[64];
|
|
|
|
|
int size = backtrace(trace, 64);
|
|
|
|
|
nvPrintStackTrace(trace, size, 1);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|