mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-13 06:33:56 +00:00
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
198 lines
5.9 KiB
C
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 ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|