| [9d944b2] | 1 | //
 | 
|---|
 | 2 | // Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // The contents of this file are covered under the licence agreement in the
 | 
|---|
 | 5 | // file "LICENCE" distributed with Cforall.
 | 
|---|
 | 6 | //
 | 
|---|
 | 7 | // interpose.c --
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // Author           : Thierry Delisle
 | 
|---|
 | 10 | // Created On       : Wed Mar 29 16:10:31 2017
 | 
|---|
| [6b0b624] | 11 | // Last Modified By : Peter A. Buhr
 | 
|---|
 | 12 | // Last Modified On : Fri Jul 21 22:27:33 2017
 | 
|---|
 | 13 | // Update Count     : 1
 | 
|---|
| [9d944b2] | 14 | //
 | 
|---|
 | 15 | 
 | 
|---|
 | 16 | #include <stdarg.h>
 | 
|---|
 | 17 | #include <stddef.h>
 | 
|---|
 | 18 | 
 | 
|---|
 | 19 | extern "C" {
 | 
|---|
 | 20 | #include <stdio.h>
 | 
|---|
 | 21 | #include <string.h>
 | 
|---|
 | 22 | #include <dlfcn.h>
 | 
|---|
 | 23 | #include <unistd.h>
 | 
|---|
 | 24 | }
 | 
|---|
 | 25 | 
 | 
|---|
| [875a72f] | 26 | #include "bits/debug.h"
 | 
|---|
| [c2b9f21] | 27 | #include "bits/defs.h"
 | 
|---|
| [9d944b2] | 28 | #include "startup.h"
 | 
|---|
 | 29 | 
 | 
|---|
 | 30 | void interpose_startup(void)  __attribute__(( constructor( STARTUP_PRIORITY_CORE ) ));
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | typedef void (*generic_fptr_t)(void);
 | 
|---|
 | 33 | generic_fptr_t interpose_symbol( const char* symbol, const char *version ) {
 | 
|---|
 | 34 |         const char * error;
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 |         static void * library;
 | 
|---|
 | 37 |         if ( ! library ) {
 | 
|---|
 | 38 |                 #if defined( RTLD_NEXT )
 | 
|---|
 | 39 |                         library = RTLD_NEXT;
 | 
|---|
 | 40 |                 #else
 | 
|---|
 | 41 |                         // missing RTLD_NEXT => must hard-code library name, assuming libstdc++
 | 
|---|
 | 42 |                         library = dlopen( "libc.so.6", RTLD_LAZY );
 | 
|---|
 | 43 |                         error = dlerror();
 | 
|---|
 | 44 |                         if ( error ) {
 | 
|---|
 | 45 |                                 abortf( "interpose_symbol : failed to open libc, %s\n", error );
 | 
|---|
 | 46 |                         }
 | 
|---|
 | 47 |                 #endif
 | 
|---|
 | 48 |         } // if
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 |         union { generic_fptr_t fptr; void* ptr; } originalFunc;
 | 
|---|
| [aca65621] | 51 | 
 | 
|---|
| [9d944b2] | 52 |         #if defined( _GNU_SOURCE )
 | 
|---|
 | 53 |                 if ( version ) {
 | 
|---|
 | 54 |                         originalFunc.ptr = dlvsym( library, symbol, version );
 | 
|---|
 | 55 |                 } else {
 | 
|---|
 | 56 |                         originalFunc.ptr = dlsym( library, symbol );
 | 
|---|
 | 57 |                 }
 | 
|---|
 | 58 |         #else
 | 
|---|
 | 59 |                 originalFunc.ptr = dlsym( library, symbol );
 | 
|---|
 | 60 |         #endif // _GNU_SOURCE
 | 
|---|
| [aca65621] | 61 | 
 | 
|---|
| [9d944b2] | 62 |         error = dlerror();
 | 
|---|
| [aca65621] | 63 |         if ( error ) abortf( "interpose_symbol : internal error, %s\n", error );
 | 
|---|
| [9d944b2] | 64 | 
 | 
|---|
 | 65 |         return originalFunc.fptr;
 | 
|---|
 | 66 | }
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 | 
 | 
|---|
 | 69 | __typeof__( exit ) libc_exit __attribute__(( noreturn ));
 | 
|---|
 | 70 | __typeof__( abort ) libc_abort __attribute__(( noreturn ));
 | 
|---|
 | 71 | 
 | 
|---|
 | 72 | forall(dtype T)
 | 
