Merge in function wrapping support from the FNWRAP branch. That
branch hereby becomes inactive. This currently breaks everything
except x86; fixes for amd64/ppc32 to follow.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5520 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
index 2e657ed..a52fb62 100644
--- a/include/pub_tool_redir.h
+++ b/include/pub_tool_redir.h
@@ -31,12 +31,32 @@
#ifndef __PUB_TOOL_REDIR_H
#define __PUB_TOOL_REDIR_H
-/* The following macros facilitate function replacement, which is one form
- of code replacement.
+/* The following macros facilitate function replacement and wrapping.
- The general idea is: you can write a function like this:
+ Function wrapping and function replacement are similar but not
+ identical.
- ret_type VG_REPLACE_FUNCTION(zEncodedSoname, fnname) ( ... args ... )
+ A replacement for some function F simply diverts all calls to F
+ to the stated replacement. There is no way to get back to F itself
+ from the replacement.
+
+ A wrapper for a function F causes all calls to F to instead go to
+ the wrapper. However, from inside the wrapper, it is possible
+ (with some difficulty) to get to F itself.
+
+ You may notice that replacement is a special case of wrapping, in
+ which the call to the original is omitted. For implementation
+ reasons, though, it is important to use the following macros
+ correctly: in particular, if you want to write a replacement, make
+ sure you use the VG_REPLACE_FN_ macros and not the VG_WRAP_FN_
+ macros.
+
+ Replacement
+ ~~~~~~~~~~~
+ To write a replacement function, do this:
+
+ ret_type
+ VG_REPLACE_FUNCTION_ZU(zEncodedSoname,fnname) ( .. args .. )
{
... body ...
}
@@ -44,52 +64,93 @@
zEncodedSoname should be a Z-encoded soname (see below for Z-encoding
details) and fnname should be an unencoded fn name. The resulting name is
- _vgi_zEncodedSoname_fnname
+ _vgrZU_zEncodedSoname_fnname
- The "_vgi_" is a prefix that gets discarded upon decoding.
+ The "_vgrZU_" is a prefix that gets discarded upon decoding.
+
+ It is also possible to write
+
+ ret_type
+ VG_REPLACE_FUNCTION_ZZ(zEncodedSoname,zEncodedFnname) ( .. args .. )
+ {
+ ... body ...
+ }
- When it sees this name, the core's symbol-table reading machinery
- and redirection machinery will conspire to cause calls to the function
- 'fnname' in object with soname 'zEncodedSoname' to actually be routed to
- the function written here. We use this below to define dozens of
- replacements of malloc, free, etc.
+ which means precisely the same, but the function name is also
+ Z-encoded. This can sometimes be necessary. In this case the
+ resulting function name is
+
+ _vgrZZ_zEncodedSoname_zEncodedFnname
+
+ When it sees this either such name, the core's symbol-table reading
+ machinery and redirection machinery first Z-decode the soname and
+ if necessary the fnname. They are encoded so that they may include
+ arbitrary characters, and in particular they may contain '*', which
+ acts as a wildcard.
+
+ They then will conspire to cause calls to any function matching
+ 'fnname' in any object whose soname matches 'soname' to actually be
+ routed to this function. This is used in Valgrind to define dozens
+ of replacements of malloc, free, etc.
The soname must be a Z-encoded bit of text because sonames can
- contain dots etc which are not valid symbol names. But don't Z-encode
- the function name, since it will already be a valid symbol name, and the
- Z-encoding might screw up the C++ demangling.
+ contain dots etc which are not valid symbol names. The function
+ name may or may not be Z-encoded: to include wildcards it has to be,
+ but Z-encoding C++ function names which are themselves already mangled
+ using Zs in some way is tedious and error prone, so the _ZU variant
+ allows them not to be Z-encoded.
- Note that the soname can contain '*' as a wildcard meaning "match
- anything".
+ Note that the soname "NONE" is specially interpreted to match any
+ shared object which doesn't have a soname.
Note also that the replacement function should probably (must be?) in
client space, so it runs on the simulated CPU. So it must be in
either vgpreload_<tool>.so or vgpreload_core.so. It also only works
with functions in shared objects, I think.
- It is important that the Z-encoded soname contains no unencoded
- underscores, since the intercept-handlers in vg_symtab2.c detect
- the end of the soname by looking for the first trailing underscore.
+ It is important that the Z-encoded names contain no unencoded
+ underscores, since the intercept-handlers in m_redir.c detect the
+ end of the soname by looking for the first trailing underscore.
- Z-encoding details: the scheme is like GHC's. It is just about
- readable enough to make a preprocessor unnecessary. First the "_vgi_"
- prefix is added, and then the following characters are transformed.
+ Wrapping
+ ~~~~~~~~
+ This is identical to replacement, except that you should use the
+ macro names
- * --> Za ('a' for "asterisk")
- + --> Zp
- : --> Zc
- . --> Zd
- _ --> Zu
- - --> Zh ('h' for "hyphen")
- (space) --> Zs
- Z --> ZZ
+ VG_WRAP_FUNCTION_ZU
+ VG_WRAP_FUNCTION_ZZ
+
+ instead.
+
+ Z-encoding
+ ~~~~~~~~~~
+ Z-encoding details: the scheme is like GHC's. It is just about
+ readable enough to make a preprocessor unnecessary. First the
+ "_vgrZU_" or "_vgrZZ_" prefix is added, and then the following
+ characters are transformed.
+
+ * --> Za (asterisk)
+ + --> Zp (plus)
+ : --> Zc (colon)
+ . --> Zd (dot)
+ _ --> Zu (underscore)
+ - --> Zh (hyphen)
+ (space) --> Zs (space)
+ @ -> ZA (at)
+ Z --> ZZ (Z)
Everything else is left unchanged.
*/
-#define VG_REPLACE_FUNCTION(soname, fnname) _vgi_##soname##_##fnname
-#define VG_REPLACE_FUNCTION_PREFIX "_vgi_"
-#define VG_REPLACE_FUNCTION_PREFIX_LEN 5
+/* If you change these, the code in VG_(maybe_Z_demangle) needs to be
+ changed accordingly. NOTE: duplicates
+ I_{WRAP,REPLACE}_SONAME_FNNAME_Z{U,Z} in valgrind.h. */
+
+#define VG_REPLACE_FUNCTION_ZU(soname,fnname) _vgrZU_##soname##_##fnname
+#define VG_REPLACE_FUNCTION_ZZ(soname,fnname) _vgrZZ_##soname##_##fnname
+
+#define VG_WRAP_FUNCTION_ZU(soname,fnname) _vgwZU_##soname##_##fnname
+#define VG_WRAP_FUNCTION_ZZ(soname,fnname) _vgwZZ_##soname##_##fnname
#endif // __PUB_TOOL_REDIR_H