ftmemsim-valgrind/coregrind/pub_core_clreq.h
Tom Hughes 00d987f91a Add support for ELF indirect functions. These are symbols of
type STT_GNU_IFUNC which, instead of pointing directly at the
function, point at a routine which will return the address of
the real function. Redirection of indirect functions is handled
by valgrind as follows:

  - When a redirection specification matches an indirect
    function symbol an active redirection is added in the
    normal way, but with the isIFunc flag set.

  - When a call is made to an address which matches an
    active redirection with the isIFunc flag set the call
    is redirected, but not to the target address of the
    redirection - instead it is sent to a small wrapper
    routine that is preloaded into the client.

  - The wrapper routine calls the original client routine
    and collects the result, which it reports to valgrind
    using a client request, and then returns the result to
    the caller.

  - When valgrind gets the client request it looks up the
    active redirection for the indirect function and then
    adds a new active redirection which redirects from the
    address returned by the indirection function to the
    redirection target. This new redirection does not have
    the isIFunc flag set so behaves as a normal redirection.

In addition to the above we also add a few new redirections to
memcheck to capture internal calls made by glibc to things like
strlen, as these internal calls do not go through the indirect
function and instead go direct to the chosen implementation.

Based on a patch from Dodji Seketeli and comments from Jakub
Jelinek, this commit closes bug 206013.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10920
2009-10-29 09:27:11 +00:00

83 lines
2.8 KiB
C

/*--------------------------------------------------------------------*/
/*--- Internal client requests. pub_core_clreq.h ---*/
/*--------------------------------------------------------------------*/
/*
This file is part of Valgrind, a dynamic binary instrumentation
framework.
Copyright (C) 2000-2009 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.
*/
#ifndef __PUB_CORE_CLREQ_H
#define __PUB_CORE_CLREQ_H
//--------------------------------------------------------------------
// PURPOSE: This module defined client requests.
//--------------------------------------------------------------------
#include "pub_tool_clreq.h"
// The strange choice of values here is due to historical reasons -- there
// used to be many more internal client requests.
typedef
enum {
/* Denote the finish of __libc_freeres_wrapper(). Also causes exit. */
VG_USERREQ__LIBC_FREERES_DONE = 0x3029,
/* Get the tool's malloc-wrapping functions */
VG_USERREQ__GET_MALLOCFUNCS = 0x3030,
/* Internal equivalent of VALGRIND_PRINTF . */
VG_USERREQ__INTERNAL_PRINTF = 0x3103,
/* Add a target for an indirect function redirection. */
VG_USERREQ__ADD_IFUNC_TARGET = 0x3104,
} Vg_InternalClientRequest;
// Function for printing from code within Valgrind, but which runs on the
// sim'd CPU. Must be a function rather than macros so that va_list can
// be used.
static int VALGRIND_INTERNAL_PRINTF(const char *format, ...)
__attribute__((format(__printf__, 1, 2), __unused__));
static int VALGRIND_INTERNAL_PRINTF(const char *format, ...)
{
unsigned long _qzz_res = 0;
va_list vargs;
va_start(vargs, format);
VALGRIND_DO_CLIENT_REQUEST(
_qzz_res, 0, VG_USERREQ__INTERNAL_PRINTF,
(unsigned long)format, (unsigned long)vargs, 0, 0, 0
);
va_end(vargs);
return _qzz_res;
}
#endif // __PUB_CORE_CLREQ_H
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/