Files
ftmemsim-valgrind/coregrind/vg_intercept.c
Jeremy Fitzhardinge 1e6361234c A complete reworking of Valgrind's handling of system calls and signals,
with the aim of making it more robust, more correct and perhaps faster.

This patch removes the need to poll blocking syscalls, by adding a proxy
LWP for each application thread.  This LWP is a kernel thread whose job
is to run all (potentially) blocking syscalls, and also to handle signals.

This allows the kernel to do more of the work of dealing with signals,
so on kernels which do this properly (2.6), Valgrind's behavious is a
lot more posix compliant.  On base 2.4 kernels, we emulate some of the
missing 2.6 functionality.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1918
2003-10-13 22:26:55 +00:00

198 lines
5.9 KiB
C

/*--------------------------------------------------------------------*/
/*--- Intercepts for various libc functions we want to capture ---*/
/*--- (mostly for threading purposes). vg_intercept.c ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, an extensible x86 protected-mode
emulator for monitoring program execution on x86-Unixes.
Copyright (C) 2000-2003 Julian Seward
jseward@acm.org
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307, USA.
The GNU General Public License is contained in the file COPYING.
*/
/* ---------------------------------------------------------------------
ALL THE CODE IN THIS FILE RUNS ON THE SIMULATED CPU. It is
intended for various reasons as drop-in replacements for libc
functions. These functions have global visibility (obviously) and
have no prototypes in vg_include.h, since they are not intended to
be called from within Valgrind.
------------------------------------------------------------------ */
/* General idea (2003-Apr-26) is that master implementations of
selected functions are done as VGR_(fnname). Then we route
all calls to the master, both here and in vg_libpthread.c.
This means we no longer have to rely on the semantics of weak
symbols, which seems to have changed in glibc >= 2.3.2 in such
a way as to make the previous interception scheme stop working.
*/
/* Sidestep the normal check which disallows using valgrind.h
directly. */
#define __VALGRIND_SOMESKIN_H
#include "valgrind.h"
#include "vg_include.h"
#include "vg_kerneliface.h"
/* This has some nasty duplication of stuff from vg_libpthread.c */
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <asm/ipc.h> /* for ipc_kludge */
#include <sys/poll.h>
#include <sys/socket.h>
#include <sys/uio.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
/* --------------------------------------------------------------- */
/* Just start up Valgrind if it's not already going. VG_(startup)()
detects and ignores second and subsequent calls. */
/* We need this guy -- it's in valgrind.so. */
extern void VG_(startup) ( void );
static __inline__
void ensure_valgrind ( char* caller )
{
VG_(startup)();
}
static __inline__
int is_kerror ( int res )
{
if (res >= -4095 && res <= -1)
return 1;
else
return 0;
}
/* --------------------------------------------------------------- */
/* Extract from Valgrind the value of VG_(clo_trace_pthread_level).
Returns 0 (none) if not running on Valgrind. */
static
int get_pt_trace_level ( void )
{
int res;
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
VG_USERREQ__GET_PTHREAD_TRACE_LEVEL,
0, 0, 0, 0);
return res;
}
static
void cat_n_send ( char* pre, char* msg )
{
char buf[1000];
if (get_pt_trace_level() >= 0) {
snprintf(buf, sizeof(buf), "%s%s", pre, msg );
buf[sizeof(buf)-1] = '\0';
VALGRIND_NON_SIMD_CALL2(VG_(message), Vg_UserMsg, buf);
}
}
static
void my_exit ( int arg )
{
VG_(do_syscall)(__NR_exit_group, arg);
VG_(do_syscall)(__NR_exit, arg);
}
static
void my_assert_fail ( const Char* expr, const Char* file, Int line, const Char* fn )
{
char buf[1000];
static Bool entered = False;
if (entered)
my_exit(2);
entered = True;
sprintf(buf, "\n%s: %s:%d (%s): Assertion `%s' failed.\n",
"valgrind", file, line, fn, expr );
cat_n_send ( "", buf );
sprintf(buf, "Please report this bug to me at: %s\n\n",
VG_EMAIL_ADDR);
cat_n_send ( "", buf );
my_exit(1);
}
#define MY__STRING(__str) #__str
#define my_assert(expr) \
((void) ((expr) ? 0 : \
(my_assert_fail (MY__STRING(expr), \
__FILE__, __LINE__, \
__PRETTY_FUNCTION__), 0)))
/* --------------------------------------------------------------- */
static __inline__
void __my_pthread_testcancel(void)
{
int res;
ensure_valgrind("__my_pthread_testcancel");
VALGRIND_MAGIC_SEQUENCE(res, (-1) /* default */,
VG_USERREQ__TESTCANCEL,
0, 0, 0, 0);
my_assert(res == 0);
}
/* ---------------------------------------------------------------------
Hook for running __libc_freeres once the program exits.
------------------------------------------------------------------ */
void VG_(__libc_freeres_wrapper)( void )
{
int res;
#ifndef __UCLIBC__
extern void __libc_freeres(void);
__libc_freeres();
#endif
VALGRIND_MAGIC_SEQUENCE(res, 0 /* default */,
VG_USERREQ__LIBC_FREERES_DONE, 0, 0, 0, 0);
/*NOTREACHED*/
vg_assert(12345+54321 == 999999);
}
/* ---------------------------------------------------------------------
Useful for skins that want to replace certain functions
------------------------------------------------------------------ */
Bool VG_(is_running_on_simd_CPU)(void)
{
return VG_(running_on_simd_CPU);
}
/*--------------------------------------------------------------------*/
/*--- end vg_intercept.c ---*/
/*--------------------------------------------------------------------*/