From: Nicholas Nethercote Date: Tue, 4 Aug 2009 05:24:46 +0000 (+0000) Subject: Various clean-ups, mostly in chapter 3. X-Git-Tag: svn/VALGRIND_3_5_0~145 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=daa35cac732853c8e039ea00c5497a020045bf79;p=thirdparty%2Fvalgrind.git Various clean-ups, mostly in chapter 3. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@10705 --- diff --git a/docs/xml/manual-core-adv.xml b/docs/xml/manual-core-adv.xml index 8d5bcc6cea..bf02d073ac 100644 --- a/docs/xml/manual-core-adv.xml +++ b/docs/xml/manual-core-adv.xml @@ -25,25 +25,27 @@ ways. The subjects covered are: 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. +and the current tool. Internally, this is used extensively +to make various things work, although that's not visible from the +outside. 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. +In particular, your program can tell Valgrind about things that it +otherwise would not know, leading to better results. + 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 valgrind/valgrind.h. Tool-specific header files are named after the tool, e.g. -valgrind/memcheck.h. All header files can be found -in the include/valgrind directory of wherever Valgrind -was installed. +valgrind/memcheck.h. Each tool-specific header file +includes valgrind/valgrind.h so you don't need to +include it in your client if you include a tool-specific header. All header +files can be found in the include/valgrind directory of +wherever Valgrind was installed. The macros in these header files have the magical property that they generate code in-line which Valgrind can spot. @@ -58,7 +60,7 @@ and is probably undetectable except in tight loops. However, if you really wish to compile out the client requests, you can compile with (analogous to 's effect on -assert()). +assert). You are encouraged to copy the valgrind/*.h headers @@ -94,7 +96,7 @@ tool-specific macros). 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. + 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 @@ -126,9 +128,9 @@ tool-specific macros). VALGRIND_MALLOCLIKE_BLOCK: If your program manages its own memory instead of using - the standard malloc() / - new / - new[], tools that track + the standard malloc / + new / + new[], 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 @@ -144,7 +146,7 @@ tool-specific macros). This should be used in conjunction with VALGRIND_MALLOCLIKE_BLOCK. - Again, see memcheck/memcheck.h for + Again, see valgrind.h for information on how to use it. @@ -193,20 +195,18 @@ tool-specific macros). VALGRIND_NON_SIMD_CALL[0123]: - Executes a function of 0, 1, 2 or 3 args in the client - program on the real 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. + Executes a function in the client program on the + real CPU, not the virtual CPU that Valgrind + normally runs code on. The function must take an integer (holding a + thread ID) as the first argument and then 0, 1, 2 or 3 more arguments + (depending on which client request is used). These are used in various + ways internally to Valgrind. They might be useful to client + programs. Warning: Only use these if you really 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. + entirely reliable, and can cause Valgrind to crash. See + valgrind.h for more details. @@ -214,22 +214,23 @@ tool-specific macros). VALGRIND_PRINTF(format, ...): - printf a message to the log file when running under - Valgrind, prefixed with the PID between a pair of - ** markers. Nothing is output if not - running under Valgrind. Output is not produced until a newline is - encountered, or subequent Valgrind output is printed; this allows you - to build up a single line of output over multiple calls. - Returns the number of characters output, excluding the PID at the - start. + Print a printf-style message to the Valgrind log file. The + message is prefixed with the PID between a pair of + ** markers. (Like all client requests, + nothing is output if the client program is not running under Valgrind.) + Output is not produced until a newline is encountered, or subequent + Valgrind output is printed; this allows you to build up a single line of + output over multiple calls. Returns the number of characters output, + excluding the PID prefix. VALGRIND_PRINTF_BACKTRACE(format, ...): - Like VALGRIND_PRINTF, but prints - a stack backtrace immediately afterwards. + Like VALGRIND_PRINTF (in + particular, the return value is identical), but prints a stack backtrace + immediately afterwards. @@ -245,6 +246,9 @@ tool-specific macros). 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. + + Warning: Unfortunately, this client request is + unreliable and best avoided. @@ -254,6 +258,9 @@ tool-specific macros). Deregisters a previously registered stack. Informs Valgrind that previously registered memory range with stack id id is no longer a stack. + + Warning: Unfortunately, this client request is + unreliable and best avoided. @@ -265,16 +272,14 @@ tool-specific macros). id has changed its start and end values. Use this if your user-level thread package implements stack growth. + + Warning: Unfortunately, this client request is + unreliable and best avoided. -Note that valgrind.h is included by -all the tool-specific header files (such as -memcheck.h), so you don't need to include it -in your client if you include a tool-specific header. - @@ -285,22 +290,21 @@ in your client if you include a tool-specific header. Function wrapping -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. +Valgrind allows calls to some specified functions to be 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. 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 +example, Helgrind wraps functions in the POSIX pthreads API so it can know +about thread status changes, and the core is able to wrap +functions in the MPI (message-passing) API so it can know 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. +requests in the wrapper functions, although the exact mechanism may vary. + A Simple Example @@ -313,7 +317,7 @@ int foo ( int x, int y ) { return x + y; }]]> A wrapper is a function of identical type, but with a special name which identifies it as the wrapper for foo. Wrappers need to include -supporting macros from valgrind.h. +supporting macros from valgrind.h. Here is a simple wrapper which prints the arguments and return value: CALL_FN_W_WW: 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, +back to the wrapper and leads to an infinite loop. Instead, the result +lvalue, OrigFn and arguments are handed to one of a family of macros of the form CALL_FN_*. These @@ -469,27 +473,27 @@ appear and disappear (are dlopen'd and dlclose'd) on the fly. Valgrind tries to maintain sensible behaviour in such situations. For example, suppose a process has dlopened (an ELF object with -soname) object1.so, which contains +soname) object1.so, which contains function1. It starts to use function1 immediately. -After a while it dlopens wrappers.so, +After a while it dlopens wrappers.so, which contains a wrapper for function1 in (soname) -object1.so. All subsequent calls to +object1.so. All subsequent calls to function1 are rerouted to the wrapper. -If wrappers.so is +If wrappers.so is later dlclose'd, calls to function1 are naturally routed back to the original. -Alternatively, if object1.so -is dlclose'd but wrappers.so remains, -then the wrapper exported by wrapper.so +Alternatively, if object1.so +is dlclose'd but wrappers.so remains, +then the wrapper exported by wrappers.so 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 -object1.so is +object1.so is eventually dlopen'd again, the wrapper will become active again. In short, valgrind inspects all code loading/unloading events to @@ -511,7 +515,7 @@ can be difficult. The this possible by showing the complete state of the redirection subsystem after every -mmap/munmap +mmap/munmap event affecting code (text). There are two central concepts: @@ -525,7 +529,7 @@ event affecting code (text). I_WRAP_SONAME_FNNAME_{ZZ,_ZU} macros. - An "active redirection" is code-address to + An "active redirection" is a code-address to code-address binding currently in effect. @@ -533,7 +537,7 @@ event affecting code (text). 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 -mmap/munmap +mmap/munmap events on code (text) sections. The active binding set is (conceptually) recomputed from the specifications, and all known symbol names, following any change @@ -551,7 +555,7 @@ flags. 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 -malloc to its +malloc 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 @@ -581,8 +585,8 @@ other wrapped function. Once you have the 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 malloc), so you can call -malloc etc safely from within wrappers. +(eg malloc), so you can call +malloc etc safely from within wrappers. The above comments are true for {x86,amd64,ppc32}-linux. On @@ -619,21 +623,21 @@ and 'v' denotes C's void type. The currently available macros are: @@ -641,14 +645,14 @@ CALL_FN_W_12W 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 +ickiness. 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. 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 +to crashes or strange behaviour. This is not 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 @@ -661,10 +665,10 @@ process. Examples In the source tree, -memcheck/tests/wrap[1-8].c provide a series of +memcheck/tests/wrap[1-8].c provide a series of examples, ranging from very simple to quite advanced. -auxprogs/libmpiwrap.c is an example +mpi/libmpiwrap.c is an example of wrapping a big, complex API (the MPI-2 interface). This file defines almost 300 different wrappers. diff --git a/memcheck/docs/mc-manual.xml b/memcheck/docs/mc-manual.xml index 4474818ea2..a1b8358cb0 100644 --- a/memcheck/docs/mc-manual.xml +++ b/memcheck/docs/mc-manual.xml @@ -1562,7 +1562,7 @@ buffer which is too small. Unlike most of the rest of Valgrind, the wrapper library is subject to a BSD-style license, so you can link it into any code base you like. -See the top of auxprogs/libmpiwrap.c +See the top of mpi/libmpiwrap.c for license details. @@ -1866,7 +1866,7 @@ to make the library thread-safe. checks. Writing new wrappers should be fairly easy. The source file is -auxprogs/libmpiwrap.c. If possible, +mpi/libmpiwrap.c. If possible, find an existing wrapper for a function of similar behaviour to the one you want to wrap, and use it as a starting point. The wrappers are organised in sections in the same order as the MPI 1.1 spec, to