rjwalsh | e4e779d | 2004-04-16 23:02:29 +0000 | [diff] [blame] | 1 | |
| 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- Intercepts for various libc functions we want to capture ---*/ |
| 4 | /*--- (mostly for threading purposes). vg_intercept.c ---*/ |
| 5 | /*--------------------------------------------------------------------*/ |
| 6 | |
| 7 | /* |
| 8 | This file is part of Valgrind, an extensible x86 protected-mode |
| 9 | emulator for monitoring program execution on x86-Unixes. |
| 10 | |
| 11 | Copyright (C) 2000-2004 Julian Seward |
| 12 | jseward@acm.org |
| 13 | |
| 14 | This program is free software; you can redistribute it and/or |
| 15 | modify it under the terms of the GNU General Public License as |
| 16 | published by the Free Software Foundation; either version 2 of the |
| 17 | License, or (at your option) any later version. |
| 18 | |
| 19 | This program is distributed in the hope that it will be useful, but |
| 20 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 22 | General Public License for more details. |
| 23 | |
| 24 | You should have received a copy of the GNU General Public License |
| 25 | along with this program; if not, write to the Free Software |
| 26 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 27 | 02111-1307, USA. |
| 28 | |
| 29 | The GNU General Public License is contained in the file COPYING. |
| 30 | */ |
| 31 | |
| 32 | |
| 33 | /* --------------------------------------------------------------------- |
| 34 | ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. It is |
| 35 | intended for various reasons as drop-in replacements for libc |
| 36 | functions. These functions are not called directly - they're the |
| 37 | targets of code redirection. They're named weirdly so that the |
| 38 | intercept code can find them when the shared object is initially |
| 39 | loaded. |
| 40 | ------------------------------------------------------------------ */ |
| 41 | |
| 42 | /* |
| 43 | The gory details: Symbols in this file are mangled by a preprocessor |
| 44 | to produce a special symbol name. All symbols that need this handling |
| 45 | should be passed to a special VG_INTERCEPT macro. This macro takes |
| 46 | two arguments: a library name and a function name. These specify the |
| 47 | function and the library that contains it that we need to intercept. |
| 48 | For example: |
| 49 | |
| 50 | int VG_INTERCEPT(soname:libc.so.6, raise)(int sig) { ... } |
| 51 | |
| 52 | This example says that the "raise" function in the shared object |
| 53 | libc.so.6 should be intercepted and redirected to the following piece |
| 54 | of code. |
| 55 | |
| 56 | Internally, what's happening here is that this intercept gets turned |
| 57 | into a special magic symbol name, with the ':' and '.' parts replaced |
| 58 | by escapes, and a special prefix stuck on front. When we slurp in |
| 59 | an object file, we scan the symbol table for the magic prefixes, |
| 60 | demangle any symbols found and set up the intercepts that way. |
| 61 | |
| 62 | This is the safest way to do this, because we're not relying on |
| 63 | intercepts being set up by code that may be called after other code |
| 64 | that need the intercepts has had a chance to run. |
| 65 | */ |
| 66 | |
| 67 | #include "valgrind.h" |
| 68 | #include "vg_include.h" |
| 69 | #include <unistd.h> |
| 70 | #include <signal.h> |
| 71 | |
| 72 | int VG_INTERCEPT(soname:libc.so.6, raise)(int sig) |
| 73 | { |
| 74 | return kill(getpid(), sig); |
| 75 | } |
| 76 | |
| 77 | int VG_INTERCEPT(soname:libc.so.6, __libc_raise)(int) |
| 78 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, raise)), |
| 79 | visibility("protected"))); |
| 80 | |
| 81 | int VG_INTERCEPT(soname:libc.so.6, __GI_raise)(int) |
| 82 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, raise)), |
| 83 | visibility("protected"))); |
| 84 | |
| 85 | int VG_INTERCEPT(soname:libc.so.6, __raise)(int) |
| 86 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, raise)), |
| 87 | visibility("protected"))); |
| 88 | |
| 89 | /* Don't alias, so there's no chance that "gsignal" will appear in a |
| 90 | message instead of "raise" */ |
| 91 | int VG_INTERCEPT(soname:libc.so.6, gsignal)(int sig) |
| 92 | { |
| 93 | return VG_INTERCEPT(soname:libc.so.6, raise)(sig); |
| 94 | } |
| 95 | |
| 96 | int VG_INTERCEPT(soname:libc.so.6, __libc_gsignal)(int) |
| 97 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, gsignal)), |
| 98 | visibility("protected"))); |
| 99 | |
| 100 | int VG_INTERCEPT(soname:libc.so.6, __GI_gsignal)(int) |
| 101 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, gsignal)), |
| 102 | visibility("protected"))); |
| 103 | |
| 104 | int VG_INTERCEPT(soname:libc.so.6, __gsignal)(int) |
| 105 | __attribute__((alias(VG_INTERCEPT_ALIAS(soname:libc.so.6, gsignal)), |
| 106 | visibility("protected"))); |
| 107 | |
| 108 | /* --------------------------------------------------------------------- |
| 109 | Hook for running __libc_freeres once the program exits. |
| 110 | ------------------------------------------------------------------ */ |
| 111 | |
| 112 | void VG_WRAPPER(freeres)( void ) |
| 113 | { |
| 114 | int res; |
| 115 | #ifndef __UCLIBC__ |
| 116 | extern void __libc_freeres(void); |
| 117 | __libc_freeres(); |
| 118 | #endif |
| 119 | VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */, |
| 120 | VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0); |
| 121 | /*NOTREACHED*/ |
| 122 | *(int *)0 = 'x'; |
| 123 | } |
| 124 | |
| 125 | /*--------------------------------------------------------------------*/ |
| 126 | /*--- end vg_intercept.c ---*/ |
| 127 | /*--------------------------------------------------------------------*/ |
| 128 | |