// -*- Mode: CFA -*- // // 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 : // Last Modified On : // Update Count : 0 // #include #include extern "C" { #include #include #include #include } #include "libhdr/libdebug.h" #include "startup.h" void abortf( const char *fmt, ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)); 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 )); // #define INIT_REALRTN( x, ver ) libc_##x = (__typeof__(libc_##x))interpose_symbol( #x, ver ) 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 ]; 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 ); __lib_debug_write( STDERR_FILENO, abort_text, len ); __lib_debug_write( STDERR_FILENO, "\n", 1 ); } len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld)\n", (long int)getpid() ); // use UNIX pid (versus getPid) __lib_debug_write( STDERR_FILENO, abort_text, len ); kernel_abort_msg( kernel_data, abort_text, abort_text_size ); libc_abort(); }