1 <?xml version="1.0"?> <!-- -*- sgml -*- -->
2 <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
3 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
4 [ <!ENTITY % vg-entities SYSTEM "vg-entities.xml"> %vg-entities; ]>
7 <chapter id="manual-core-adv" xreflabel="Valgrind's core: advanced topics">
8 <title>Using and understanding the Valgrind core: Advanced Topics</title>
10 <para>This chapter describes advanced aspects of the Valgrind core
11 services, which are mostly of interest to power users who wish to
12 customise and modify Valgrind's default behaviours in certain useful
13 ways. The subjects covered are:</para>
16 <listitem><para>The "Client Request" mechanism</para></listitem>
17 <listitem><para>Function Wrapping</para></listitem>
22 <sect1 id="manual-core-adv.clientreq"
23 xreflabel="The Client Request mechanism">
24 <title>The Client Request mechanism</title>
26 <para>Valgrind has a trapdoor mechanism via which the client
27 program can pass all manner of requests and queries to Valgrind
28 and the current tool. Internally, this is used extensively
29 to make various things work, although that's not visible from the
32 <para>For your convenience, a subset of these so-called client
33 requests is provided to allow you to tell Valgrind facts about
34 the behaviour of your program, and also to make queries.
35 In particular, your program can tell Valgrind about things that it
36 otherwise would not know, leading to better results.
39 <para>Clients need to include a header file to make this work.
40 Which header file depends on which client requests you use. Some
41 client requests are handled by the core, and are defined in the
42 header file <filename>valgrind/valgrind.h</filename>. Tool-specific
43 header files are named after the tool, e.g.
44 <filename>valgrind/memcheck.h</filename>. Each tool-specific header file
45 includes <filename>valgrind/valgrind.h</filename> so you don't need to
46 include it in your client if you include a tool-specific header. All header
47 files can be found in the <literal>include/valgrind</literal> directory of
48 wherever Valgrind was installed.</para>
50 <para>The macros in these header files have the magical property
51 that they generate code in-line which Valgrind can spot.
52 However, the code does nothing when not run on Valgrind, so you
53 are not forced to run your program under Valgrind just because you
54 use the macros in this file. Also, you are not required to link your
55 program with any extra supporting libraries.</para>
57 <para>The code added to your binary has negligible performance impact:
58 on x86, amd64, ppc32 and ppc64, the overhead is 6 simple integer instructions
59 and is probably undetectable except in tight loops.
60 However, if you really wish to compile out the client requests, you can
61 compile with <option>-DNVALGRIND</option> (analogous to
62 <option>-DNDEBUG</option>'s effect on
63 <function>assert</function>).
66 <para>You are encouraged to copy the <filename>valgrind/*.h</filename> headers
67 into your project's include directory, so your program doesn't have a
68 compile-time dependency on Valgrind being installed. The Valgrind headers,
69 unlike most of the rest of the code, are under a BSD-style license so you may
70 include them without worrying about license incompatibility.</para>
72 <para>Here is a brief description of the macros available in
73 <filename>valgrind.h</filename>, which work with more than one
74 tool (see the tool-specific documentation for explanations of the
75 tool-specific macros).</para>
80 <term><command><computeroutput>RUNNING_ON_VALGRIND</computeroutput></command>:</term>
82 <para>Returns 1 if running on Valgrind, 0 if running on the
83 real CPU. If you are running Valgrind on itself, returns the
84 number of layers of Valgrind emulation you're running on.
90 <term><command><computeroutput>VALGRIND_DISCARD_TRANSLATIONS</computeroutput>:</command></term>
92 <para>Discards translations of code in the specified address
93 range. Useful if you are debugging a JIT compiler or some other
94 dynamic code generation system. After this call, attempts to
95 execute code in the invalidated address range will cause
96 Valgrind to make new translations of that code, which is
97 probably the semantics you want. Note that code invalidations
98 are expensive because finding all the relevant translations
99 quickly is very difficult, so try not to call it often.
100 Note that you can be clever about
101 this: you only need to call it when an area which previously
102 contained code is overwritten with new code. You can choose
103 to write code into fresh memory, and just call this
104 occasionally to discard large chunks of old code all at
107 Alternatively, for transparent self-modifying-code support,
108 use<option>--smc-check=all</option>, or run
109 on ppc32/Linux or ppc64/Linux.
115 <term><command><computeroutput>VALGRIND_COUNT_ERRORS</computeroutput>:</command></term>
117 <para>Returns the number of errors found so far by Valgrind. Can be
118 useful in test harness code when combined with the
119 <option>--log-fd=-1</option> option; this runs Valgrind silently,
120 but the client program can detect when errors occur. Only useful
121 for tools that report errors, e.g. it's useful for Memcheck, but for
122 Cachegrind it will always return zero because Cachegrind doesn't
123 report errors.</para>
128 <term><command><computeroutput>VALGRIND_MALLOCLIKE_BLOCK</computeroutput>:</command></term>
130 <para>If your program manages its own memory instead of using
131 the standard <function>malloc</function> /
132 <function>new</function> /
133 <function>new[]</function>, tools that track
134 information about heap blocks will not do nearly as good a
135 job. For example, Memcheck won't detect nearly as many
136 errors, and the error messages won't be as informative. To
137 improve this situation, use this macro just after your custom
138 allocator allocates some new memory. See the comments in
139 <filename>valgrind.h</filename> for information on how to use
145 <term><command><computeroutput>VALGRIND_FREELIKE_BLOCK</computeroutput>:</command></term>
147 <para>This should be used in conjunction with
148 <computeroutput>VALGRIND_MALLOCLIKE_BLOCK</computeroutput>.
149 Again, see <filename>valgrind.h</filename> for
150 information on how to use it.</para>
156 <command><computeroutput>VALGRIND_CREATE_MEMPOOL</computeroutput></command>,
157 <command><computeroutput>VALGRIND_DESTROY_MEMPOOL</computeroutput></command>,
158 <command><computeroutput>VALGRIND_MEMPOOL_ALLOC</computeroutput></command>,
159 <command><computeroutput>VALGRIND_MEMPOOL_FREE</computeroutput></command>,
160 <command><computeroutput>VALGRIND_MOVE_MEMPOOL</computeroutput></command>,
161 <command><computeroutput>VALGRIND_MEMPOOL_CHANGE</computeroutput></command>,
162 <command><computeroutput>VALGRIND_MEMPOOL_EXISTS</computeroutput></command>:
165 <para>These are similar to
166 <computeroutput>VALGRIND_MALLOCLIKE_BLOCK</computeroutput> and
167 <computeroutput>VALGRIND_FREELIKE_BLOCK</computeroutput>
168 but are tailored towards code that uses memory pools. See
169 <xref linkend="mc-manual.mempools"/> for a detailed description.</para>
174 <term><command><computeroutput>VALGRIND_NON_SIMD_CALL[0123]</computeroutput>:</command></term>
176 <para>Executes a function in the client program on the
177 <emphasis>real</emphasis> CPU, not the virtual CPU that Valgrind
178 normally runs code on. The function must take an integer (holding a
179 thread ID) as the first argument and then 0, 1, 2 or 3 more arguments
180 (depending on which client request is used). These are used in various
181 ways internally to Valgrind. They might be useful to client
184 <para><command>Warning:</command> Only use these if you
185 <emphasis>really</emphasis> know what you are doing. They aren't
186 entirely reliable, and can cause Valgrind to crash. See
187 <filename>valgrind.h</filename> for more details.
193 <term><command><computeroutput>VALGRIND_PRINTF(format, ...)</computeroutput>:</command></term>
195 <para>Print a printf-style message to the Valgrind log file. The
196 message is prefixed with the PID between a pair of
197 <computeroutput>**</computeroutput> markers. (Like all client requests,
198 nothing is output if the client program is not running under Valgrind.)
199 Output is not produced until a newline is encountered, or subequent
200 Valgrind output is printed; this allows you to build up a single line of
201 output over multiple calls. Returns the number of characters output,
202 excluding the PID prefix.</para>
207 <term><command><computeroutput>VALGRIND_PRINTF_BACKTRACE(format, ...)</computeroutput>:</command></term>
209 <para>Like <computeroutput>VALGRIND_PRINTF</computeroutput> (in
210 particular, the return value is identical), but prints a stack backtrace
211 immediately afterwards.</para>
216 <term><command><computeroutput>VALGRIND_STACK_REGISTER(start, end)</computeroutput>:</command></term>
218 <para>Registers a new stack. Informs Valgrind that the memory range
219 between start and end is a unique stack. Returns a stack identifier
220 that can be used with other
221 <computeroutput>VALGRIND_STACK_*</computeroutput> calls.</para>
222 <para>Valgrind will use this information to determine if a change to
223 the stack pointer is an item pushed onto the stack or a change over
224 to a new stack. Use this if you're using a user-level thread package
225 and are noticing spurious errors from Valgrind about uninitialized
228 <para><command>Warning:</command> Unfortunately, this client request is
229 unreliable and best avoided.</para>
234 <term><command><computeroutput>VALGRIND_STACK_DEREGISTER(id)</computeroutput>:</command></term>
236 <para>Deregisters a previously registered stack. Informs
237 Valgrind that previously registered memory range with stack id
238 <computeroutput>id</computeroutput> is no longer a stack.</para>
240 <para><command>Warning:</command> Unfortunately, this client request is
241 unreliable and best avoided.</para>
246 <term><command><computeroutput>VALGRIND_STACK_CHANGE(id, start, end)</computeroutput>:</command></term>
248 <para>Changes a previously registered stack. Informs
249 Valgrind that the previously registered stack with stack id
250 <computeroutput>id</computeroutput> has changed its start and end
251 values. Use this if your user-level thread package implements
254 <para><command>Warning:</command> Unfortunately, this client request is
255 unreliable and best avoided.</para>
267 <sect1 id="manual-core-adv.wrapping" xreflabel="Function Wrapping">
268 <title>Function wrapping</title>
271 Valgrind allows calls to some specified functions to be intercepted and
272 rerouted to a different, user-supplied function. This can do whatever it
273 likes, typically examining the arguments, calling onwards to the original,
274 and possibly examining the result. Any number of functions may be
278 Function wrapping is useful for instrumenting an API in some way. For
279 example, Helgrind wraps functions in the POSIX pthreads API so it can know
280 about thread status changes, and the core is able to wrap
281 functions in the MPI (message-passing) API so it can know
282 of memory status changes associated with message arrival/departure.
283 Such information is usually passed to Valgrind by using client
284 requests in the wrapper functions, although the exact mechanism may vary.
287 <sect2 id="manual-core-adv.wrapping.example" xreflabel="A Simple Example">
288 <title>A Simple Example</title>
290 <para>Supposing we want to wrap some function</para>
292 <programlisting><![CDATA[
293 int foo ( int x, int y ) { return x + y; }]]></programlisting>
295 <para>A wrapper is a function of identical type, but with a special name
296 which identifies it as the wrapper for <computeroutput>foo</computeroutput>.
297 Wrappers need to include
298 supporting macros from <filename>valgrind.h</filename>.
299 Here is a simple wrapper which prints the arguments and return value:</para>
301 <programlisting><![CDATA[
303 #include "valgrind.h"
304 int I_WRAP_SONAME_FNNAME_ZU(NONE,foo)( int x, int y )
308 VALGRIND_GET_ORIG_FN(fn);
309 printf("foo's wrapper: args %d %d\n", x, y);
310 CALL_FN_W_WW(result, fn, x,y);
311 printf("foo's wrapper: result %d\n", result);
316 <para>To become active, the wrapper merely needs to be present in a text
317 section somewhere in the same process' address space as the function
318 it wraps, and for its ELF symbol name to be visible to Valgrind. In
319 practice, this means either compiling to a
320 <computeroutput>.o</computeroutput> and linking it in, or
321 compiling to a <computeroutput>.so</computeroutput> and
322 <computeroutput>LD_PRELOAD</computeroutput>ing it in. The latter is more
323 convenient in that it doesn't require relinking.</para>
325 <para>All wrappers have approximately the above form. There are three
326 crucial macros:</para>
328 <para><computeroutput>I_WRAP_SONAME_FNNAME_ZU</computeroutput>:
329 this generates the real name of the wrapper.
330 This is an encoded name which Valgrind notices when reading symbol
331 table information. What it says is: I am the wrapper for any function
332 named <computeroutput>foo</computeroutput> which is found in
333 an ELF shared object with an empty
334 ("<computeroutput>NONE</computeroutput>") soname field. The specification
335 mechanism is powerful in
336 that wildcards are allowed for both sonames and function names.
337 The details are discussed below.</para>
339 <para><computeroutput>VALGRIND_GET_ORIG_FN</computeroutput>:
340 once in the the wrapper, the first priority is
341 to get hold of the address of the original (and any other supporting
342 information needed). This is stored in a value of opaque
343 type <computeroutput>OrigFn</computeroutput>.
344 The information is acquired using
345 <computeroutput>VALGRIND_GET_ORIG_FN</computeroutput>. It is crucial
346 to make this macro call before calling any other wrapped function
347 in the same thread.</para>
349 <para><computeroutput>CALL_FN_W_WW</computeroutput>: eventually we will
350 want to call the function being
351 wrapped. Calling it directly does not work, since that just gets us
352 back to the wrapper and leads to an infinite loop. Instead, the result
354 <computeroutput>OrigFn</computeroutput> and arguments are
355 handed to one of a family of macros of the form
356 <computeroutput>CALL_FN_*</computeroutput>. These
357 cause Valgrind to call the original and avoid recursion back to the
361 <sect2 id="manual-core-adv.wrapping.specs" xreflabel="Wrapping Specifications">
362 <title>Wrapping Specifications</title>
364 <para>This scheme has the advantage of being self-contained. A library of
365 wrappers can be compiled to object code in the normal way, and does
366 not rely on an external script telling Valgrind which wrappers pertain
367 to which originals.</para>
369 <para>Each wrapper has a name which, in the most general case says: I am the
370 wrapper for any function whose name matches FNPATT and whose ELF
371 "soname" matches SOPATT. Both FNPATT and SOPATT may contain wildcards
372 (asterisks) and other characters (spaces, dots, @, etc) which are not
373 generally regarded as valid C identifier names.</para>
375 <para>This flexibility is needed to write robust wrappers for POSIX pthread
376 functions, where typically we are not completely sure of either the
377 function name or the soname, or alternatively we want to wrap a whole
378 set of functions at once.</para>
380 <para>For example, <computeroutput>pthread_create</computeroutput>
381 in GNU libpthread is usually a
382 versioned symbol - one whose name ends in, eg,
383 <computeroutput>@GLIBC_2.3</computeroutput>. Hence we
384 are not sure what its real name is. We also want to cover any soname
385 of the form <computeroutput>libpthread.so*</computeroutput>.
386 So the header of the wrapper will be</para>
388 <programlisting><![CDATA[
389 int I_WRAP_SONAME_FNNAME_ZZ(libpthreadZdsoZd0,pthreadZucreateZAZa)
394 <para>In order to write unusual characters as valid C function names, a
395 Z-encoding scheme is used. Names are written literally, except that
396 a capital Z acts as an escape character, with the following encoding:</para>
398 <programlisting><![CDATA[
408 ZL ( # only in valgrind 3.3.0 and later
409 ZR ) # only in valgrind 3.3.0 and later
412 <para>Hence <computeroutput>libpthreadZdsoZd0</computeroutput> is an
413 encoding of the soname <computeroutput>libpthread.so.0</computeroutput>
414 and <computeroutput>pthreadZucreateZAZa</computeroutput> is an encoding
415 of the function name <computeroutput>pthread_create@*</computeroutput>.
418 <para>The macro <computeroutput>I_WRAP_SONAME_FNNAME_ZZ</computeroutput>
419 constructs a wrapper name in which
420 both the soname (first component) and function name (second component)
421 are Z-encoded. Encoding the function name can be tiresome and is
422 often unnecessary, so a second macro,
423 <computeroutput>I_WRAP_SONAME_FNNAME_ZU</computeroutput>, can be
424 used instead. The <computeroutput>_ZU</computeroutput> variant is
425 also useful for writing wrappers for
426 C++ functions, in which the function name is usually already mangled
427 using some other convention in which Z plays an important role. Having
428 to encode a second time quickly becomes confusing.</para>
430 <para>Since the function name field may contain wildcards, it can be
431 anything, including just <computeroutput>*</computeroutput>.
432 The same is true for the soname.
433 However, some ELF objects - specifically, main executables - do not
434 have sonames. Any object lacking a soname is treated as if its soname
435 was <computeroutput>NONE</computeroutput>, which is why the original
436 example above had a name
437 <computeroutput>I_WRAP_SONAME_FNNAME_ZU(NONE,foo)</computeroutput>.</para>
439 <para>Note that the soname of an ELF object is not the same as its
440 file name, although it is often similar. You can find the soname of
441 an object <computeroutput>libfoo.so</computeroutput> using the command
442 <computeroutput>readelf -a libfoo.so | grep soname</computeroutput>.</para>
445 <sect2 id="manual-core-adv.wrapping.semantics" xreflabel="Wrapping Semantics">
446 <title>Wrapping Semantics</title>
448 <para>The ability for a wrapper to replace an infinite family of functions
449 is powerful but brings complications in situations where ELF objects
450 appear and disappear (are dlopen'd and dlclose'd) on the fly.
451 Valgrind tries to maintain sensible behaviour in such situations.</para>
453 <para>For example, suppose a process has dlopened (an ELF object with
454 soname) <filename>object1.so</filename>, which contains
455 <computeroutput>function1</computeroutput>. It starts to use
456 <computeroutput>function1</computeroutput> immediately.</para>
458 <para>After a while it dlopens <filename>wrappers.so</filename>,
459 which contains a wrapper
460 for <computeroutput>function1</computeroutput> in (soname)
461 <filename>object1.so</filename>. All subsequent calls to
462 <computeroutput>function1</computeroutput> are rerouted to the wrapper.</para>
464 <para>If <filename>wrappers.so</filename> is
465 later dlclose'd, calls to <computeroutput>function1</computeroutput> are
466 naturally routed back to the original.</para>
468 <para>Alternatively, if <filename>object1.so</filename>
469 is dlclose'd but <filename>wrappers.so</filename> remains,
470 then the wrapper exported by <filename>wrappers.so</filename>
471 becomes inactive, since there
472 is no way to get to it - there is no original to call any more. However,
473 Valgrind remembers that the wrapper is still present. If
474 <filename>object1.so</filename> is
475 eventually dlopen'd again, the wrapper will become active again.</para>
477 <para>In short, valgrind inspects all code loading/unloading events to
478 ensure that the set of currently active wrappers remains consistent.</para>
480 <para>A second possible problem is that of conflicting wrappers. It is
481 easily possible to load two or more wrappers, both of which claim
482 to be wrappers for some third function. In such cases Valgrind will
483 complain about conflicting wrappers when the second one appears, and
484 will honour only the first one.</para>
487 <sect2 id="manual-core-adv.wrapping.debugging" xreflabel="Debugging">
488 <title>Debugging</title>
490 <para>Figuring out what's going on given the dynamic nature of wrapping
491 can be difficult. The
492 <option>--trace-redir=yes</option> option makes
494 by showing the complete state of the redirection subsystem after
496 <function>mmap</function>/<function>munmap</function>
497 event affecting code (text).</para>
499 <para>There are two central concepts:</para>
503 <listitem><para>A "redirection specification" is a binding of
504 a (soname pattern, fnname pattern) pair to a code address.
505 These bindings are created by writing functions with names
507 <computeroutput>I_WRAP_SONAME_FNNAME_{ZZ,_ZU}</computeroutput>
508 macros.</para></listitem>
510 <listitem><para>An "active redirection" is a code-address to
511 code-address binding currently in effect.</para></listitem>
515 <para>The state of the wrapping-and-redirection subsystem comprises a set of
516 specifications and a set of active bindings. The specifications are
517 acquired/discarded by watching all
518 <function>mmap</function>/<function>munmap</function>
519 events on code (text)
520 sections. The active binding set is (conceptually) recomputed from
521 the specifications, and all known symbol names, following any change
522 to the specification set.</para>
524 <para><option>--trace-redir=yes</option> shows the contents
525 of both sets following any such event.</para>
527 <para><option>-v</option> prints a line of text each
528 time an active specification is used for the first time.</para>
530 <para>Hence for maximum debugging effectiveness you will need to use both
533 <para>One final comment. The function-wrapping facility is closely
534 tied to Valgrind's ability to replace (redirect) specified
535 functions, for example to redirect calls to
536 <function>malloc</function> to its
537 own implementation. Indeed, a replacement function can be
538 regarded as a wrapper function which does not call the original.
539 However, to make the implementation more robust, the two kinds
540 of interception (wrapping vs replacement) are treated differently.
543 <para><option>--trace-redir=yes</option> shows
544 specifications and bindings for both
545 replacement and wrapper functions. To differentiate the
546 two, replacement bindings are printed using
547 <computeroutput>R-></computeroutput> whereas
548 wraps are printed using <computeroutput>W-></computeroutput>.
553 <sect2 id="manual-core-adv.wrapping.limitations-cf"
554 xreflabel="Limitations - control flow">
555 <title>Limitations - control flow</title>
557 <para>For the most part, the function wrapping implementation is robust.
558 The only important caveat is: in a wrapper, get hold of
559 the <computeroutput>OrigFn</computeroutput> information using
560 <computeroutput>VALGRIND_GET_ORIG_FN</computeroutput> before calling any
561 other wrapped function. Once you have the
562 <computeroutput>OrigFn</computeroutput>, arbitrary
563 calls between, recursion between, and longjumps out of wrappers
564 should work correctly. There is never any interaction between wrapped
565 functions and merely replaced functions
566 (eg <function>malloc</function>), so you can call
567 <function>malloc</function> etc safely from within wrappers.
570 <para>The above comments are true for {x86,amd64,ppc32}-linux. On
571 ppc64-linux function wrapping is more fragile due to the (arguably
572 poorly designed) ppc64-linux ABI. This mandates the use of a shadow
573 stack which tracks entries/exits of both wrapper and replacement
574 functions. This gives two limitations: firstly, longjumping out of
575 wrappers will rapidly lead to disaster, since the shadow stack will
576 not get correctly cleared. Secondly, since the shadow stack has
577 finite size, recursion between wrapper/replacement functions is only
578 possible to a limited depth, beyond which Valgrind has to abort the
579 run. This depth is currently 16 calls.</para>
581 <para>For all platforms ({x86,amd64,ppc32,ppc64}-linux) all the above
582 comments apply on a per-thread basis. In other words, wrapping is
583 thread-safe: each thread must individually observe the above
584 restrictions, but there is no need for any kind of inter-thread
589 <sect2 id="manual-core-adv.wrapping.limitations-sigs"
590 xreflabel="Limitations - original function signatures">
591 <title>Limitations - original function signatures</title>
593 <para>As shown in the above example, to call the original you must use a
594 macro of the form <computeroutput>CALL_FN_*</computeroutput>.
595 For technical reasons it is impossible
596 to create a single macro to deal with all argument types and numbers,
597 so a family of macros covering the most common cases is supplied. In
598 what follows, 'W' denotes a machine-word-typed value (a pointer or a
599 C <computeroutput>long</computeroutput>),
600 and 'v' denotes C's <computeroutput>void</computeroutput> type.
601 The currently available macros are:</para>
603 <programlisting><![CDATA[
604 CALL_FN_v_v -- call an original of type void fn ( void )
605 CALL_FN_W_v -- call an original of type long fn ( void )
607 CALL_FN_v_W -- call an original of type void fn ( long )
608 CALL_FN_W_W -- call an original of type long fn ( long )
610 CALL_FN_v_WW -- call an original of type void fn ( long, long )
611 CALL_FN_W_WW -- call an original of type long fn ( long, long )
613 CALL_FN_v_WWW -- call an original of type void fn ( long, long, long )
614 CALL_FN_W_WWW -- call an original of type long fn ( long, long, long )
616 CALL_FN_W_WWWW -- call an original of type long fn ( long, long, long, long )
617 CALL_FN_W_5W -- call an original of type long fn ( long, long, long, long, long )
618 CALL_FN_W_6W -- call an original of type long fn ( long, long, long, long, long, long )
623 <para>The set of supported types can be expanded as needed. It is
624 regrettable that this limitation exists. Function wrapping has proven
625 difficult to implement, with a certain apparently unavoidable level of
626 ickiness. After several implementation attempts, the present
627 arrangement appears to be the least-worst tradeoff. At least it works
628 reliably in the presence of dynamic linking and dynamic code
629 loading/unloading.</para>
631 <para>You should not attempt to wrap a function of one type signature with a
632 wrapper of a different type signature. Such trickery will surely lead
633 to crashes or strange behaviour. This is not a limitation
634 of the function wrapping implementation, merely a reflection of the
635 fact that it gives you sweeping powers to shoot yourself in the foot
636 if you are not careful. Imagine the instant havoc you could wreak by
637 writing a wrapper which matched any function name in any soname - in
638 effect, one which claimed to be a wrapper for all functions in the
642 <sect2 id="manual-core-adv.wrapping.examples" xreflabel="Examples">
643 <title>Examples</title>
645 <para>In the source tree,
646 <filename>memcheck/tests/wrap[1-8].c</filename> provide a series of
647 examples, ranging from very simple to quite advanced.</para>
649 <para><filename>mpi/libmpiwrap.c</filename> is an example
650 of wrapping a big, complex API (the MPI-2 interface). This file defines
651 almost 300 different wrappers.</para>