Small refactoring of stacktrace printing code
This commit is contained in:
parent
87ce88d6ab
commit
03ecb980a5
|
@ -146,7 +146,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) {
|
else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) {
|
||||||
_settings->exceptionHandling = true;
|
_settings->exceptionHandling = true;
|
||||||
const std::string exceptionOutfilename = &(argv[i][21]);
|
const std::string exceptionOutfilename = &(argv[i][21]);
|
||||||
CppCheckExecutor::setExceptionOutput(exceptionOutfilename);
|
CppCheckExecutor::setExceptionOutput((exceptionOutfilename=="stderr") ? stderr : stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inconclusive checking
|
// Inconclusive checking
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "cppcheckexecutor.h"
|
#include "cppcheckexecutor.h"
|
||||||
#include "cmdlineparser.h"
|
#include "cmdlineparser.h"
|
||||||
#include "cppcheck.h"
|
#include "cppcheck.h"
|
||||||
#include "errorlogger.h"
|
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "pathmatch.h"
|
#include "pathmatch.h"
|
||||||
|
@ -67,7 +66,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*static*/ std::string CppCheckExecutor::exceptionOutput = "stdout";
|
/*static*/ FILE* CppCheckExecutor::exceptionOutput = stdout;
|
||||||
|
|
||||||
CppCheckExecutor::CppCheckExecutor()
|
CppCheckExecutor::CppCheckExecutor()
|
||||||
: _settings(0), time1(0), errorlist(false)
|
: _settings(0), time1(0), errorlist(false)
|
||||||
|
@ -86,7 +85,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
if (parser.GetShowVersion() && !parser.GetShowErrorMessages()) {
|
if (parser.GetShowVersion() && !parser.GetShowErrorMessages()) {
|
||||||
const char * extraVersion = cppcheck->extraVersion();
|
const char * const extraVersion = cppcheck->extraVersion();
|
||||||
if (*extraVersion != 0)
|
if (*extraVersion != 0)
|
||||||
std::cout << "Cppcheck " << cppcheck->version() << " ("
|
std::cout << "Cppcheck " << cppcheck->version() << " ("
|
||||||
<< extraVersion << ')' << std::endl;
|
<< extraVersion << ')' << std::endl;
|
||||||
|
@ -206,13 +205,12 @@ namespace {
|
||||||
* That is very sensitive to the operating system, hardware, compiler and runtime!
|
* That is very sensitive to the operating system, hardware, compiler and runtime!
|
||||||
* The code is not meant for production environment, it's using functions not whitelisted for usage in a signal handler function.
|
* The code is not meant for production environment, it's using functions not whitelisted for usage in a signal handler function.
|
||||||
*/
|
*/
|
||||||
void print_stacktrace(bool useStdout, bool demangling, int maxdepth, bool bLowMem)
|
void print_stacktrace(FILE* output, bool demangling, int maxdepth, bool lowMem)
|
||||||
{
|
{
|
||||||
#if defined(USE_UNIX_BACKTRACE_SUPPORT)
|
#if defined(USE_UNIX_BACKTRACE_SUPPORT)
|
||||||
// 32 vs. 64bit
|
// 32 vs. 64bit
|
||||||
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
|
#define ADDRESSDISPLAYLENGTH ((sizeof(long)==8)?12:8)
|
||||||
FILE* f = (useStdout) ? stdout : stderr;
|
const int fd = fileno(output);
|
||||||
const int fd = (useStdout) ? 1 : 2;
|
|
||||||
void *array[32]= {0}; // the less resources the better...
|
void *array[32]= {0}; // the less resources the better...
|
||||||
const int currentdepth = backtrace(array, (int)GetArrayLength(array));
|
const int currentdepth = backtrace(array, (int)GetArrayLength(array));
|
||||||
const int offset=2; // some entries on top are within our own exception handling code or libc
|
const int offset=2; // some entries on top are within our own exception handling code or libc
|
||||||
|
@ -220,13 +218,15 @@ namespace {
|
||||||
maxdepth=currentdepth-offset;
|
maxdepth=currentdepth-offset;
|
||||||
else
|
else
|
||||||
maxdepth = std::min(maxdepth, currentdepth);
|
maxdepth = std::min(maxdepth, currentdepth);
|
||||||
if (bLowMem) {
|
if (lowMem) {
|
||||||
fputs("Callstack:\n", f);
|
fputs("Callstack (symbols only):\n", output);
|
||||||
|
fflush(output);
|
||||||
backtrace_symbols_fd(array+offset, maxdepth, fd);
|
backtrace_symbols_fd(array+offset, maxdepth, fd);
|
||||||
|
fflush(output);
|
||||||
} else {
|
} else {
|
||||||
char **symbolstrings = backtrace_symbols(array, currentdepth);
|
char **symbolstrings = backtrace_symbols(array, currentdepth);
|
||||||
if (symbolstrings) {
|
if (symbolstrings) {
|
||||||
fputs("Callstack:\n", f);
|
fputs("Callstack:\n", output);
|
||||||
for (int i = offset; i < maxdepth; ++i) {
|
for (int i = offset; i < maxdepth; ++i) {
|
||||||
const char * const symbol = symbolstrings[i];
|
const char * const symbol = symbolstrings[i];
|
||||||
char * realname = nullptr;
|
char * realname = nullptr;
|
||||||
|
@ -248,24 +248,24 @@ namespace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const int ordinal=i-offset;
|
const int ordinal=i-offset;
|
||||||
fprintf(f, "#%-2d 0x",
|
fprintf(output, "#%-2d 0x",
|
||||||
ordinal);
|
ordinal);
|
||||||
if (padLen>0)
|
if (padLen>0)
|
||||||
fprintf(f, "%0*d",
|
fprintf(output, "%0*d",
|
||||||
padLen, 0);
|
padLen, 0);
|
||||||
if (realname) {
|
if (realname) {
|
||||||
fprintf(f, "%.*s in %s\n",
|
fprintf(output, "%.*s in %s\n",
|
||||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||||
realname);
|
realname);
|
||||||
} else {
|
} else {
|
||||||
fprintf(f, "%.*s in %.*s\n",
|
fprintf(output, "%.*s in %.*s\n",
|
||||||
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
(int)(secondBracketAddress-firstBracketAddress-3), firstBracketAddress+3,
|
||||||
(int)(firstBracketAddress-symbol), symbol);
|
(int)(firstBracketAddress-symbol), symbol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(symbolstrings);
|
free(symbolstrings);
|
||||||
} else {
|
} else {
|
||||||
fputs("Callstack could not be obtained\n", f);
|
fputs("Callstack could not be obtained\n", output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef ADDRESSDISPLAYLENGTH
|
#undef ADDRESSDISPLAYLENGTH
|
||||||
|
@ -277,10 +277,11 @@ namespace {
|
||||||
bool bStackBelowHeap=false; // lame attempt to locate heap vs. stack address space. See CppCheckExecutor::check_wrapper()
|
bool bStackBelowHeap=false; // lame attempt to locate heap vs. stack address space. See CppCheckExecutor::check_wrapper()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
* \param[in] ptr address to be examined.
|
||||||
* \return true if address is supposed to be on stack (contrary to heap or elsewhere). If ptr is 0 false will be returned.
|
* \return true if address is supposed to be on stack (contrary to heap or elsewhere). If ptr is 0 false will be returned.
|
||||||
* If unknown better return false.
|
* If unknown better return false.
|
||||||
*/
|
*/
|
||||||
bool isAddressOnStack(const void* ptr)
|
bool IsAddressOnStack(const void* ptr)
|
||||||
{
|
{
|
||||||
if (nullptr==ptr)
|
if (nullptr==ptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -312,6 +313,7 @@ namespace {
|
||||||
DECLARE_SIGNAL(SIGUSR1)
|
DECLARE_SIGNAL(SIGUSR1)
|
||||||
DECLARE_SIGNAL(SIGUSR2)
|
DECLARE_SIGNAL(SIGUSR2)
|
||||||
;
|
;
|
||||||
|
#undef DECLARE_SIGNAL
|
||||||
/*
|
/*
|
||||||
* Entry pointer for signal handlers
|
* Entry pointer for signal handlers
|
||||||
* It uses functions which are not safe to be called from a signal handler,
|
* It uses functions which are not safe to be called from a signal handler,
|
||||||
|
@ -331,138 +333,137 @@ namespace {
|
||||||
#endif
|
#endif
|
||||||
const Signalmap_t::const_iterator it=listofsignals.find(signo);
|
const Signalmap_t::const_iterator it=listofsignals.find(signo);
|
||||||
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
|
const char * const signame = (it==listofsignals.end()) ? "unknown" : it->second.c_str();
|
||||||
bool bPrintCallstack=true;
|
bool printCallstack=true;
|
||||||
bool bLowMem=false;
|
bool lowMem=false;
|
||||||
bool bUnexpectedSignal=true;
|
bool unexpectedSignal=true;
|
||||||
const bool isaddressonstack = isAddressOnStack(info->si_addr);
|
const bool isaddressonstack = IsAddressOnStack(info->si_addr);
|
||||||
const bool useStdout = CppCheckExecutor::getExceptionOutput()=="stdout";
|
FILE* output = CppCheckExecutor::getExceptionOutput();
|
||||||
FILE* f = (useStdout) ? stdout : stderr;
|
|
||||||
switch (signo) {
|
switch (signo) {
|
||||||
case SIGABRT:
|
case SIGABRT:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
fputs(" - out of memory?\n", f);
|
fputs(" - out of memory?\n", output);
|
||||||
bLowMem=true;
|
lowMem=true; // educated guess
|
||||||
break;
|
break;
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case BUS_ADRALN: // invalid address alignment
|
case BUS_ADRALN: // invalid address alignment
|
||||||
fputs(" - BUS_ADRALN", f);
|
fputs(" - BUS_ADRALN", output);
|
||||||
break;
|
break;
|
||||||
case BUS_ADRERR: // nonexistent physical address
|
case BUS_ADRERR: // nonexistent physical address
|
||||||
fputs(" - BUS_ADRERR", f);
|
fputs(" - BUS_ADRERR", output);
|
||||||
break;
|
break;
|
||||||
case BUS_OBJERR: // object-specific hardware error
|
case BUS_OBJERR: // object-specific hardware error
|
||||||
fputs(" - BUS_OBJERR", f);
|
fputs(" - BUS_OBJERR", output);
|
||||||
break;
|
break;
|
||||||
#ifdef BUS_MCEERR_AR
|
#ifdef BUS_MCEERR_AR
|
||||||
case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check;
|
case BUS_MCEERR_AR: // Hardware memory error consumed on a machine check;
|
||||||
fputs(" - BUS_MCEERR_AR", f);
|
fputs(" - BUS_MCEERR_AR", output);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUS_MCEERR_AO
|
#ifdef BUS_MCEERR_AO
|
||||||
case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed
|
case BUS_MCEERR_AO: // Hardware memory error detected in process but not consumed
|
||||||
fputs(" - BUS_MCEERR_AO", f);
|
fputs(" - BUS_MCEERR_AO", output);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(f, " (at 0x%lx).\n",
|
fprintf(output, " (at 0x%lx).\n",
|
||||||
(unsigned long)info->si_addr);
|
(unsigned long)info->si_addr);
|
||||||
break;
|
break;
|
||||||
case SIGFPE:
|
case SIGFPE:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case FPE_INTDIV: // integer divide by zero
|
case FPE_INTDIV: // integer divide by zero
|
||||||
fputs(" - FPE_INTDIV", f);
|
fputs(" - FPE_INTDIV", output);
|
||||||
break;
|
break;
|
||||||
case FPE_INTOVF: // integer overflow
|
case FPE_INTOVF: // integer overflow
|
||||||
fputs(" - FPE_INTOVF", f);
|
fputs(" - FPE_INTOVF", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTDIV: // floating-point divide by zero
|
case FPE_FLTDIV: // floating-point divide by zero
|
||||||
fputs(" - FPE_FLTDIV", f);
|
fputs(" - FPE_FLTDIV", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTOVF: // floating-point overflow
|
case FPE_FLTOVF: // floating-point overflow
|
||||||
fputs(" - FPE_FLTOVF", f);
|
fputs(" - FPE_FLTOVF", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTUND: // floating-point underflow
|
case FPE_FLTUND: // floating-point underflow
|
||||||
fputs(" - FPE_FLTUND", f);
|
fputs(" - FPE_FLTUND", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTRES: // floating-point inexact result
|
case FPE_FLTRES: // floating-point inexact result
|
||||||
fputs(" - FPE_FLTRES", f);
|
fputs(" - FPE_FLTRES", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTINV: // floating-point invalid operation
|
case FPE_FLTINV: // floating-point invalid operation
|
||||||
fputs(" - FPE_FLTINV", f);
|
fputs(" - FPE_FLTINV", output);
|
||||||
break;
|
break;
|
||||||
case FPE_FLTSUB: // subscript out of range
|
case FPE_FLTSUB: // subscript out of range
|
||||||
fputs(" - FPE_FLTSUB", f);
|
fputs(" - FPE_FLTSUB", output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(f, " (at 0x%lx).\n",
|
fprintf(output, " (at 0x%lx).\n",
|
||||||
(unsigned long)info->si_addr);
|
(unsigned long)info->si_addr);
|
||||||
break;
|
break;
|
||||||
case SIGILL:
|
case SIGILL:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case ILL_ILLOPC: // illegal opcode
|
case ILL_ILLOPC: // illegal opcode
|
||||||
fputs(" - ILL_ILLOPC", f);
|
fputs(" - ILL_ILLOPC", output);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLOPN: // illegal operand
|
case ILL_ILLOPN: // illegal operand
|
||||||
fputs(" - ILL_ILLOPN", f);
|
fputs(" - ILL_ILLOPN", output);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLADR: // illegal addressing mode
|
case ILL_ILLADR: // illegal addressing mode
|
||||||
fputs(" - ILL_ILLADR", f);
|
fputs(" - ILL_ILLADR", output);
|
||||||
break;
|
break;
|
||||||
case ILL_ILLTRP: // illegal trap
|
case ILL_ILLTRP: // illegal trap
|
||||||
fputs(" - ILL_ILLTRP", f);
|
fputs(" - ILL_ILLTRP", output);
|
||||||
break;
|
break;
|
||||||
case ILL_PRVOPC: // privileged opcode
|
case ILL_PRVOPC: // privileged opcode
|
||||||
fputs(" - ILL_PRVOPC", f);
|
fputs(" - ILL_PRVOPC", output);
|
||||||
break;
|
break;
|
||||||
case ILL_PRVREG: // privileged register
|
case ILL_PRVREG: // privileged register
|
||||||
fputs(" - ILL_PRVREG", f);
|
fputs(" - ILL_PRVREG", output);
|
||||||
break;
|
break;
|
||||||
case ILL_COPROC: // coprocessor error
|
case ILL_COPROC: // coprocessor error
|
||||||
fputs(" - ILL_COPROC", f);
|
fputs(" - ILL_COPROC", output);
|
||||||
break;
|
break;
|
||||||
case ILL_BADSTK: // internal stack error
|
case ILL_BADSTK: // internal stack error
|
||||||
fputs(" - ILL_BADSTK", f);
|
fputs(" - ILL_BADSTK", output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(f, " (at 0x%lx).%s\n",
|
fprintf(output, " (at 0x%lx).%s\n",
|
||||||
(unsigned long)info->si_addr,
|
(unsigned long)info->si_addr,
|
||||||
(isaddressonstack)?" Stackoverflow?":"");
|
(isaddressonstack)?" Stackoverflow?":"");
|
||||||
break;
|
break;
|
||||||
case SIGINT:
|
case SIGINT:
|
||||||
bUnexpectedSignal=false;
|
unexpectedSignal=false;
|
||||||
fputs("cppcheck received signal ", f);
|
fputs("cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
bPrintCallstack=true;
|
printCallstack=true;
|
||||||
fputs(".\n", f);
|
fputs(".\n", output);
|
||||||
break;
|
break;
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
switch (info->si_code) {
|
switch (info->si_code) {
|
||||||
case SEGV_MAPERR: // address not mapped to object
|
case SEGV_MAPERR: // address not mapped to object
|
||||||
fputs(" - SEGV_MAPERR", f);
|
fputs(" - SEGV_MAPERR", output);
|
||||||
break;
|
break;
|
||||||
case SEGV_ACCERR: // invalid permissions for mapped object
|
case SEGV_ACCERR: // invalid permissions for mapped object
|
||||||
fputs(" - SEGV_ACCERR", f);
|
fputs(" - SEGV_ACCERR", output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fprintf(f, " (%sat 0x%lx).%s\n",
|
fprintf(output, " (%sat 0x%lx).%s\n",
|
||||||
(type==-1)? "" :
|
(type==-1)? "" :
|
||||||
(type==0) ? "reading " : "writing ",
|
(type==0) ? "reading " : "writing ",
|
||||||
(unsigned long)info->si_addr,
|
(unsigned long)info->si_addr,
|
||||||
|
@ -470,24 +471,24 @@ namespace {
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case SIGUSR1:
|
case SIGUSR1:
|
||||||
bUnexpectedSignal=false;
|
unexpectedSignal=false;
|
||||||
fputs("cppcheck received signal ", f);
|
fputs("cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
fputs(".\n", f);
|
fputs(".\n", output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fputs("Internal error: cppcheck received signal ", f);
|
fputs("Internal error: cppcheck received signal ", output);
|
||||||
fputs(signame, f);
|
fputs(signame, output);
|
||||||
fputs(".\n", f);
|
fputs(".\n", output);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (bPrintCallstack) {
|
if (printCallstack) {
|
||||||
print_stacktrace(f, true, -1, bLowMem);
|
print_stacktrace(output, true, -1, lowMem);
|
||||||
}
|
}
|
||||||
if (bUnexpectedSignal) {
|
if (unexpectedSignal) {
|
||||||
fputs("\nPlease report this to the cppcheck developers!\n", f);
|
fputs("\nPlease report this to the cppcheck developers!\n", output);
|
||||||
}
|
}
|
||||||
fflush(f);
|
fflush(output);
|
||||||
|
|
||||||
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
// now let things proceed, shutdown and hopefully dump core for post-mortem analysis
|
||||||
signal(signo, SIG_DFL);
|
signal(signo, SIG_DFL);
|
||||||
|
@ -535,7 +536,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PrintCallstack(FILE* f, PEXCEPTION_POINTERS ex)
|
void PrintCallstack(FILE* output, PEXCEPTION_POINTERS ex)
|
||||||
{
|
{
|
||||||
if (!loadDbgHelp())
|
if (!loadDbgHelp())
|
||||||
return;
|
return;
|
||||||
|
@ -594,11 +595,11 @@ namespace {
|
||||||
++beyond_main;
|
++beyond_main;
|
||||||
if (_tcscmp(undname, _T("main"))==0)
|
if (_tcscmp(undname, _T("main"))==0)
|
||||||
beyond_main=0;
|
beyond_main=0;
|
||||||
fprintf(f,
|
fprintf(output,
|
||||||
"%lu. 0x%08I64X in ",
|
"%lu. 0x%08I64X in ",
|
||||||
frame, (ULONG64)stack.AddrPC.Offset);
|
frame, (ULONG64)stack.AddrPC.Offset);
|
||||||
fputs((const char *)undname, f);
|
fputs((const char *)undname, output);
|
||||||
fputc('\n', f);
|
fputc('\n', output);
|
||||||
if (0==stack.AddrReturn.Offset || beyond_main>2) // StackWalk64() sometimes doesn't reach any end...
|
if (0==stack.AddrReturn.Offset || beyond_main>2) // StackWalk64() sometimes doesn't reach any end...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -607,24 +608,24 @@ namespace {
|
||||||
hLibDbgHelp=0;
|
hLibDbgHelp=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeMemoryErrorDetails(FILE* f, PEXCEPTION_POINTERS ex, const char* description)
|
void writeMemoryErrorDetails(FILE* output, PEXCEPTION_POINTERS ex, const char* description)
|
||||||
{
|
{
|
||||||
fputs(description, f);
|
fputs(description, output);
|
||||||
fprintf(f, " (instruction: 0x%p) ", ex->ExceptionRecord->ExceptionAddress);
|
fprintf(output, " (instruction: 0x%p) ", ex->ExceptionRecord->ExceptionAddress);
|
||||||
// Using %p for ULONG_PTR later on, so it must have size identical to size of pointer
|
// Using %p for ULONG_PTR later on, so it must have size identical to size of pointer
|
||||||
// This is not the universally portable solution but good enough for Win32/64
|
// This is not the universally portable solution but good enough for Win32/64
|
||||||
C_ASSERT(sizeof(void*) == sizeof(ex->ExceptionRecord->ExceptionInformation[1]));
|
C_ASSERT(sizeof(void*) == sizeof(ex->ExceptionRecord->ExceptionInformation[1]));
|
||||||
switch (ex->ExceptionRecord->ExceptionInformation[0]) {
|
switch (ex->ExceptionRecord->ExceptionInformation[0]) {
|
||||||
case 0:
|
case 0:
|
||||||
fprintf(f, "reading from 0x%p",
|
fprintf(output, "reading from 0x%p",
|
||||||
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
fprintf(f, "writing to 0x%p",
|
fprintf(output, "writing to 0x%p",
|
||||||
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
fprintf(f, "data execution prevention at 0x%p",
|
fprintf(output, "data execution prevention at 0x%p",
|
||||||
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
reinterpret_cast<void*>(ex->ExceptionRecord->ExceptionInformation[1]));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -637,82 +638,82 @@ namespace {
|
||||||
*/
|
*/
|
||||||
int filterException(int code, PEXCEPTION_POINTERS ex)
|
int filterException(int code, PEXCEPTION_POINTERS ex)
|
||||||
{
|
{
|
||||||
FILE *f = stdout;
|
FILE *output = stdout;
|
||||||
fputs("Internal error: ", f);
|
fputs("Internal error: ", output);
|
||||||
switch (ex->ExceptionRecord->ExceptionCode) {
|
switch (ex->ExceptionRecord->ExceptionCode) {
|
||||||
case EXCEPTION_ACCESS_VIOLATION:
|
case EXCEPTION_ACCESS_VIOLATION:
|
||||||
writeMemoryErrorDetails(f, ex, "Access violation");
|
writeMemoryErrorDetails(output, ex, "Access violation");
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||||
fputs("Out of array bounds", f);
|
fputs("Out of array bounds", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_BREAKPOINT:
|
case EXCEPTION_BREAKPOINT:
|
||||||
fputs("Breakpoint", f);
|
fputs("Breakpoint", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||||
fputs("Misaligned data", f);
|
fputs("Misaligned data", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||||
fputs("Denormalized floating-point value", f);
|
fputs("Denormalized floating-point value", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||||
fputs("Floating-point divide-by-zero", f);
|
fputs("Floating-point divide-by-zero", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||||
fputs("Inexact floating-point value", f);
|
fputs("Inexact floating-point value", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||||
fputs("Invalid floating-point operation", f);
|
fputs("Invalid floating-point operation", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_OVERFLOW:
|
case EXCEPTION_FLT_OVERFLOW:
|
||||||
fputs("Floating-point overflow", f);
|
fputs("Floating-point overflow", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_STACK_CHECK:
|
case EXCEPTION_FLT_STACK_CHECK:
|
||||||
fputs("Floating-point stack overflow", f);
|
fputs("Floating-point stack overflow", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_FLT_UNDERFLOW:
|
case EXCEPTION_FLT_UNDERFLOW:
|
||||||
fputs("Floating-point underflow", f);
|
fputs("Floating-point underflow", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_GUARD_PAGE:
|
case EXCEPTION_GUARD_PAGE:
|
||||||
fputs("Page-guard access", f);
|
fputs("Page-guard access", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||||
fputs("Illegal instruction", f);
|
fputs("Illegal instruction", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_IN_PAGE_ERROR:
|
case EXCEPTION_IN_PAGE_ERROR:
|
||||||
writeMemoryErrorDetails(f, ex, "Invalid page access");
|
writeMemoryErrorDetails(output, ex, "Invalid page access");
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||||
fputs("Integer divide-by-zero", f);
|
fputs("Integer divide-by-zero", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_INT_OVERFLOW:
|
case EXCEPTION_INT_OVERFLOW:
|
||||||
fputs("Integer overflow", f);
|
fputs("Integer overflow", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_INVALID_DISPOSITION:
|
case EXCEPTION_INVALID_DISPOSITION:
|
||||||
fputs("Invalid exception dispatcher", f);
|
fputs("Invalid exception dispatcher", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_INVALID_HANDLE:
|
case EXCEPTION_INVALID_HANDLE:
|
||||||
fputs("Invalid handle", f);
|
fputs("Invalid handle", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
|
||||||
fputs("Non-continuable exception", f);
|
fputs("Non-continuable exception", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_PRIV_INSTRUCTION:
|
case EXCEPTION_PRIV_INSTRUCTION:
|
||||||
fputs("Invalid instruction", f);
|
fputs("Invalid instruction", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_SINGLE_STEP:
|
case EXCEPTION_SINGLE_STEP:
|
||||||
fputs("Single instruction step", f);
|
fputs("Single instruction step", output);
|
||||||
break;
|
break;
|
||||||
case EXCEPTION_STACK_OVERFLOW:
|
case EXCEPTION_STACK_OVERFLOW:
|
||||||
fputs("Stack overflow", f);
|
fputs("Stack overflow", output);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(f, "Unknown exception (%d)\n",
|
fprintf(output, "Unknown exception (%d)\n",
|
||||||
code);
|
code);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fputc('\n', f);
|
fputc('\n', output);
|
||||||
PrintCallstack(f, ex);
|
PrintCallstack(output, ex);
|
||||||
fflush(f);
|
fflush(f);
|
||||||
return EXCEPTION_EXECUTE_HANDLER;
|
return EXCEPTION_EXECUTE_HANDLER;
|
||||||
}
|
}
|
||||||
|
@ -728,12 +729,12 @@ namespace {
|
||||||
int CppCheckExecutor::check_wrapper(CppCheck& cppcheck, int argc, const char* const argv[])
|
int CppCheckExecutor::check_wrapper(CppCheck& cppcheck, int argc, const char* const argv[])
|
||||||
{
|
{
|
||||||
#ifdef USE_WINDOWS_SEH
|
#ifdef USE_WINDOWS_SEH
|
||||||
FILE *f = stdout;
|
FILE *output = stdout;
|
||||||
__try {
|
__try {
|
||||||
return check_internal(cppcheck, argc, argv);
|
return check_internal(cppcheck, argc, argv);
|
||||||
} __except (filterException(GetExceptionCode(), GetExceptionInformation())) {
|
} __except (filterException(GetExceptionCode(), GetExceptionInformation())) {
|
||||||
// reporting to stdout may not be helpful within a GUI application...
|
// reporting to stdout may not be helpful within a GUI application...
|
||||||
fputs("Please report this to the cppcheck developers!\n", f);
|
fputs("Please report this to the cppcheck developers!\n", output);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#elif defined(USE_UNIX_SIGNAL_HANDLING)
|
#elif defined(USE_UNIX_SIGNAL_HANDLING)
|
||||||
|
@ -955,12 +956,12 @@ void CppCheckExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CppCheckExecutor::setExceptionOutput(const std::string& fn)
|
void CppCheckExecutor::setExceptionOutput(FILE* exception_output)
|
||||||
{
|
{
|
||||||
exceptionOutput=fn;
|
exceptionOutput=exception_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& CppCheckExecutor::getExceptionOutput()
|
FILE* CppCheckExecutor::getExceptionOutput()
|
||||||
{
|
{
|
||||||
return exceptionOutput;
|
return exceptionOutput;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#define CPPCHECKEXECUTOR_H
|
#define CPPCHECKEXECUTOR_H
|
||||||
|
|
||||||
#include "errorlogger.h"
|
#include "errorlogger.h"
|
||||||
|
#include <cstdio>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -89,14 +90,13 @@ public:
|
||||||
static void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal);
|
static void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param fn file name to be used from exception handler: Has to be either "stdout" or "stderr".
|
* @param fp Output file
|
||||||
* Invalid arguments will be silently ignored. Default is "stdout".
|
|
||||||
*/
|
*/
|
||||||
static void setExceptionOutput(const std::string& fn);
|
static void setExceptionOutput(FILE* fp);
|
||||||
/**
|
/**
|
||||||
* @return file name to be used for output from exception handler. Has to be either "stdout" or "stderr".
|
* @return file name to be used for output from exception handler. Has to be either "stdout" or "stderr".
|
||||||
*/
|
*/
|
||||||
static const std::string& getExceptionOutput();
|
static FILE* getExceptionOutput();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to load a library and prints warning/error messages
|
* Tries to load a library and prints warning/error messages
|
||||||
|
@ -172,7 +172,7 @@ private:
|
||||||
/**
|
/**
|
||||||
* Output file name for exception handler
|
* Output file name for exception handler
|
||||||
*/
|
*/
|
||||||
static std::string exceptionOutput;
|
static FILE* exceptionOutput;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Has --errorlist been given?
|
* Has --errorlist been given?
|
||||||
|
|
Loading…
Reference in New Issue