3535#if defined(__GNUC__)
3636#define USE_UNIX_SIGNAL_HANDLING
3737#include < execinfo.h>
38+ #include < cxxabi.h>
3839#endif
3940
4041#ifdef USE_UNIX_SIGNAL_HANDLING
@@ -179,45 +180,146 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
179180}
180181
181182#if defined(USE_UNIX_SIGNAL_HANDLING)
182- extern " C" void MySignalHandler (int signo, siginfo_t *info, void *context);
183-
184183/* (declare this list here, so it may be used in signal handlers in addition to main())
185184 * A list of signals available in ISO C
186185 * Check out http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html
187186 * For now we only want to detect abnormal behaviour for a few selected signals:
188187 */
189- static const int listofsignals[] = {
190- /* don't care: SIGABRT, */
191- SIGFPE,
192- SIGILL,
193- SIGINT,
194- SIGSEGV,
195- /* don't care: SIGTERM */
188+ struct Signaltype {
189+ int signalnumber;
190+ const char *signalname;
191+ };
192+ #define DECLARE_SIGNAL (x ) {x, #x}
193+ static const Signaltype listofsignals[] = {
194+ // don't care: SIGABRT,
195+ DECLARE_SIGNAL (SIGFPE),
196+ DECLARE_SIGNAL (SIGILL),
197+ DECLARE_SIGNAL (SIGINT),
198+ DECLARE_SIGNAL (SIGSEGV),
199+ // don't care: SIGTERM
196200};
197201
198- static void print_stacktrace (FILE* f)
202+ // Simple helper function
203+ template <typename T, int size>
204+ int GetArrayLength (T(&)[size])
205+ {
206+ return size;
207+ }
208+
209+
210+ /*
211+ * Try to print the callstack.
212+ * That is very sensitive to the operating system, hardware, compiler and runtime!
213+ */
214+ static void print_stacktrace (FILE* f, bool demangling)
199215{
200216#if defined(__GNUC__)
201217 void *array[50 ]= {0 };
202- size_t size = backtrace (array, int (sizeof (array)/sizeof (array[0 ])));
203- char **strings = backtrace_symbols (array, (int )size);
204- fprintf (f, " Callstack:\n " );
205- for (std::size_t i = 0 ; i < size; i++) {
206- fprintf (f, " %s\n " , strings[i]);
218+ const int depth = backtrace (array, (int )GetArrayLength (array));
219+ char **symbolstrings = backtrace_symbols (array, depth);
220+ if (symbolstrings) {
221+ fprintf (f, " Callstack:\n " );
222+ const int offset=3 ; // the first two entries are simply within our own exception handling code, third is within libc
223+ for (int i = offset; i < depth; ++i) {
224+ const char * const symbol = symbolstrings[i];
225+ char * realname = nullptr ;
226+ const char * const firstBracket = strchr (symbol, ' (' );
227+ if (demangling && firstBracket) {
228+ const char * const plus = strchr (firstBracket, ' +' );
229+ if (plus) {
230+ char input_buffer[512 ]= {0 };
231+ strncpy (input_buffer, firstBracket+1 , plus-firstBracket-1 );
232+ char output_buffer[1024 ]= {0 };
233+ size_t length = GetArrayLength (output_buffer);
234+ int status=0 ;
235+ realname = abi::__cxa_demangle (input_buffer, output_buffer, &length, &status); // non-NULL on success
236+ }
237+ }
238+
239+ fprintf (f, " %d. %s\n " ,
240+ i-offset, (realname) ? realname : symbolstrings[i]);
241+ }
242+ free (symbolstrings);
243+ } else {
244+ fprintf (f, " Callstack could not be obtained\n " );
207245 }
208- free (strings);
209246#endif
210247}
211248
212- void MySignalHandler (int signo, siginfo_t * /* info*/ , void * /* context*/ )
249+ /*
250+ * Simple mapping
251+ */
252+ static const char *signal_name (int signo)
213253{
214- fprintf (stderr, " Internal error (caught signal %d). Please report this to the cppcheck developers!\n " ,
215- signo);
216- print_stacktrace (stderr);
254+ for (size_t s=0 ; s<GetArrayLength (listofsignals); ++s) {
255+ if (listofsignals[s].signalnumber ==signo)
256+ return listofsignals[s].signalname ;
257+ }
258+ return " " ;
259+ }
260+
261+ /*
262+ * Entry pointer for signal handlers
263+ */
264+ static void CppcheckSignalHandler (int signo, siginfo_t * info, void * /* context*/ )
265+ {
266+ const char * const signame=signal_name (signo);
267+ bool bPrintCallstack=true ;
268+ switch (signo) {
269+ case SIGILL:
270+ fprintf (stderr, " Internal error (caught signal %d=%s at 0x%p)\n " ,
271+ signo, signame, info->si_addr );
272+ break ;
273+ case SIGFPE:
274+ fprintf (stderr, " Internal error (caught signal %d=%s at 0x%p)\n " ,
275+ signo, signame, info->si_addr );
276+ break ;
277+ case SIGSEGV:
278+ fprintf (stderr, " Internal error (caught signal %d=%s at 0x%p)\n " ,
279+ signo, signame, info->si_addr );
280+ break ;
281+ /*
282+ case SIGBUS:
283+ fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n",
284+ signo, signame, info->si_addr);
285+ break;
286+ case SIGTRAP:
287+ fprintf(stderr, "Internal error (caught signal %d=%s at 0x%p)\n",
288+ signo, signame, info->si_addr);
289+ break;
290+ */
291+ case SIGINT:
292+ bPrintCallstack=false ;
293+ break ;
294+ default :
295+ fprintf (stderr, " Internal error (caught signal %d)\n " ,
296+ signo);
297+ break ;
298+ }
299+ if (bPrintCallstack) {
300+ print_stacktrace (stderr, false );
301+ fprintf (stderr, " Please report this to the cppcheck developers!\n " );
302+ }
217303 abort ();
218304}
219305#endif
220306
307+ #ifdef _MSC_VER
308+ /*
309+ * Any evaluation of the information about the exception needs to be done here!
310+ */
311+ static int filterException (int code, PEXCEPTION_POINTERS ex)
312+ {
313+ // TODO we should try to extract some information here.
314+ return EXCEPTION_EXECUTE_HANDLER;
315+ }
316+ #endif
317+
318+ /* *
319+ * Signal/SEH handling
320+ * TODO Check for multi-threading issues!
321+ *
322+ */
221323int CppCheckExecutor::check_wrapper (CppCheck& cppCheck, int argc, const char * const argv[])
222324{
223325#ifdef _MSC_VER
@@ -226,17 +328,21 @@ int CppCheckExecutor::check_wrapper(CppCheck& cppCheck, int argc, const char* co
226328 */
227329 return check_internal (cppCheck, argc, argv);
228330 /*
229- }
230- except() {
231- return -1;
232- }
331+ }
332+ __except(filterException(GetExceptionCode(), GetExceptionInformation())) {
333+ // reporting to stdout may not be helpful within a GUI application..
334+ fprintf(stderr, "Internal error\n");
335+ fprintf(stderr, "Please report this to the cppcheck developers!\n");
336+ return -1;
337+ }
233338 */
234339#elif defined(USE_UNIX_SIGNAL_HANDLING)
235- struct sigaction act = {0 };
340+ struct sigaction act;
341+ memset (&act, 0 , sizeof (act));
236342 act.sa_flags =SA_SIGINFO;
237- act.sa_sigaction =MySignalHandler ;
238- for (std::size_t s=0 ; s<sizeof (listofsignals)/ sizeof (listofsignals[ 0 ] ); ++s) {
239- sigaction (listofsignals[s], &act, NULL );
343+ act.sa_sigaction =CppcheckSignalHandler ;
344+ for (std::size_t s=0 ; s<GetArrayLength (listofsignals); ++s) {
345+ sigaction (listofsignals[s]. signalnumber , &act, NULL );
240346 }
241347 return check_internal (cppCheck, argc, argv);
242348#else
0 commit comments