Changes in libcfa/src/interpose.cfa [4f37255:6791213]
- File:
-
- 1 edited
-
libcfa/src/interpose.cfa (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/interpose.cfa
r4f37255 r6791213 10 10 // Created On : Wed Mar 29 16:10:31 2017 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sun Jul 14 22:57:16 201913 // Update Count : 1 1612 // Last Modified On : Fri Mar 13 17:35:37 2020 13 // Update Count : 178 14 14 // 15 15 … … 29 29 #include "bits/signal.hfa" // sigHandler_? 30 30 #include "startup.hfa" // STARTUP_PRIORITY_CORE 31 #include <assert.h> 31 32 32 33 //============================================================================================= … … 40 41 41 42 typedef void (* generic_fptr_t)(void); 42 generic_fptr_t interpose_symbol( const char * symbol, const char * version) {43 generic_fptr_t interpose_symbol( const char symbol[], const char version[] ) { 43 44 const char * error; 44 45 … … 95 96 void __cfaabi_interpose_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_CORE ) )); 96 97 void __cfaabi_interpose_startup( void ) { 97 const char *version = NULL;98 const char *version = 0p; 98 99 99 100 preload_libgcc(); … … 105 106 #pragma GCC diagnostic pop 106 107 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 107 125 // 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 115 134 } 116 135 } … … 123 142 void exit( int status, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 124 143 void abort( const char fmt[], ... ) __attribute__(( format(printf, 1, 2), __nothrow__, __leaf__, __noreturn__ )); 144 void abort( bool signalAbort, const char fmt[], ... ) __attribute__(( format(printf, 2, 3), __nothrow__, __leaf__, __noreturn__ )); 145 void __abort( bool signalAbort, const char fmt[], va_list args ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )); 125 146 126 147 extern "C" { 127 148 void abort( void ) __attribute__(( __nothrow__, __leaf__, __noreturn__ )) { 128 abort( NULL);149 abort( false, "%s", "" ); 129 150 } 130 151 … … 132 153 va_list argp; 133 154 va_start( argp, fmt ); 134 abort(fmt, argp );155 __abort( false, fmt, argp ); 135 156 va_end( argp ); 136 157 } … … 141 162 } 142 163 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__ )) {} 164 void * kernel_abort( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 0p; } 165 void 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. 145 167 int kernel_abort_lastframe( void ) __attribute__(( __nothrow__, __leaf__, __weak__ )) { return 4; } 146 168 147 169 enum { abort_text_size = 1024 }; 148 170 static 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 172 static 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 189 175 190 176 void * array[Frames]; 191 177 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); 204 188 if ( *p == '(' ) { 205 189 name = p; … … 212 196 } 213 197 214 // if line contains symbol print it215 int frameNo = i - Start;198 // if line contains symbol, print it 199 int frameNo = i - start; 216 200 if ( name && offset_begin && offset_end && name < offset_begin ) { 217 // delimit strings 218 *name++ = '\0'; 201 *name++ = '\0'; // delimit strings 219 202 *offset_begin++ = '\0'; 220 203 *offset_end++ = '\0'; 221 204 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); 223 206 } 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] ); 225 208 } 226 209 } … … 228 211 } 229 212 213 void 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. 222 void __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 245 void 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 253 void 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 230 261 void 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 } 234 269 } 235 270 236 271 void sigHandler_ill( __CFA_SIGPARMS__ ) { 237 abort( "Executing illegal instruction at location %p.\n"272 abort( true, "Executing illegal instruction at location %p.\n" 238 273 "Possible cause is stack corruption.\n", 239 274 sfp->si_addr ); … … 251 286 default: msg = "unknown"; 252 287 } // 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 ); 263 289 } 264 290 265 291 void 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 ) ); 267 293 } 268 294
Note:
See TracChangeset
for help on using the changeset viewer.