|---|
 | 73 | static inline void assign_ptr( T** symbol_ptr, const char * symbol_name, const char * version) {
 | 
|---|
| [aca65621] | 74 |         union {
 | 
|---|
| [9d944b2] | 75 |                 generic_fptr_t gp;
 | 
|---|
| [aca65621] | 76 |                 T* tp;
 | 
|---|
| [9d944b2] | 77 |         } u;
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 |         u.gp = interpose_symbol( symbol_name, version );
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 |         *symbol_ptr = u.tp;
 | 
|---|
 | 82 | }
 | 
|---|
 | 83 | 
 | 
|---|
 | 84 | #define INIT_REALRTN( x, ver ) assign_ptr( (void**)&libc_##x, #x, ver)
 | 
|---|
 | 85 | 
 | 
|---|
 | 86 | void interpose_startup() {
 | 
|---|
 | 87 |         const char *version = NULL;
 | 
|---|
 | 88 | 
 | 
|---|
 | 89 |         INIT_REALRTN( abort, version );
 | 
|---|
 | 90 |         INIT_REALRTN( exit, version );
 | 
|---|
 | 91 | }
 | 
|---|
 | 92 | 
 | 
|---|
 | 93 | extern "C" {
 | 
|---|
 | 94 |         void abort (void) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
 | 
|---|
 | 95 |                 abortf( NULL );
 | 
|---|
 | 96 |         }
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 |         void exit (int __status) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
 | 
|---|
 | 99 |                 libc_exit(__status);
 | 
|---|
 | 100 |         }
 | 
|---|
 | 101 | }
 | 
|---|
 | 102 | 
 | 
|---|
 | 103 | void abort( const char *fmt, va_list argp ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
 | 
|---|
 | 104 |         abortf( fmt, argp );
 | 
|---|
 | 105 | }
 | 
|---|
 | 106 | 
 | 
|---|
 | 107 | void * kernel_abort    (void) __attribute__ ((__nothrow__, __leaf__, __weak__)) { return NULL; }
 | 
|---|
 | 108 | void   kernel_abort_msg(void * data, char * buffer, int size) __attribute__ ((__nothrow__, __leaf__, __weak__)) {}
 | 
|---|
 | 109 | 
 | 
|---|
 | 110 | enum { abort_text_size = 1024 };
 | 
|---|
 | 111 | static char abort_text[ abort_text_size ];
 | 
|---|
 | 112 | 
 | 
|---|
| [e464759] | 113 | extern "C" {
 | 
|---|
 | 114 |         void abortf( const char fmt[], ... ) __attribute__ ((__nothrow__, __leaf__, __noreturn__)) {
 | 
|---|
 | 115 |                 void * kernel_data = kernel_abort();
 | 
|---|
| [9d944b2] | 116 | 
 | 
|---|
| [e464759] | 117 |                 int len;
 | 
|---|
| [9d944b2] | 118 | 
 | 
|---|
| [e464759] | 119 |                 if( fmt ) {
 | 
|---|
 | 120 |                         va_list args;
 | 
|---|
 | 121 |                         va_start( args, fmt );
 | 
|---|
| [9d944b2] | 122 | 
 | 
|---|
| [e464759] | 123 |                         len = vsnprintf( abort_text, abort_text_size, fmt, args );
 | 
|---|
| [9d944b2] | 124 | 
 | 
|---|
| [e464759] | 125 |                         va_end( args );
 | 
|---|
| [9d944b2] | 126 | 
 | 
|---|
| [36982fc] | 127 |                         __cfaabi_dbg_bits_write( abort_text, len );
 | 
|---|
 | 128 |                         __cfaabi_dbg_bits_write( "\n", 1 );
 | 
|---|
| [e464759] | 129 |                 }
 | 
|---|
 | 130 | 
 | 
|---|
 | 131 |                 len = snprintf( abort_text, abort_text_size, "Cforall Runtime error (UNIX pid:%ld)\n", (long int)getpid() ); // use UNIX pid (versus getPid)
 | 
|---|
| [36982fc] | 132 |                 __cfaabi_dbg_bits_write( abort_text, len );
 | 
|---|
| [9d944b2] | 133 | 
 | 
|---|
 | 134 | 
 | 
|---|
| [e464759] | 135 |                 kernel_abort_msg( kernel_data, abort_text, abort_text_size );
 | 
|---|
 | 136 | 
 | 
|---|
 | 137 |                 libc_abort();
 | 
|---|
 | 138 |         }
 | 
|---|
| [aca65621] | 139 | }
 | 
|---|
| [6b0b624] | 140 | 
 | 
|---|
 | 141 | // Local Variables: //
 | 
|---|
 | 142 | // mode: c //
 | 
|---|
 | 143 | // tab-width: 4 //
 | 
|---|
 | 144 | // End: //
 | 
|---|