Changeset f660b10 for src


Ignore:
Timestamp:
Sep 18, 2024, 4:51:28 PM (3 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
0185b68
Parents:
59627b3
Message:

Moved the backtrace/signal code to the bottom of the main file (so people don't have to scroll past it.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/main.cpp

    r59627b3 rf660b10  
    125125static void dump( ast::TranslationUnit && transUnit, ostream & out = cout );
    126126
    127 static void backtrace( int start ) {                                    // skip first N stack frames
    128         enum { Frames = 50, };                                                          // maximum number of stack frames
    129         void * array[Frames];
    130         size_t size = ::backtrace( array, Frames );
    131         char ** messages = ::backtrace_symbols( array, size ); // does not demangle names
    132 
    133         *index( messages[0], '(' ) = '\0';                                      // find executable name
    134         cerr << "Stack back trace for: " << messages[0] << endl;
    135 
    136         // skip last 2 stack frames after main
    137         for ( unsigned int i = start; i < size - 2 && messages != nullptr; i += 1 ) {
    138                 char * mangled_name = nullptr, * offset_begin = nullptr, * offset_end = nullptr;
    139 
    140                 for ( char * p = messages[i]; *p; p += 1 ) {    // find parantheses and +offset
    141                         if ( *p == '(' ) {
    142                                 mangled_name = p;
    143                         } else if ( *p == '+' ) {
    144                                 offset_begin = p;
    145                         } else if ( *p == ')' ) {
    146                                 offset_end = p;
    147                                 break;
    148                         } // if
    149                 } // for
    150 
    151                 // if line contains symbol, attempt to demangle
    152                 int frameNo = i - start;
    153                 if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin ) {
    154                         *mangled_name++ = '\0';                                         // delimit strings
    155                         *offset_begin++ = '\0';
    156                         *offset_end++ = '\0';
    157 
    158                         int status;
    159                         char * real_name = __cxxabiv1::__cxa_demangle( mangled_name, 0, 0, &status );
    160                         // bug in __cxa_demangle for single-character lower-case non-mangled names
    161                         if ( status == 0 ) {                                            // demangling successful ?
    162                                 cerr << "(" << frameNo << ") " << messages[i] << " : "
    163                                          << real_name << "+" << offset_begin << offset_end << endl;
    164                         } else {                                                                        // otherwise, output mangled name
    165                                 cerr << "(" << frameNo << ") " << messages[i] << " : "
    166                                          << mangled_name << "(/*unknown*/)+" << offset_begin << offset_end << endl;
    167                         } // if
    168 
    169                         free( real_name );
    170                 } else {                                                                                // otherwise, print the whole line
    171                         cerr << "(" << frameNo << ") " << messages[i] << endl;
    172                 } // if
    173         } // for
    174 
    175         free( messages );
    176 } // backtrace
    177 
    178 #define SIGPARMS int sig __attribute__(( unused )), siginfo_t * sfp __attribute__(( unused )), ucontext_t * cxt __attribute__(( unused ))
    179 
    180 static void _Signal(struct sigaction & act, int sig, int flags ) {
    181         sigemptyset( &act.sa_mask );
    182         act.sa_flags = flags;
    183 
    184         if ( sigaction( sig, &act, nullptr ) == -1 ) {
    185             cerr << "*cfa-cpp compilation error* problem installing signal handler, error(" << errno << ") " << strerror( errno ) << endl;
    186             _exit( EXIT_FAILURE );
    187         } // if
    188 }
    189 
    190 static void Signal( int sig, void (* handler)(SIGPARMS), int flags ) {
    191         struct sigaction act;
    192         act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
    193         _Signal(act, sig, flags);
    194 } // Signal
    195 
    196 static void Signal( int sig, void (* handler)(int), int flags ) {
    197         struct sigaction act;
    198         act.sa_handler = handler;
    199         _Signal(act, sig, flags);
    200 } // Signal
    201 
    202 static void sigSegvBusHandler( SIGPARMS ) {
    203         if ( sfp->si_addr == nullptr ) {
    204                 cerr << "Null pointer (nullptr) dereference." << endl;
    205         } else {
    206                 cerr << (sig == SIGSEGV ? "Segment fault" : "Bus error") << " at memory location " << sfp->si_addr << "." << endl
    207                          << "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript." << endl;
    208         } // if
    209         backtrace( 2 );                                                                         // skip first 2 stack frames
    210         abort();                                                                                        // cause core dump for debugging
    211 } // sigSegvBusHandler
    212 
    213 static void sigFpeHandler( SIGPARMS ) {
    214         const char * msg;
    215 
    216         switch ( sfp->si_code ) {
    217           case FPE_INTDIV: case FPE_FLTDIV: msg = "divide by zero"; break;
    218           case FPE_FLTOVF: msg = "overflow"; break;
    219           case FPE_FLTUND: msg = "underflow"; break;
    220           case FPE_FLTRES: msg = "inexact result"; break;
    221           case FPE_FLTINV: msg = "invalid operation"; break;
    222           default: msg = "unknown";
    223         } // choose
    224         cerr << "Computation error " << msg << " at location " << sfp->si_addr << endl
    225                  << "Possible cause is constant-expression evaluation invalid." << endl;
    226         backtrace( 2 );                                                                         // skip first 2 stack frames
    227         abort();                                                                                        // cause core dump for debugging
    228 } // sigFpeHandler
    229 
    230 static void sigAbortHandler( SIGPARMS ) {
    231         backtrace( 6 );                                                                         // skip first 6 stack frames
    232         Signal( SIGABRT, SIG_DFL, SA_SIGINFO ); // reset default signal handler
    233         raise( SIGABRT );                                                                       // reraise SIGABRT
    234 } // sigAbortHandler
     127static void backtrace( int start );
     128static void initSignals();
    235129
    236130int main( int argc, char * argv[] ) {
     
    239133        ast::TranslationUnit transUnit;
    240134
    241         Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO );
    242         Signal( SIGBUS, sigSegvBusHandler, SA_SIGINFO );
    243         Signal( SIGFPE, sigFpeHandler, SA_SIGINFO );
    244         Signal( SIGABRT, sigAbortHandler, SA_SIGINFO );
     135        initSignals();
    245136
    246137        // cout << "main" << endl;
     
    713604}
    714605
     606static void backtrace( int start ) {                                    // skip first N stack frames
     607        enum { Frames = 50, };                                                          // maximum number of stack frames
     608        void * array[Frames];
     609        size_t size = ::backtrace( array, Frames );
     610        char ** messages = ::backtrace_symbols( array, size ); // does not demangle names
     611
     612        *index( messages[0], '(' ) = '\0';                                      // find executable name
     613        cerr << "Stack back trace for: " << messages[0] << endl;
     614
     615        // skip last 2 stack frames after main
     616        for ( unsigned int i = start; i < size - 2 && messages != nullptr; i += 1 ) {
     617                char * mangled_name = nullptr, * offset_begin = nullptr, * offset_end = nullptr;
     618
     619                for ( char * p = messages[i]; *p; p += 1 ) {    // find parantheses and +offset
     620                        if ( *p == '(' ) {
     621                                mangled_name = p;
     622                        } else if ( *p == '+' ) {
     623                                offset_begin = p;
     624                        } else if ( *p == ')' ) {
     625                                offset_end = p;
     626                                break;
     627                        } // if
     628                } // for
     629
     630                // if line contains symbol, attempt to demangle
     631                int frameNo = i - start;
     632                if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin ) {
     633                        *mangled_name++ = '\0';                                         // delimit strings
     634                        *offset_begin++ = '\0';
     635                        *offset_end++ = '\0';
     636
     637                        int status;
     638                        char * real_name = __cxxabiv1::__cxa_demangle( mangled_name, 0, 0, &status );
     639                        // bug in __cxa_demangle for single-character lower-case non-mangled names
     640                        if ( status == 0 ) {                                            // demangling successful ?
     641                                cerr << "(" << frameNo << ") " << messages[i] << " : "
     642                                         << real_name << "+" << offset_begin << offset_end << endl;
     643                        } else {                                                                        // otherwise, output mangled name
     644                                cerr << "(" << frameNo << ") " << messages[i] << " : "
     645                                         << mangled_name << "(/*unknown*/)+" << offset_begin << offset_end << endl;
     646                        } // if
     647
     648                        free( real_name );
     649                } else {                                                                                // otherwise, print the whole line
     650                        cerr << "(" << frameNo << ") " << messages[i] << endl;
     651                } // if
     652        } // for
     653
     654        free( messages );
     655} // backtrace
     656
     657#define SIGPARMS int sig __attribute__(( unused )), siginfo_t * sfp __attribute__(( unused )), ucontext_t * cxt __attribute__(( unused ))
     658
     659static void _Signal(struct sigaction & act, int sig, int flags ) {
     660        sigemptyset( &act.sa_mask );
     661        act.sa_flags = flags;
     662
     663        if ( sigaction( sig, &act, nullptr ) == -1 ) {
     664            cerr << "*cfa-cpp compilation error* problem installing signal handler, error(" << errno << ") " << strerror( errno ) << endl;
     665            _exit( EXIT_FAILURE );
     666        } // if
     667}
     668
     669static void Signal( int sig, void (* handler)(SIGPARMS), int flags ) {
     670        struct sigaction act;
     671        act.sa_sigaction = (void (*)(int, siginfo_t *, void *))handler;
     672        _Signal(act, sig, flags);
     673} // Signal
     674
     675static void Signal( int sig, void (* handler)(int), int flags ) {
     676        struct sigaction act;
     677        act.sa_handler = handler;
     678        _Signal(act, sig, flags);
     679} // Signal
     680
     681static void sigSegvBusHandler( SIGPARMS ) {
     682        if ( sfp->si_addr == nullptr ) {
     683                cerr << "Null pointer (nullptr) dereference." << endl;
     684        } else {
     685                cerr << (sig == SIGSEGV ? "Segment fault" : "Bus error") << " at memory location " << sfp->si_addr << "." << endl
     686                         << "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript." << endl;
     687        } // if
     688        backtrace( 2 );                                                                         // skip first 2 stack frames
     689        abort();                                                                                        // cause core dump for debugging
     690} // sigSegvBusHandler
     691
     692static void sigFpeHandler( SIGPARMS ) {
     693        const char * msg;
     694
     695        switch ( sfp->si_code ) {
     696          case FPE_INTDIV: case FPE_FLTDIV: msg = "divide by zero"; break;
     697          case FPE_FLTOVF: msg = "overflow"; break;
     698          case FPE_FLTUND: msg = "underflow"; break;
     699          case FPE_FLTRES: msg = "inexact result"; break;
     700          case FPE_FLTINV: msg = "invalid operation"; break;
     701          default: msg = "unknown";
     702        } // choose
     703        cerr << "Computation error " << msg << " at location " << sfp->si_addr << endl
     704                 << "Possible cause is constant-expression evaluation invalid." << endl;
     705        backtrace( 2 );                                                                         // skip first 2 stack frames
     706        abort();                                                                                        // cause core dump for debugging
     707} // sigFpeHandler
     708
     709static void sigAbortHandler( SIGPARMS ) {
     710        backtrace( 6 );                                                                         // skip first 6 stack frames
     711        Signal( SIGABRT, SIG_DFL, SA_SIGINFO ); // reset default signal handler
     712        raise( SIGABRT );                                                                       // reraise SIGABRT
     713} // sigAbortHandler
     714
     715static void initSignals() {
     716        Signal( SIGSEGV, sigSegvBusHandler, SA_SIGINFO );
     717        Signal( SIGBUS, sigSegvBusHandler, SA_SIGINFO );
     718        Signal( SIGFPE, sigFpeHandler, SA_SIGINFO );
     719        Signal( SIGABRT, sigAbortHandler, SA_SIGINFO );
     720}
     721
    715722// Local Variables: //
    716723// tab-width: 4 //
Note: See TracChangeset for help on using the changeset viewer.