// // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // interpose.c -- // // Author : Thierry Delisle // Created On : Wed Mar 29 16:10:31 2017 // Last Modified By : Peter A. Buhr // Last Modified On : Fri Jul 21 22:27:33 2017 // Update Count : 1 // #include #include extern "C" { #include #include #include #include } #include "bits/debug.h" #include "libhdr/libtools.h" #include "startup.h" void interpose_startup(void) __attribute__(( constructor( STARTUP_PRIORITY_CORE ) )); typedef void (*generic_fptr_t)(void); generic_fptr_t interpose_symbol( const char* symbol, const char *version ) { const char * error; static void * library; if ( ! library ) { #if defined( RTLD_NEXT ) library = RTLD_NEXT; #else // missing RTLD_NEXT => must hard-code library name, assuming libstdc++ library = dlopen( "libc.so.6", RTLD_LAZY ); error = dlerror(); if ( error ) { abortf( "interpose_symbol : failed to open libc, %s\n", error ); } #endif } // if union { generic_fptr_t fptr; void* ptr; } originalFunc; #if defined( _GNU_SOURCE ) if ( version ) { originalFunc.ptr = dlvsym( library, symbol, version ); } else { originalFunc.ptr = dlsym( library, symbol ); } #else originalFunc.ptr = dlsym( library, symbol ); #endif // _GNU_SOURCE error = dlerror(); if ( error ) abortf( "interpose_symbol : internal error, %s\n", error ); return originalFunc.fptr; } __typeof__( exit ) libc_exit __attribute__(( noreturn )); __typeof__( abort ) libc_abort __attribute__(( noreturn )); forall(dtype T) static inline void assign_ptr( T** symbol_ptr, const char * symbol_name, const char * version) { union { generic_fptr_t gp; T* tp; } u; u.gp = interpose_symbol( symbol_name, version ); *symbol_ptr = u.tp; } #define INIT_REALRTN( x, ver ) assign_ptr( (void**)&libc_##x, #x, ver) void interpose_startup() { const char *version = NULL; INIT_REALRTN( abort, version ); INIT_REALRTN( exit, version ); } extern "C" { void abort (void) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) { abortf( NULL ); } void exit (int __status) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) { libc_exit(__status); } } void abort( const char *fmt, va_list argp ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) { abortf( fmt, argp ); } void * kernel_abort (void) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return NULL; } void kernel_abort_msg(void * data, char * buffer, int size) __attribute__ ((__nothrow__, __leaf__, __weak__)) {} enum { abort_text_size = 1024 }; static char abort_text[ abort_text_size ]; extern "C" { void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) { void * kernel_data = kernel_abort(); int len; if( fmt ) { va_list args; va_start( args, fmt ); len = vsnprintf( abort_text, abort_text_size, fmt, args ); va_end( args ); __cfaabi_dbg_bits_write( abort_text, len ); __cfaabi_dbg_bits_write( "\n", 1 ); } len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld)\n", (long int)getpid() ); // use UNIX pid (versus getPid) __cfaabi_dbg_bits_write( abort_text, len ); kernel_abort_msg( kernel_data, abort_text, abort_text_size ); libc_abort(); } } // Local Variables: // // mode: c // // tab-width: 4 // // End: //