Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/interpose.cfa

    r4f37255 r6791213  
    1010// Created On       : Wed Mar 29 16:10:31 2017
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sun Jul 14 22:57:16 2019
    13 // Update Count     : 116
     12// Last Modified On : Fri Mar 13 17:35:37 2020
     13// Update Count     : 178
    1414//
    1515
     
    2929#include "bits/signal.hfa"                                                              // sigHandler_?
    3030#include "startup.hfa"                                                                  // STARTUP_PRIORITY_CORE
     31#include <assert.h>
    3132
    3233//=============================================================================================
     
    4041
    4142typedef void (* generic_fptr_t)(void);
    42 generic_fptr_t interpose_symbol( const char * symbol, const char * version ) {
     43generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) {
    4344        const char * error;
    4445
     
    9596        void __cfaabi_interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
    9697        void __cfaabi_interpose_startup( void ) {
    97                 const char *version = NULL;
     98                const char *version = 0p;
    9899
    99100                preload_libgcc();
     
    105106#pragma GCC diagnostic pop
    106107
     108                // As a precaution (and necessity), errors that result in termination are delivered on a separate stack because
     109                // task stacks might be very small (4K) and the signal delivery corrupts memory to the point that a clean
     110                // shutdown is impossible. Also, when a stack overflow encounters the non-accessible sentinel page (debug only)
     111                // and generates a segment fault, the signal cannot be delivered on the sentinel page. Finally, calls to abort
     112                // print a stack trace that uses substantial stack space.
     113
     114                #define MINSTKSZ SIGSTKSZ * 8
     115                static char stack[MINSTKSZ] __attribute__(( aligned (16) ));
     116                static stack_t ss;
     117
     118                ss.ss_sp = stack;
     119                ss.ss_size = MINSTKSZ;
     120                ss.ss_flags = 0;
     121                if ( sigaltstack( &ss, 0p ) == -1 ) {
     122                        abort( "__cfaabi_interpose_startup : internal error, sigaltstack error(%d) %s.", errno, strerror( errno ) );
     123                } // if
     124
    107125                // Failure handler
    108                 __cfaabi_sigaction( SIGSEGV, sigHandler_segv , SA_SIGINFO );
    109                 __cfaabi_sigaction( SIGBUS , sigHandler_segv , SA_SIGINFO );
    110                 __cfaabi_sigaction( SIGILL , sigHandler_ill  , SA_SIGINFO );
    111                 __cfaabi_sigaction( SIGFPE , sigHandler_fpe  , SA_SIGINFO );
    112                 __cfaabi_sigaction( SIGABRT, sigHandler_abrt, SA_SIGINFO | SA_RESETHAND);
    113                 __cfaabi_sigaction( SIGTERM, sigHandler_term , SA_SIGINFO );
    114                 __cfaabi_sigaction( SIGINT , sigHandler_term , SA_SIGINFO );
     126                __cfaabi_sigaction( SIGSEGV, sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
     127                __cfaabi_sigaction( SIGBUS , sigHandler_segv, SA_SIGINFO | SA_ONSTACK );
     128                __cfaabi_sigaction( SIGILL , sigHandler_ill , SA_SIGINFO | SA_ONSTACK );
     129                __cfaabi_sigaction( SIGFPE , sigHandler_fpe , SA_SIGINFO | SA_ONSTACK );
     130                __cfaabi_sigaction( SIGTERM, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // one shot handler, return to default
     131                __cfaabi_sigaction( SIGINT , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
     132                __cfaabi_sigaction( SIGABRT, sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND );
     133                __cfaabi_sigaction( SIGHUP , sigHandler_term, SA_SIGINFO | SA_ONSTACK | SA_RESETHAND ); // terminal hangup
    115134        }
    116135}
     
    123142void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
    124143void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ ));
     144void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ ));
     145void __abort( bool signalAbort, const char fmt[], va_list args ) __attribute__(( __nothrow__, __leaf__, __noreturn__ ));
    125146
    126147extern "C" {
    127148        void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) {
    128                 abort( NULL );
     149                abort( false, "%s", "" );
    129150        }
    130151
     
    132153                va_list argp;
    133154                va_start( argp, fmt );
    134                 abort( fmt, argp );
     155                __abort( false, fmt, argp );
    135156                va_end( argp );
    136157        }
     
    141162}
    142163
    143 void * kernel_abort    ( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return NULL; }
    144 void   kernel_abort_msg( void * data, char * buffer, int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
     164void * kernel_abort( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 0p; }
     165void kernel_abort_msg( void * data, char buffer[], int size ) __attribute__(( __nothrow__, __leaf__, __weak__ )) {}
     166// See concurrency/kernel.cfa for strong definition used in multi-processor mode.
    145167int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; }
    146168
    147169enum { abort_text_size = 1024 };
    148170static char abort_text[ abort_text_size ];
    149 static int abort_lastframe;
    150 
    151 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )) {
    152     va_list args;
    153     va_start( args, fmt );
    154     vfprintf( stderr, fmt, args );
    155     va_end( args );
    156         __cabi_libc.exit( status );
    157 }
    158 
    159 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )) {
    160         void * kernel_data = kernel_abort();                    // must be done here to lock down kernel
    161         int len;
    162 
    163         abort_lastframe = kernel_abort_lastframe();
    164         len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
    165         __cfaabi_dbg_bits_write( abort_text, len );
    166 
    167         if ( fmt ) {
    168                 va_list args;
    169                 va_start( args, fmt );
    170 
    171                 len = vsnprintf( abort_text, abort_text_size, fmt, args );
    172                 va_end( args );
    173                 __cfaabi_dbg_bits_write( abort_text, len );
    174 
    175                 if ( fmt[strlen( fmt ) - 1] != '\n' ) {         // add optional newline if missing at the end of the format text
    176                         __cfaabi_dbg_bits_write( "\n", 1 );
    177                 }
    178         }
    179 
    180         kernel_abort_msg( kernel_data, abort_text, abort_text_size );
    181         __cabi_libc.abort();
    182 }
    183 
    184 static void __cfaabi_backtrace() {
    185         enum {
    186                 Frames = 50,                                                                    // maximum number of stack frames
    187                 Start = 8,                                                                              // skip first N stack frames
    188         };
     171
     172static void __cfaabi_backtrace( int start ) {
     173        enum { Frames = 50, };                                                          // maximum number of stack frames
     174        int last = kernel_abort_lastframe();                            // skip last N stack frames
    189175
    190176        void * array[Frames];
    191177        size_t size = backtrace( array, Frames );
    192         char ** messages = backtrace_symbols( array, size );
    193 
    194         // find executable name
    195         *index( messages[0], '(' ) = '\0';
    196         __cfaabi_dbg_bits_print_nolock( "Stack back trace for: %s\n", messages[0]);
    197 
    198         for ( int i = Start; i < size - abort_lastframe && messages != NULL; i += 1 ) {
    199                 char * name = NULL, * offset_begin = NULL, * offset_end = NULL;
    200 
    201                 for ( char * p = messages[i]; *p; ++p ) {
    202                         //__cfaabi_dbg_bits_print_nolock( "X %s\n", p);
    203                         // find parantheses and +offset
     178        char ** messages = backtrace_symbols( array, size ); // does not demangle names
     179
     180        *index( messages[0], '(' ) = '\0';                                      // find executable name
     181        __cfaabi_bits_print_nolock( STDERR_FILENO, "Stack back trace for: %s\n", messages[0]);
     182
     183        for ( unsigned int i = start; i < size - last && messages != 0p; i += 1 ) {
     184                char * name = 0p, * offset_begin = 0p, * offset_end = 0p;
     185
     186                for ( char * p = messages[i]; *p; p += 1 ) {    // find parantheses and +offset
     187                        //__cfaabi_bits_print_nolock( "X %s\n", p);
    204188                        if ( *p == '(' ) {
    205189                                name = p;
     
    212196                }
    213197
    214                 // if line contains symbol print it
    215                 int frameNo = i - Start;
     198                // if line contains symbol, print it
     199                int frameNo = i - start;
    216200                if ( name && offset_begin && offset_end && name < offset_begin ) {
    217                         // delimit strings
    218                         *name++ = '\0';
     201                        *name++ = '\0';                                                         // delimit strings
    219202                        *offset_begin++ = '\0';
    220203                        *offset_end++ = '\0';
    221204
    222                         __cfaabi_dbg_bits_print_nolock( "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
     205                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s : %s + %s %s\n", frameNo, messages[i], name, offset_begin, offset_end);
    223206                } else {                                                                                // otherwise, print the whole line
    224                         __cfaabi_dbg_bits_print_nolock( "(%i) %s\n", frameNo, messages[i] );
     207                        __cfaabi_bits_print_nolock( STDERR_FILENO, "(%i) %s\n", frameNo, messages[i] );
    225208                }
    226209        }
     
    228211}
    229212
     213void exit( int status, const char fmt[], ... ) {
     214        va_list args;
     215        va_start( args, fmt );
     216        vfprintf( stderr, fmt, args );
     217        va_end( args );
     218        __cabi_libc.exit( status );
     219}
     220
     221// Cannot forward va_list.
     222void __abort( bool signalAbort, const char fmt[], va_list args ) {
     223        void * kernel_data = kernel_abort();                            // must be done here to lock down kernel
     224        int len;
     225
     226        signal( SIGABRT, SIG_DFL );                                                     // prevent final "real" abort from recursing to handler
     227
     228        len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld) ", (long int)getpid() ); // use UNIX pid (versus getPid)
     229        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
     230
     231        assert( fmt );
     232        len = vsnprintf( abort_text, abort_text_size, fmt, args );
     233        __cfaabi_bits_write( STDERR_FILENO, abort_text, len );
     234
     235        if ( fmt[strlen( fmt ) - 1] != '\n' ) {                         // add optional newline if missing at the end of the format text
     236                __cfaabi_bits_write( STDERR_FILENO, "\n", 1 );
     237        } // if
     238        kernel_abort_msg( kernel_data, abort_text, abort_text_size );
     239
     240        __cfaabi_backtrace( signalAbort ? 4 : 2 );
     241
     242        __cabi_libc.abort();                                                            // print stack trace in handler
     243}
     244
     245void abort( const char fmt[], ... ) {
     246        va_list args;
     247        va_start( args, fmt );
     248        __abort( false, fmt, args );
     249    // CONTROL NEVER REACHES HERE!
     250        va_end( args );
     251}
     252
     253void abort( bool signalAbort, const char fmt[], ... ) {
     254    va_list args;
     255    va_start( args, fmt );
     256    __abort( signalAbort, fmt, args );
     257    // CONTROL NEVER REACHES HERE!
     258    va_end( args );
     259}
     260
    230261void sigHandler_segv( __CFA_SIGPARMS__ ) {
    231         abort( "Addressing invalid memory at location %p\n"
    232                         "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
    233                         sfp->si_addr );
     262                if ( sfp->si_addr == 0p ) {
     263                        abort( true, "Null pointer (0p) dereference.\n" );
     264                } else {
     265                        abort( true, "%s at memory location %p.\n"
     266                                   "Possible cause is reading outside the address space or writing to a protected area within the address space with an invalid pointer or subscript.\n",
     267                                   (sig == SIGSEGV ? "Segment fault" : "Bus error"), sfp->si_addr );
     268                }
    234269}
    235270
    236271void sigHandler_ill( __CFA_SIGPARMS__ ) {
    237         abort( "Executing illegal instruction at location %p.\n"
     272        abort( true, "Executing illegal instruction at location %p.\n"
    238273                        "Possible cause is stack corruption.\n",
    239274                        sfp->si_addr );
     
    251286          default: msg = "unknown";
    252287        } // choose
    253         abort( "Computation error %s at location %p.\n", msg, sfp->si_addr );
    254 }
    255 
    256 void sigHandler_abrt( __CFA_SIGPARMS__ ) {
    257         __cfaabi_backtrace();
    258 
    259         // reset default signal handler
    260         __cfaabi_sigdefault( SIGABRT );
    261 
    262         raise( SIGABRT );
     288        abort( true, "Computation error %s at location %p.\n", msg, sfp->si_addr );
    263289}
    264290
    265291void sigHandler_term( __CFA_SIGPARMS__ ) {
    266         abort( "Application stopped by %s signal.", sig == SIGINT ? "an interrupt (SIGINT)" : "a terminate (SIGTERM)" );
     292        abort( true, "Application interrupted by signal: %s.\n", strsignal( sig ) );
    267293}
    268294
Note: See TracChangeset for help on using the changeset viewer.