Author: sewardj
Date: 2007-12-11 03:10:44 +0000 (Tue, 11 Dec 2007)
New Revision: 342
Log:
Add new chapter.
Added:
trunk/docs/manual/manual-core-adv.html
Added: trunk/docs/manual/manual-core-adv.html
===================================================================
--- trunk/docs/manual/manual-core-adv.html (rev 0)
+++ trunk/docs/manual/manual-core-adv.html 2007-12-11 03:10:44 UTC (rev
342)
@@ -0,0 +1,569 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>3.�Using and understanding the Valgrind core: Advanced Topics</title>
+<link rel="stylesheet" href="vg_basic.css" type="text/css">
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+<link rel="start" href="index.html" title="Valgrind Documentation">
+<link rel="up" href="manual.html" title="Valgrind User Manual">
+<link rel="prev" href="manual-core.html" title="2.�Using and understanding the
Valgrind core">
+<link rel="next" href="mc-manual.html" title="4.�Memcheck: a heavyweight
memory checker">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084"
alink="#0000FF">
+<div><table class="nav" width="100%" cellspacing="3" cellpadding="3"
border="0" summary="Navigation header"><tr>
+<td width="22px" align="center" valign="middle"><a accesskey="p"
href="manual-core.html"><img src="images/prev.png" width="18" height="21"
border="0" alt="Prev"></a></td>
+<td width="25px" align="center" valign="middle"><a accesskey="u"
href="manual.html"><img src="images/up.png" width="21" height="18" border="0"
alt="Up"></a></td>
+<td width="31px" align="center" valign="middle"><a accesskey="h"
href="index.html"><img src="images/home.png" width="27" height="20" border="0"
alt="Up"></a></td>
+<th align="center" valign="middle">Valgrind User Manual</th>
+<td width="22px" align="center" valign="middle"><a accesskey="n"
href="mc-manual.html"><img src="images/next.png" width="18" height="21"
border="0" alt="Next"></a></td>
+</tr></table></div>
+<div class="chapter" lang="en">
+<div class="titlepage"><div><div><h2 class="title">
+<a name="manual-core-adv"></a>3.�Using and understanding the Valgrind core:
Advanced Topics</h2></div></div></div>
+<div class="toc">
+<p><b>Table of Contents</b></p>
+<dl>
+<dt><span class="sect1"><a
href="manual-core-adv.html#manual-core-adv.clientreq">3.1. The Client Request
mechanism</a></span></dt>
+<dt><span class="sect1"><a
href="manual-core-adv.html#manual-core-adv.wrapping">3.2. Function
wrapping</a></span></dt>
+<dd><dl>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.example">3.2.1. A Simple
Example</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.specs">3.2.2. Wrapping
Specifications</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.semantics">3.2.3. Wrapping
Semantics</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.debugging">3.2.4.
Debugging</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.limitations-cf">3.2.5.
Limitations - control flow</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.limitations-sigs">3.2.6.
Limitations - original function signatures</a></span></dt>
+<dt><span class="sect2"><a
href="manual-core-adv.html#manual-core-adv.wrapping.examples">3.2.7.
Examples</a></span></dt>
+</dl></dd>
+</dl>
+</div>
+<p>This chapter describes advanced aspects of the Valgrind core
+services, which are mostly of interest to power users who wish to
+customise and modify Valgrind's default behaviours in certain useful
+ways. The subjects covered are:</p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>The "Client Request" mechanism</p></li>
+<li><p>Function Wrapping</p></li>
+</ul></div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="manual-core-adv.clientreq"></a>3.1.�The Client Request
mechanism</h2></div></div></div>
+<p>Valgrind has a trapdoor mechanism via which the client
+program can pass all manner of requests and queries to Valgrind
+and the current tool. Internally, this is used extensively to
+make malloc, free, etc, work, although you don't see that.</p>
+<p>For your convenience, a subset of these so-called client
+requests is provided to allow you to tell Valgrind facts about
+the behaviour of your program, and also to make queries.
+In particular, your program can tell Valgrind about changes in
+memory range permissions that Valgrind would not otherwise know
+about, and so allows clients to get Valgrind to do arbitrary
+custom checks.</p>
+<p>Clients need to include a header file to make this work.
+Which header file depends on which client requests you use. Some
+client requests are handled by the core, and are defined in the
+header file <code class="filename">valgrind/valgrind.h</code>. Tool-specific
+header files are named after the tool, e.g.
+<code class="filename">valgrind/memcheck.h</code>. All header files can be
found
+in the <code class="literal">include/valgrind</code> directory of wherever
Valgrind
+was installed.</p>
+<p>The macros in these header files have the magical property
+that they generate code in-line which Valgrind can spot.
+However, the code does nothing when not run on Valgrind, so you
+are not forced to run your program under Valgrind just because you
+use the macros in this file. Also, you are not required to link your
+program with any extra supporting libraries.</p>
+<p>The code added to your binary has negligible performance impact:
+on x86, amd64, ppc32 and ppc64, the overhead is 6 simple integer instructions
+and is probably undetectable except in tight loops.
+However, if you really wish to compile out the client requests, you can
+compile with <code class="computeroutput">-DNVALGRIND</code> (analogous to
+<code class="computeroutput">-DNDEBUG</code>'s effect on
+<code class="computeroutput">assert()</code>).
+</p>
+<p>You are encouraged to copy the <code class="filename">valgrind/*.h</code>
headers
+into your project's include directory, so your program doesn't have a
+compile-time dependency on Valgrind being installed. The Valgrind headers,
+unlike most of the rest of the code, are under a BSD-style license so you may
+include them without worrying about license incompatibility.</p>
+<p>Here is a brief description of the macros available in
+<code class="filename">valgrind.h</code>, which work with more than one
+tool (see the tool-specific documentation for explanations of the
+tool-specific macros).</p>
+<div class="variablelist"><dl>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">RUNNING_ON_VALGRIND</code></strong></span>:</span></dt>
+<dd><p>Returns 1 if running on Valgrind, 0 if running on the
+ real CPU. If you are running Valgrind on itself, returns the
+ number of layers of Valgrind emulation you're running on.
+ </p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_DISCARD_TRANSLATIONS</code>:</strong></span></span></dt>
+<dd>
+<p>Discards translations of code in the specified address
+ range. Useful if you are debugging a JIT compiler or some other
+ dynamic code generation system. After this call, attempts to
+ execute code in the invalidated address range will cause
+ Valgrind to make new translations of that code, which is
+ probably the semantics you want. Note that code invalidations
+ are expensive because finding all the relevant translations
+ quickly is very difficult. So try not to call it often.
+ Note that you can be clever about
+ this: you only need to call it when an area which previously
+ contained code is overwritten with new code. You can choose
+ to write code into fresh memory, and just call this
+ occasionally to discard large chunks of old code all at
+ once.</p>
+<p>
+ Alternatively, for transparent self-modifying-code support,
+ use<code class="computeroutput">--smc-check=all</code>, or run
+ on ppc32/Linux or ppc64/Linux.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_COUNT_ERRORS</code>:</strong></span></span></dt>
+<dd><p>Returns the number of errors found so far by Valgrind. Can be
+ useful in test harness code when combined with the
+ <code class="option">--log-fd=-1</code> option; this runs Valgrind
silently,
+ but the client program can detect when errors occur. Only useful
+ for tools that report errors, e.g. it's useful for Memcheck, but for
+ Cachegrind it will always return zero because Cachegrind doesn't
+ report errors.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_MALLOCLIKE_BLOCK</code>:</strong></span></span></dt>
+<dd><p>If your program manages its own memory instead of using
+ the standard <code class="computeroutput">malloc()</code> /
+ <code class="computeroutput">new</code> /
+ <code class="computeroutput">new[]</code>, tools that track
+ information about heap blocks will not do nearly as good a
+ job. For example, Memcheck won't detect nearly as many
+ errors, and the error messages won't be as informative. To
+ improve this situation, use this macro just after your custom
+ allocator allocates some new memory. See the comments in
+ <code class="filename">valgrind.h</code> for information on how to use
+ it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_FREELIKE_BLOCK</code>:</strong></span></span></dt>
+<dd><p>This should be used in conjunction with
+ <code class="computeroutput">VALGRIND_MALLOCLIKE_BLOCK</code>.
+ Again, see <code class="filename">memcheck/memcheck.h</code> for
+ information on how to use it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_CREATE_MEMPOOL</code>:</strong></span></span></dt>
+<dd><p>This is similar to
+ <code class="computeroutput">VALGRIND_MALLOCLIKE_BLOCK</code>,
+ but is tailored towards code that uses memory pools. See the
+ comments in <code class="filename">valgrind.h</code> for information
+ on how to use it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_DESTROY_MEMPOOL</code>:</strong></span></span></dt>
+<dd><p>This should be used in conjunction with
+ <code class="computeroutput">VALGRIND_CREATE_MEMPOOL</code>.
+ Again, see the comments in <code class="filename">valgrind.h</code> for
+ information on how to use it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_MEMPOOL_ALLOC</code>:</strong></span></span></dt>
+<dd><p>This should be used in conjunction with
+ <code class="computeroutput">VALGRIND_CREATE_MEMPOOL</code>.
+ Again, see the comments in <code class="filename">valgrind.h</code> for
+ information on how to use it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_MEMPOOL_FREE</code>:</strong></span></span></dt>
+<dd><p>This should be used in conjunction with
+ <code class="computeroutput">VALGRIND_CREATE_MEMPOOL</code>.
+ Again, see the comments in <code class="filename">valgrind.h</code> for
+ information on how to use it.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_NON_SIMD_CALL[0123]</code>:</strong></span></span></dt>
+<dd>
+<p>Executes a function of 0, 1, 2 or 3 args in the client
+ program on the <span class="emphasis"><em>real</em></span> CPU, not the
virtual
+ CPU that Valgrind normally runs code on. These are used in
+ various ways internally to Valgrind. They might be useful to
+ client programs.</p>
+<p><span><strong class="command">Warning:</strong></span> Only use these if you
+ <span class="emphasis"><em>really</em></span> know what you are doing.
They aren't
+ entirely reliable, and can cause Valgrind to crash.
+ Generally, your prospects of these working are made higher if the called
+ function does not refer to any global variables, and does not refer to any
+ libc or other functions (printf et al). Any kind of entanglement with libc
+ or dynamic linking is likely to have a bad outcome, for tricky reasons
+ which we've grappled with a lot in the past.
+ </p>
+</dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_PRINTF(format,
...)</code>:</strong></span></span></dt>
+<dd><p>printf a message to the log file when running under
+ Valgrind. Nothing is output if not running under Valgrind.
+ Returns the number of characters output.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_PRINTF_BACKTRACE(format,
...)</code>:</strong></span></span></dt>
+<dd><p>printf a message to the log file along with a stack
+ backtrace when running under Valgrind. Nothing is output if
+ not running under Valgrind. Returns the number of characters
+ output.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_STACK_REGISTER(start,
end)</code>:</strong></span></span></dt>
+<dd>
+<p>Registers a new stack. Informs Valgrind that the memory range
+ between start and end is a unique stack. Returns a stack identifier
+ that can be used with other
+ <code class="computeroutput">VALGRIND_STACK_*</code> calls.</p>
+<p>Valgrind will use this information to determine if a change to
+ the stack pointer is an item pushed onto the stack or a change over
+ to a new stack. Use this if you're using a user-level thread package
+ and are noticing spurious errors from Valgrind about uninitialized
+ memory reads.</p>
+</dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_STACK_DEREGISTER(id)</code>:</strong></span></span></dt>
+<dd><p>Deregisters a previously registered stack. Informs
+ Valgrind that previously registered memory range with stack id
+ <code class="computeroutput">id</code> is no longer a stack.</p></dd>
+<dt><span class="term"><span><strong class="command"><code
class="computeroutput">VALGRIND_STACK_CHANGE(id, start,
end)</code>:</strong></span></span></dt>
+<dd><p>Changes a previously registered stack. Informs
+ Valgrind that the previously registered stack with stack id
+ <code class="computeroutput">id</code> has changed its start and end
+ values. Use this if your user-level thread package implements
+ stack growth.</p></dd>
+</dl></div>
+<p>Note that <code class="filename">valgrind.h</code> is included by
+all the tool-specific header files (such as
+<code class="filename">memcheck.h</code>), so you don't need to include it
+in your client if you include a tool-specific header.</p>
+</div>
+<div class="sect1" lang="en">
+<div class="titlepage"><div><div><h2 class="title" style="clear: both">
+<a name="manual-core-adv.wrapping"></a>3.2.�Function
wrapping</h2></div></div></div>
+<p>
+Valgrind versions 3.2.0 and above can do function wrapping on all
+supported targets. In function wrapping, calls to some specified
+function are intercepted and rerouted to a different, user-supplied
+function. This can do whatever it likes, typically examining the
+arguments, calling onwards to the original, and possibly examining the
+result. Any number of functions may be wrapped.</p>
+<p>
+Function wrapping is useful for instrumenting an API in some way. For
+example, wrapping functions in the POSIX pthreads API makes it
+possible to notify Valgrind of thread status changes, and wrapping
+functions in the MPI (message-passing) API allows notifying Valgrind
+of memory status changes associated with message arrival/departure.
+Such information is usually passed to Valgrind by using client
+requests in the wrapper functions, although that is not of relevance
+here.</p>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="manual-core-adv.wrapping.example"></a>3.2.1.�A Simple
Example</h3></div></div></div>
+<p>Supposing we want to wrap some function</p>
+<pre class="programlisting">
+int foo ( int x, int y ) { return x + y; }</pre>
+<p>A wrapper is a function of identical type, but with a special name
+which identifies it as the wrapper for <code class="computeroutput">foo</code>.
+Wrappers need to include
+supporting macros from <code class="computeroutput">valgrind.h</code>.
+Here is a simple wrapper which prints the arguments and return value:</p>
+<pre class="programlisting">
+#include <stdio.h>
+#include "valgrind.h"
+int I_WRAP_SONAME_FNNAME_ZU(NONE,foo)( int x, int y )
+{
+ int result;
+ OrigFn fn;
+ VALGRIND_GET_ORIG_FN(fn);
+ printf("foo's wrapper: args %d %d\n", x, y);
+ CALL_FN_W_WW(result, fn, x,y);
+ printf("foo's wrapper: result %d\n", result);
+ return result;
+}
+</pre>
+<p>To become active, the wrapper merely needs to be present in a text
+section somewhere in the same process' address space as the function
+it wraps, and for its ELF symbol name to be visible to Valgrind. In
+practice, this means either compiling to a
+<code class="computeroutput">.o</code> and linking it in, or
+compiling to a <code class="computeroutput">.so</code> and
+<code class="computeroutput">LD_PRELOAD</code>ing it in. The latter is more
+convenient in that it doesn't require relinking.</p>
+<p>All wrappers have approximately the above form. There are three
+crucial macros:</p>
+<p><code class="computeroutput">I_WRAP_SONAME_FNNAME_ZU</code>:
+this generates the real name of the wrapper.
+This is an encoded name which Valgrind notices when reading symbol
+table information. What it says is: I am the wrapper for any function
+named <code class="computeroutput">foo</code> which is found in
+an ELF shared object with an empty
+("<code class="computeroutput">NONE</code>") soname field. The specification
+mechanism is powerful in
+that wildcards are allowed for both sonames and function names.
+The details are discussed below.</p>
+<p><code class="computeroutput">VALGRIND_GET_ORIG_FN</code>:
+once in the the wrapper, the first priority is
+to get hold of the address of the original (and any other supporting
+information needed). This is stored in a value of opaque
+type <code class="computeroutput">OrigFn</code>.
+The information is acquired using
+<code class="computeroutput">VALGRIND_GET_ORIG_FN</code>. It is crucial
+to make this macro call before calling any other wrapped function
+in the same thread.</p>
+<p><code class="computeroutput">CALL_FN_W_WW</code>: eventually we will
+want to call the function being
+wrapped. Calling it directly does not work, since that just gets us
+back to the wrapper and tends to kill the program in short order by
+stack overflow. Instead, the result lvalue,
+<code class="computeroutput">OrigFn</code> and arguments are
+handed to one of a family of macros of the form
+<code class="computeroutput">CALL_FN_*</code>. These
+cause Valgrind to call the original and avoid recursion back to the
+wrapper.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="manual-core-adv.wrapping.specs"></a>3.2.2.�Wrapping
Specifications</h3></div></div></div>
+<p>This scheme has the advantage of being self-contained. A library of
+wrappers can be compiled to object code in the normal way, and does
+not rely on an external script telling Valgrind which wrappers pertain
+to which originals.</p>
+<p>Each wrapper has a name which, in the most general case says: I am the
+wrapper for any function whose name matches FNPATT and whose ELF
+"soname" matches SOPATT. Both FNPATT and SOPATT may contain wildcards
+(asterisks) and other characters (spaces, dots, @, etc) which are not
+generally regarded as valid C identifier names.</p>
+<p>This flexibility is needed to write robust wrappers for POSIX pthread
+functions, where typically we are not completely sure of either the
+function name or the soname, or alternatively we want to wrap a whole
+set of functions at once.</p>
+<p>For example, <code class="computeroutput">pthread_create</code>
+in GNU libpthread is usually a
+versioned symbol - one whose name ends in, eg,
+<code class="computeroutput">@GLIBC_2.3</code>. Hence we
+are not sure what its real name is. We also want to cover any soname
+of the form <code class="computeroutput">libpthread.so*</code>.
+So the header of the wrapper will be</p>
+<pre class="programlisting">
+int I_WRAP_SONAME_FNNAME_ZZ(libpthreadZdsoZd0,pthreadZucreateZAZa)
+ ( ... formals ... )
+ { ... body ... }
+</pre>
+<p>In order to write unusual characters as valid C function names, a
+Z-encoding scheme is used. Names are written literally, except that
+a capital Z acts as an escape character, with the following encoding:</p>
+<pre class="programlisting">
+ Za encodes *
+ Zp +
+ Zc :
+ Zd .
+ Zu _
+ Zh -
+ Zs (space)
+ ZA @
+ ZZ Z
+ ZL ( # only in valgrind 3.3.0 and later
+ ZR ) # only in valgrind 3.3.0 and later
+</pre>
+<p>Hence <code class="computeroutput">libpthreadZdsoZd0</code> is an
+encoding of the soname <code class="computeroutput">libpthread.so.0</code>
+and <code class="computeroutput">pthreadZucreateZAZa</code> is an encoding
+of the function name <code class="computeroutput">[EMAIL PROTECTED]</code>.
+</p>
+<p>The macro <code class="computeroutput">I_WRAP_SONAME_FNNAME_ZZ</code>
+constructs a wrapper name in which
+both the soname (first component) and function name (second component)
+are Z-encoded. Encoding the function name can be tiresome and is
+often unnecessary, so a second macro,
+<code class="computeroutput">I_WRAP_SONAME_FNNAME_ZU</code>, can be
+used instead. The <code class="computeroutput">_ZU</code> variant is
+also useful for writing wrappers for
+C++ functions, in which the function name is usually already mangled
+using some other convention in which Z plays an important role. Having
+to encode a second time quickly becomes confusing.</p>
+<p>Since the function name field may contain wildcards, it can be
+anything, including just <code class="computeroutput">*</code>.
+The same is true for the soname.
+However, some ELF objects - specifically, main executables - do not
+have sonames. Any object lacking a soname is treated as if its soname
+was <code class="computeroutput">NONE</code>, which is why the original
+example above had a name
+<code class="computeroutput">I_WRAP_SONAME_FNNAME_ZU(NONE,foo)</code>.</p>
+<p>Note that the soname of an ELF object is not the same as its
+file name, although it is often similar. You can find the soname of
+an object <code class="computeroutput">libfoo.so</code> using the command
+<code class="computeroutput">readelf -a libfoo.so | grep soname</code>.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="manual-core-adv.wrapping.semantics"></a>3.2.3.�Wrapping
Semantics</h3></div></div></div>
+<p>The ability for a wrapper to replace an infinite family of functions
+is powerful but brings complications in situations where ELF objects
+appear and disappear (are dlopen'd and dlclose'd) on the fly.
+Valgrind tries to maintain sensible behaviour in such situations.</p>
+<p>For example, suppose a process has dlopened (an ELF object with
+soname) <code class="computeroutput">object1.so</code>, which contains
+<code class="computeroutput">function1</code>. It starts to use
+<code class="computeroutput">function1</code> immediately.</p>
+<p>After a while it dlopens <code class="computeroutput">wrappers.so</code>,
+which contains a wrapper
+for <code class="computeroutput">function1</code> in (soname)
+<code class="computeroutput">object1.so</code>. All subsequent calls to
+<code class="computeroutput">function1</code> are rerouted to the wrapper.</p>
+<p>If <code class="computeroutput">wrappers.so</code> is
+later dlclose'd, calls to <code class="computeroutput">function1</code> are
+naturally routed back to the original.</p>
+<p>Alternatively, if <code class="computeroutput">object1.so</code>
+is dlclose'd but wrappers.so remains,
+then the wrapper exported by <code class="computeroutput">wrapper.so</code>
+becomes inactive, since there
+is no way to get to it - there is no original to call any more. However,
+Valgrind remembers that the wrapper is still present. If
+<code class="computeroutput">object1.so</code> is
+eventually dlopen'd again, the wrapper will become active again.</p>
+<p>In short, valgrind inspects all code loading/unloading events to
+ensure that the set of currently active wrappers remains consistent.</p>
+<p>A second possible problem is that of conflicting wrappers. It is
+easily possible to load two or more wrappers, both of which claim
+to be wrappers for some third function. In such cases Valgrind will
+complain about conflicting wrappers when the second one appears, and
+will honour only the first one.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a
name="manual-core-adv.wrapping.debugging"></a>3.2.4.�Debugging</h3></div></div></div>
+<p>Figuring out what's going on given the dynamic nature of wrapping
+can be difficult. The
+<code class="computeroutput">--trace-redir=yes</code> flag makes
+this possible
+by showing the complete state of the redirection subsystem after
+every
+<code class="computeroutput">mmap</code>/<code
class="computeroutput">munmap</code>
+event affecting code (text).</p>
+<p>There are two central concepts:</p>
+<div class="itemizedlist"><ul type="disc">
+<li><p>A "redirection specification" is a binding of
+ a (soname pattern, fnname pattern) pair to a code address.
+ These bindings are created by writing functions with names
+ made with the
+ <code class="computeroutput">I_WRAP_SONAME_FNNAME_{ZZ,_ZU}</code>
+ macros.</p></li>
+<li><p>An "active redirection" is code-address to
+ code-address binding currently in effect.</p></li>
+</ul></div>
+<p>The state of the wrapping-and-redirection subsystem comprises a set of
+specifications and a set of active bindings. The specifications are
+acquired/discarded by watching all
+<code class="computeroutput">mmap</code>/<code
class="computeroutput">munmap</code>
+events on code (text)
+sections. The active binding set is (conceptually) recomputed from
+the specifications, and all known symbol names, following any change
+to the specification set.</p>
+<p><code class="computeroutput">--trace-redir=yes</code> shows the contents
+of both sets following any such event.</p>
+<p><code class="computeroutput">-v</code> prints a line of text each
+time an active specification is used for the first time.</p>
+<p>Hence for maximum debugging effectiveness you will need to use both
+flags.</p>
+<p>One final comment. The function-wrapping facility is closely
+tied to Valgrind's ability to replace (redirect) specified
+functions, for example to redirect calls to
+<code class="computeroutput">malloc</code> to its
+own implementation. Indeed, a replacement function can be
+regarded as a wrapper function which does not call the original.
+However, to make the implementation more robust, the two kinds
+of interception (wrapping vs replacement) are treated differently.
+</p>
+<p><code class="computeroutput">--trace-redir=yes</code> shows
+specifications and bindings for both
+replacement and wrapper functions. To differentiate the
+two, replacement bindings are printed using
+<code class="computeroutput">R-></code> whereas
+wraps are printed using <code class="computeroutput">W-></code>.
+</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="manual-core-adv.wrapping.limitations-cf"></a>3.2.5.�Limitations -
control flow</h3></div></div></div>
+<p>For the most part, the function wrapping implementation is robust.
+The only important caveat is: in a wrapper, get hold of
+the <code class="computeroutput">OrigFn</code> information using
+<code class="computeroutput">VALGRIND_GET_ORIG_FN</code> before calling any
+other wrapped function. Once you have the
+<code class="computeroutput">OrigFn</code>, arbitrary
+calls between, recursion between, and longjumps out of wrappers
+should work correctly. There is never any interaction between wrapped
+functions and merely replaced functions
+(eg <code class="computeroutput">malloc</code>), so you can call
+<code class="computeroutput">malloc</code> etc safely from within wrappers.
+</p>
+<p>The above comments are true for {x86,amd64,ppc32}-linux. On
+ppc64-linux function wrapping is more fragile due to the (arguably
+poorly designed) ppc64-linux ABI. This mandates the use of a shadow
+stack which tracks entries/exits of both wrapper and replacement
+functions. This gives two limitations: firstly, longjumping out of
+wrappers will rapidly lead to disaster, since the shadow stack will
+not get correctly cleared. Secondly, since the shadow stack has
+finite size, recursion between wrapper/replacement functions is only
+possible to a limited depth, beyond which Valgrind has to abort the
+run. This depth is currently 16 calls.</p>
+<p>For all platforms ({x86,amd64,ppc32,ppc64}-linux) all the above
+comments apply on a per-thread basis. In other words, wrapping is
+thread-safe: each thread must individually observe the above
+restrictions, but there is no need for any kind of inter-thread
+cooperation.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a name="manual-core-adv.wrapping.limitations-sigs"></a>3.2.6.�Limitations -
original function signatures</h3></div></div></div>
+<p>As shown in the above example, to call the original you must use a
+macro of the form <code class="computeroutput">CALL_FN_*</code>.
+For technical reasons it is impossible
+to create a single macro to deal with all argument types and numbers,
+so a family of macros covering the most common cases is supplied. In
+what follows, 'W' denotes a machine-word-typed value (a pointer or a
+C <code class="computeroutput">long</code>),
+and 'v' denotes C's <code class="computeroutput">void</code> type.
+The currently available macros are:</p>
+<pre class="programlisting">
+CALL_FN_v_v -- call an original of type void fn ( void )
+CALL_FN_W_v -- call an original of type long fn ( void )
+
+CALL_FN_v_W -- void fn ( long )
+CALL_FN_W_W -- long fn ( long )
+
+CALL_FN_v_WW -- void fn ( long, long )
+CALL_FN_W_WW -- long fn ( long, long )
+
+CALL_FN_v_WWW -- void fn ( long, long, long )
+CALL_FN_W_WWW -- long fn ( long, long, long )
+
+CALL_FN_W_WWWW -- long fn ( long, long, long, long )
+CALL_FN_W_5W -- long fn ( long, long, long, long, long )
+CALL_FN_W_6W -- long fn ( long, long, long, long, long, long )
+and so on, up to
+CALL_FN_W_12W
+</pre>
+<p>The set of supported types can be expanded as needed. It is
+regrettable that this limitation exists. Function wrapping has proven
+difficult to implement, with a certain apparently unavoidable level of
+ickyness. After several implementation attempts, the present
+arrangement appears to be the least-worst tradeoff. At least it works
+reliably in the presence of dynamic linking and dynamic code
+loading/unloading.</p>
+<p>You should not attempt to wrap a function of one type signature with a
+wrapper of a different type signature. Such trickery will surely lead
+to crashes or strange behaviour. This is not of course a limitation
+of the function wrapping implementation, merely a reflection of the
+fact that it gives you sweeping powers to shoot yourself in the foot
+if you are not careful. Imagine the instant havoc you could wreak by
+writing a wrapper which matched any function name in any soname - in
+effect, one which claimed to be a wrapper for all functions in the
+process.</p>
+</div>
+<div class="sect2" lang="en">
+<div class="titlepage"><div><div><h3 class="title">
+<a
name="manual-core-adv.wrapping.examples"></a>3.2.7.�Examples</h3></div></div></div>
+<p>In the source tree,
+<code class="computeroutput">memcheck/tests/wrap[1-8].c</code> provide a
series of
+examples, ranging from very simple to quite advanced.</p>
+<p><code class="computeroutput">auxprogs/libmpiwrap.c</code> is an example
+of wrapping a big, complex API (the MPI-2 interface). This file defines
+almost 300 different wrappers.</p>
+</div>
+</div>
+</div>
+<div>
+<br><table class="nav" width="100%" cellspacing="3" cellpadding="2" border="0"
summary="Navigation footer">
+<tr>
+<td rowspan="2" width="40%" align="left">
+<a accesskey="p" href="manual-core.html"><<�2.�Using and understanding
the Valgrind core</a>�</td>
+<td width="20%" align="center"><a accesskey="u" href="manual.html">Up</a></td>
+<td rowspan="2" width="40%" align="right">�<a accesskey="n"
href="mc-manual.html">4.�Memcheck: a heavyweight memory checker�>></a>
+</td>
+</tr>
+<tr><td width="20%" align="center"><a accesskey="h"
href="index.html">Home</a></td></tr>
+</table>
+</div>
+</body>
+</html>
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Valgrind-developers mailing list
Valgrind-developers@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-developers