• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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; ]>
5
6
7<chapter id="manual-core-adv" xreflabel="Valgrind's core: advanced topics">
8<title>Using and understanding the Valgrind core: Advanced Topics</title>
9
10<para>This chapter describes advanced aspects of the Valgrind core
11services, which are mostly of interest to power users who wish to
12customise and modify Valgrind's default behaviours in certain useful
13ways.  The subjects covered are:</para>
14
15<itemizedlist>
16  <listitem><para>The "Client Request" mechanism</para></listitem>
17  <listitem><para>Function Wrapping</para></listitem>
18</itemizedlist>
19
20
21
22<sect1 id="manual-core-adv.clientreq"
23       xreflabel="The Client Request mechanism">
24<title>The Client Request mechanism</title>
25
26<para>Valgrind has a trapdoor mechanism via which the client
27program can pass all manner of requests and queries to Valgrind
28and the current tool.  Internally, this is used extensively
29to make various things work, although that's not visible from the
30outside.</para>
31
32<para>For your convenience, a subset of these so-called client
33requests is provided to allow you to tell Valgrind facts about
34the behaviour of your program, and also to make queries.
35In particular, your program can tell Valgrind about things that it
36otherwise would not know, leading to better results.
37</para>
38
39<para>Clients need to include a header file to make this work.
40Which header file depends on which client requests you use.  Some
41client requests are handled by the core, and are defined in the
42header file <filename>valgrind/valgrind.h</filename>.  Tool-specific
43header files are named after the tool, e.g.
44<filename>valgrind/memcheck.h</filename>.  Each tool-specific header file
45includes <filename>valgrind/valgrind.h</filename> so you don't need to
46include it in your client if you include a tool-specific header.  All header
47files can be found in the <literal>include/valgrind</literal> directory of
48wherever Valgrind was installed.</para>
49
50<para>The macros in these header files have the magical property
51that they generate code in-line which Valgrind can spot.
52However, the code does nothing when not run on Valgrind, so you
53are not forced to run your program under Valgrind just because you
54use the macros in this file.  Also, you are not required to link your
55program with any extra supporting libraries.</para>
56
57<para>The code added to your binary has negligible performance impact:
58on x86, amd64, ppc32, ppc64 and ARM, the overhead is 6 simple integer
59instructions and is probably undetectable except in tight loops.
60However, if you really wish to compile out the client requests, you
61can compile with <option>-DNVALGRIND</option> (analogous to
62<option>-DNDEBUG</option>'s effect on
63<function>assert</function>).
64</para>
65
66<para>You are encouraged to copy the <filename>valgrind/*.h</filename> headers
67into your project's include directory, so your program doesn't have a
68compile-time dependency on Valgrind being installed.  The Valgrind headers,
69unlike most of the rest of the code, are under a BSD-style license so you may
70include them without worrying about license incompatibility.</para>
71
72<para>Here is a brief description of the macros available in
73<filename>valgrind.h</filename>, which work with more than one
74tool (see the tool-specific documentation for explanations of the
75tool-specific macros).</para>
76
77 <variablelist>
78
79  <varlistentry>
80   <term><command><computeroutput>RUNNING_ON_VALGRIND</computeroutput></command>:</term>
81   <listitem>
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.
85    </para>
86   </listitem>
87  </varlistentry>
88
89  <varlistentry>
90   <term><command><computeroutput>VALGRIND_DISCARD_TRANSLATIONS</computeroutput>:</command></term>
91   <listitem>
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
105    once.</para>
106    <para>
107    Alternatively, for transparent self-modifying-code support,
108    use<option>--smc-check=all</option>, or run
109    on ppc32/Linux, ppc64/Linux or ARM/Linux.
110    </para>
111   </listitem>
112  </varlistentry>
113
114  <varlistentry>
115   <term><command><computeroutput>VALGRIND_COUNT_ERRORS</computeroutput>:</command></term>
116   <listitem>
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>
124   </listitem>
125  </varlistentry>
126
127  <varlistentry>
128   <term><command><computeroutput>VALGRIND_MALLOCLIKE_BLOCK</computeroutput>:</command></term>
129   <listitem>
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
140    it.</para>
141   </listitem>
142  </varlistentry>
143
144  <varlistentry>
145   <term><command><computeroutput>VALGRIND_FREELIKE_BLOCK</computeroutput>:</command></term>
146   <listitem>
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>
151   </listitem>
152  </varlistentry>
153
154  <varlistentry>
155   <term>
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>:
163   </term>
164   <listitem>
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>
170   </listitem>
171  </varlistentry>
172
173  <varlistentry>
174   <term><command><computeroutput>VALGRIND_NON_SIMD_CALL[0123]</computeroutput>:</command></term>
175   <listitem>
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
182    programs.</para>
183
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.
188    </para>
189   </listitem>
190  </varlistentry>
191
192  <varlistentry>
193   <term><command><computeroutput>VALGRIND_PRINTF(format, ...)</computeroutput>:</command></term>
194   <listitem>
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 subsequent
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>
203   </listitem>
204  </varlistentry>
205
206  <varlistentry>
207   <term><command><computeroutput>VALGRIND_PRINTF_BACKTRACE(format, ...)</computeroutput>:</command></term>
208   <listitem>
209    <para>Like <computeroutput>VALGRIND_PRINTF</computeroutput> (in
210    particular, the return value is identical), but prints a stack backtrace
211    immediately afterwards.</para>
212   </listitem>
213  </varlistentry>
214
215  <varlistentry>
216   <term><command><computeroutput>VALGRIND_STACK_REGISTER(start, end)</computeroutput>:</command></term>
217   <listitem>
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
226    memory reads.</para>
227
228    <para><command>Warning:</command> Unfortunately, this client request is
229    unreliable and best avoided.</para>
230   </listitem>
231  </varlistentry>
232
233  <varlistentry>
234   <term><command><computeroutput>VALGRIND_STACK_DEREGISTER(id)</computeroutput>:</command></term>
235   <listitem>
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>
239
240    <para><command>Warning:</command> Unfortunately, this client request is
241    unreliable and best avoided.</para>
242   </listitem>
243  </varlistentry>
244
245  <varlistentry>
246   <term><command><computeroutput>VALGRIND_STACK_CHANGE(id, start, end)</computeroutput>:</command></term>
247   <listitem>
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
252    stack growth.</para>
253
254    <para><command>Warning:</command> Unfortunately, this client request is
255    unreliable and best avoided.</para>
256   </listitem>
257  </varlistentry>
258
259 </variablelist>
260
261</sect1>
262
263
264
265
266
267<sect1 id="manual-core-adv.wrapping" xreflabel="Function Wrapping">
268<title>Function wrapping</title>
269
270<para>
271Valgrind allows calls to some specified functions to be intercepted and
272rerouted to a different, user-supplied function.  This can do whatever it
273likes, typically examining the arguments, calling onwards to the original,
274and possibly examining the result.  Any number of functions may be
275wrapped.</para>
276
277<para>
278Function wrapping is useful for instrumenting an API in some way.  For
279example, Helgrind wraps functions in the POSIX pthreads API so it can know
280about thread status changes, and the core is able to wrap
281functions in the MPI (message-passing) API so it can know
282of memory status changes associated with message arrival/departure.
283Such information is usually passed to Valgrind by using client
284requests in the wrapper functions, although the exact mechanism may vary.
285</para>
286
287<sect2 id="manual-core-adv.wrapping.example" xreflabel="A Simple Example">
288<title>A Simple Example</title>
289
290<para>Supposing we want to wrap some function</para>
291
292<programlisting><![CDATA[
293int foo ( int x, int y ) { return x + y; }]]></programlisting>
294
295<para>A wrapper is a function of identical type, but with a special name
296which identifies it as the wrapper for <computeroutput>foo</computeroutput>.
297Wrappers need to include
298supporting macros from <filename>valgrind.h</filename>.
299Here is a simple wrapper which prints the arguments and return value:</para>
300
301<programlisting><![CDATA[
302#include <stdio.h>
303#include "valgrind.h"
304int I_WRAP_SONAME_FNNAME_ZU(NONE,foo)( int x, int y )
305{
306   int    result;
307   OrigFn fn;
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);
312   return result;
313}
314]]></programlisting>
315
316<para>To become active, the wrapper merely needs to be present in a text
317section somewhere in the same process' address space as the function
318it wraps, and for its ELF symbol name to be visible to Valgrind.  In
319practice, this means either compiling to a
320<computeroutput>.o</computeroutput> and linking it in, or
321compiling to a <computeroutput>.so</computeroutput> and
322<computeroutput>LD_PRELOAD</computeroutput>ing it in.  The latter is more
323convenient in that it doesn't require relinking.</para>
324
325<para>All wrappers have approximately the above form.  There are three
326crucial macros:</para>
327
328<para><computeroutput>I_WRAP_SONAME_FNNAME_ZU</computeroutput>:
329this generates the real name of the wrapper.
330This is an encoded name which Valgrind notices when reading symbol
331table information.  What it says is: I am the wrapper for any function
332named <computeroutput>foo</computeroutput> which is found in
333an ELF shared object with an empty
334("<computeroutput>NONE</computeroutput>") soname field.  The specification
335mechanism is powerful in
336that wildcards are allowed for both sonames and function names.
337The details are discussed below.</para>
338
339<para><computeroutput>VALGRIND_GET_ORIG_FN</computeroutput>:
340once in the the wrapper, the first priority is
341to get hold of the address of the original (and any other supporting
342information needed).  This is stored in a value of opaque
343type <computeroutput>OrigFn</computeroutput>.
344The information is acquired using
345<computeroutput>VALGRIND_GET_ORIG_FN</computeroutput>.  It is crucial
346to make this macro call before calling any other wrapped function
347in the same thread.</para>
348
349<para><computeroutput>CALL_FN_W_WW</computeroutput>: eventually we will
350want to call the function being
351wrapped.  Calling it directly does not work, since that just gets us
352back to the wrapper and leads to an infinite loop.  Instead, the result
353lvalue,
354<computeroutput>OrigFn</computeroutput> and arguments are
355handed to one of a family of macros of the form
356<computeroutput>CALL_FN_*</computeroutput>.  These
357cause Valgrind to call the original and avoid recursion back to the
358wrapper.</para>
359</sect2>
360
361<sect2 id="manual-core-adv.wrapping.specs" xreflabel="Wrapping Specifications">
362<title>Wrapping Specifications</title>
363
364<para>This scheme has the advantage of being self-contained.  A library of
365wrappers can be compiled to object code in the normal way, and does
366not rely on an external script telling Valgrind which wrappers pertain
367to which originals.</para>
368
369<para>Each wrapper has a name which, in the most general case says: I am the
370wrapper 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
373generally regarded as valid C identifier names.</para>
374
375<para>This flexibility is needed to write robust wrappers for POSIX pthread
376functions, where typically we are not completely sure of either the
377function name or the soname, or alternatively we want to wrap a whole
378set of functions at once.</para>
379
380<para>For example, <computeroutput>pthread_create</computeroutput>
381in GNU libpthread is usually a
382versioned symbol - one whose name ends in, eg,
383<computeroutput>@GLIBC_2.3</computeroutput>.  Hence we
384are not sure what its real name is.  We also want to cover any soname
385of the form <computeroutput>libpthread.so*</computeroutput>.
386So the header of the wrapper will be</para>
387
388<programlisting><![CDATA[
389int I_WRAP_SONAME_FNNAME_ZZ(libpthreadZdsoZd0,pthreadZucreateZAZa)
390  ( ... formals ... )
391  { ... body ... }
392]]></programlisting>
393
394<para>In order to write unusual characters as valid C function names, a
395Z-encoding scheme is used.  Names are written literally, except that
396a capital Z acts as an escape character, with the following encoding:</para>
397
398<programlisting><![CDATA[
399     Za   encodes    *
400     Zp              +
401     Zc              :
402     Zd              .
403     Zu              _
404     Zh              -
405     Zs              (space)
406     ZA              @
407     ZZ              Z
408     ZL              (       # only in valgrind 3.3.0 and later
409     ZR              )       # only in valgrind 3.3.0 and later
410]]></programlisting>
411
412<para>Hence <computeroutput>libpthreadZdsoZd0</computeroutput> is an
413encoding of the soname <computeroutput>libpthread.so.0</computeroutput>
414and <computeroutput>pthreadZucreateZAZa</computeroutput> is an encoding
415of the function name <computeroutput>pthread_create@*</computeroutput>.
416</para>
417
418<para>The macro <computeroutput>I_WRAP_SONAME_FNNAME_ZZ</computeroutput>
419constructs a wrapper name in which
420both the soname (first component) and function name (second component)
421are Z-encoded.  Encoding the function name can be tiresome and is
422often unnecessary, so a second macro,
423<computeroutput>I_WRAP_SONAME_FNNAME_ZU</computeroutput>, can be
424used instead.  The <computeroutput>_ZU</computeroutput> variant is
425also useful for writing wrappers for
426C++ functions, in which the function name is usually already mangled
427using some other convention in which Z plays an important role.  Having
428to encode a second time quickly becomes confusing.</para>
429
430<para>Since the function name field may contain wildcards, it can be
431anything, including just <computeroutput>*</computeroutput>.
432The same is true for the soname.
433However, some ELF objects - specifically, main executables - do not
434have sonames.  Any object lacking a soname is treated as if its soname
435was <computeroutput>NONE</computeroutput>, which is why the original
436example above had a name
437<computeroutput>I_WRAP_SONAME_FNNAME_ZU(NONE,foo)</computeroutput>.</para>
438
439<para>Note that the soname of an ELF object is not the same as its
440file name, although it is often similar.  You can find the soname of
441an object <computeroutput>libfoo.so</computeroutput> using the command
442<computeroutput>readelf -a libfoo.so | grep soname</computeroutput>.</para>
443</sect2>
444
445<sect2 id="manual-core-adv.wrapping.semantics" xreflabel="Wrapping Semantics">
446<title>Wrapping Semantics</title>
447
448<para>The ability for a wrapper to replace an infinite family of functions
449is powerful but brings complications in situations where ELF objects
450appear and disappear (are dlopen'd and dlclose'd) on the fly.
451Valgrind tries to maintain sensible behaviour in such situations.</para>
452
453<para>For example, suppose a process has dlopened (an ELF object with
454soname) <filename>object1.so</filename>, which contains
455<computeroutput>function1</computeroutput>.  It starts to use
456<computeroutput>function1</computeroutput> immediately.</para>
457
458<para>After a while it dlopens <filename>wrappers.so</filename>,
459which contains a wrapper
460for <computeroutput>function1</computeroutput> in (soname)
461<filename>object1.so</filename>.  All subsequent calls to
462<computeroutput>function1</computeroutput> are rerouted to the wrapper.</para>
463
464<para>If <filename>wrappers.so</filename> is
465later dlclose'd, calls to <computeroutput>function1</computeroutput> are
466naturally routed back to the original.</para>
467
468<para>Alternatively, if <filename>object1.so</filename>
469is dlclose'd but <filename>wrappers.so</filename> remains,
470then the wrapper exported by <filename>wrappers.so</filename>
471becomes inactive, since there
472is no way to get to it - there is no original to call any more.  However,
473Valgrind remembers that the wrapper is still present.  If
474<filename>object1.so</filename> is
475eventually dlopen'd again, the wrapper will become active again.</para>
476
477<para>In short, valgrind inspects all code loading/unloading events to
478ensure that the set of currently active wrappers remains consistent.</para>
479
480<para>A second possible problem is that of conflicting wrappers.  It is
481easily possible to load two or more wrappers, both of which claim
482to be wrappers for some third function.  In such cases Valgrind will
483complain about conflicting wrappers when the second one appears, and
484will honour only the first one.</para>
485</sect2>
486
487<sect2 id="manual-core-adv.wrapping.debugging" xreflabel="Debugging">
488<title>Debugging</title>
489
490<para>Figuring out what's going on given the dynamic nature of wrapping
491can be difficult.  The
492<option>--trace-redir=yes</option> option makes
493this possible
494by showing the complete state of the redirection subsystem after
495every
496<function>mmap</function>/<function>munmap</function>
497event affecting code (text).</para>
498
499<para>There are two central concepts:</para>
500
501<itemizedlist>
502
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
506  made with the
507  <computeroutput>I_WRAP_SONAME_FNNAME_{ZZ,_ZU}</computeroutput>
508  macros.</para></listitem>
509
510  <listitem><para>An "active redirection" is a code-address to
511  code-address binding currently in effect.</para></listitem>
512
513</itemizedlist>
514
515<para>The state of the wrapping-and-redirection subsystem comprises a set of
516specifications and a set of active bindings.  The specifications are
517acquired/discarded by watching all
518<function>mmap</function>/<function>munmap</function>
519events on code (text)
520sections.  The active binding set is (conceptually) recomputed from
521the specifications, and all known symbol names, following any change
522to the specification set.</para>
523
524<para><option>--trace-redir=yes</option> shows the contents
525of both sets following any such event.</para>
526
527<para><option>-v</option> prints a line of text each
528time an active specification is used for the first time.</para>
529
530<para>Hence for maximum debugging effectiveness you will need to use both
531options.</para>
532
533<para>One final comment.  The function-wrapping facility is closely
534tied to Valgrind's ability to replace (redirect) specified
535functions, for example to redirect calls to
536<function>malloc</function> to its
537own implementation.  Indeed, a replacement function can be
538regarded as a wrapper function which does not call the original.
539However, to make the implementation more robust, the two kinds
540of interception (wrapping vs replacement) are treated differently.
541</para>
542
543<para><option>--trace-redir=yes</option> shows
544specifications and bindings for both
545replacement and wrapper functions.  To differentiate the
546two, replacement bindings are printed using
547<computeroutput>R-></computeroutput> whereas
548wraps are printed using <computeroutput>W-></computeroutput>.
549</para>
550</sect2>
551
552
553<sect2 id="manual-core-adv.wrapping.limitations-cf"
554       xreflabel="Limitations - control flow">
555<title>Limitations - control flow</title>
556
557<para>For the most part, the function wrapping implementation is robust.
558The only important caveat is: in a wrapper, get hold of
559the <computeroutput>OrigFn</computeroutput> information using
560<computeroutput>VALGRIND_GET_ORIG_FN</computeroutput> before calling any
561other wrapped function.  Once you have the
562<computeroutput>OrigFn</computeroutput>, arbitrary
563calls between, recursion between, and longjumps out of wrappers
564should work correctly.  There is never any interaction between wrapped
565functions and merely replaced functions
566(eg <function>malloc</function>), so you can call
567<function>malloc</function> etc safely from within wrappers.
568</para>
569
570<para>The above comments are true for {x86,amd64,ppc32,arm}-linux.  On
571ppc64-linux function wrapping is more fragile due to the (arguably
572poorly designed) ppc64-linux ABI.  This mandates the use of a shadow
573stack which tracks entries/exits of both wrapper and replacement
574functions.  This gives two limitations: firstly, longjumping out of
575wrappers will rapidly lead to disaster, since the shadow stack will
576not get correctly cleared.  Secondly, since the shadow stack has
577finite size, recursion between wrapper/replacement functions is only
578possible to a limited depth, beyond which Valgrind has to abort the
579run.  This depth is currently 16 calls.</para>
580
581<para>For all platforms ({x86,amd64,ppc32,ppc64,arm}-linux) all the above
582comments apply on a per-thread basis.  In other words, wrapping is
583thread-safe: each thread must individually observe the above
584restrictions, but there is no need for any kind of inter-thread
585cooperation.</para>
586</sect2>
587
588
589<sect2 id="manual-core-adv.wrapping.limitations-sigs"
590       xreflabel="Limitations - original function signatures">
591<title>Limitations - original function signatures</title>
592
593<para>As shown in the above example, to call the original you must use a
594macro of the form <computeroutput>CALL_FN_*</computeroutput>.
595For technical reasons it is impossible
596to create a single macro to deal with all argument types and numbers,
597so a family of macros covering the most common cases is supplied.  In
598what follows, 'W' denotes a machine-word-typed value (a pointer or a
599C <computeroutput>long</computeroutput>),
600and 'v' denotes C's <computeroutput>void</computeroutput> type.
601The currently available macros are:</para>
602
603<programlisting><![CDATA[
604CALL_FN_v_v    -- call an original of type  void fn ( void )
605CALL_FN_W_v    -- call an original of type  long fn ( void )
606
607CALL_FN_v_W    -- call an original of type  void fn ( long )
608CALL_FN_W_W    -- call an original of type  long fn ( long )
609
610CALL_FN_v_WW   -- call an original of type  void fn ( long, long )
611CALL_FN_W_WW   -- call an original of type  long fn ( long, long )
612
613CALL_FN_v_WWW  -- call an original of type  void fn ( long, long, long )
614CALL_FN_W_WWW  -- call an original of type  long fn ( long, long, long )
615
616CALL_FN_W_WWWW -- call an original of type  long fn ( long, long, long, long )
617CALL_FN_W_5W   -- call an original of type  long fn ( long, long, long, long, long )
618CALL_FN_W_6W   -- call an original of type  long fn ( long, long, long, long, long, long )
619and so on, up to
620CALL_FN_W_12W
621]]></programlisting>
622
623<para>The set of supported types can be expanded as needed.  It is
624regrettable that this limitation exists.  Function wrapping has proven
625difficult to implement, with a certain apparently unavoidable level of
626ickiness.  After several implementation attempts, the present
627arrangement appears to be the least-worst tradeoff.  At least it works
628reliably in the presence of dynamic linking and dynamic code
629loading/unloading.</para>
630
631<para>You should not attempt to wrap a function of one type signature with a
632wrapper of a different type signature.  Such trickery will surely lead
633to crashes or strange behaviour.  This is not a limitation
634of the function wrapping implementation, merely a reflection of the
635fact that it gives you sweeping powers to shoot yourself in the foot
636if you are not careful.  Imagine the instant havoc you could wreak by
637writing a wrapper which matched any function name in any soname - in
638effect, one which claimed to be a wrapper for all functions in the
639process.</para>
640</sect2>
641
642<sect2 id="manual-core-adv.wrapping.examples" xreflabel="Examples">
643<title>Examples</title>
644
645<para>In the source tree,
646<filename>memcheck/tests/wrap[1-8].c</filename> provide a series of
647examples, ranging from very simple to quite advanced.</para>
648
649<para><filename>mpi/libmpiwrap.c</filename> is an example
650of wrapping a big, complex API (the MPI-2 interface).  This file defines
651almost 300 different wrappers.</para>
652</sect2>
653
654</sect1>
655
656
657
658
659</chapter>
660