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