summaryrefslogtreecommitdiff
path: root/include/.svn
diff options
context:
space:
mode:
Diffstat (limited to 'include/.svn')
-rw-r--r--include/.svn/dir-prop-base8
-rw-r--r--include/.svn/entries442
-rw-r--r--include/.svn/format1
-rw-r--r--include/.svn/prop-base/Makefile.am.svn-base9
-rw-r--r--include/.svn/prop-base/pub_tool_wordfm.h.svn-base5
-rw-r--r--include/.svn/prop-base/valgrind.h.svn-base9
-rw-r--r--include/.svn/text-base/Makefile.am.svn-base39
-rw-r--r--include/.svn/text-base/pub_tool_aspacemgr.h.svn-base158
-rw-r--r--include/.svn/text-base/pub_tool_basics.h.svn-base214
-rw-r--r--include/.svn/text-base/pub_tool_basics_asm.h.svn-base58
-rw-r--r--include/.svn/text-base/pub_tool_clientstate.h.svn-base70
-rw-r--r--include/.svn/text-base/pub_tool_clreq.h.svn-base40
-rw-r--r--include/.svn/text-base/pub_tool_cpuid.h.svn-base46
-rw-r--r--include/.svn/text-base/pub_tool_debuginfo.h.svn-base236
-rw-r--r--include/.svn/text-base/pub_tool_errormgr.h.svn-base132
-rw-r--r--include/.svn/text-base/pub_tool_execontext.h.svn-base117
-rw-r--r--include/.svn/text-base/pub_tool_hashtable.h.svn-base100
-rw-r--r--include/.svn/text-base/pub_tool_libcassert.h.svn-base64
-rw-r--r--include/.svn/text-base/pub_tool_libcbase.h.svn-base151
-rw-r--r--include/.svn/text-base/pub_tool_libcfile.h.svn-base91
-rw-r--r--include/.svn/text-base/pub_tool_libcprint.h.svn-base111
-rw-r--r--include/.svn/text-base/pub_tool_libcproc.h.svn-base95
-rw-r--r--include/.svn/text-base/pub_tool_libcsignal.h.svn-base47
-rw-r--r--include/.svn/text-base/pub_tool_machine.h.svn-base137
-rw-r--r--include/.svn/text-base/pub_tool_mallocfree.h.svn-base58
-rw-r--r--include/.svn/text-base/pub_tool_options.h.svn-base198
-rw-r--r--include/.svn/text-base/pub_tool_oset.h.svn-base259
-rw-r--r--include/.svn/text-base/pub_tool_redir.h.svn-base205
-rw-r--r--include/.svn/text-base/pub_tool_replacemalloc.h.svn-base74
-rw-r--r--include/.svn/text-base/pub_tool_seqmatch.h.svn-base91
-rw-r--r--include/.svn/text-base/pub_tool_signals.h.svn-base47
-rw-r--r--include/.svn/text-base/pub_tool_sparsewa.h.svn-base99
-rw-r--r--include/.svn/text-base/pub_tool_stacktrace.h.svn-base82
-rw-r--r--include/.svn/text-base/pub_tool_threadstate.h.svn-base53
-rw-r--r--include/.svn/text-base/pub_tool_tooliface.h.svn-base643
-rw-r--r--include/.svn/text-base/pub_tool_vki.h.svn-base62
-rw-r--r--include/.svn/text-base/pub_tool_vkiscnums.h.svn-base88
-rw-r--r--include/.svn/text-base/pub_tool_wordfm.h.svn-base220
-rw-r--r--include/.svn/text-base/pub_tool_xarray.h.svn-base115
-rw-r--r--include/.svn/text-base/valgrind.h.svn-base3937
40 files changed, 8611 insertions, 0 deletions
diff --git a/include/.svn/dir-prop-base b/include/.svn/dir-prop-base
new file mode 100644
index 0000000..c344368
--- /dev/null
+++ b/include/.svn/dir-prop-base
@@ -0,0 +1,8 @@
+K 10
+svn:ignore
+V 38
+Makefile.in
+Makefile
+tool.h
+valgrind.h
+END
diff --git a/include/.svn/entries b/include/.svn/entries
new file mode 100644
index 0000000..7f0f628
--- /dev/null
+++ b/include/.svn/entries
@@ -0,0 +1,442 @@
+8
+
+dir
+9703
+svn://svn.valgrind.org/valgrind/trunk/include
+svn://svn.valgrind.org/valgrind
+
+
+
+2009-04-30T05:23:22.182900Z
+9700
+njn
+has-props
+
+svn:special svn:externals svn:needs-lock
+
+
+
+
+
+
+
+
+
+
+
+a5019735-40e9-0310-863c-91ae7b9d1cf9
+
+pub_tool_vki.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+8c0df23baf33da26840760d758d9045b
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_options.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+86b1b3974b7f58ee7fa3c44c1f903dfa
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_hashtable.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+a3b8d051b833c480c137a4edfad36958
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_aspacemgr.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+4ecf208eea211774d1bbd9864cdf7743
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_machine.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+95e8e0473517c37c55579dad517694c9
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_libcbase.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+1d0bac6294ceefc80b5c9d58d7b27369
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_basics_asm.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+8ff719c2299ba39f01a779d67b54eb58
+2009-04-24T04:57:07.028318Z
+9601
+njn
+
+pub_tool_cpuid.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+b5f4eed0320ee5682727fa6c640e858c
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_tooliface.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+764813639dfc11934392fe4d2e73e993
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_seqmatch.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+4d9283faf4350f2fb2f8541d1863e6cd
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_clreq.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+4ae6e4f917a160ad4485384c464ffe8a
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_threadstate.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+359cc0a78af71ec69d02508cbe897f58
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_clientstate.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+70f7717a93645dae31d8d146d2bd1169
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_vkiscnums.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+0302afd0234e0764f5557decd2548fd1
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_stacktrace.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+3192155a184517799e8b0ca100694c82
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_sparsewa.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+e527dad02f04fc93db02388361a92c0e
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_libcprint.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+22571e17a647bcd48765ddf2f6cfe500
+2009-04-30T04:17:45.496239Z
+9693
+njn
+
+pub_tool_execontext.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+2bdb1c23f24375f69d4cde5cd46edc39
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_libcassert.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+d65d5859175e57e7eff56c383b5e431a
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_libcproc.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+44340a7ee527423a7d7f170b576c23a7
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_wordfm.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+98d950ed66b67627ac30dd56e13a1e0b
+2009-03-10T22:02:09.669944Z
+9344
+njn
+has-props
+
+pub_tool_errormgr.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+010abc7e891425aff3905c7aba8d281e
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+vki
+dir
+
+pub_tool_signals.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+514b83cf57f4319e5a98fe84b66f9c44
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_debuginfo.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+40e2b13a6023dc68be40e0a6305e5b74
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+valgrind.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+f562afeb8973591fa41b46a0667f0009
+2009-04-22T22:42:10.255420Z
+9580
+sewardj
+has-props
+
+pub_tool_replacemalloc.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+b9789db48287d26f144105711141ddc2
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_basics.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+77c531e7628c6db35c29d12af5a83043
+2009-04-24T04:57:07.028318Z
+9601
+njn
+
+pub_tool_redir.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+228612233618db51771d95eba93d9f0e
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_xarray.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+a6c6bb6ba595696ce82c8f9634aac49c
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_libcsignal.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+9290e85a737bf052598334941719d888
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_mallocfree.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+aaf6d5f22425aea9aa9a228a2ae3567f
+2009-03-15T23:25:38.213170Z
+9416
+njn
+
+pub_tool_libcfile.h
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+00fcd9b8d4c5ab5675022d3a09a0501e
+2009-03-10T22:02:09.669944Z
+9344
+njn
+
+pub_tool_oset.h
+file
+
+
+
+
+2009-04-30T16:43:59.000000Z
+abafe3130a5f81588bc7ac5dc9d2c1f5
+2009-04-26T07:15:58.034266Z
+9634
+bart
+
+Makefile.am
+file
+
+
+
+
+2009-03-13T17:30:10.000000Z
+43988b1cd4881956b04dd5567ad6cc30
+2008-12-12T08:07:49.045161Z
+8816
+sewardj
+has-props
+
diff --git a/include/.svn/format b/include/.svn/format
new file mode 100644
index 0000000..45a4fb7
--- /dev/null
+++ b/include/.svn/format
@@ -0,0 +1 @@
+8
diff --git a/include/.svn/prop-base/Makefile.am.svn-base b/include/.svn/prop-base/Makefile.am.svn-base
new file mode 100644
index 0000000..df54a06
--- /dev/null
+++ b/include/.svn/prop-base/Makefile.am.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+author date id revision
+END
diff --git a/include/.svn/prop-base/pub_tool_wordfm.h.svn-base b/include/.svn/prop-base/pub_tool_wordfm.h.svn-base
new file mode 100644
index 0000000..3160658
--- /dev/null
+++ b/include/.svn/prop-base/pub_tool_wordfm.h.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mergeinfo
+V 0
+
+END
diff --git a/include/.svn/prop-base/valgrind.h.svn-base b/include/.svn/prop-base/valgrind.h.svn-base
new file mode 100644
index 0000000..df54a06
--- /dev/null
+++ b/include/.svn/prop-base/valgrind.h.svn-base
@@ -0,0 +1,9 @@
+K 13
+svn:eol-style
+V 6
+native
+K 12
+svn:keywords
+V 23
+author date id revision
+END
diff --git a/include/.svn/text-base/Makefile.am.svn-base b/include/.svn/text-base/Makefile.am.svn-base
new file mode 100644
index 0000000..e73f5cd
--- /dev/null
+++ b/include/.svn/text-base/Makefile.am.svn-base
@@ -0,0 +1,39 @@
+
+SUBDIRS = vki
+
+incincdir = $(includedir)/valgrind
+
+incinc_HEADERS = \
+ pub_tool_basics.h \
+ pub_tool_basics_asm.h \
+ pub_tool_aspacemgr.h \
+ pub_tool_clientstate.h \
+ pub_tool_clreq.h \
+ pub_tool_cpuid.h \
+ pub_tool_debuginfo.h \
+ pub_tool_errormgr.h \
+ pub_tool_execontext.h \
+ pub_tool_hashtable.h \
+ pub_tool_libcbase.h \
+ pub_tool_libcassert.h \
+ pub_tool_libcfile.h \
+ pub_tool_libcprint.h \
+ pub_tool_libcproc.h \
+ pub_tool_libcsignal.h \
+ pub_tool_machine.h \
+ pub_tool_mallocfree.h \
+ pub_tool_options.h \
+ pub_tool_oset.h \
+ pub_tool_redir.h \
+ pub_tool_replacemalloc.h \
+ pub_tool_seqmatch.h \
+ pub_tool_signals.h \
+ pub_tool_sparsewa.h \
+ pub_tool_stacktrace.h \
+ pub_tool_threadstate.h \
+ pub_tool_tooliface.h \
+ pub_tool_vki.h \
+ pub_tool_vkiscnums.h \
+ pub_tool_wordfm.h \
+ pub_tool_xarray.h \
+ valgrind.h
diff --git a/include/.svn/text-base/pub_tool_aspacemgr.h.svn-base b/include/.svn/text-base/pub_tool_aspacemgr.h.svn-base
new file mode 100644
index 0000000..f84dfa6
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_aspacemgr.h.svn-base
@@ -0,0 +1,158 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Address space manager. pub_tool_aspacemgr.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_ASPACEMGR_H
+#define __PUB_TOOL_ASPACEMGR_H
+
+
+//--------------------------------------------------------------
+// Definition of address-space segments
+
+/* Describes segment kinds. */
+typedef
+ enum {
+ SkFree, // unmapped space
+ SkAnonC, // anonymous mapping belonging to the client
+ SkAnonV, // anonymous mapping belonging to valgrind
+ SkFileC, // file mapping belonging to the client
+ SkFileV, // file mapping belonging to valgrind
+ SkShmC, // shared memory segment belonging to the client
+ SkResvn // reservation
+ }
+ SegKind;
+
+/* Describes how a reservation segment can be resized. */
+typedef
+ enum {
+ SmLower, // lower end can move up
+ SmFixed, // cannot be shrunk
+ SmUpper // upper end can move down
+ }
+ ShrinkMode;
+
+/* Describes a segment. Invariants:
+
+ kind == SkFree:
+ // the only meaningful fields are .start and .end
+
+ kind == SkAnon{C,V}:
+ // smode==SmFixed
+ // there's no associated file:
+ dev==ino==foff = 0, fnidx == -1
+ // segment may have permissions
+
+ kind == SkFile{C,V}:
+ // smode==SmFixed
+ moveLo == moveHi == NotMovable, maxlen == 0
+ // there is an associated file
+ // segment may have permissions
+
+ kind == SkShmC:
+ // smode==SmFixed
+ // there's no associated file:
+ dev==ino==foff = 0, fnidx == -1
+ // segment may have permissions
+
+ kind == SkResvn
+ // the segment may be resized if required
+ // there's no associated file:
+ dev==ino==foff = 0, fnidx == -1
+ // segment has no permissions
+ hasR==hasW==hasX==anyTranslated == False
+
+ Also: anyTranslated==True is only allowed in SkFileV and SkAnonV
+ (viz, not allowed to make translations from non-client areas)
+*/
+typedef
+ struct {
+ SegKind kind;
+ /* Extent (SkFree, SkAnon{C,V}, SkFile{C,V}, SkResvn) */
+ Addr start; // lowest address in range
+ Addr end; // highest address in range
+ /* Shrinkable? (SkResvn only) */
+ ShrinkMode smode;
+ /* Associated file (SkFile{C,V} only) */
+ ULong dev;
+ ULong ino;
+ Off64T offset;
+ UInt mode;
+ Int fnIdx; // file name table index, if name is known
+ /* Permissions (SkAnon{C,V}, SkFile{C,V} only) */
+ Bool hasR;
+ Bool hasW;
+ Bool hasX;
+ Bool hasT; // True --> translations have (or MAY have)
+ // been taken from this segment
+ Bool isCH; // True --> is client heap (SkAnonC ONLY)
+ /* Admin */
+ Bool mark;
+ }
+ NSegment;
+
+
+/* Collect up the start addresses of all non-free, non-resvn segments.
+ The interface is a bit strange in order to avoid potential
+ segment-creation races caused by dynamic allocation of the result
+ buffer *starts.
+
+ The function first computes how many entries in the result
+ buffer *starts will be needed. If this number <= nStarts,
+ they are placed in starts[0..], and the number is returned.
+ If nStarts is not large enough, nothing is written to
+ starts[0..], and the negation of the size is returned.
+
+ Correct use of this function may mean calling it multiple times in
+ order to establish a suitably-sized buffer. */
+extern Int VG_(am_get_segment_starts)( Addr* starts, Int nStarts );
+
+
+// See pub_core_aspacemgr.h for description.
+extern NSegment const * VG_(am_find_nsegment) ( Addr a );
+
+// See pub_core_aspacemgr.h for description.
+extern HChar* VG_(am_get_filename)( NSegment const * );
+
+// See pub_core_aspacemgr.h for description.
+extern Bool VG_(am_is_valid_for_client) ( Addr start, SizeT len,
+ UInt prot );
+
+// See pub_core_aspacemgr.h for description.
+/* Really just a wrapper around VG_(am_mmap_anon_float_valgrind). */
+extern void* VG_(am_shadow_alloc)(SizeT size);
+
+/* Unmap the given address range and update the segment array
+ accordingly. This fails if the range isn't valid for valgrind. */
+extern SysRes VG_(am_munmap_valgrind)( Addr start, SizeT length );
+
+#endif // __PUB_TOOL_ASPACEMGR_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_basics.h.svn-base b/include/.svn/text-base/pub_tool_basics.h.svn-base
new file mode 100644
index 0000000..9bff837
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_basics.h.svn-base
@@ -0,0 +1,214 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Header included by every tool C file. pub_tool_basics.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_BASICS_H
+#define __PUB_TOOL_BASICS_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This header should be imported by every single C file in
+// tools. It contains the basic types and other things needed everywhere.
+// There is no corresponding C file because this isn't a module
+// containing executable code, it's all just declarations.
+//--------------------------------------------------------------------
+
+/* ---------------------------------------------------------------------
+ Other headers to include
+ ------------------------------------------------------------------ */
+
+// VEX defines Char, UChar, Short, UShort, Int, UInt, Long, ULong,
+// Addr32, Addr64, HWord, HChar, Bool, False and True.
+#include "libvex_basictypes.h"
+
+// For varargs types
+#include <stdarg.h>
+
+/* For HAVE_BUILTIN_EXPECT */
+#include "config.h"
+
+
+/* ---------------------------------------------------------------------
+ symbol prefixing
+ ------------------------------------------------------------------ */
+
+// All symbols externally visible from Valgrind are prefixed
+// as specified here to avoid namespace conflict problems.
+//
+// VG_ is for symbols exported from modules. ML_ (module-local) is
+// for symbols which are not intended to be visible outside modules,
+// but which cannot be declared as C 'static's since they need to be
+// visible across C files within a given module. It is a mistake for
+// a ML_ name to appear in a pub_core_*.h or pub_tool_*.h file.
+// Likewise it is a mistake for a VG_ name to appear in a priv_*.h
+// file.
+
+#define VGAPPEND(str1,str2) str1##str2
+
+#define VG_(str) VGAPPEND(vgPlain_, str)
+#define ML_(str) VGAPPEND(vgModuleLocal_, str)
+
+
+/* ---------------------------------------------------------------------
+ builtin types
+ ------------------------------------------------------------------ */
+
+// By choosing the right types, we can get these right for 32-bit and 64-bit
+// platforms without having to do any conditional compilation or anything.
+// POSIX references:
+// - http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
+// - http://www.opengroup.org/onlinepubs/009695399/basedefs/stddef.h.html
+//
+// Size in bits on: 32-bit archs 64-bit archs
+// ------------ ------------
+typedef unsigned long UWord; // 32 64
+typedef signed long Word; // 32 64
+
+// Addr is for holding an address. AddrH was intended to be "Addr on the
+// host", for the notional case where host word size != guest word size.
+// But since the assumption that host arch == guest arch has become so
+// deeply wired in, it's a pretty pointless distinction now.
+typedef UWord Addr; // 32 64
+typedef UWord AddrH; // 32 64
+
+// Our equivalents of POSIX 'size_t' and 'ssize_t':
+// - size_t is an "unsigned integer type of the result of the sizeof operator".
+// - ssize_t is "used for a count of bytes or an error indication".
+typedef UWord SizeT; // 32 64
+typedef Word SSizeT; // 32 64
+
+// Our equivalent of POSIX 'ptrdiff_t':
+// - ptrdiff_t is a "signed integer type of the result of subtracting two
+// pointers".
+// We use it for memory offsets, eg. the offset into a memory block.
+typedef Word PtrdiffT; // 32 64
+
+// Our equivalent of POSIX 'off_t':
+// - off_t is "used for file sizes".
+// At one point we were using it for memory offsets, but PtrdiffT should be
+// used in those cases.
+typedef Word OffT; // 32 64
+typedef Long Off64T; // 64 64
+
+#if !defined(NULL)
+# define NULL ((void*)0)
+#endif
+
+/* This is just too useful to not have around the place somewhere. */
+typedef struct { UWord uw1; UWord uw2; } UWordPair;
+
+
+/* ---------------------------------------------------------------------
+ non-builtin types
+ ------------------------------------------------------------------ */
+
+// These probably shouldn't be here, but moving them to their logical
+// modules results in a lot more #includes...
+
+/* ThreadIds are simply indices into the VG_(threads)[] array. */
+typedef UInt ThreadId;
+
+/* An abstraction of syscall return values.
+ Linux:
+ When .isError == False,
+ res holds the return value, and err is zero.
+ When .isError == True,
+ err holds the error code, and res is zero.
+
+ AIX:
+ res is the POSIX result of the syscall.
+ err is the corresponding errno value.
+ isError === err==0
+
+ Unlike on Linux, it is possible for 'err' to be nonzero (thus an
+ error has occurred), nevertheless 'res' is also nonzero. AIX
+ userspace does not appear to consistently inspect 'err' to
+ determine whether or not an error has occurred. For example,
+ sys_open() will return -1 for 'val' if a file cannot be opened,
+ as well as the relevant errno value in 'err', but AIX userspace
+ then consults 'val' to figure out if the syscall failed, rather
+ than looking at 'err'. Hence we need to represent them both.
+*/
+typedef
+ struct {
+ UWord res;
+ UWord err;
+ Bool isError;
+ }
+ SysRes;
+
+
+/* ---------------------------------------------------------------------
+ Miscellaneous (word size, endianness, regparmness, stringification)
+ ------------------------------------------------------------------ */
+
+/* Word size: this is going to be either 4 or 8. */
+// It should probably be in m_machine.
+#define VG_WORDSIZE VEX_HOST_WORDSIZE
+
+/* Endianness */
+#undef VG_BIGENDIAN
+#undef VG_LITTLEENDIAN
+
+#if defined(VGA_x86) || defined(VGA_amd64)
+# define VG_LITTLEENDIAN 1
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
+# define VG_BIGENDIAN 1
+#endif
+
+/* Regparmness */
+#if defined(VGA_x86)
+# define VG_REGPARM(n) __attribute__((regparm(n)))
+#elif defined(VGA_amd64) || defined(VGA_ppc32) || defined(VGA_ppc64)
+# define VG_REGPARM(n) /* */
+#else
+# error Unknown arch
+#endif
+
+/* Macro games */
+#define VG_STRINGIFZ(__str) #__str
+#define VG_STRINGIFY(__str) VG_STRINGIFZ(__str)
+
+// Where to send bug reports to.
+#define VG_BUGS_TO "www.valgrind.org"
+
+/* Branch prediction hints. */
+#if HAVE_BUILTIN_EXPECT
+# define LIKELY(x) __builtin_expect(!!(x), 1)
+# define UNLIKELY(x) __builtin_expect((x), 0)
+#else
+# define LIKELY(x) (x)
+# define UNLIKELY(x) (x)
+#endif
+
+
+#endif /* __PUB_TOOL_BASICS_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_basics_asm.h.svn-base b/include/.svn/text-base/pub_tool_basics_asm.h.svn-base
new file mode 100644
index 0000000..201c1b5
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_basics_asm.h.svn-base
@@ -0,0 +1,58 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Header imported directly by every tool asm file. ---*/
+/*--- pub_tool_basics_asm.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_BASICS_ASM_H
+#define __PUB_TOOL_BASICS_ASM_H
+
+// See pub_tool_basics.h for the purpose of these macros.
+//
+// Note that although the macros here (which are used in asm files) have the
+// same name as those in pub_tool_basics.h (which are used in C files), they
+// have different definitions. Actually, on Linux the definitions are the
+// same, but on Darwin they are different. The reason is that C names on
+// Darwin always get a '_' prepended to them by the compiler. But in order to
+// refer to them from asm code, we have to add the '_' ourselves. Having two
+// versions of these macros makes that difference transparent, so we can use
+// VG_/ML_ in both asm and C files.
+//
+// Note also that the exact prefixes used have to match those used in
+// pub_tool_basics.h.
+
+#define VGAPPEND(str1,str2) str1##str2
+
+#define VG_(str) VGAPPEND(vgPlain_, str)
+#define ML_(str) VGAPPEND(vgModuleLocal_, str)
+
+#endif /* __PUB_TOOL_BASICS_ASM_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_clientstate.h.svn-base b/include/.svn/text-base/pub_tool_clientstate.h.svn-base
new file mode 100644
index 0000000..9a47fcc
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_clientstate.h.svn-base
@@ -0,0 +1,70 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Misc client state info pub_tool_clientstate.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_CLIENTSTATE_H
+#define __PUB_TOOL_CLIENTSTATE_H
+
+/* Note, this header requires pub_{core,tool}_xarray.h to be
+ included ahead of it. */
+
+// Command line pieces, after they have been extracted from argv in
+// m_main.main(). These are all NULL-terminated vectors.
+
+/* Args for the client. */
+extern XArray* /* of HChar* */ VG_(args_for_client);
+
+/* Args for V. This is the concatenation of the following:
+ - contents of ~/.valgrindrc
+ - contents of $VALGRIND_OPTS
+ - contents of ./.valgrindrc
+ - args from the command line
+ in the stated order.
+
+ Only the last of these is passed onwards to child Valgrinds at
+ client sys_execve, since the children will re-acquire the first 3
+ categories for themselves. Therefore we also record the number of
+ these no-pass-at-execve arguments -- that is what
+ VG_(args_for_valgrind_noexecpass) is. */
+extern XArray* /* of HChar* */ VG_(args_for_valgrind);
+
+/* Number of leading args in VG_(args_for_valgrind) not to pass on at
+ exec time. */
+extern Int VG_(args_for_valgrind_noexecpass);
+
+/* The name of the client executable, as specified on the command
+ line. */
+extern HChar* VG_(args_the_exename);
+
+
+#endif // __PUB_TOOL_CLIENTSTATE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_clreq.h.svn-base b/include/.svn/text-base/pub_tool_clreq.h.svn-base
new file mode 100644
index 0000000..f200d12
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_clreq.h.svn-base
@@ -0,0 +1,40 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Client requests. pub_tool_clreq.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_CLREQ_H
+#define __PUB_TOOL_CLREQ_H
+
+#include "valgrind.h"
+
+#endif // __PUB_TOOL_CLREQ_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_cpuid.h.svn-base b/include/.svn/text-base/pub_tool_cpuid.h.svn-base
new file mode 100644
index 0000000..9e994c5
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_cpuid.h.svn-base
@@ -0,0 +1,46 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Interface to CPUID. pub_tool_cpuid.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_CPUID_H
+#define __PUB_TOOL_CPUID_H
+
+#if defined(VGA_x86) || defined(VGA_amd64)
+extern Bool VG_(has_cpuid) ( void );
+
+extern void VG_(cpuid) ( UInt eax,
+ UInt* eax_ret, UInt* ebx_ret,
+ UInt* ecx_ret, UInt* edx_ret );
+#endif
+
+#endif // __PUB_TOOL_CPUID_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_debuginfo.h.svn-base b/include/.svn/text-base/pub_tool_debuginfo.h.svn-base
new file mode 100644
index 0000000..e5ad9f7
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_debuginfo.h.svn-base
@@ -0,0 +1,236 @@
+
+/*--------------------------------------------------------------------*/
+/*--- DebugInfo. pub_tool_debuginfo.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_DEBUGINFO_H
+#define __PUB_TOOL_DEBUGINFO_H
+
+/*====================================================================*/
+/*=== Obtaining debug information ===*/
+/*====================================================================*/
+
+/* Get the file/function/line number of the instruction at address
+ 'a'. For these four, if debug info for the address is found, it
+ copies the info into the buffer/UInt and returns True. If not, it
+ returns False and nothing is copied. VG_(get_fnname) always
+ demangles C++ function names. VG_(get_fnname_w_offset) is the
+ same, except it appends "+N" to symbol names to indicate offsets. */
+extern Bool VG_(get_filename) ( Addr a, Char* filename, Int n_filename );
+extern Bool VG_(get_fnname) ( Addr a, Char* fnname, Int n_fnname );
+extern Bool VG_(get_linenum) ( Addr a, UInt* linenum );
+extern Bool VG_(get_fnname_w_offset)
+ ( Addr a, Char* fnname, Int n_fnname );
+
+/* This one is the most general. It gives filename, line number and
+ optionally directory name. filename and linenum may not be NULL.
+ dirname may be NULL, meaning that the caller does not want
+ directory name info, in which case dirname_available must also be
+ NULL. If dirname is non-null, directory info is written to it, if
+ it is available; if not available, '\0' is written to the first
+ byte. In either case *dirname_available is set to indicate whether
+ or not directory information was available.
+
+ Returned value indicates whether any filename/line info could be
+ found. */
+extern Bool VG_(get_filename_linenum)
+ ( Addr a,
+ /*OUT*/Char* filename, Int n_filename,
+ /*OUT*/Char* dirname, Int n_dirname,
+ /*OUT*/Bool* dirname_available,
+ /*OUT*/UInt* linenum );
+
+/* Succeeds only if we find from debug info that 'a' is the address of the
+ first instruction in a function -- as opposed to VG_(get_fnname) which
+ succeeds if we find from debug info that 'a' is the address of any
+ instruction in a function. Use this to instrument the start of
+ a particular function. Nb: if an executable/shared object is stripped
+ of its symbols, this function will not be able to recognise function
+ entry points within it. */
+extern Bool VG_(get_fnname_if_entry) ( Addr a, Char* fnname, Int n_fnname );
+
+typedef
+ enum {
+ Vg_FnNameNormal, // A normal function.
+ Vg_FnNameMain, // "main"
+ Vg_FnNameBelowMain // Something below "main", eg. __libc_start_main.
+ } Vg_FnNameKind; // Such names are often filtered.
+
+/* Indicates what kind of fnname it is. */
+extern Vg_FnNameKind VG_(get_fnname_kind) ( Char* name );
+
+/* Like VG_(get_fnname_kind), but takes a code address. */
+extern Vg_FnNameKind VG_(get_fnname_kind_from_IP) ( Addr ip );
+
+/* Looks up data_addr in the collection of data symbols, and if found
+ puts its name (or as much as will fit) into dname[0 .. n_dname-1],
+ which is guaranteed to be zero terminated. Also data_addr's offset
+ from the symbol start is put into *offset. */
+extern Bool VG_(get_datasym_and_offset)( Addr data_addr,
+ /*OUT*/Char* dname, Int n_dname,
+ /*OUT*/PtrdiffT* offset );
+
+/* Try to form some description of data_addr by looking at the DWARF3
+ debug info we have. This considers all global variables, and all
+ frames in the stacks of all threads. Result (or as much as will
+ fit) is put into into dname{1,2}[0 .. n_dname-1] and is guaranteed
+ to be zero terminated. */
+extern Bool VG_(get_data_description)( /*OUT*/Char* dname1,
+ /*OUT*/Char* dname2,
+ Int n_dname,
+ Addr data_addr );
+
+/* Succeeds if the address is within a shared object or the main executable.
+ It doesn't matter if debug info is present or not. */
+extern Bool VG_(get_objname) ( Addr a, Char* objname, Int n_objname );
+
+/* Puts into 'buf' info about the code address %eip: the address, function
+ name (if known) and filename/line number (if known), like this:
+
+ 0x4001BF05: realloc (vg_replace_malloc.c:339)
+
+ 'n_buf' gives length of 'buf'. Returns 'buf'.
+*/
+extern Char* VG_(describe_IP)(Addr eip, Char* buf, Int n_buf);
+
+
+/* Get an XArray of StackBlock which describe the stack (auto) blocks
+ for this ip. The caller is expected to free the XArray at some
+ point. If 'arrays_only' is True, only array-typed blocks are
+ returned; otherwise blocks of all types are returned. */
+
+typedef
+ struct {
+ PtrdiffT base; /* offset from sp or fp */
+ SizeT szB; /* size in bytes */
+ Bool spRel; /* True => sp-rel, False => fp-rel */
+ Bool isVec; /* does block have an array type, or not? */
+ HChar name[16]; /* first 15 chars of name (asciiz) */
+ }
+ StackBlock;
+
+extern void* /* really, XArray* of StackBlock */
+ VG_(di_get_stack_blocks_at_ip)( Addr ip, Bool arrays_only );
+
+
+/* Get an array of GlobalBlock which describe the global blocks owned
+ by the shared object characterised by the given di_handle. Asserts
+ if the handle is invalid. The caller is responsible for freeing
+ the array at some point. If 'arrays_only' is True, only
+ array-typed blocks are returned; otherwise blocks of all types are
+ returned. */
+
+typedef
+ struct {
+ Addr addr;
+ SizeT szB;
+ Bool isVec; /* does block have an array type, or not? */
+ HChar name[16]; /* first 15 chars of name (asciiz) */
+ HChar soname[16]; /* first 15 chars of name (asciiz) */
+ }
+ GlobalBlock;
+
+extern void* /* really, XArray* of GlobalBlock */
+VG_(di_get_global_blocks_from_dihandle) ( ULong di_handle,
+ Bool arrays_only );
+
+
+/*====================================================================*/
+/*=== Obtaining segment information ===*/
+/*====================================================================*/
+
+/* A way to get information about what segments are mapped */
+typedef struct _DebugInfo DebugInfo;
+
+/* Returns NULL if the DebugInfo isn't found. It doesn't matter if
+ debug info is present or not. */
+extern DebugInfo* VG_(find_seginfo) ( Addr a );
+
+/* Fish bits out of DebugInfos. */
+extern Addr VG_(seginfo_get_text_avma)( const DebugInfo *di );
+extern SizeT VG_(seginfo_get_text_size)( const DebugInfo *di );
+extern Addr VG_(seginfo_get_plt_avma) ( const DebugInfo *di );
+extern SizeT VG_(seginfo_get_plt_size) ( const DebugInfo *di );
+extern Addr VG_(seginfo_get_gotplt_avma)( const DebugInfo *di );
+extern SizeT VG_(seginfo_get_gotplt_size)( const DebugInfo *di );
+extern const UChar* VG_(seginfo_soname) ( const DebugInfo *di );
+extern const UChar* VG_(seginfo_filename) ( const DebugInfo *di );
+extern PtrdiffT VG_(seginfo_get_text_bias)( const DebugInfo *di );
+
+/* Function for traversing the seginfo list. When called with NULL it
+ returns the first element; otherwise it returns the given element's
+ successor. */
+extern const DebugInfo* VG_(next_seginfo) ( const DebugInfo *di );
+
+/* Functions for traversing all the symbols in a DebugInfo. _howmany
+ tells how many there are. _getidx retrieves the n'th, for n in 0
+ .. _howmany-1. You may not modify the function name thereby
+ acquired; if you want to do so, first strdup it. */
+extern Int VG_(seginfo_syms_howmany) ( const DebugInfo *di );
+extern void VG_(seginfo_syms_getidx) ( const DebugInfo *di,
+ Int idx,
+ /*OUT*/Addr* avma,
+ /*OUT*/Addr* tocptr,
+ /*OUT*/UInt* size,
+ /*OUT*/HChar** name,
+ /*OUT*/Bool* isText );
+
+/* A simple enumeration to describe the 'kind' of various kinds of
+ segments that arise from the mapping of object files. */
+typedef
+ enum {
+ Vg_SectUnknown,
+ Vg_SectText,
+ Vg_SectData,
+ Vg_SectBSS,
+ Vg_SectGOT,
+ Vg_SectPLT,
+ Vg_SectGOTPLT,
+ Vg_SectOPD
+ }
+ VgSectKind;
+
+/* Convert a VgSectKind to a string, which must be copied if you want
+ to change it. */
+extern
+const HChar* VG_(pp_SectKind)( VgSectKind kind );
+
+/* Given an address 'a', make a guess of which section of which object
+ it comes from. If name is non-NULL, then the last n_name-1
+ characters of the object's name is put in name[0 .. n_name-2], and
+ name[n_name-1] is set to zero (guaranteed zero terminated). */
+extern
+VgSectKind VG_(seginfo_sect_kind)( /*OUT*/UChar* name, SizeT n_name,
+ Addr a);
+
+
+#endif // __PUB_TOOL_DEBUGINFO_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_errormgr.h.svn-base b/include/.svn/text-base/pub_tool_errormgr.h.svn-base
new file mode 100644
index 0000000..0d22c1b
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_errormgr.h.svn-base
@@ -0,0 +1,132 @@
+/*--------------------------------------------------------------------*/
+/*--- ErrorMgr: management of errors and suppressions. ---*/
+/*--- pub_tool_errormgr.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_ERRORMGR_H
+#define __PUB_TOOL_ERRORMGR_H
+
+#include "pub_tool_execontext.h"
+
+/* ------------------------------------------------------------------ */
+/* Error records contain enough info to generate an error report. The idea
+ is that (typically) the same few points in the program generate thousands
+ of errors, and we don't want to spew out a fresh error message for each
+ one. Instead, we use these structures to common up duplicates.
+*/
+
+typedef
+ Int /* Do not make this unsigned! */
+ ErrorKind;
+
+/* The tool-relevant parts of an Error are:
+ kind: what kind of error; must be in the range (0..)
+ addr: use is optional. 0 by default.
+ string: use is optional. NULL by default.
+ extra: use is optional. NULL by default. void* so it's extensible.
+*/
+typedef
+ struct _Error
+ Error;
+
+/* Useful in VG_(tdict).tool_error_matches_suppression(),
+ * VG_(tdict).tool_pp_Error(), etc */
+ExeContext* VG_(get_error_where) ( Error* err );
+ErrorKind VG_(get_error_kind) ( Error* err );
+Addr VG_(get_error_address) ( Error* err );
+Char* VG_(get_error_string) ( Error* err );
+void* VG_(get_error_extra) ( Error* err );
+
+/* Call this when an error occurs. It will be recorded if it hasn't been
+ seen before. If it has, the existing error record will have its count
+ incremented.
+
+ 'tid' can be found as for VG_(record_ExeContext)(). The `extra' field can
+ be stack-allocated; it will be copied by the core if needed (but it
+ won't be copied if it's NULL).
+
+ If no 'a', 's' or 'extra' of interest needs to be recorded, just use
+ NULL for them. */
+extern void VG_(maybe_record_error) ( ThreadId tid, ErrorKind ekind,
+ Addr a, Char* s, void* extra );
+
+/* Similar to VG_(maybe_record_error)(), except this one doesn't record the
+ error -- useful for errors that can only happen once. The errors can be
+ suppressed, though. Return value is True if it was suppressed.
+ 'print_error' dictates whether to print the error, which is a bit of a
+ hack that's useful sometimes if you just want to know if the error would
+ be suppressed without possibly printing it. 'count_error' dictates
+ whether to add the error in the error total count (another mild hack). */
+extern Bool VG_(unique_error) ( ThreadId tid, ErrorKind ekind,
+ Addr a, Char* s, void* extra,
+ ExeContext* where, Bool print_error,
+ Bool allow_GDB_attach, Bool count_error );
+
+/* Gets a non-blank, non-comment line of at most nBuf chars from fd.
+ Skips leading spaces on the line. Returns True if EOF was hit instead.
+ Useful for reading in extra tool-specific suppression lines. */
+extern Bool VG_(get_line) ( Int fd, Char* buf, Int nBuf );
+
+
+/* ------------------------------------------------------------------ */
+/* Suppressions describe errors which we want to suppress, ie, not
+ show the user, usually because it is caused by a problem in a library
+ which we can't fix, replace or work around. Suppressions are read from
+ a file at startup time. This gives flexibility so that new
+ suppressions can be added to the file as and when needed.
+*/
+typedef
+ Int /* Do not make this unsigned! */
+ SuppKind;
+
+/* The tool-relevant parts of a suppression are:
+ kind: what kind of suppression; must be in the range (0..)
+ string: use is optional. NULL by default.
+ extra: use is optional. NULL by default. void* so it's extensible.
+*/
+typedef
+ struct _Supp
+ Supp;
+
+/* Useful in VG_(tdict).tool_error_matches_suppression() */
+SuppKind VG_(get_supp_kind) ( Supp* su );
+Char* VG_(get_supp_string) ( Supp* su );
+void* VG_(get_supp_extra) ( Supp* su );
+
+/* Must be used in VG_(recognised_suppression)() */
+void VG_(set_supp_kind) ( Supp* su, SuppKind suppkind );
+/* May be used in VG_(read_extra_suppression_info)() */
+void VG_(set_supp_string) ( Supp* su, Char* string );
+void VG_(set_supp_extra) ( Supp* su, void* extra );
+
+
+#endif // __PUB_TOOL_ERRORMGR_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_execontext.h.svn-base b/include/.svn/text-base/pub_tool_execontext.h.svn-base
new file mode 100644
index 0000000..3506026
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_execontext.h.svn-base
@@ -0,0 +1,117 @@
+/*--------------------------------------------------------------------*/
+/*--- ExeContexts: long-lived stack traces. pub_tool_execontext.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_EXECONTEXT_H
+#define __PUB_TOOL_EXECONTEXT_H
+
+// It's an abstract type.
+typedef
+ struct _ExeContext
+ ExeContext;
+
+// Resolution type used to decide how closely to compare two errors for
+// equality.
+typedef
+ enum { Vg_LowRes, Vg_MedRes, Vg_HighRes }
+ VgRes;
+
+// Take a snapshot of the client's stack. Search our collection of
+// ExeContexts to see if we already have it, and if not, allocate a
+// new one. Either way, return a pointer to the context. Context size
+// controlled by --num-callers option.
+//
+// This should only be used for long-lived stack traces. If you want a
+// short-lived stack trace, use VG_(get_StackTrace)().
+//
+// If called from generated code, use VG_(get_running_tid)() to get the
+// current ThreadId. If called from non-generated code, the current
+// ThreadId should be passed in by the core. The initial IP value to
+// use is adjusted by first_ip_delta before the stack is unwound.
+// A safe value to pass is zero.
+//
+// See comments in pub_tool_stacktrace.h for precise definition of
+// the meaning of the code addresses in the returned ExeContext.
+extern
+ExeContext* VG_(record_ExeContext) ( ThreadId tid, Word first_ip_delta );
+
+// Trivial version of VG_(record_ExeContext), which just records the
+// thread's current program counter but does not do any stack
+// unwinding. This is useful in some rare cases when we suspect the
+// stack might be outside mapped storage, and so unwinding
+// might cause a segfault. In this case we can at least safely
+// produce a one-element stack trace, which is better than nothing.
+extern
+ExeContext* VG_(record_depth_1_ExeContext)( ThreadId tid );
+
+// Apply a function to every element in the ExeContext. The parameter 'n'
+// gives the index of the passed ip. Doesn't go below main() unless
+// --show-below-main=yes is set.
+extern void VG_(apply_ExeContext)( void(*action)(UInt n, Addr ip),
+ ExeContext* ec, UInt n_ips );
+
+// Compare two ExeContexts. Number of callers considered depends on `res':
+// Vg_LowRes: 2
+// Vg_MedRes: 4
+// Vg_HighRes: all
+extern Bool VG_(eq_ExeContext) ( VgRes res, ExeContext* e1, ExeContext* e2 );
+
+// Print an ExeContext.
+extern void VG_(pp_ExeContext) ( ExeContext* ec );
+
+// Get the 32-bit unique reference number for this ExeContext
+// (the "ExeContext Unique"). Guaranteed to be nonzero and to be a
+// multiple of four (iow, the lowest two bits are guaranteed to
+// be zero, so that callers can store other information there.
+extern UInt VG_(get_ECU_from_ExeContext)( ExeContext* e );
+
+// How many entries (frames) in this ExeContext?
+extern Int VG_(get_ExeContext_n_ips)( ExeContext* e );
+
+// Find the ExeContext that has the given ECU, if any.
+// NOTE: very slow. Do not call often.
+extern ExeContext* VG_(get_ExeContext_from_ECU)( UInt uniq );
+
+// Make an ExeContext containing just 'a', and nothing else
+ExeContext* VG_(make_depth_1_ExeContext_from_Addr)( Addr a );
+
+// Is this a plausible-looking ECU ? Catches some obvious stupid
+// cases, but does not guarantee that the ECU is really valid, that
+// is, has an associated ExeContext.
+static inline Bool VG_(is_plausible_ECU)( UInt ecu ) {
+ return (ecu > 0) && ((ecu & 3) == 0);
+}
+
+// Make an ExeContext containing exactly the specified stack frames.
+ExeContext* VG_(make_ExeContext_from_StackTrace)( Addr* ips, UInt n_ips );
+
+#endif // __PUB_TOOL_EXECONTEXT_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_hashtable.h.svn-base b/include/.svn/text-base/pub_tool_hashtable.h.svn-base
new file mode 100644
index 0000000..6348799
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_hashtable.h.svn-base
@@ -0,0 +1,100 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A hash table implementation. pub_tool_hashtable.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2005-2009 Nicholas Nethercote
+ njn@valgrind.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_HASHTABLE_H
+#define __PUB_TOOL_HASHTABLE_H
+
+/* Generic type for a separately-chained hash table. Via a kind of dodgy
+ C-as-C++ style inheritance, tools can extend the VgHashNode type, so long
+ as the first two fields match the sizes of these two fields. Requires
+ a bit of casting by the tool. */
+
+// Problems with this data structure:
+// - Separate chaining gives bad cache behaviour. Hash tables with linear
+// probing give better cache behaviour.
+
+typedef
+ struct _VgHashNode {
+ struct _VgHashNode * next;
+ UWord key;
+ }
+ VgHashNode;
+
+typedef struct _VgHashTable * VgHashTable;
+
+/* Make a new table. Allocates the memory with VG_(calloc)(), so can
+ be freed with VG_(free)(). The table starts small but will
+ periodically be expanded. This is transparent to the users of this
+ module. */
+extern VgHashTable VG_(HT_construct) ( HChar* name );
+
+/* Count the number of nodes in a table. */
+extern Int VG_(HT_count_nodes) ( VgHashTable table );
+
+/* Add a node to the table. */
+extern void VG_(HT_add_node) ( VgHashTable t, void* node );
+
+/* Looks up a VgHashNode in the table. Returns NULL if not found. */
+extern void* VG_(HT_lookup) ( VgHashTable table, UWord key );
+
+/* Removes a VgHashNode from the table. Returns NULL if not found. */
+extern void* VG_(HT_remove) ( VgHashTable table, UWord key );
+
+/* Allocates a suitably-sized array, copies all the hashtable elements
+ into it, then returns both the array and the size of it. This is
+ used by the memory-leak detector. The array must be freed with
+ VG_(free). */
+extern VgHashNode** VG_(HT_to_array) ( VgHashTable t, /*OUT*/ UInt* n_elems );
+
+/* Reset the table's iterator to point to the first element. */
+extern void VG_(HT_ResetIter) ( VgHashTable table );
+
+/* Return the element pointed to by the iterator and move on to the
+ next one. Returns NULL if the last one has been passed, or if
+ HT_ResetIter() has not been called previously. Asserts if the
+ table has been modified (HT_add_node, HT_remove) since
+ HT_ResetIter. This guarantees that callers cannot screw up by
+ modifying the table whilst iterating over it (and is necessary to
+ make the implementation safe; specifically we must guarantee that
+ the table will not get resized whilst iteration is happening.
+ Since resizing only happens as a result of calling HT_add_node,
+ disallowing HT_add_node during iteration should give the required
+ assurance. */
+extern void* VG_(HT_Next) ( VgHashTable table );
+
+/* Destroy a table. */
+extern void VG_(HT_destruct) ( VgHashTable t );
+
+
+#endif // __PUB_TOOL_HASHTABLE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcassert.h.svn-base b/include/.svn/text-base/pub_tool_libcassert.h.svn-base
new file mode 100644
index 0000000..6e4f69a
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcassert.h.svn-base
@@ -0,0 +1,64 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Assertions, etc. pub_tool_libcassert.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCBASSERT_H
+#define __PUB_TOOL_LIBCBASSERT_H
+
+#define tl_assert(expr) \
+ ((void) ((expr) ? 0 : \
+ (VG_(assert_fail) (/*isCore?*/False, #expr, \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+ ""), \
+ 0)))
+
+#define tl_assert2(expr, format, args...) \
+ ((void) ((expr) ? 0 : \
+ (VG_(assert_fail) (/*isCore?*/False, #expr, \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+ format, ##args), \
+ 0)))
+
+__attribute__ ((__noreturn__))
+extern void VG_(exit)( Int status );
+
+/* Prints a panic message, appends newline and bug reporting info, aborts. */
+__attribute__ ((__noreturn__))
+extern void VG_(tool_panic) ( Char* str );
+
+__attribute__ ((__noreturn__))
+extern void VG_(assert_fail) ( Bool isCore, const Char* expr, const Char* file,
+ Int line, const Char* fn,
+ const HChar* format, ... );
+
+#endif // __PUB_TOOL_LIBCBASSERT_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcbase.h.svn-base b/include/.svn/text-base/pub_tool_libcbase.h.svn-base
new file mode 100644
index 0000000..4e627be
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcbase.h.svn-base
@@ -0,0 +1,151 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Standalone libc stuff. pub_tool_libcbase.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCBASE_H
+#define __PUB_TOOL_LIBCBASE_H
+
+/* ---------------------------------------------------------------------
+ Char functions.
+ ------------------------------------------------------------------ */
+
+extern Bool VG_(isspace) ( Char c );
+extern Bool VG_(isdigit) ( Char c );
+
+/* ---------------------------------------------------------------------
+ Converting strings to numbers
+ ------------------------------------------------------------------ */
+
+// Convert strings to numbers according to various bases. Leading
+// whitespace is ignored. A subsequent '-' or '+' is accepted. For strtoll16,
+// accepts an initial "0x" or "0X" prefix, but only if it's followed by a
+// hex digit (if not, the '0' will be read and then it will stop on the
+// "x"/"X".) If 'endptr' isn't NULL, it gets filled in with the first
+// non-digit char. Returns 0 if no number could be converted, and 'endptr'
+// is set to the start of the string. None of them test that the number
+// fits into 64 bits.
+//
+// Nb: if you're wondering why we don't just have a single VG_(strtoll) which
+// takes a base, it's because I wanted it to assert if it was given a bogus
+// base (the standard glibc one sets 'errno' in this case). But
+// m_libcbase.c doesn't import any code, not even vg_assert. --njn
+//
+// Nb: we also don't provide VG_(atoll*); these functions are worse than
+// useless because they don't do any error checking and so accept malformed
+// numbers and non-numbers -- eg. "123xyz" gives 123, and "foo" gives 0!
+// If you really want that behaviour, you can use "VG_(strtoll10)(str, NULL)".
+extern Long VG_(strtoll10) ( Char* str, Char** endptr );
+extern Long VG_(strtoll16) ( Char* str, Char** endptr );
+
+// Convert a string to a double. After leading whitespace is ignored, a
+// '+' or '-' is allowed, and then it accepts a non-empty sequence of
+// decimal digits possibly containing a '.'. Hexadecimal floats are not
+// accepted, nor are "fancy" floats (eg. "3.4e-5", "NAN").
+extern double VG_(strtod) ( Char* str, Char** endptr );
+
+/* ---------------------------------------------------------------------
+ String functions and macros
+ ------------------------------------------------------------------ */
+
+/* Use this for normal null-termination-style string comparison. */
+#define VG_STREQ(s1,s2) ( (s1 != NULL && s2 != NULL \
+ && VG_(strcmp)((s1),(s2))==0) ? True : False )
+#define VG_STREQN(n,s1,s2) ( (s1 != NULL && s2 != NULL \
+ && VG_(strncmp)((s1),(s2),(n))==0) ? True : False )
+
+extern SizeT VG_(strlen) ( const Char* str );
+extern Char* VG_(strcat) ( Char* dest, const Char* src );
+extern Char* VG_(strncat) ( Char* dest, const Char* src, SizeT n );
+extern Char* VG_(strpbrk) ( const Char* s, const Char* accpt );
+extern Char* VG_(strcpy) ( Char* dest, const Char* src );
+extern Char* VG_(strncpy) ( Char* dest, const Char* src, SizeT ndest );
+extern Int VG_(strcmp) ( const Char* s1, const Char* s2 );
+extern Int VG_(strncmp) ( const Char* s1, const Char* s2, SizeT nmax );
+extern Char* VG_(strstr) ( const Char* haystack, Char* needle );
+extern Char* VG_(strchr) ( const Char* s, Char c );
+extern Char* VG_(strrchr) ( const Char* s, Char c );
+extern SizeT VG_(strspn) ( const Char* s, const Char* accept );
+extern SizeT VG_(strcspn) ( const Char* s, const char* reject );
+
+/* Like strncpy(), but if 'src' is longer than 'ndest' inserts a '\0' as the
+ last character. */
+extern void VG_(strncpy_safely) ( Char* dest, const Char* src, SizeT ndest );
+
+/* ---------------------------------------------------------------------
+ mem* functions
+ ------------------------------------------------------------------ */
+
+extern void* VG_(memcpy) ( void *d, const void *s, SizeT sz );
+extern void* VG_(memmove)( void *d, const void *s, SizeT sz );
+extern void* VG_(memset) ( void *s, Int c, SizeT sz );
+extern Int VG_(memcmp) ( const void* s1, const void* s2, SizeT n );
+
+/* ---------------------------------------------------------------------
+ Address computation helpers
+ ------------------------------------------------------------------ */
+
+// Check if an address/whatever is aligned
+#define VG_IS_2_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)0x1)))
+#define VG_IS_4_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)0x3)))
+#define VG_IS_8_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)0x7)))
+#define VG_IS_16_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)0xf)))
+#define VG_IS_WORD_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)(sizeof(Addr)-1))))
+#define VG_IS_PAGE_ALIGNED(aaa_p) (0 == (((Addr)(aaa_p)) & ((Addr)(VKI_PAGE_SIZE-1))))
+
+// 'a' -- the alignment -- must be a power of 2.
+// The latter two require the vki-*.h header to be imported also.
+#define VG_ROUNDDN(p, a) ((Addr)(p) & ~((Addr)(a)-1))
+#define VG_ROUNDUP(p, a) VG_ROUNDDN((p)+(a)-1, (a))
+#define VG_PGROUNDDN(p) VG_ROUNDDN(p, VKI_PAGE_SIZE)
+#define VG_PGROUNDUP(p) VG_ROUNDUP(p, VKI_PAGE_SIZE)
+
+/* ---------------------------------------------------------------------
+ Misc useful functions
+ ------------------------------------------------------------------ */
+
+/* Like qsort(). The name VG_(ssort) is for historical reasons -- it used
+ * to be a shell sort, but is now a quicksort. */
+extern void VG_(ssort)( void* base, SizeT nmemb, SizeT size,
+ Int (*compar)(void*, void*) );
+
+/* Returns the base-2 logarithm of x. Returns -1 if x is not a power
+ of two. Nb: VG_(log2)(1) == 0. */
+extern Int VG_(log2) ( UInt x );
+
+// A pseudo-random number generator returning a random UInt. If pSeed
+// is NULL, it uses its own seed, which starts at zero. If pSeed is
+// non-NULL, it uses and updates whatever pSeed points at.
+extern UInt VG_(random) ( /*MOD*/UInt* pSeed );
+#define VG_RAND_MAX (1ULL << 32)
+
+#endif // __PUB_TOOL_LIBCBASE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcfile.h.svn-base b/include/.svn/text-base/pub_tool_libcfile.h.svn-base
new file mode 100644
index 0000000..f870109
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcfile.h.svn-base
@@ -0,0 +1,91 @@
+
+/*--------------------------------------------------------------------*/
+/*--- File/socket-related libc stuff. pub_tool_libcfile.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCFILE_H
+#define __PUB_TOOL_LIBCFILE_H
+
+/* ---------------------------------------------------------------------
+ File-related functions.
+ ------------------------------------------------------------------ */
+
+/* To use this file you must first include pub_tool_vki.h. */
+
+/* Note that VG_(stat) and VG_(fstat) write to a 'struct vg_stat*' and
+ not a 'struct vki_stat*' or a 'struct vki_stat64*'. 'struct
+ vg_stat*' is not the same as either of the vki_ versions. No
+ specific vki_stat{,64} kernel structure will work and is
+ consistently available on different architectures on Linux, so we
+ have to use this 'struct vg_stat' impedance-matching type
+ instead. */
+struct vg_stat {
+ ULong st_dev;
+ ULong st_ino;
+ ULong st_nlink;
+ UInt st_mode;
+ UInt st_uid;
+ UInt st_gid;
+ ULong st_rdev;
+ Long st_size;
+ ULong st_blksize;
+ ULong st_blocks;
+ ULong st_atime;
+ ULong st_atime_nsec;
+ ULong st_mtime;
+ ULong st_mtime_nsec;
+ ULong st_ctime;
+ ULong st_ctime_nsec;
+};
+
+extern SysRes VG_(open) ( const Char* pathname, Int flags, Int mode );
+extern void VG_(close) ( Int fd );
+extern Int VG_(read) ( Int fd, void* buf, Int count);
+extern Int VG_(write) ( Int fd, const void* buf, Int count);
+extern Int VG_(pipe) ( Int fd[2] );
+extern OffT VG_(lseek) ( Int fd, OffT offset, Int whence );
+
+extern SysRes VG_(stat) ( Char* file_name, struct vg_stat* buf );
+extern Int VG_(fstat) ( Int fd, struct vg_stat* buf );
+extern SysRes VG_(dup) ( Int oldfd );
+extern SysRes VG_(dup2) ( Int oldfd, Int newfd );
+extern Int VG_(rename) ( Char* old_name, Char* new_name );
+extern Int VG_(unlink) ( Char* file_name );
+
+extern Int VG_(readlink)( Char* path, Char* buf, UInt bufsize );
+extern Int VG_(getdents)( UInt fd, struct vki_dirent *dirp, UInt count );
+
+/* Copy the working directory at startup into buf[0 .. size-1], or return
+ False if buf is too small. */
+extern Bool VG_(get_startup_wd) ( Char* buf, SizeT size );
+
+#endif // __PUB_TOOL_LIBCFILE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcprint.h.svn-base b/include/.svn/text-base/pub_tool_libcprint.h.svn-base
new file mode 100644
index 0000000..b3386b2
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcprint.h.svn-base
@@ -0,0 +1,111 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Printing libc stuff. pub_tool_libcprint.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCPRINT_H
+#define __PUB_TOOL_LIBCPRINT_H
+
+
+/* Enable compile-time format string checking by gcc.
+ This feature is supported since at least gcc version 2.95.
+ For more information about the format attribute, see also
+ http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html.
+ */
+
+#if defined(__GNUC__)
+#define PRINTF_CHECK(x, y) __attribute__((format(__printf__, x, y)))
+#else
+#define PRINTF_CHECK(x, y)
+#endif
+
+
+/* ---------------------------------------------------------------------
+ Basic printing
+ ------------------------------------------------------------------ */
+
+/* Note that they all output to the file descriptor given by the
+ * --log-fd/--log-file/--log-socket argument, which defaults to 2 (stderr).
+ * Hence no need for VG_(fprintf)().
+ */
+extern UInt VG_(printf) ( const HChar *format, ... ) PRINTF_CHECK(1, 2);
+extern UInt VG_(vprintf) ( const HChar *format, va_list vargs ) PRINTF_CHECK(1, 0);
+extern UInt VG_(sprintf) ( Char* buf, const HChar* format, ... ) PRINTF_CHECK(2, 3);
+extern UInt VG_(vsprintf) ( Char* buf, const HChar* format, va_list vargs ) PRINTF_CHECK(2, 0);
+extern UInt VG_(snprintf) ( Char* buf, Int size,
+ const HChar *format, ... ) PRINTF_CHECK(3, 4);
+extern UInt VG_(vsnprintf)( Char* buf, Int size,
+ const HChar *format, va_list vargs ) PRINTF_CHECK(3, 0);
+
+// Percentify n/m with d decimal places. Includes the '%' symbol at the end.
+// Right justifies in 'buf'.
+extern void VG_(percentify)(ULong n, ULong m, UInt d, Int n_buf, char buf[]);
+
+/* ---------------------------------------------------------------------
+ Messages for the user
+ ------------------------------------------------------------------ */
+
+/* No, really. I _am_ that strange. */
+#define OINK(nnn) VG_(message)(Vg_DebugMsg, "OINK %d",nnn)
+
+/* Print a message prefixed by "??<pid>?? "; '?' depends on the VgMsgKind.
+ Should be used for all user output. */
+
+typedef
+ enum { Vg_UserMsg, /* '?' == '=' */
+ Vg_DebugMsg, /* '?' == '-' */
+ Vg_DebugExtraMsg, /* '?' == '+' */
+ Vg_ClientMsg /* '?' == '*' */
+ }
+ VgMsgKind;
+
+/* Send a single-part message. Appends a newline. The format
+ specification may contain any ISO C format specifier or %t.
+ No attempt is made to let the compiler verify consistency of the
+ format string and the argument list. */
+extern UInt VG_(message_no_f_c)( VgMsgKind kind, const HChar* format, ... );
+/* Send a single-part message. Appends a newline. The format
+ specification may contain any ISO C format specifier. The gcc compiler
+ will verify consistency of the format string and the argument list. */
+extern UInt VG_(message)( VgMsgKind kind, const HChar* format, ... )
+ PRINTF_CHECK(2, 3);
+
+extern UInt VG_(vmessage)( VgMsgKind kind, const HChar* format, va_list vargs )
+ PRINTF_CHECK(2, 0);
+
+// Short-cuts for VG_(message)().
+#define VG_UMSG( format, args... ) VG_(message)(Vg_UserMsg, format, ##args)
+#define VG_DMSG( format, args... ) VG_(message)(Vg_DebugMsg, format, ##args)
+#define VG_EMSG( format, args... ) VG_(message)(Vg_DebugExtraMsg, \
+ format, ##args)
+
+#endif // __PUB_TOOL_LIBCPRINT_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcproc.h.svn-base b/include/.svn/text-base/pub_tool_libcproc.h.svn-base
new file mode 100644
index 0000000..cd668b1
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcproc.h.svn-base
@@ -0,0 +1,95 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Process-related libc stuff pub_tool_libcproc.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCPROC_H
+#define __PUB_TOOL_LIBCPROC_H
+
+/* ---------------------------------------------------------------------
+ Command-line and environment stuff
+ ------------------------------------------------------------------ */
+
+/* Client environment. */
+extern Char** VG_(client_envp);
+
+/* Looks up VG_(client_envp) */
+extern Char* VG_(getenv) ( Char* name );
+
+/* Path to all our library/aux files */
+extern const Char *VG_(libdir);
+
+/* ---------------------------------------------------------------------
+ Important syscalls
+ ------------------------------------------------------------------ */
+
+extern Int VG_(waitpid)( Int pid, Int *status, Int options );
+extern Int VG_(system) ( Char* cmd );
+extern Int VG_(fork) ( void);
+extern void VG_(execv) ( Char* filename, Char** argv );
+
+/* ---------------------------------------------------------------------
+ Resource limits
+ ------------------------------------------------------------------ */
+
+extern Int VG_(getrlimit) ( Int resource, struct vki_rlimit *rlim );
+extern Int VG_(setrlimit) ( Int resource, const struct vki_rlimit *rlim );
+
+/* ---------------------------------------------------------------------
+ pids, etc
+ ------------------------------------------------------------------ */
+
+extern Int VG_(gettid) ( void );
+extern Int VG_(getpid) ( void );
+extern Int VG_(getppid) ( void );
+extern Int VG_(getpgrp) ( void );
+extern Int VG_(geteuid) ( void );
+extern Int VG_(getegid) ( void );
+
+/* ---------------------------------------------------------------------
+ Timing
+ ------------------------------------------------------------------ */
+
+// Returns the number of milliseconds passed since the progam started
+// (roughly; it gets initialised partway through Valgrind's initialisation
+// steps).
+extern UInt VG_(read_millisecond_timer) ( void );
+
+/* ---------------------------------------------------------------------
+ atfork
+ ------------------------------------------------------------------ */
+
+typedef void (*vg_atfork_t)(ThreadId);
+extern void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child);
+
+
+#endif // __PUB_TOOL_LIBCPROC_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_libcsignal.h.svn-base b/include/.svn/text-base/pub_tool_libcsignal.h.svn-base
new file mode 100644
index 0000000..d8aa0f5
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_libcsignal.h.svn-base
@@ -0,0 +1,47 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Signal-related libc stuff. pub_tool_libcsignal.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_LIBCBSIGNAL_H
+#define __PUB_TOOL_LIBCBSIGNAL_H
+
+/* Note that these use the vki_ (kernel) structure
+ definitions, which are different in places from those that glibc
+ defines. Since we're operating right at the kernel interface, glibc's view
+ of the world is entirely irrelevant. */
+
+/* --- Mess with the kernel's sig state --- */
+extern Int VG_(sigprocmask) ( Int how, const vki_sigset_t* set,
+ vki_sigset_t* oldset );
+
+#endif // __PUB_TOOL_LIBCBSIGNAL_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_machine.h.svn-base b/include/.svn/text-base/pub_tool_machine.h.svn-base
new file mode 100644
index 0000000..7301d51
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_machine.h.svn-base
@@ -0,0 +1,137 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Machine-related stuff. pub_tool_machine.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_MACHINE_H
+#define __PUB_TOOL_MACHINE_H
+
+#if defined(VGP_x86_linux)
+# define VG_MIN_INSTR_SZB 1 // min length of native instruction
+# define VG_MAX_INSTR_SZB 16 // max length of native instruction
+# define VG_CLREQ_SZB 14 // length of a client request, may
+ // be larger than VG_MAX_INSTR_SZB
+# define VG_STACK_REDZONE_SZB 0 // number of addressable bytes below %RSP
+#elif defined(VGP_amd64_linux)
+# define VG_MIN_INSTR_SZB 1
+# define VG_MAX_INSTR_SZB 16
+# define VG_CLREQ_SZB 19
+# define VG_STACK_REDZONE_SZB 128
+#elif defined(VGP_ppc32_linux)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4
+# define VG_CLREQ_SZB 20
+# define VG_STACK_REDZONE_SZB 0
+#elif defined(VGP_ppc64_linux)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4
+# define VG_CLREQ_SZB 20
+# define VG_STACK_REDZONE_SZB 288 // number of addressable bytes below R1
+ // from 64-bit PowerPC ELF ABI Supplement 1.7
+#elif defined(VGP_ppc32_aix5)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4
+# define VG_CLREQ_SZB 20
+ /* The PowerOpen ABI actually says 220 bytes, but that is not an
+ 8-aligned number, and frequently forces Memcheck's
+ mc_{new,die}_mem_stack_N routines into slow cases by losing
+ 8-alignment of the area to be messed with. So let's just say
+ 224 instead. Gdb has a similar kludge. */
+# define VG_STACK_REDZONE_SZB 224
+#elif defined(VGP_ppc64_aix5)
+# define VG_MIN_INSTR_SZB 4
+# define VG_MAX_INSTR_SZB 4
+# define VG_CLREQ_SZB 20
+# define VG_STACK_REDZONE_SZB 288 // is this right?
+#else
+# error Unknown platform
+#endif
+
+// Guest state accessors
+extern Addr VG_(get_SP) ( ThreadId tid );
+extern Addr VG_(get_IP) ( ThreadId tid );
+extern Addr VG_(get_FP) ( ThreadId tid );
+extern Addr VG_(get_LR) ( ThreadId tid );
+
+extern void VG_(set_SP) ( ThreadId tid, Addr sp );
+extern void VG_(set_IP) ( ThreadId tid, Addr ip );
+
+// For get/set, 'area' is where the asked-for guest state will be copied
+// into/from. If shadowNo == 0, the real (non-shadow) guest state is
+// accessed. If shadowNo == 1, the first shadow area is accessed, and
+// if shadowNo == 2, the second shadow area is accessed. This gives a
+// completely general way to read/modify a thread's guest register state
+// providing you know the offsets you need.
+void
+VG_(get_shadow_regs_area) ( ThreadId tid,
+ /*DST*/UChar* dst,
+ /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size );
+void
+VG_(set_shadow_regs_area) ( ThreadId tid,
+ /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
+ /*SRC*/const UChar* src );
+
+// Sets the shadow values for the syscall return value register(s).
+// This is platform specific.
+void VG_(set_syscall_return_shadows) ( ThreadId tid,
+ /* shadow vals for the result */
+ UWord s1res, UWord s2res,
+ /* shadow vals for the error val */
+ UWord s1err, UWord s2err );
+
+// Apply a function 'f' to all the general purpose registers in all the
+// current threads.
+// This is very Memcheck-specific -- it's used to find the roots when
+// doing leak checking.
+extern void VG_(apply_to_GP_regs)(void (*f)(UWord val));
+
+// This iterator lets you inspect each live thread's stack bounds.
+// Returns False at the end. 'tid' is the iterator and you can only
+// safely change it by making calls to these functions.
+extern void VG_(thread_stack_reset_iter) ( /*OUT*/ThreadId* tid );
+extern Bool VG_(thread_stack_next) ( /*MOD*/ThreadId* tid,
+ /*OUT*/Addr* stack_min,
+ /*OUT*/Addr* stack_max );
+
+// Returns .client_stack_highest_word for the given thread
+extern Addr VG_(thread_get_stack_max) ( ThreadId tid );
+
+// Returns how many bytes have been allocated for the stack of the given thread
+extern Addr VG_(thread_get_stack_size) ( ThreadId tid );
+
+// Given a pointer to a function as obtained by "& functionname" in C,
+// produce a pointer to the actual entry point for the function. For
+// most platforms it's the identity function. Unfortunately, on
+// ppc64-linux it isn't (sigh).
+extern void* VG_(fnptr_to_fnentry)( void* );
+
+#endif // __PUB_TOOL_MACHINE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_mallocfree.h.svn-base b/include/.svn/text-base/pub_tool_mallocfree.h.svn-base
new file mode 100644
index 0000000..efab2c2
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_mallocfree.h.svn-base
@@ -0,0 +1,58 @@
+
+/*--------------------------------------------------------------------*/
+/*--- MallocFree: high-level memory management. ---*/
+/*--- pub_tool_mallocfree.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_MALLOCFREE_H
+#define __PUB_TOOL_MALLOCFREE_H
+
+// These can be for allocating memory used by tools.
+// Nb: the allocators *always succeed* -- they never return NULL (Valgrind
+// will abort if they can't allocate the memory).
+extern void* VG_(malloc) ( HChar* cc, SizeT nbytes );
+extern void VG_(free) ( void* p );
+extern void* VG_(calloc) ( HChar* cc, SizeT n, SizeT bytes_per_elem );
+extern void* VG_(realloc) ( HChar* cc, void* p, SizeT size );
+extern Char* VG_(strdup) ( HChar* cc, const Char* s );
+
+// Returns the usable size of a heap-block. It's the asked-for size plus
+// possibly some more due to rounding up.
+extern SizeT VG_(malloc_usable_size)( void* p );
+
+// TODO: move somewhere else
+// Call here to bomb the system when out of memory (mmap anon fails)
+__attribute__((noreturn))
+extern void VG_(out_of_memory_NORETURN) ( HChar* who, SizeT szB );
+
+#endif // __PUB_TOOL_MALLOCFREE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
+
diff --git a/include/.svn/text-base/pub_tool_options.h.svn-base b/include/.svn/text-base/pub_tool_options.h.svn-base
new file mode 100644
index 0000000..cab2101
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_options.h.svn-base
@@ -0,0 +1,198 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Command line options. pub_tool_options.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_OPTIONS_H
+#define __PUB_TOOL_OPTIONS_H
+
+#include "libvex.h" // for VexControl
+
+
+// Higher-level command-line option recognisers; use in if/else chains.
+// Note that they assign a value to the 'qq_var' argument. So often they
+// can be used like this:
+//
+// if VG_STR_CLO(arg, "--foo", clo_foo) { }
+//
+// But if you want to do further checking or processing, you can do this:
+//
+// if VG_STR_CLO(arg, "--foo", clo_foo) { <further checking or processing> }
+//
+// They use GNU statement expressions to do the qq_var assignment within a
+// conditional expression.
+
+// String argument, eg. --foo=yes or --foo=no
+#define VG_BOOL_CLO(qq_arg, qq_option, qq_var) \
+ (VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=") && \
+ ({ \
+ Char* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ]; \
+ if VG_STREQ(val, "yes") (qq_var) = True; \
+ else if VG_STREQ(val, "no") (qq_var) = False; \
+ True; \
+ }) \
+ )
+
+// String argument, eg. --foo=bar
+#define VG_STR_CLO(qq_arg, qq_option, qq_var) \
+ (VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=") && \
+ ({ \
+ Char* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ]; \
+ (qq_var) = val; \
+ True; \
+ }) \
+ )
+
+// Unbounded integer arg, eg. --foo=10
+#define VG_INT_CLO(qq_arg, qq_option, qq_var) \
+ (VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=") && \
+ ({ \
+ Char* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ]; \
+ Char* s; \
+ Long n = VG_(strtoll10)( val, &s ); \
+ (qq_var) = n; \
+ /* Check for non-numeralness, or overflow. */ \
+ if ('\0' != s[0] || (qq_var) != n) VG_(err_bad_option)(qq_arg); \
+ True; \
+ }) \
+ )
+
+// Bounded integer arg, eg. --foo=10 ; if the value exceeds the bounds it
+// causes an abort. 'qq_base' can be 10 or 16.
+#define VG_BINTN_CLO(qq_base, qq_arg, qq_option, qq_var, qq_lo, qq_hi) \
+ (VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=") && \
+ ({ \
+ Char* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ]; \
+ Char* s; \
+ Long n = VG_(strtoll##qq_base)( val, &s ); \
+ (qq_var) = n; \
+ /* Check for non-numeralness, or overflow. */ \
+ /* Nb: it will overflow if qq_var is unsigned and qq_val is negative! */ \
+ if ('\0' != s[0] || (qq_var) != n) VG_(err_bad_option)(qq_arg); \
+ /* Check bounds. */ \
+ if ((qq_var) < (qq_lo) || (qq_var) > (qq_hi)) { \
+ VG_(message)(Vg_UserMsg, \
+ "'%s' argument must be between %lld and %lld", \
+ (qq_option), (Long)(qq_lo), (Long)(qq_hi)); \
+ VG_(err_bad_option)(qq_arg); \
+ } \
+ True; \
+ }) \
+ )
+
+// Bounded decimal integer arg, eg. --foo=100
+#define VG_BINT_CLO(qq_arg, qq_option, qq_var, qq_lo, qq_hi) \
+ VG_BINTN_CLO(10, (qq_arg), qq_option, (qq_var), (qq_lo), (qq_hi))
+
+// Bounded hexadecimal integer arg, eg. --foo=0x1fa8
+#define VG_BHEX_CLO(qq_arg, qq_option, qq_var, qq_lo, qq_hi) \
+ VG_BINTN_CLO(16, (qq_arg), qq_option, (qq_var), (qq_lo), (qq_hi))
+
+// Double (decimal) arg, eg. --foo=4.6
+// XXX: there's not VG_BDBL_CLO because we don't have a good way of printing
+// floats at the moment!
+#define VG_DBL_CLO(qq_arg, qq_option, qq_var) \
+ (VG_STREQN(VG_(strlen)(qq_option)+1, qq_arg, qq_option"=") && \
+ ({ \
+ Char* val = &(qq_arg)[ VG_(strlen)(qq_option)+1 ]; \
+ Char* s; \
+ double n = VG_(strtod)( val, &s ); \
+ (qq_var) = n; \
+ /* Check for non-numeralness */ \
+ if ('\0' != s[0]) VG_(err_bad_option)(qq_arg); \
+ True; \
+ }) \
+ )
+
+// Arg whose value is denoted by the exact presence of the given string;
+// if it matches, qq_var is assigned the value in qq_val.
+#define VG_XACT_CLO(qq_arg, qq_option, qq_var, qq_val) \
+ (VG_STREQ((qq_arg), (qq_option)) && \
+ ({ \
+ (qq_var) = (qq_val); \
+ True; \
+ }) \
+ )
+
+/* Verbosity level: 0 = silent, 1 (default), > 1 = more verbose. */
+extern Int VG_(clo_verbosity);
+
+/* Emit all messages as XML? default: NO */
+/* If clo_xml is set, various other options are set in a non-default
+ way. See vg_main.c and mc_main.c. */
+extern Bool VG_(clo_xml);
+
+/* An arbitrary user-supplied string which is copied into the
+ XML output, in between <usercomment> tags. */
+extern HChar* VG_(clo_xml_user_comment);
+
+/* Vex iropt control. Tool-visible so tools can make Vex optimise
+ less aggressively if that is needed (callgrind needs this). */
+extern VexControl VG_(clo_vex_control);
+
+/* Number of parents of a backtrace. Default: 8. */
+extern Int VG_(clo_backtrace_size);
+
+/* Continue stack traces below main()? Default: NO */
+extern Bool VG_(clo_show_below_main);
+
+
+/* Call this if a recognised option was bad for some reason. Note:
+ don't use it just because an option was unrecognised -- return
+ 'False' from VG_(tdict).tool_process_cmd_line_option) to indicate that --
+ use it if eg. an option was given an inappropriate argument.
+ This function prints an error message, then shuts down the entire system.
+ It returns a Bool so it can be used in the _CLO_ macros. */
+__attribute__((noreturn))
+extern void VG_(err_bad_option) ( Char* opt );
+
+/* Used to expand file names. "option_name" is the option name, eg.
+ "--log-file". 'format' is what follows, eg. "cachegrind.out.%p". In
+ 'format':
+ - "%p" is replaced with PID.
+ - "%q{QUAL}" is replaced with the environment variable $QUAL. If $QUAL
+ isn't set, we abort. If the "{QUAL}" part is malformed, we abort.
+ - "%%" is replaced with "%".
+ Anything else after '%' causes an abort.
+ If the format specifies a relative file name, it's put in the program's
+ initial working directory. If it specifies an absolute file name (ie.
+ starts with '/') then it is put there.
+
+ Note that "option_name" has no effect on the returned string: the
+ returned string depends only on "format" and the PIDs and
+ environment variables that it references (if any). "option_name" is
+ merely used in printing error messages, if an error message needs
+ to be printed due to malformedness of the "format" argument.
+*/
+extern Char* VG_(expand_file_name)(Char* option_name, Char* format);
+
+#endif // __PUB_TOOL_OPTIONS_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_oset.h.svn-base b/include/.svn/text-base/pub_tool_oset.h.svn-base
new file mode 100644
index 0000000..687d34f
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_oset.h.svn-base
@@ -0,0 +1,259 @@
+
+/*--------------------------------------------------------------------*/
+/*--- OSet: a fast data structure with no dups. pub_tool_oset.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2005-2009 Nicholas Nethercote
+ njn@valgrind.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_OSET_H
+#define __PUB_TOOL_OSET_H
+
+// This module implements an ordered set, a data structure with fast
+// (eg. amortised log(n) or better) insertion, lookup and deletion of
+// elements. It does not allow duplicates, and will assert if you insert a
+// duplicate to an OSet.
+//
+// It has two interfaces.
+//
+// - The "OSetWord_" interface provides an easier-to-use interface for the
+// case where you just want to store UWord-sized values. The user
+// provides the allocation and deallocation functions, and possibly a
+// comparison function.
+//
+// - The "OSetGen_" interface provides a totally generic interface, which
+// allows any kind of structure to be put into the set. The user provides
+// the allocation and deallocation functions. Also, each element has a
+// key, which the lookup is done with. The key may be the whole element
+// (eg. in an OSet of integers, each integer serves both as an element and
+// a key), or it may be only part of it (eg. if the key is a single field
+// in a struct). The user can provide a function that compares an element
+// with a key; this is very flexible, and with the right comparison
+// function even a (non-overlapping) interval list can be created. But
+// the cost of calling a function for every comparison can be high during
+// lookup. If no comparison function is provided, we assume that keys are
+// (signed or unsigned) words, and that the key is the first word in each
+// element. This fast comparison is suitable for an OSet containing
+// structs where the first element is an Addr, for example.
+//
+// Each OSet interface also has an iterator, which makes it simple to
+// traverse all the nodes in order. Note that the iterator maintains state
+// and so is non-reentrant.
+//
+// Note that once you insert an element into an OSet, if you modify any part
+// of it looked at by your cmp() function, this may cause incorrect
+// behaviour as the sorted order maintained will be wrong.
+
+/*--------------------------------------------------------------------*/
+/*--- Types ---*/
+/*--------------------------------------------------------------------*/
+
+typedef struct _OSet OSet;
+
+// - Cmp: returns -1, 0 or 1 if key is <, == or > elem.
+// - Alloc: allocates a chunk of memory.
+// - Free: frees a chunk of memory allocated with Alloc.
+
+typedef Word (*OSetCmp_t) ( const void* key, const void* elem );
+typedef void* (*OSetAlloc_t) ( HChar* ec, SizeT szB );
+typedef void (*OSetFree_t) ( void* p );
+
+/*--------------------------------------------------------------------*/
+/*--- Creating and destroying OSets (UWord) ---*/
+/*--------------------------------------------------------------------*/
+
+// * Create: allocates and initialises the OSet. Arguments:
+// - alloc The allocation function used internally for allocating the
+// OSet and all its nodes.
+// - free The deallocation function used internally for freeing nodes
+// called by VG_(OSetWord_Destroy)().
+//
+// * CreateWithCmp: like Create, but you specify your own comparison
+// function.
+//
+// * Destroy: frees all nodes in the table, plus the memory used by
+// the table itself. The passed-in function is called on each node first
+// to allow the destruction of any attached resources; if NULL it is not
+// called.
+
+extern OSet* VG_(OSetWord_Create) ( OSetAlloc_t alloc, HChar* ec,
+ OSetFree_t _free );
+extern void VG_(OSetWord_Destroy) ( OSet* os );
+
+/*--------------------------------------------------------------------*/
+/*--- Operations on OSets (UWord) ---*/
+/*--------------------------------------------------------------------*/
+
+// In everything that follows, the parameter 'key' is always the *address*
+// of the key, and 'elem' is *address* of the elem, as are the return values
+// of the functions that return elems.
+//
+// * Size: The number of elements in the set.
+//
+// * Contains: Determines if the value is in the set.
+//
+// * Insert: Inserts a new element into the set. Duplicates are forbidden,
+// and will cause assertion failures.
+//
+// * Remove: Removes the value from the set, if present. Returns a Bool
+// indicating if the value was removed.
+//
+// * ResetIter: Each OSet has an iterator. This resets it to point to the
+// first element in the OSet.
+//
+// * Next: Copies the next value according to the OSet's iterator into &val,
+// advances the iterator by one, and returns True; the elements are
+// visited in increasing order of unsigned words (UWord). Or, returns
+// False if the iterator has reached the set's end.
+//
+// You can thus iterate in order through a set like this:
+//
+// Word val;
+// VG_(OSetWord_ResetIter)(oset);
+// while ( VG_(OSetWord_Next)(oset, &val) ) {
+// ... do stuff with 'val' ...
+// }
+//
+// Note that iterators are cleared any time an element is inserted or
+// removed from the OSet, to avoid possible mayhem caused by the iterator
+// getting out of sync with the OSet's contents. "Cleared" means that
+// they will return False if VG_(OSetWord_Next)() is called without an
+// intervening call to VG_(OSetWord_ResetIter)().
+
+extern Word VG_(OSetWord_Size) ( OSet* os );
+extern void VG_(OSetWord_Insert) ( OSet* os, UWord val );
+extern Bool VG_(OSetWord_Contains) ( OSet* os, UWord val );
+extern Bool VG_(OSetWord_Remove) ( OSet* os, UWord val );
+extern void VG_(OSetWord_ResetIter) ( OSet* os );
+extern Bool VG_(OSetWord_Next) ( OSet* os, /*OUT*/UWord* val );
+
+
+/*--------------------------------------------------------------------*/
+/*--- Creating and destroying OSets and OSet members (Gen) ---*/
+/*--------------------------------------------------------------------*/
+
+// * Create: allocates and initialises the OSet. Arguments:
+// - keyOff The offset of the key within the element.
+// - cmp The comparison function between keys and elements, or NULL
+// if the OSet should use fast comparisons.
+// - alloc The allocation function used for allocating the OSet itself;
+// it's also called for each invocation of
+// VG_(OSetGen_AllocNode)().
+// - free The deallocation function used by VG_(OSetGen_FreeNode)() and
+// VG_(OSetGen_Destroy)().
+//
+// If cmp is NULL, keyOff must be zero. This is checked.
+//
+// * Destroy: frees all nodes in the table, plus the memory used by
+// the table itself. The passed-in function is called on each node first
+// to allow the destruction of any attached resources; if NULL it is not
+// called.
+//
+// * AllocNode: Allocate and zero memory for a node to go into the OSet.
+// Uses the alloc function given to VG_(OSetGen_Create)() to allocated a
+// node which is big enough for both an element and the OSet metadata.
+// Not all elements in one OSet have to be the same size.
+//
+// Note that the element allocated will be at most word-aligned, which may
+// be less aligned than the element type would normally be.
+//
+// * FreeNode: Deallocate a node allocated with OSetGen_AllocNode(). Using
+// a deallocation function (such as VG_(free)()) directly will likely
+// lead to assertions in Valgrind's allocator.
+
+extern OSet* VG_(OSetGen_Create) ( PtrdiffT keyOff, OSetCmp_t cmp,
+ OSetAlloc_t alloc, HChar* ec,
+ OSetFree_t _free );
+extern void VG_(OSetGen_Destroy) ( OSet* os );
+extern void* VG_(OSetGen_AllocNode) ( OSet* os, SizeT elemSize );
+extern void VG_(OSetGen_FreeNode) ( OSet* os, void* elem );
+
+/*--------------------------------------------------------------------*/
+/*--- Operations on OSets (Gen) ---*/
+/*--------------------------------------------------------------------*/
+
+// In everything that follows, the parameter 'key' is always the *address*
+// of the key, and 'elem' is *address* of the elem, as are the return values
+// of the functions that return elems.
+//
+// * Size: The number of elements in the set.
+//
+// * Insert: Inserts a new element into the set. Note that 'elem' must
+// have been allocated using VG_(OSetGen_AllocNode)(), otherwise you will
+// get assertion failures about "bad magic". Duplicates are forbidden,
+// and will also cause assertion failures.
+//
+// * Contains: Determines if any element in the OSet matches the key.
+//
+// * Lookup: Returns a pointer to the element matching the key, if there is
+// one, otherwise returns NULL.
+//
+// * LookupWithCmp: Like Lookup, but you specify the comparison function,
+// which overrides the OSet's normal one.
+//
+// * Remove: Removes the element matching the key, if there is one. Returns
+// NULL if no element matches the key.
+//
+// * ResetIter: Each OSet has an iterator. This resets it to point to the
+// first element in the OSet.
+//
+// * Next: Returns a pointer to the element pointed to by the OSet's
+// iterator, and advances the iterator by one; the elements are visited
+// in order. Or, returns NULL if the iterator has reached the OSet's end.
+//
+// You can thus iterate in order through a set like this:
+//
+// VG_(OSetGen_ResetIter)(oset);
+// while ( (elem = VG_(OSetGen_Next)(oset)) ) {
+// ... do stuff with 'elem' ...
+// }
+//
+// Note that iterators are cleared any time an element is inserted or
+// removed from the OSet, to avoid possible mayhem caused by the iterator
+// getting out of sync with the OSet's contents. "Cleared" means that
+// they will return NULL if VG_(OSetGen_Next)() is called without an
+// intervening call to VG_(OSetGen_ResetIter)().
+
+extern Word VG_(OSetGen_Size) ( const OSet* os );
+extern void VG_(OSetGen_Insert) ( OSet* os, void* elem );
+extern Bool VG_(OSetGen_Contains) ( const OSet* os, const void* key );
+extern void* VG_(OSetGen_Lookup) ( const OSet* os, const void* key );
+extern void* VG_(OSetGen_LookupWithCmp)( OSet* os,
+ const void* key, OSetCmp_t cmp );
+extern void* VG_(OSetGen_Remove) ( OSet* os, const void* key );
+extern void VG_(OSetGen_ResetIter) ( OSet* os );
+extern void* VG_(OSetGen_Next) ( OSet* os );
+
+// set up 'oset' for iteration so that the first key subsequently
+// produced VG_(OSetGen_Next) is the smallest key in the map
+// >= start_at. Naturally ">=" is defined by the comparison
+// function supplied to VG_(OSetGen_Create).
+extern void VG_(OSetGen_ResetIterAt) ( OSet* oset, const void* key );
+
+#endif // __PUB_TOOL_OSET_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_redir.h.svn-base b/include/.svn/text-base/pub_tool_redir.h.svn-base
new file mode 100644
index 0000000..a249fb2
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_redir.h.svn-base
@@ -0,0 +1,205 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Redirections, etc. pub_tool_redir.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_REDIR_H
+#define __PUB_TOOL_REDIR_H
+
+/* The following macros facilitate function replacement and wrapping.
+
+ Function wrapping and function replacement are similar but not
+ identical.
+
+ 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 ...
+ }
+
+ 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
+
+ _vgrZU_zEncodedSoname_fnname
+
+ 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 ...
+ }
+
+ 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. 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 "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 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.
+
+ Wrapping
+ ~~~~~~~~
+ This is identical to replacement, except that you should use the
+ macro names
+
+ 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)
+ ( --> ZL (left)
+ ) --> ZR (right)
+
+ Everything else is left unchanged.
+*/
+
+/* 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. */
+
+/* Use an extra level of macroisation so as to ensure the soname/fnname
+ args are fully macro-expanded before pasting them together. */
+#define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd
+
+#define VG_REPLACE_FUNCTION_ZU(soname,fnname) VG_CONCAT4(_vgrZU_,soname,_,fnname)
+#define VG_REPLACE_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgrZZ_,soname,_,fnname)
+
+#define VG_WRAP_FUNCTION_ZU(soname,fnname) VG_CONCAT4(_vgwZU_,soname,_,fnname)
+#define VG_WRAP_FUNCTION_ZZ(soname,fnname) VG_CONCAT4(_vgwZZ_,soname,_,fnname)
+
+/* --------- Some handy Z-encoded names. --------- */
+
+/* --- Soname of the standard C library. --- */
+
+#if defined(VGO_linux)
+# define VG_Z_LIBC_SONAME libcZdsoZa // libc.so*
+#elif defined(VGP_ppc32_aix5)
+ /* AIX has both /usr/lib/libc.a and /usr/lib/libc_r.a. */
+# define VG_Z_LIBC_SONAME libcZaZdaZLshrZdoZR // libc*.a(shr.o)
+#elif defined(VGP_ppc64_aix5)
+# define VG_Z_LIBC_SONAME libcZaZdaZLshrZu64ZdoZR // libc*.a(shr_64.o)
+#else
+# error "Unknown platform"
+#endif
+
+/* --- Soname of the GNU C++ library. --- */
+
+// DDD: this one and those below should probably be conditionally compiled,
+// as should all the redirects in the tools that use them.
+#define VG_Z_LIBSTDCXX_SONAME libstdcZpZpZa // libstdc++*
+
+/* --- Soname of XLC's C++ library. --- */
+
+/* AIX: xlC's C++ runtime library is called libC.a, and the
+ interesting symbols appear to be in ansicore_32.o or ansicore_64.o
+ respectively. */
+#if defined(VGP_ppc32_aix5)
+# define VG_Z_LIBC_DOT_A libCZdaZLansicoreZu32ZdoZR // libC.a(ansicore_32.o)
+#elif defined(VGP_ppc64_aix5)
+# define VG_Z_LIBC_DOT_A libCZdaZLansicoreZu64ZdoZR // libC.a(ansicore_64.o)
+#endif
+
+/* --- Sonames for Linux ELF linkers. --- */
+
+#define VG_Z_LD_LINUX_SO_2 ldZhlinuxZdsoZd2 // ld-linux.so.2
+#define VG_Z_LD_LINUX_X86_64_SO_2 ldZhlinuxZhx86Zh64ZdsoZd2 // ld-linux-x86-64.so.2
+#define VG_Z_LD64_SO_1 ld64ZdsoZd1 // ld64.so.1
+#define VG_Z_LD_SO_1 ldZdsoZd1 // ld.so.1
+
+
+#endif // __PUB_TOOL_REDIR_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_replacemalloc.h.svn-base b/include/.svn/text-base/pub_tool_replacemalloc.h.svn-base
new file mode 100644
index 0000000..9cb2e9e
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_replacemalloc.h.svn-base
@@ -0,0 +1,74 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Malloc replacement. pub_tool_replacemalloc.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_REPLACEMALLOC_H
+#define __PUB_TOOL_REPLACEMALLOC_H
+
+/* If a tool replaces malloc() et al, the easiest way to do so is to
+ link libreplacemalloc_toolpreload.o into its vgpreload_*.so file, and
+ use the functions declared below. You can do it from scratch,
+ though, if you enjoy that sort of thing. */
+
+/* Can be called from VG_(tdict).malloc_malloc et al to do the actual
+ * alloc/freeing. */
+extern void* VG_(cli_malloc) ( SizeT align, SizeT nbytes );
+extern void VG_(cli_free) ( void* p );
+
+/* If a tool uses deferred freeing (e.g. memcheck to catch accesses to
+ freed memory) it can maintain number and total size of queued blocks
+ in these variable to provide more accurate statistics about client
+ memory usage. Currently used by mallinfo(). */
+extern Long VG_(free_queue_volume);
+extern Long VG_(free_queue_length);
+
+/* Check if an address is within a range, allowing for redzones at edges */
+extern Bool VG_(addr_is_in_block)( Addr a, Addr start,
+ SizeT size, SizeT rz_szB );
+
+/* ------------------------------------------------------------------ */
+/* Some options that can be used by a tool if malloc() et al are replaced.
+ The tool should call the functions in the appropriate places to give
+ control over these aspects of Valgrind's version of malloc(). */
+
+/* DEBUG: print malloc details? default: NO */
+extern Bool VG_(clo_trace_malloc);
+/* Minimum alignment in functions that don't specify alignment explicitly.
+ default: VG_MIN_MALLOC_SZB */
+extern UInt VG_(clo_alignment);
+
+extern Bool VG_(replacement_malloc_process_cmd_line_option) ( Char* arg );
+extern void VG_(replacement_malloc_print_usage) ( void );
+extern void VG_(replacement_malloc_print_debug_usage) ( void );
+
+#endif // __PUB_TOOL_REPLACEMALLOC_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_seqmatch.h.svn-base b/include/.svn/text-base/pub_tool_seqmatch.h.svn-base
new file mode 100644
index 0000000..a1763b7
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_seqmatch.h.svn-base
@@ -0,0 +1,91 @@
+
+/*--------------------------------------------------------------------*/
+/*--- A simple sequence matching facility. ---*/
+/*--- pub_tool_seqmatch.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2008-2009 OpenWorks Ltd
+ info@open-works.co.uk
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_SEQMATCH_H
+#define __PUB_TOOL_SEQMATCH_H
+
+/* Perform totally abstractified sequence matching, of an input
+ sequence against a pattern sequence. The pattern sequence may
+ include '*' elements (matches any number of anything) and '?'
+ elements (matches exactly one element). '*' patterns are matched
+ frugally, meaning that they are "assigned" the minimum amount of
+ input needed to make the match work.
+
+ This routine is recursive. The recursion depth is equal to the
+ number of '*' elements in the pattern. There is no guard against
+ excessive recursion. This function has no global state and so is
+ thread-safe and re-entrant. (It needs to be, since m_errormgr will
+ effectively construct two simultaneous calls to it, once to match
+ at the frame level, and whilst that is happening, once at the
+ function/object-name level.)
+
+ When matchAll is True, the entire input sequence must match the
+ pattern, else the match fails. When False, it's ok for some tail
+ of the input sequence to be unused -- so we're only matching a
+ prefix.
+
+ The pattern array is starts at 'patt' and consists of 'nPatt'
+ elements each of size 'szbPatt'. For the initial call, pass a
+ value of zero to 'ixPatt'.
+
+ Ditto for input/nInput/szbInput/ixInput.
+
+ pIsStar should return True iff the pointed-to pattern element is
+ conceptually a '*'.
+
+ pIsQuery should return True iff the pointed-to-pattern element is
+ conceptually a '?'.
+
+ pattEQinp takes a pointer to a pattern element and a pointer to an
+ input element. It should return True iff they are considered
+ equal. Note that the pattern element is guaranteed to be neither
+ (conceptually) '*' nor '?', so it must be a literal (in the sense
+ that all the input sequence elements are literal).
+*/
+Bool VG_(generic_match) (
+ Bool matchAll,
+ void* patt, SizeT szbPatt, UWord nPatt, UWord ixPatt,
+ void* input, SizeT szbInput, UWord nInput, UWord ixInput,
+ Bool (*pIsStar)(void*),
+ Bool (*pIsQuery)(void*),
+ Bool (*pattEQinp)(void*,void*)
+ );
+
+/* Mini-regexp function. Searches for 'pat' in 'str'. Supports
+ meta-symbols '*' and '?'. There is no way to escape meta-symbols
+ in the pattern. */
+Bool VG_(string_match) ( const Char* pat, const Char* str );
+
+#endif // __PUB_TOOL_SEQMATCH_H
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_tool_seqmatch.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_signals.h.svn-base b/include/.svn/text-base/pub_tool_signals.h.svn-base
new file mode 100644
index 0000000..bb96018
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_signals.h.svn-base
@@ -0,0 +1,47 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Signals stuff. pub_tool_signals.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_SIGNALS_H
+#define __PUB_TOOL_SIGNALS_H
+
+// Register an interest in apparently internal faults; used code which
+// wanders around dangerous memory (ie, leakcheck). The catcher is
+// not expected to return.
+//
+// It's frustrating that we need this header for a single function used
+// only by Memcheck during leak checking. We should find a way to remove
+// the need for this file.
+extern void VG_(set_fault_catcher)(void (*catcher)(Int sig, Addr addr));
+
+#endif // __PUB_TOOL_SIGNALS_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_sparsewa.h.svn-base b/include/.svn/text-base/pub_tool_sparsewa.h.svn-base
new file mode 100644
index 0000000..29bb336
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_sparsewa.h.svn-base
@@ -0,0 +1,99 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An sparse array (of words) implementation. ---*/
+/*--- pub_tool_sparsewa.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2008-2009 OpenWorks Ltd
+ info@open-works.co.uk
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_SPARSEWA_H
+#define __PUB_TOOL_SPARSEWA_H
+
+//--------------------------------------------------------------------
+// PURPOSE: (see coregrind/pub_core_sparsewa.h for details)
+//--------------------------------------------------------------------
+
+/////////////////////////////////////////////////////////
+// //
+// SparseWA: Interface //
+// //
+/////////////////////////////////////////////////////////
+
+// This interface is a very cut-down version of WordFM.
+// If you understand how to use WordFM then it should be
+// trivial to use SparseWA.
+
+typedef struct _SparseWA SparseWA; /* opaque */
+
+// Create a new one, using the specified allocator/deallocator
+SparseWA* VG_(newSWA) ( void*(*alloc_nofail)(HChar* cc, SizeT),
+ HChar* cc,
+ void(*dealloc)(void*) );
+
+// Delete one, and free all associated storage
+void VG_(deleteSWA) ( SparseWA* swa );
+
+// Add the binding key -> val to this swa. Any existing binding is
+// overwritten. Returned Bool is True iff a previous binding existed.
+Bool VG_(addToSWA) ( SparseWA* swa, UWord key, UWord val );
+
+// Delete key from swa, returning associated key and val if found.
+// Note: returning associated key is stupid (it can only be the
+// key you just specified). This behaviour is retained to make it
+// easier to migrate from WordFM. Returned Bool is True iff
+// the key was actually bound in the mapping.
+Bool VG_(delFromSWA) ( SparseWA* swa,
+ /*OUT*/UWord* oldK, /*OUT*/UWord* oldV,
+ UWord key );
+
+// Indexes swa at 'key' (or, if you like, looks up 'key' in the
+// mapping), and returns the associated value, if any, in *valP. For
+// compatibility with WordFM, 'key' is also returned in *keyP. Returned
+// Bool is True iff a binding for 'key' actually existed.
+Bool VG_(lookupSWA) ( SparseWA* swa,
+ /*OUT*/UWord* keyP, /*OUT*/UWord* valP,
+ UWord key );
+
+// Set up 'swa' for iteration.
+void VG_(initIterSWA) ( SparseWA* swa );
+
+// Get the next key/val pair. Behaviour undefined (highly likely
+// to segfault) if 'swa' has been modified since initIterSWA was
+// called. Returned Bool is False iff there are no more pairs
+// that can be extracted.
+Bool VG_(nextIterSWA)( SparseWA* swa,
+ /*OUT*/UWord* keyP, /*OUT*/UWord* valP );
+
+// How many elements are there in 'swa'? NOTE: dangerous in the
+// sense that this is not an O(1) operation but rather O(N),
+// since it involves walking the whole tree.
+UWord VG_(sizeSWA) ( SparseWA* swa );
+
+#endif // __PUB_TOOL_SPARSEWA_H
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_tool_sparsewa.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_stacktrace.h.svn-base b/include/.svn/text-base/pub_tool_stacktrace.h.svn-base
new file mode 100644
index 0000000..f17758b
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_stacktrace.h.svn-base
@@ -0,0 +1,82 @@
+/*--------------------------------------------------------------------*/
+/*--- Stack traces: getting, traversing, printing. ---*/
+/*--- tool_stacktrace.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_STACKTRACE_H
+#define __PUB_TOOL_STACKTRACE_H
+
+// The basic stack trace type: just an array of code addresses.
+typedef Addr* StackTrace;
+
+// Walks the stack to get instruction pointers from the top stack frames
+// for thread 'tid'. Maximum of 'n_ips' addresses put into 'ips';
+// 0 is the top of the stack, 1 is its caller, etc. Everything from
+// ips[return_value] onwards is undefined and should not be read.
+// The initial IP value to use is adjusted by first_ip_delta before
+// the stack is unwound. A safe value to pass is zero.
+//
+// The specific meaning of the returned addresses is:
+//
+// [0] is the IP of thread 'tid'
+// [1] points to the last byte of the call instruction that called [0].
+// [2] points to the last byte of the call instruction that called [1].
+// etc etc
+//
+// Hence ips[0 .. return_value-1] should all point to currently
+// 'active' (in the sense of a stack of unfinished function calls)
+// instructions. [0] points to the start of an arbitrary instruction.#
+// [1 ..] point to the last byte of a chain of call instructions.
+//
+// If sps and fps are non-NULL, the corresponding frame-pointer and
+// stack-pointer values for each frame are stored there.
+
+extern UInt VG_(get_StackTrace) ( ThreadId tid,
+ /*OUT*/StackTrace ips, UInt n_ips,
+ /*OUT*/StackTrace sps,
+ /*OUT*/StackTrace fps,
+ Word first_ip_delta );
+
+// Apply a function to every element in the StackTrace. The parameter 'n'
+// gives the index of the passed ip. Doesn't go below main() unless
+// --show-below-main=yes is set.
+extern void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip),
+ StackTrace ips, UInt n_ips );
+
+// Print a StackTrace.
+extern void VG_(pp_StackTrace) ( StackTrace ips, UInt n_ips );
+
+// Gets and immediately prints a StackTrace. Just a bit simpler than
+// calling VG_(get_StackTrace)() then VG_(pp_StackTrace)().
+extern void VG_(get_and_pp_StackTrace) ( ThreadId tid, UInt n_ips );
+
+#endif // __PUB_TOOL_STACKTRACE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_threadstate.h.svn-base b/include/.svn/text-base/pub_tool_threadstate.h.svn-base
new file mode 100644
index 0000000..d572e87
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_threadstate.h.svn-base
@@ -0,0 +1,53 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The thread state. pub_tool_threadstate.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_THREADSTATE_H
+#define __PUB_TOOL_THREADSTATE_H
+
+/* The maximum number of pthreads that we support. This is
+ deliberately not very high since our implementation of some of the
+ scheduler algorithms is surely O(N) in the number of threads, since
+ that's simple, at least. And (in practice) we hope that most
+ programs do not need many threads. */
+#define VG_N_THREADS 300
+
+/* Special magic value for an invalid ThreadId. It corresponds to
+ LinuxThreads using zero as the initial value for
+ pthread_mutex_t.__m_owner and pthread_cond_t.__c_waiting. */
+#define VG_INVALID_THREADID ((ThreadId)(0))
+
+/* Get the TID of the thread which currently has the CPU. */
+extern ThreadId VG_(get_running_tid) ( void );
+
+#endif // __PUB_TOOL_THREADSTATE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_tooliface.h.svn-base b/include/.svn/text-base/pub_tool_tooliface.h.svn-base
new file mode 100644
index 0000000..3a7c391
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_tooliface.h.svn-base
@@ -0,0 +1,643 @@
+
+/*--------------------------------------------------------------------*/
+/*--- The core/tool interface. pub_tool_tooliface.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_TOOLIFACE_H
+#define __PUB_TOOL_TOOLIFACE_H
+
+#include "pub_tool_errormgr.h" // for Error, Supp
+#include "libvex.h" // for all Vex stuff
+
+/* ------------------------------------------------------------------ */
+/* The interface version */
+
+/* Initialise tool. Must do the following:
+ - initialise the `details' struct, via the VG_(details_*)() functions
+ - register the basic tool functions, via VG_(basic_tool_funcs)().
+ May do the following:
+ - initialise the `needs' struct to indicate certain requirements, via
+ the VG_(needs_*)() functions
+ - any other tool-specific initialisation
+*/
+extern void (*VG_(tl_pre_clo_init)) ( void );
+
+/* Every tool must include this macro somewhere, exactly once. The
+ interface version is no longer relevant, but we kept the same name
+ to avoid requiring changes to tools.
+*/
+#define VG_DETERMINE_INTERFACE_VERSION(pre_clo_init) \
+ void (*VG_(tl_pre_clo_init)) ( void ) = pre_clo_init;
+
+/* ------------------------------------------------------------------ */
+/* Basic tool functions */
+
+/* The tool_instrument function is passed as a callback to
+ LibVEX_Translate. VgCallbackClosure carries additional info
+ which the instrumenter might like to know, but which is opaque to
+ Vex.
+*/
+typedef
+ struct {
+ Addr64 nraddr; /* non-redirected guest address */
+ Addr64 readdr; /* redirected guest address */
+ ThreadId tid; /* tid requesting translation */
+ }
+ VgCallbackClosure;
+
+extern void VG_(basic_tool_funcs)(
+ // Do any initialisation that can only be done after command line
+ // processing.
+ void (*post_clo_init)(void),
+
+ // Instrument a basic block. Must be a true function, ie. the same
+ // input always results in the same output, because basic blocks
+ // can be retranslated, unless you're doing something really
+ // strange. Anyway, the arguments. Mostly they are straightforward
+ // except for the distinction between redirected and non-redirected
+ // guest code addresses, which is important to understand.
+ //
+ // VgCallBackClosure* closure contains extra arguments passed
+ // from Valgrind to the instrumenter, which Vex doesn't know about.
+ // You are free to look inside this structure.
+ //
+ // * closure->tid is the ThreadId of the thread requesting the
+ // translation. Not sure why this is here; perhaps callgrind
+ // uses it.
+ //
+ // * closure->nraddr is the non-redirected guest address of the
+ // start of the translation. In other words, the translation is
+ // being constructed because the guest program jumped to
+ // closure->nraddr but no translation of it was found.
+ //
+ // * closure->readdr is the redirected guest address, from which
+ // the translation was really made.
+ //
+ // To clarify this, consider what happens when, in Memcheck, the
+ // first call to malloc() happens. The guest program will be
+ // trying to jump to malloc() in libc; hence ->nraddr will contain
+ // that address. However, Memcheck intercepts and replaces
+ // malloc, hence ->readdr will be the address of Memcheck's
+ // malloc replacement in
+ // coregrind/m_replacemalloc/vg_replacemalloc.c. It follows
+ // that the first IMark in the translation will be labelled as
+ // from ->readdr rather than ->nraddr.
+ //
+ // Since most functions are not redirected, the majority of the
+ // time ->nraddr will be the same as ->readdr. However, you
+ // cannot assume this: if your tool has metadata associated
+ // with code addresses it will get into deep trouble if it does
+ // make this assumption.
+ //
+ // IRSB* sb_in is the incoming superblock to be instrumented,
+ // in flat IR form.
+ //
+ // VexGuestLayout* layout contains limited info on the layout of
+ // the guest state: where the stack pointer and program counter
+ // are, and which fields should be regarded as 'always defined'.
+ // Memcheck uses this.
+ //
+ // VexGuestExtents* vge points to a structure which states the
+ // precise byte ranges of original code from which this translation
+ // was made (there may be up to three different ranges involved).
+ // Note again that these are the real addresses from which the code
+ // came. And so it should be the case that closure->readdr is the
+ // same as vge->base[0]; indeed Cachegrind contains this assertion.
+ //
+ // Tools which associate shadow data with code addresses
+ // (cachegrind, callgrind) need to be particularly clear about
+ // whether they are making the association with redirected or
+ // non-redirected code addresses. Both approaches are viable
+ // but you do need to understand what's going on. See comments
+ // below on discard_basic_block_info().
+ //
+ // IRType gWordTy and IRType hWordTy contain the types of native
+ // words on the guest (simulated) and host (real) CPUs. They will
+ // by either Ity_I32 or Ity_I64. So far we have never built a
+ // cross-architecture Valgrind so they should always be the same.
+ //
+ /* --- Further comments about the IR that your --- */
+ /* --- instrumentation function will receive. --- */
+ /*
+ In the incoming IRSB, the IR for each instruction begins with an
+ IRStmt_IMark, which states the address and length of the
+ instruction from which this IR came. This makes it easy for
+ profiling-style tools to know precisely which guest code
+ addresses are being executed.
+
+ However, before the first IRStmt_IMark, there may be other IR
+ statements -- a preamble. In most cases this preamble is empty,
+ but when it isn't, what it contains is some supporting IR that
+ the JIT uses to ensure control flow works correctly. This
+ preamble does not modify any architecturally defined guest state
+ (registers or memory) and so does not contain anything that will
+ be of interest to your tool.
+
+ You should therefore
+
+ (1) copy any IR preceding the first IMark verbatim to the start
+ of the output IRSB.
+
+ (2) not try to instrument it or modify it in any way.
+
+ For the record, stuff that may be in the preamble at
+ present is:
+
+ - A self-modifying-code check has been requested for this block.
+ The preamble will contain instructions to checksum the block,
+ compare against the expected value, and exit the dispatcher
+ requesting a discard (hence forcing a retranslation) if they
+ don't match.
+
+ - This block is known to be the entry point of a wrapper of some
+ function F. In this case the preamble contains code to write
+ the address of the original F (the fn being wrapped) into a
+ 'hidden' guest state register _NRADDR. The wrapper can later
+ read this register using a client request and make a
+ non-redirected call to it using another client-request-like
+ magic macro.
+
+ - For platforms that use the AIX ABI (including ppc64-linux), it
+ is necessary to have a preamble even for replacement functions
+ (not just for wrappers), because it is necessary to switch the
+ R2 register (constant-pool pointer) to a different value when
+ swizzling the program counter.
+
+ Hence the preamble pushes both R2 and LR (the return address)
+ on a small 16-entry stack in the guest state and sets R2 to an
+ appropriate value for the wrapper/replacement fn. LR is then
+ set so that the wrapper/replacement fn returns to a magic IR
+ stub which restores R2 and LR and returns.
+
+ It's all hugely ugly and fragile. And it places a stringent
+ requirement on m_debuginfo to find out the correct R2 (toc
+ pointer) value for the wrapper/replacement function. So much
+ so that m_redir will refuse to honour a redirect-to-me request
+ if it cannot find (by asking m_debuginfo) a plausible R2 value
+ for 'me'.
+
+ Because this mechanism maintains a shadow stack of (R2,LR)
+ pairs in the guest state, it will fail if the
+ wrapper/redirection function, or anything it calls, longjumps
+ out past the wrapper, because then the magic return stub will
+ not be run and so the shadow stack will not be popped. So it
+ will quickly fill up. Fortunately none of this applies to
+ {x86,amd64,ppc32}-linux; on those platforms, wrappers can
+ longjump and recurse arbitrarily and everything should work
+ fine.
+
+ Note that copying the preamble verbatim may cause complications
+ for your instrumenter if you shadow IR temporaries. See big
+ comment in MC_(instrument) in memcheck/mc_translate.c for
+ details.
+ */
+ IRSB*(*instrument)(VgCallbackClosure* closure,
+ IRSB* sb_in,
+ VexGuestLayout* layout,
+ VexGuestExtents* vge,
+ IRType gWordTy,
+ IRType hWordTy),
+
+ // Finish up, print out any results, etc. `exitcode' is program's exit
+ // code. The shadow can be found with VG_(get_exit_status_shadow)().
+ void (*fini)(Int)
+);
+
+/* ------------------------------------------------------------------ */
+/* Details */
+
+/* Default value for avg_translations_sizeB (in bytes), indicating typical
+ code expansion of about 6:1. */
+#define VG_DEFAULT_TRANS_SIZEB 172
+
+/* Information used in the startup message. `name' also determines the
+ string used for identifying suppressions in a suppression file as
+ belonging to this tool. `version' can be NULL, in which case (not
+ surprisingly) no version info is printed; this mechanism is designed for
+ tools distributed with Valgrind that share a version number with
+ Valgrind. Other tools not distributed as part of Valgrind should
+ probably have their own version number. */
+extern void VG_(details_name) ( Char* name );
+extern void VG_(details_version) ( Char* version );
+extern void VG_(details_description) ( Char* description );
+extern void VG_(details_copyright_author) ( Char* copyright_author );
+
+/* Average size of a translation, in bytes, so that the translation
+ storage machinery can allocate memory appropriately. Not critical,
+ setting is optional. */
+extern void VG_(details_avg_translation_sizeB) ( UInt size );
+
+/* String printed if an `tl_assert' assertion fails or VG_(tool_panic)
+ is called. Should probably be an email address. */
+extern void VG_(details_bug_reports_to) ( Char* bug_reports_to );
+
+/* ------------------------------------------------------------------ */
+/* Needs */
+
+/* Should __libc_freeres() be run? Bugs in it can crash the tool. */
+extern void VG_(needs_libc_freeres) ( void );
+
+/* Want to have errors detected by Valgrind's core reported? Includes:
+ - pthread API errors (many; eg. unlocking a non-locked mutex)
+ [currently disabled]
+ - invalid file descriptors to syscalls like read() and write()
+ - bad signal numbers passed to sigaction()
+ - attempt to install signal handler for SIGKILL or SIGSTOP */
+extern void VG_(needs_core_errors) ( void );
+
+/* Booleans that indicate extra operations are defined; if these are True,
+ the corresponding template functions (given below) must be defined. A
+ lot like being a member of a type class. */
+
+/* Want to report errors from tool? This implies use of suppressions, too. */
+extern void VG_(needs_tool_errors) (
+ // Identify if two errors are equal, or equal enough. `res' indicates how
+ // close is "close enough". `res' should be passed on as necessary, eg. if
+ // the Error's `extra' part contains an ExeContext, `res' should be
+ // passed to VG_(eq_ExeContext)() if the ExeContexts are considered. Other
+ // than that, probably don't worry about it unless you have lots of very
+ // similar errors occurring.
+ Bool (*eq_Error)(VgRes res, Error* e1, Error* e2),
+
+ // Print error context.
+ void (*pp_Error)(Error* err),
+
+ // Should the core indicate which ThreadId each error comes from?
+ Bool show_ThreadIDs_for_errors,
+
+ // Should fill in any details that could be postponed until after the
+ // decision whether to ignore the error (ie. details not affecting the
+ // result of VG_(tdict).tool_eq_Error()). This saves time when errors
+ // are ignored.
+ // Yuk.
+ // Return value: must be the size of the `extra' part in bytes -- used by
+ // the core to make a copy.
+ UInt (*update_extra)(Error* err),
+
+ // Return value indicates recognition. If recognised, must set skind using
+ // VG_(set_supp_kind)().
+ Bool (*recognised_suppression)(Char* name, Supp* su),
+
+ // Read any extra info for this suppression kind. Most likely for filling
+ // in the `extra' and `string' parts (with VG_(set_supp_{extra, string})())
+ // of a suppression if necessary. Should return False if a syntax error
+ // occurred, True otherwise.
+ Bool (*read_extra_suppression_info)(Int fd, Char* buf, Int nBuf, Supp* su),
+
+ // This should just check the kinds match and maybe some stuff in the
+ // `string' and `extra' field if appropriate (using VG_(get_supp_*)() to
+ // get the relevant suppression parts).
+ Bool (*error_matches_suppression)(Error* err, Supp* su),
+
+ // This should return the suppression name, for --gen-suppressions, or NULL
+ // if that error type cannot be suppressed. This is the inverse of
+ // VG_(tdict).tool_recognised_suppression().
+ Char* (*get_error_name)(Error* err),
+
+ // This should print any extra info for the error, for --gen-suppressions,
+ // including the newline. This is the inverse of
+ // VG_(tdict).tool_read_extra_suppression_info().
+ void (*print_extra_suppression_info)(Error* err)
+);
+
+/* Is information kept by the tool about specific instructions or
+ translations? (Eg. for cachegrind there are cost-centres for every
+ instruction, stored in a per-translation fashion.) If so, the info
+ may have to be discarded when translations are unloaded (eg. due to
+ .so unloading, or otherwise at the discretion of m_transtab, eg
+ when the table becomes too full) to avoid stale information being
+ reused for new translations. */
+extern void VG_(needs_superblock_discards) (
+ // Discard any information that pertains to specific translations
+ // or instructions within the address range given. There are two
+ // possible approaches.
+ // - If info is being stored at a per-translation level, use orig_addr
+ // to identify which translation is being discarded. Each translation
+ // will be discarded exactly once.
+ // This orig_addr will match the closure->nraddr which was passed to
+ // to instrument() (see extensive comments above) when this
+ // translation was made. Note that orig_addr won't necessarily be
+ // the same as the first address in "extents".
+ // - If info is being stored at a per-instruction level, you can get
+ // the address range(s) being discarded by stepping through "extents".
+ // Note that any single instruction may belong to more than one
+ // translation, and so could be covered by the "extents" of more than
+ // one call to this function.
+ // Doing it the first way (as eg. Cachegrind does) is probably easier.
+ void (*discard_superblock_info)(Addr64 orig_addr, VexGuestExtents extents)
+);
+
+/* Tool defines its own command line options? */
+extern void VG_(needs_command_line_options) (
+ // Return True if option was recognised. Presumably sets some state to
+ // record the option as well. Nb: tools can assume that the argv will
+ // never disappear. So they can, for example, store a pointer to a string
+ // within an option, rather than having to make a copy.
+ Bool (*process_cmd_line_option)(Char* argv),
+
+ // Print out command line usage for options for normal tool operation.
+ void (*print_usage)(void),
+
+ // Print out command line usage for options for debugging the tool.
+ void (*print_debug_usage)(void)
+);
+
+/* Tool defines its own client requests? */
+extern void VG_(needs_client_requests) (
+ // If using client requests, the number of the first request should be equal
+ // to VG_USERREQ_TOOL_BASE('X', 'Y'), where 'X' and 'Y' form a suitable two
+ // character identification for the string. The second and subsequent
+ // requests should follow.
+ //
+ // This function should use the VG_IS_TOOL_USERREQ macro (in
+ // include/valgrind.h) to first check if it's a request for this tool. Then
+ // should handle it if it's recognised (and return True), or return False if
+ // not recognised. arg_block[0] holds the request number, any further args
+ // from the request are in arg_block[1..]. 'ret' is for the return value...
+ // it should probably be filled, if only with 0.
+ Bool (*handle_client_request)(ThreadId tid, UWord* arg_block, UWord* ret)
+);
+
+/* Tool does stuff before and/or after system calls? */
+// Nb: If either of the pre_ functions malloc() something to return, the
+// corresponding post_ function had better free() it!
+extern void VG_(needs_syscall_wrapper) (
+ void (* pre_syscall)(ThreadId tid, UInt syscallno),
+ void (*post_syscall)(ThreadId tid, UInt syscallno, SysRes res)
+);
+
+/* Are tool-state sanity checks performed? */
+// Can be useful for ensuring a tool's correctness. cheap_sanity_check()
+// is called very frequently; expensive_sanity_check() is called less
+// frequently and can be more involved.
+extern void VG_(needs_sanity_checks) (
+ Bool(*cheap_sanity_check)(void),
+ Bool(*expensive_sanity_check)(void)
+);
+
+/* Do we need to see variable type and location information? */
+extern void VG_(needs_var_info) ( void );
+
+/* Does the tool replace malloc() and friends with its own versions?
+ This has to be combined with the use of a vgpreload_<tool>.so module
+ or it won't work. See massif/Makefile.am for how to build it. */
+// The 'p' prefix avoids GCC complaints about overshadowing global names.
+extern void VG_(needs_malloc_replacement)(
+ void* (*pmalloc) ( ThreadId tid, SizeT n ),
+ void* (*p__builtin_new) ( ThreadId tid, SizeT n ),
+ void* (*p__builtin_vec_new) ( ThreadId tid, SizeT n ),
+ void* (*pmemalign) ( ThreadId tid, SizeT align, SizeT n ),
+ void* (*pcalloc) ( ThreadId tid, SizeT nmemb, SizeT size1 ),
+ void (*pfree) ( ThreadId tid, void* p ),
+ void (*p__builtin_delete) ( ThreadId tid, void* p ),
+ void (*p__builtin_vec_delete) ( ThreadId tid, void* p ),
+ void* (*prealloc) ( ThreadId tid, void* p, SizeT new_size ),
+ SizeT (*pmalloc_usable_size) ( ThreadId tid, void* p),
+ SizeT client_malloc_redzone_szB
+);
+
+/* Can the tool do XML output? This is a slight misnomer, because the tool
+ * is not requesting the core to do anything, rather saying "I can handle
+ * it". */
+extern void VG_(needs_xml_output)( void );
+
+/* Does the tool want to have one final pass over the IR after tree
+ building but before instruction selection? If so specify the
+ function here. */
+extern void VG_(needs_final_IR_tidy_pass) ( IRSB*(*final_tidy)(IRSB*) );
+
+
+/* ------------------------------------------------------------------ */
+/* Core events to track */
+
+/* Part of the core from which this call was made. Useful for determining
+ what kind of error message should be emitted. */
+typedef
+ enum { Vg_CoreStartup=1, Vg_CoreSignal, Vg_CoreSysCall,
+ Vg_CoreTranslate, Vg_CoreClientReq }
+ CorePart;
+
+/* Events happening in core to track. To be notified, pass a callback
+ function to the appropriate function. To ignore an event, don't do
+ anything (the default is for events to be ignored).
+
+ Note that most events aren't passed a ThreadId. If the event is one called
+ from generated code (eg. new_mem_stack_*), you can use
+ VG_(get_running_tid)() to find it. Otherwise, it has to be passed in,
+ as in pre_mem_read, and so the event signature will require changing.
+
+ Memory events (Nb: to track heap allocation/freeing, a tool must replace
+ malloc() et al. See above how to do this.)
+
+ These ones occur at startup, upon some signals, and upon some syscalls.
+
+ For new_mem_brk and new_mem_stack_signal, the supplied ThreadId
+ indicates the thread for whom the new memory is being allocated.
+
+ For new_mem_startup and new_mem_mmap, the di_handle argument is a
+ handle which can be used to retrieve debug info associated with the
+ mapping or allocation (because it is of a file that Valgrind has
+ decided to read debug info from). If the value is zero, there is
+ no associated debug info. If the value exceeds zero, it can be
+ supplied as an argument to selected queries in m_debuginfo.
+*/
+void VG_(track_new_mem_startup) (void(*f)(Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx,
+ ULong di_handle));
+void VG_(track_new_mem_stack_signal)(void(*f)(Addr a, SizeT len, ThreadId tid));
+void VG_(track_new_mem_brk) (void(*f)(Addr a, SizeT len, ThreadId tid));
+void VG_(track_new_mem_mmap) (void(*f)(Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx,
+ ULong di_handle));
+
+void VG_(track_copy_mem_remap) (void(*f)(Addr from, Addr to, SizeT len));
+void VG_(track_change_mem_mprotect) (void(*f)(Addr a, SizeT len,
+ Bool rr, Bool ww, Bool xx));
+void VG_(track_die_mem_stack_signal)(void(*f)(Addr a, SizeT len));
+void VG_(track_die_mem_brk) (void(*f)(Addr a, SizeT len));
+void VG_(track_die_mem_munmap) (void(*f)(Addr a, SizeT len));
+
+/* These ones are called when SP changes. A tool could track these itself
+ (except for ban_mem_stack) but it's much easier to use the core's help.
+
+ The specialised ones are called in preference to the general one, if they
+ are defined. These functions are called a lot if they are used, so
+ specialising can optimise things significantly. If any of the
+ specialised cases are defined, the general case must be defined too.
+
+ Nb: all the specialised ones must use the VG_REGPARM(n) attribute.
+
+ For the _new functions, a tool may specify with with-ECU
+ (ExeContext Unique) or without-ECU version for each size, but not
+ both. If the with-ECU version is supplied, then the core will
+ arrange to pass, as the ecu argument, a 32-bit int which uniquely
+ identifies the instruction moving the stack pointer down. This
+ 32-bit value is as obtained from VG_(get_ECU_from_ExeContext).
+ VG_(get_ExeContext_from_ECU) can then be used to retrieve the
+ associated depth-1 ExeContext for the location. All this
+ complexity is provided to support origin tracking in Memcheck.
+*/
+void VG_(track_new_mem_stack_4_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_8_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_12_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_16_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_32_w_ECU) (VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_112_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_128_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_144_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_160_w_ECU)(VG_REGPARM(2) void(*f)(Addr new_ESP, UInt ecu));
+void VG_(track_new_mem_stack_w_ECU) (void(*f)(Addr a, SizeT len,
+ UInt ecu));
+
+void VG_(track_new_mem_stack_4) (VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_8) (VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_12) (VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_16) (VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_32) (VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_112)(VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_128)(VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_144)(VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack_160)(VG_REGPARM(1) void(*f)(Addr new_ESP));
+void VG_(track_new_mem_stack) (void(*f)(Addr a, SizeT len));
+
+void VG_(track_die_mem_stack_4) (VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_8) (VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_12) (VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_16) (VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_32) (VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_112)(VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_128)(VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_144)(VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack_160)(VG_REGPARM(1) void(*f)(Addr die_ESP));
+void VG_(track_die_mem_stack) (void(*f)(Addr a, SizeT len));
+
+/* Used for redzone at end of thread stacks */
+void VG_(track_ban_mem_stack) (void(*f)(Addr a, SizeT len));
+
+/* These ones occur around syscalls, signal handling, etc */
+void VG_(track_pre_mem_read) (void(*f)(CorePart part, ThreadId tid,
+ Char* s, Addr a, SizeT size));
+void VG_(track_pre_mem_read_asciiz)(void(*f)(CorePart part, ThreadId tid,
+ Char* s, Addr a));
+void VG_(track_pre_mem_write) (void(*f)(CorePart part, ThreadId tid,
+ Char* s, Addr a, SizeT size));
+void VG_(track_post_mem_write) (void(*f)(CorePart part, ThreadId tid,
+ Addr a, SizeT size));
+
+/* Register events. Use VG_(set_shadow_state_area)() to set the shadow regs
+ for these events. */
+void VG_(track_pre_reg_read) (void(*f)(CorePart part, ThreadId tid,
+ Char* s, PtrdiffT guest_state_offset,
+ SizeT size));
+void VG_(track_post_reg_write)(void(*f)(CorePart part, ThreadId tid,
+ PtrdiffT guest_state_offset,
+ SizeT size));
+
+/* This one is called for malloc() et al if they are replaced by a tool. */
+void VG_(track_post_reg_write_clientcall_return)(
+ void(*f)(ThreadId tid, PtrdiffT guest_state_offset, SizeT size, Addr f));
+
+
+/* Scheduler events (not exhaustive) */
+
+/* Called when 'tid' starts or stops running client code blocks.
+ Gives the total dispatched block count at that event. Note, this
+ is not the same as 'tid' holding the BigLock (the lock that ensures
+ that only one thread runs at a time): a thread can hold the lock
+ for other purposes (making translations, etc) yet not be running
+ client blocks. Obviously though, a thread must hold the lock in
+ order to run client code blocks, so the times bracketed by
+ 'start_client_code'..'stop_client_code' are a subset of the times
+ when thread 'tid' holds the cpu lock.
+*/
+void VG_(track_start_client_code)(
+ void(*f)(ThreadId tid, ULong blocks_dispatched)
+ );
+void VG_(track_stop_client_code)(
+ void(*f)(ThreadId tid, ULong blocks_dispatched)
+ );
+
+
+/* Thread events (not exhaustive)
+
+ ll_create: low level thread creation. Called before the new thread
+ has run any instructions (or touched any memory). In fact, called
+ immediately before the new thread has come into existence; the new
+ thread can be assumed to exist when notified by this call.
+
+ ll_exit: low level thread exit. Called after the exiting thread
+ has run its last instruction.
+
+ The _ll_ part makes it clear these events are not to do with
+ pthread_create or pthread_exit/pthread_join (etc), which are a
+ higher level abstraction synthesised by libpthread. What you can
+ be sure of from _ll_create/_ll_exit is the absolute limits of each
+ thread's lifetime, and hence be assured that all memory references
+ made by the thread fall inside the _ll_create/_ll_exit pair. This
+ is important for tools that need a 100% accurate account of which
+ thread is responsible for every memory reference in the process.
+
+ pthread_create/join/exit do not give this property. Calls/returns
+ to/from them happen arbitrarily far away from the relevant
+ low-level thread create/quit event. In general a few hundred
+ instructions; hence a few hundred(ish) memory references could get
+ misclassified each time.
+
+ pre_thread_first_insn: is called when the thread is all set up and
+ ready to go (stack in place, etc) but has not executed its first
+ instruction yet. Gives threading tools a chance to ask questions
+ about the thread (eg, what is its initial client stack pointer)
+ that are not easily answered at pre_thread_ll_create time.
+
+ For a given thread, the call sequence is:
+ ll_create (in the parent's context)
+ first_insn (in the child's context)
+ ll_exit (in the child's context)
+*/
+void VG_(track_pre_thread_ll_create) (void(*f)(ThreadId tid, ThreadId child));
+void VG_(track_pre_thread_first_insn)(void(*f)(ThreadId tid));
+void VG_(track_pre_thread_ll_exit) (void(*f)(ThreadId tid));
+
+
+/* Signal events (not exhaustive)
+
+ ... pre_send_signal, post_send_signal ...
+
+ Called before a signal is delivered; `alt_stack' indicates if it is
+ delivered on an alternative stack. */
+void VG_(track_pre_deliver_signal) (void(*f)(ThreadId tid, Int sigNo,
+ Bool alt_stack));
+/* Called after a signal is delivered. Nb: unfortunately, if the signal
+ handler longjmps, this won't be called. */
+void VG_(track_post_deliver_signal)(void(*f)(ThreadId tid, Int sigNo));
+
+#endif // __PUB_TOOL_TOOLIFACE_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_vki.h.svn-base b/include/.svn/text-base/pub_tool_vki.h.svn-base
new file mode 100644
index 0000000..75da646
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_vki.h.svn-base
@@ -0,0 +1,62 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Top level for kernel interface declarations. ---*/
+/*--- pub_tool_vki.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward
+ jseward@acm.org
+ Copyright (C) 2005-2009 Nicholas Nethercote
+ njn@valgrind.org
+ Copyright (C) 2006-2009 OpenWorks LLP
+ info@open-works.co.uk
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* This file defines types and constants for the kernel interface, and to
+ make that clear everything is prefixed VKI_/vki_.
+
+ This file is merely a top-level "steering" file, which pulls in the
+ correct bits for the relevant platform. You should not directly
+ #include any file in include/vki; instead #include only this one or
+ pub_core_vki.h.
+*/
+
+#ifndef __PUB_TOOL_VKI_H
+#define __PUB_TOOL_VKI_H
+
+#if defined(VGO_linux)
+# include "vki/vki-linux.h"
+#elif defined(VGP_ppc32_aix5)
+# include "vki/vki-ppc32-aix5.h"
+#elif defined(VGP_ppc64_aix5)
+# include "vki/vki-ppc64-aix5.h"
+#else
+# error Unknown Plat/OS
+#endif
+
+#endif // __PUB_TOOL_VKI_H
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_tool_vki.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_vkiscnums.h.svn-base b/include/.svn/text-base/pub_tool_vkiscnums.h.svn-base
new file mode 100644
index 0000000..147a761
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_vkiscnums.h.svn-base
@@ -0,0 +1,88 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Top level for kernel interface system call numbers. ---*/
+/*--- pub_tool_vkiscnums.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2005-2009 Nicholas Nethercote
+ njn@valgrind.org
+ Copyright (C) 2006-2009 OpenWorks LLP
+ info@open-works.co.uk
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* This file defines the system call numbers.
+
+ On Linux they are a bunch of #define'd constants of the form
+ __NR_name, and this file must contain nothing else, since it will
+ be included in assembly code (m_trampoline.S).
+
+ On AIX the __NR_name consts are renamings of global variables which
+ tell us the number for each syscall. This elaboration is necessary
+ because on AIX the syscall numbers are not constant; they can be
+ different for each process (in principle; in practice they rarely
+ change). 32- and 64-bit AIX5 share a common "implementation".
+
+ This file is merely a top-level "steering" file, which pulls in the
+ correct bits for the relevant platform. You should not directly
+ #include any file in include/vki; instead #include only this one or
+ pub_core_vkiscnums.h.
+*/
+
+#ifndef __PUB_TOOL_VKISCNUMS_H
+#define __PUB_TOOL_VKISCNUMS_H
+
+#if defined(VGP_x86_linux)
+# include "vki/vki-scnums-x86-linux.h"
+
+#elif defined(VGP_amd64_linux)
+# include "vki/vki-scnums-amd64-linux.h"
+
+#elif defined(VGP_ppc32_linux)
+# include "vki/vki-scnums-ppc32-linux.h"
+
+#elif defined(VGP_ppc64_linux)
+# include "vki/vki-scnums-ppc64-linux.h"
+
+#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+# include "vki/vki-scnums-aix5.h"
+
+/* Make it possible to include this file in assembly sources. */
+#if !defined(VG_IN_ASSEMBLY_SOURCE)
+
+/* Look up the name of a syscall, using the bindings previously
+ created by VG_(aix5_register_syscall), for the purposes of making
+ error messages. */
+extern UChar* VG_(aix5_sysno_to_sysname)( Int sysno );
+
+#endif /* !defined(VG_IN_ASSEMBLY_SOURCE) */
+
+#else
+# error Unknown platform
+#endif
+
+#endif // __PUB_TOOL_VKISCNUMS_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_wordfm.h.svn-base b/include/.svn/text-base/pub_tool_wordfm.h.svn-base
new file mode 100644
index 0000000..57c57db
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_wordfm.h.svn-base
@@ -0,0 +1,220 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An AVL tree based finite map for word keys and word values. ---*/
+/*--- Inspired by Haskell's "FiniteMap" library. ---*/
+/*--- pub_tool_wordfm.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2007-2009 Julian Seward
+ jseward@acm.org
+
+ This code is based on previous work by Nicholas Nethercote
+ (coregrind/m_oset.c) which is
+
+ Copyright (C) 2005-2009 Nicholas Nethercote
+ njn@valgrind.org
+
+ which in turn was derived partially from:
+
+ AVL C library
+ Copyright (C) 2000,2002 Daniel Nagy
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of
+ the License, or (at your option) any later version.
+ [...]
+
+ (taken from libavl-0.4/debian/copyright)
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_WORDFM_H
+#define __PUB_TOOL_WORDFM_H
+
+//------------------------------------------------------------------//
+//--- WordFM ---//
+//--- Public interface ---//
+//------------------------------------------------------------------//
+
+/* As of r7409 (15 Feb 08), all these word-based abstractions (WordFM,
+ WordSet, WordBag) now operate on unsigned words (UWord), whereas
+ they previously operated on signed words (Word). This became a
+ problem, when using unboxed comparisons (when kCmp == NULL), with
+ the introduction of VG_(initIterAtFM), which allows iteration over
+ parts of mappings. Iterating over a mapping in increasing order of
+ signed Word keys is not what callers expect when iterating through
+ maps whose keys represent addresses (Addr) since Addr is unsigned,
+ and causes logical problems and assertion failures. */
+
+typedef struct _WordFM WordFM; /* opaque */
+
+/* Allocate and initialise a WordFM. If kCmp is non-NULL, elements in
+ the set are ordered according to the ordering specified by kCmp,
+ which becomes obvious if you use VG_(initIterFM),
+ VG_(initIterAtFM), VG_(nextIterFM), VG_(doneIterFM) to iterate over
+ sections of the map, or the whole thing. If kCmp is NULL then the
+ ordering used is unsigned word ordering (UWord) on the key
+ values. */
+WordFM* VG_(newFM) ( void* (*alloc_nofail)( HChar* cc, SizeT ),
+ HChar* cc,
+ void (*dealloc)(void*),
+ Word (*kCmp)(UWord,UWord) );
+
+/* Free up the FM. If kFin is non-NULL, it is applied to keys
+ before the FM is deleted; ditto with vFin for vals. */
+void VG_(deleteFM) ( WordFM*, void(*kFin)(UWord), void(*vFin)(UWord) );
+
+/* Add (k,v) to fm. If a binding for k already exists, it is updated
+ to map to this new v. In that case we should really return the
+ previous v so that caller can finalise it. Oh well. Returns
+ True if a binding for k already exists. */
+Bool VG_(addToFM) ( WordFM* fm, UWord k, UWord v );
+
+// Delete key from fm, returning associated key and val if found
+Bool VG_(delFromFM) ( WordFM* fm,
+ /*OUT*/UWord* oldK, /*OUT*/UWord* oldV, UWord key );
+
+// Look up in fm, assigning found key & val at spec'd addresses
+Bool VG_(lookupFM) ( WordFM* fm,
+ /*OUT*/UWord* keyP, /*OUT*/UWord* valP, UWord key );
+
+// Find the closest key values bracketing the given key, assuming the
+// given key is not present in the map. minKey and maxKey are the
+// minimum and maximum possible key values. The resulting bracket
+// values are returned in *kMinP and *kMaxP. It follows that if fm is
+// empty then the returned values are simply minKey and maxKey.
+//
+// For convenience the associated value fields are also returned
+// through *vMinP and *vMaxP. To make that possible in the general
+// case, the caller must supply via minVal and maxVal, the value
+// fields associated with minKey and maxKey.
+//
+// If the operation was successful (that is, the given key is not
+// present), True is returned. If the given key is in fact present,
+// False is returned, and *kMinP, *vMinP, *kMaxP and *vMaxP are
+// undefined. Any of kMinP, vMinP, kMaxP and vMaxP may be safely
+// supplied as NULL.
+Bool VG_(findBoundsFM)( WordFM* fm,
+ /*OUT*/UWord* kMinP, /*OUT*/UWord* vMinP,
+ /*OUT*/UWord* kMaxP, /*OUT*/UWord* vMaxP,
+ UWord minKey, UWord minVal,
+ UWord maxKey, UWord maxVal,
+ UWord key );
+
+// How many elements are there in fm? NOTE: dangerous in the
+// sense that this is not an O(1) operation but rather O(N),
+// since it involves walking the whole tree.
+UWord VG_(sizeFM) ( WordFM* fm );
+
+// Is fm empty? This at least is an O(1) operation.
+// Code is present in m_wordfm.c but commented out due to no
+// current usage. Un-comment (and TEST IT) if required.
+//Bool VG_(isEmptyFM)( WordFM* fm );
+
+// set up FM for iteration
+void VG_(initIterFM) ( WordFM* fm );
+
+// set up FM for iteration so that the first key subsequently produced
+// by VG_(nextIterFM) is the smallest key in the map >= start_at.
+// Naturally ">=" is defined by the comparison function supplied to
+// VG_(newFM), as documented above.
+void VG_(initIterAtFM) ( WordFM* fm, UWord start_at );
+
+// get next key/val pair. Will assert if fm has been modified
+// or looked up in since initIterFM/initIterWithStartFM was called.
+Bool VG_(nextIterFM) ( WordFM* fm,
+ /*OUT*/UWord* pKey, /*OUT*/UWord* pVal );
+
+// clear the I'm iterating flag
+void VG_(doneIterFM) ( WordFM* fm );
+
+// Deep copy a FM. If dopyK is NULL, keys are copied verbatim.
+// If non-null, dopyK is applied to each key to generate the
+// version in the new copy. In that case, if the argument to dopyK
+// is non-NULL but the result is NULL, it is assumed that dopyK
+// could not allocate memory, in which case the copy is abandoned
+// and NULL is returned. Ditto with dopyV for values.
+WordFM* VG_(dopyFM) ( WordFM* fm,
+ UWord(*dopyK)(UWord), UWord(*dopyV)(UWord) );
+
+// admin: what's the 'common' allocation size (for tree nodes?)
+SizeT VG_(getNodeSizeFM)( void );
+
+//------------------------------------------------------------------//
+//--- end WordFM ---//
+//--- Public interface ---//
+//------------------------------------------------------------------//
+
+//------------------------------------------------------------------//
+//--- WordBag (unboxed words only) ---//
+//--- Public interface ---//
+//------------------------------------------------------------------//
+
+typedef struct _WordBag WordBag; /* opaque */
+
+/* Allocate and initialise a WordBag */
+WordBag* VG_(newBag) ( void* (*alloc_nofail)( HChar* cc, SizeT ),
+ HChar* cc,
+ void (*dealloc)(void*) );
+
+/* Free up the Bag. */
+void VG_(deleteBag) ( WordBag* );
+
+/* Add a word. */
+void VG_(addToBag)( WordBag*, UWord );
+
+/* Find out how many times the given word exists in the bag. */
+UWord VG_(elemBag) ( WordBag*, UWord );
+
+/* Delete a word from the bag. */
+Bool VG_(delFromBag)( WordBag*, UWord );
+
+/* Is the bag empty? */
+Bool VG_(isEmptyBag)( WordBag* );
+
+/* Does the bag have exactly one element? */
+Bool VG_(isSingletonTotalBag)( WordBag* );
+
+/* Return an arbitrary element from the bag. */
+UWord VG_(anyElementOfBag)( WordBag* );
+
+/* How many different / total elements are in the bag? */
+UWord VG_(sizeUniqueBag)( WordBag* ); /* fast */
+UWord VG_(sizeTotalBag)( WordBag* ); /* warning: slow */
+
+/* Iterating over the elements of a bag. */
+void VG_(initIterBag)( WordBag* );
+Bool VG_(nextIterBag)( WordBag*, /*OUT*/UWord* pVal, /*OUT*/UWord* pCount );
+void VG_(doneIterBag)( WordBag* );
+
+//------------------------------------------------------------------//
+//--- end WordBag (unboxed words only) ---//
+//--- Public interface ---//
+//------------------------------------------------------------------//
+
+#endif /* ! __PUB_TOOL_WORDFM_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_tool_wordfm.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/pub_tool_xarray.h.svn-base b/include/.svn/text-base/pub_tool_xarray.h.svn-base
new file mode 100644
index 0000000..111f63a
--- /dev/null
+++ b/include/.svn/text-base/pub_tool_xarray.h.svn-base
@@ -0,0 +1,115 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An expandable array implementation. pub_tool_xarray.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2007-2009 OpenWorks LLP
+ info@open-works.co.uk
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_TOOL_XARRAY_H
+#define __PUB_TOOL_XARRAY_H
+
+//--------------------------------------------------------------------
+// PURPOSE: Provides a simple but useful structure, which is an array
+// in which elements can be added at the end. The array is expanded
+// as needed by multiplying its size by a constant factor (usually 2).
+// This gives amortised O(1) insertion cost, and, following sorting,
+// the usual O(log N) binary search cost. Arbitrary element sizes
+// are allowed; the comparison function for sort/lookup can be changed
+// at any time, and duplicates (modulo the comparison function) are
+// allowed.
+//--------------------------------------------------------------------
+
+
+/* It's an abstract type. Bwaha. */
+typedef struct _XArray XArray;
+
+/* Create new XArray, using given allocation and free function, and
+ for elements of the specified size. Alloc fn must not fail (that
+ is, if it returns it must have succeeded.) */
+extern XArray* VG_(newXA) ( void*(*alloc_fn)(HChar*,SizeT),
+ HChar* cc,
+ void(*free_fn)(void*),
+ Word elemSzB );
+
+/* Free all memory associated with an XArray. */
+extern void VG_(deleteXA) ( XArray* );
+
+/* Set the comparison function for this XArray. This clears an
+ internal 'array is sorted' flag, which means you must call sortXA
+ before making further queries with lookupXA. */
+extern void VG_(setCmpFnXA) ( XArray*, Int (*compar)(void*,void*) );
+
+/* Add an element to an XArray. Element is copied into the XArray.
+ Index at which it was added is returned. Note this will be
+ invalidated if the array is later sortXA'd. */
+extern Word VG_(addToXA) ( XArray*, void* elem );
+
+/* Add a sequence of bytes to an XArray of bytes. Asserts if nbytes
+ is negative or the array's element size is not 1. Returns the
+ index at which the first byte was added. */
+extern Word VG_(addBytesToXA) ( XArray* xao, void* bytesV, Word nbytes );
+
+/* Sort an XArray using its comparison function, if set; else bomb.
+ Probably not a stable sort w.r.t. equal elements module cmpFn. */
+extern void VG_(sortXA) ( XArray* );
+
+/* Lookup (by binary search) 'key' in the array. Set *first to be the
+ index of the first, and *last to be the index of the last matching
+ value found. If any values are found, return True, else return
+ False, and don't change *first or *last. Bomb if the array is not
+ sorted. */
+extern Bool VG_(lookupXA) ( XArray*, void* key,
+ /*OUT*/Word* first, /*OUT*/Word* last );
+
+/* How elements are there in this XArray now? */
+extern Word VG_(sizeXA) ( XArray* );
+
+/* Index into the XArray. Checks bounds and bombs if the index is
+ invalid. What this returns is the address of the specified element
+ in the array, not (of course) the element itself. Note that the
+ element may get moved by subsequent addToXAs/sortXAs, so you should
+ copy it out immediately and not regard its address as unchanging.
+ Note also that indexXA will of course not return NULL if it
+ succeeds. */
+extern void* VG_(indexXA) ( XArray*, Word );
+
+/* Drop the last n elements of an XArray. Bombs if there are less
+ than n elements in the array. */
+extern void VG_(dropTailXA) ( XArray*, Word );
+
+/* Make a new, completely independent copy of the given XArray, using
+ the existing allocation function to allocate the new space.
+ Returns NULL if the allocation function didn't manage to allocate
+ space (but did return NULL rather than merely abort.) Space for
+ the clone (and all additions to it) is billed to 'cc' unless that
+ is NULL, in which case the parent's cost-center is used. */
+extern XArray* VG_(cloneXA)( HChar* cc, XArray* xa );
+
+#endif // __PUB_TOOL_XARRAY_H
+
+/*--------------------------------------------------------------------*/
+/*--- end pub_tool_xarray.h ---*/
+/*--------------------------------------------------------------------*/
diff --git a/include/.svn/text-base/valgrind.h.svn-base b/include/.svn/text-base/valgrind.h.svn-base
new file mode 100644
index 0000000..5b4b8af
--- /dev/null
+++ b/include/.svn/text-base/valgrind.h.svn-base
@@ -0,0 +1,3937 @@
+/* -*- c -*-
+ ----------------------------------------------------------------
+
+ Notice that the following BSD-style license applies to this one
+ file (valgrind.h) only. The rest of Valgrind is licensed under the
+ terms of the GNU General Public License, version 2, unless
+ otherwise indicated. See the COPYING file in the source
+ distribution for details.
+
+ ----------------------------------------------------------------
+
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2009 Julian Seward. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+ 3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+ 4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ ----------------------------------------------------------------
+
+ Notice that the above BSD-style license applies to this one file
+ (valgrind.h) only. The entire rest of Valgrind is licensed under
+ the terms of the GNU General Public License, version 2. See the
+ COPYING file in the source distribution for details.
+
+ ----------------------------------------------------------------
+*/
+
+
+/* This file is for inclusion into client (your!) code.
+
+ You can use these macros to manipulate and query Valgrind's
+ execution inside your own programs.
+
+ The resulting executables will still run without Valgrind, just a
+ little bit more slowly than they otherwise would, but otherwise
+ unchanged. When not running on valgrind, each client request
+ consumes very few (eg. 7) instructions, so the resulting performance
+ loss is negligible unless you plan to execute client requests
+ millions of times per second. Nevertheless, if that is still a
+ problem, you can compile with the NVALGRIND symbol defined (gcc
+ -DNVALGRIND) so that client requests are not even compiled in. */
+
+#ifndef __VALGRIND_H
+#define __VALGRIND_H
+
+#include <stdarg.h>
+
+/* Nb: this file might be included in a file compiled with -ansi. So
+ we can't use C++ style "//" comments nor the "asm" keyword (instead
+ use "__asm__"). */
+
+/* Derive some tags indicating what the target platform is. Note
+ that in this file we're using the compiler's CPP symbols for
+ identifying architectures, which are different to the ones we use
+ within the rest of Valgrind. Note, __powerpc__ is active for both
+ 32 and 64-bit PPC, whereas __powerpc64__ is only active for the
+ latter (on Linux, that is). */
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
+
+#if !defined(_AIX) && defined(__i386__)
+# define PLAT_x86_linux 1
+#elif !defined(_AIX) && defined(__x86_64__)
+# define PLAT_amd64_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__)
+# define PLAT_ppc32_linux 1
+#elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__)
+# define PLAT_ppc64_linux 1
+#elif defined(_AIX) && defined(__64BIT__)
+# define PLAT_ppc64_aix5 1
+#elif defined(_AIX) && !defined(__64BIT__)
+# define PLAT_ppc32_aix5 1
+#endif
+
+
+/* If we're not compiling for our target platform, don't generate
+ any inline asms. */
+#if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \
+ && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \
+ && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5)
+# if !defined(NVALGRIND)
+# define NVALGRIND 1
+# endif
+#endif
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */
+/* in here of use to end-users -- skip to the next section. */
+/* ------------------------------------------------------------------ */
+
+#if defined(NVALGRIND)
+
+/* Define NVALGRIND to completely remove the Valgrind magic sequence
+ from the compiled code (analogous to NDEBUG's effects on
+ assert()) */
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { \
+ (_zzq_rlval) = (_zzq_default); \
+ }
+
+#else /* ! NVALGRIND */
+
+/* The following defines the magic code sequences which the JITter
+ spots and handles magically. Don't look too closely at them as
+ they will rot your brain.
+
+ The assembly code sequences for all architectures is in this one
+ file. This is because this file must be stand-alone, and we don't
+ want to have multiple files.
+
+ For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default
+ value gets put in the return slot, so that everything works when
+ this is executed not under Valgrind. Args are passed in a memory
+ block, and so there's no intrinsic limit to the number that could
+ be passed, but it's currently five.
+
+ The macro args are:
+ _zzq_rlval result lvalue
+ _zzq_default default value (result returned when running on real CPU)
+ _zzq_request request code
+ _zzq_arg1..5 request params
+
+ The other two macros are used to support function wrapping, and are
+ a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the
+ guest's NRADDR pseudo-register and whatever other information is
+ needed to safely run the call original from the wrapper: on
+ ppc64-linux, the R2 value at the divert point is also needed. This
+ information is abstracted into a user-visible type, OrigFn.
+
+ VALGRIND_CALL_NOREDIR_* behaves the same as the following on the
+ guest, but guarantees that the branch instruction will not be
+ redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64:
+ branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a
+ complete inline asm, since it needs to be combined with more magic
+ inline asm stuff to be useful.
+*/
+
+/* ------------------------- x86-linux ------------------------- */
+
+#if defined(PLAT_x86_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "roll $3, %%edi ; roll $13, %%edi\n\t" \
+ "roll $29, %%edi ; roll $19, %%edi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EDX = client_request ( %EAX ) */ \
+ "xchgl %%ebx,%%ebx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EAX = guest_NRADDR */ \
+ "xchgl %%ecx,%%ecx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_EAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%EAX */ \
+ "xchgl %%edx,%%edx\n\t"
+#endif /* PLAT_x86_linux */
+
+/* ------------------------ amd64-linux ------------------------ */
+
+#if defined(PLAT_amd64_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
+ "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned long long int _zzq_args[6]; \
+ volatile unsigned long long int _zzq_result; \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RDX = client_request ( %RAX ) */ \
+ "xchgq %%rbx,%%rbx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RAX = guest_NRADDR */ \
+ "xchgq %%rcx,%%rcx" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_RAX \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* call-noredir *%RAX */ \
+ "xchgq %%rdx,%%rdx\n\t"
+#endif /* PLAT_amd64_linux */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[6]; \
+ unsigned int _zzq_result; \
+ unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 3,%1\n\t" /*default*/ \
+ "mr 4,%2\n\t" /*ptr*/ \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" /*result*/ \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_default), "b" (_zzq_ptr) \
+ : "cc", "memory", "r3", "r4"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "cc", "memory", "r3" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[6]; \
+ register unsigned long long int _zzq_result __asm__("r3"); \
+ register unsigned long long int* _zzq_ptr __asm__("r4"); \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1" \
+ : "=r" (_zzq_result) \
+ : "0" (_zzq_default), "r" (_zzq_ptr) \
+ : "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr __asm__("r3"); \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4" \
+ : "=r" (__addr) \
+ : \
+ : "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+typedef
+ struct {
+ unsigned int nraddr; /* where's the code? */
+ unsigned int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \
+ "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned int _zzq_args[7]; \
+ register unsigned int _zzq_result; \
+ register unsigned int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "lwz 3, 24(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ unsigned long long int r2; /* what tocptr do we need? */
+ }
+ OrigFn;
+
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \
+ "rotldi 0,0,61 ; rotldi 0,0,51\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ \
+ { unsigned long long int _zzq_args[7]; \
+ register unsigned long long int _zzq_result; \
+ register unsigned long long int* _zzq_ptr; \
+ _zzq_args[0] = (unsigned int long long)(_zzq_request); \
+ _zzq_args[1] = (unsigned int long long)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int long long)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int long long)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int long long)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int long long)(_zzq_arg5); \
+ _zzq_args[6] = (unsigned int long long)(_zzq_default); \
+ _zzq_ptr = _zzq_args; \
+ __asm__ volatile("mr 4,%1\n\t" \
+ "ld 3, 48(4)\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = client_request ( %R4 ) */ \
+ "or 1,1,1\n\t" \
+ "mr %0,3" \
+ : "=b" (_zzq_result) \
+ : "b" (_zzq_ptr) \
+ : "r3", "r4", "cc", "memory"); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ register unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR */ \
+ "or 2,2,2\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %R3 = guest_NRADDR_GPR2 */ \
+ "or 4,4,4\n\t" \
+ "mr %0,3" \
+ : "=b" (__addr) \
+ : \
+ : "r3", "cc", "memory" \
+ ); \
+ _zzq_orig->r2 = __addr; \
+ }
+
+#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ /* branch-and-link-to-noredir *%R11 */ \
+ "or 3,3,3\n\t"
+
+#endif /* PLAT_ppc64_aix5 */
+
+/* Insert assembly code for other platforms here... */
+
+#endif /* NVALGRIND */
+
+
+/* ------------------------------------------------------------------ */
+/* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */
+/* ugly. It's the least-worst tradeoff I can think of. */
+/* ------------------------------------------------------------------ */
+
+/* This section defines magic (a.k.a appalling-hack) macros for doing
+ guaranteed-no-redirection macros, so as to get from function
+ wrappers to the functions they are wrapping. The whole point is to
+ construct standard call sequences, but to do the call itself with a
+ special no-redirect call pseudo-instruction that the JIT
+ understands and handles specially. This section is long and
+ repetitious, and I can't see a way to make it shorter.
+
+ The naming scheme is as follows:
+
+ CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc}
+
+ 'W' stands for "word" and 'v' for "void". Hence there are
+ different macros for calling arity 0, 1, 2, 3, 4, etc, functions,
+ and for each, the possibility of returning a word-typed result, or
+ no result.
+*/
+
+/* Use these to write the name of your wrapper. NOTE: duplicates
+ VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */
+
+#define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \
+ _vgwZU_##soname##_##fnname
+
+#define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \
+ _vgwZZ_##soname##_##fnname
+
+/* Use this macro from within a wrapper function to collect the
+ context (address and possibly other info) of the original function.
+ Once you have that you can then use it in one of the CALL_FN_
+ macros. The type of the argument _lval is OrigFn. */
+#define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval)
+
+/* Derivatives of the main macros below, for calling functions
+ returning void. */
+
+#define CALL_FN_v_v(fnptr) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_v(_junk,fnptr); } while (0)
+
+#define CALL_FN_v_W(fnptr, arg1) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_W(_junk,fnptr,arg1); } while (0)
+
+#define CALL_FN_v_WW(fnptr, arg1,arg2) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0)
+
+#define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \
+ do { volatile unsigned long _junk; \
+ CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0)
+
+/* ------------------------- x86-linux ------------------------- */
+
+#if defined(PLAT_x86_linux)
+
+/* These regs are trashed by the hidden call. No need to mention eax
+ as gcc can already see that, plus causes gcc to bomb. */
+#define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx"
+
+/* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $4, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $8, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $12, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $16, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $20, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $24, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $28, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $32, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $36, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $40, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $44, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \
+ arg6,arg7,arg8,arg9,arg10, \
+ arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "pushl 48(%%eax)\n\t" \
+ "pushl 44(%%eax)\n\t" \
+ "pushl 40(%%eax)\n\t" \
+ "pushl 36(%%eax)\n\t" \
+ "pushl 32(%%eax)\n\t" \
+ "pushl 28(%%eax)\n\t" \
+ "pushl 24(%%eax)\n\t" \
+ "pushl 20(%%eax)\n\t" \
+ "pushl 16(%%eax)\n\t" \
+ "pushl 12(%%eax)\n\t" \
+ "pushl 8(%%eax)\n\t" \
+ "pushl 4(%%eax)\n\t" \
+ "movl (%%eax), %%eax\n\t" /* target->%eax */ \
+ VALGRIND_CALL_NOREDIR_EAX \
+ "addl $48, %%esp\n" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_x86_linux */
+
+/* ------------------------ amd64-linux ------------------------ */
+
+#if defined(PLAT_amd64_linux)
+
+/* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \
+ "rdi", "r8", "r9", "r10", "r11"
+
+/* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned
+ long) == 8. */
+
+/* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_
+ macros. In order not to trash the stack redzone, we need to drop
+ %rsp by 128 before the hidden call, and restore afterwards. The
+ nastyness is that it is only by luck that the stack still appears
+ to be unwindable during the hidden call - since then the behaviour
+ of any routine using this macro does not match what the CFI data
+ says. Sigh.
+
+ Why is this important? Imagine that a wrapper has a stack
+ allocated local, and passes to the hidden call, a pointer to it.
+ Because gcc does not know about the hidden call, it may allocate
+ that local in the redzone. Unfortunately the hidden call may then
+ trash it before it comes to use it. So we must step clear of the
+ redzone, for the duration of the hidden call, to make it safe.
+
+ Probably the same problem afflicts the other redzone-style ABIs too
+ (ppc64-linux, ppc32-aix5, ppc64-aix5); but for those, the stack is
+ self describing (none of this CFI nonsense) so at least messing
+ with the stack pointer doesn't give a danger of non-unwindable
+ stack. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ "addq $128,%%rsp\n\t" \
+ VALGRIND_CALL_NOREDIR_RAX \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $8, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $16, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $24, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $32, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $40, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)(arg1); \
+ _argvec[2] = (unsigned long)(arg2); \
+ _argvec[3] = (unsigned long)(arg3); \
+ _argvec[4] = (unsigned long)(arg4); \
+ _argvec[5] = (unsigned long)(arg5); \
+ _argvec[6] = (unsigned long)(arg6); \
+ _argvec[7] = (unsigned long)(arg7); \
+ _argvec[8] = (unsigned long)(arg8); \
+ _argvec[9] = (unsigned long)(arg9); \
+ _argvec[10] = (unsigned long)(arg10); \
+ _argvec[11] = (unsigned long)(arg11); \
+ _argvec[12] = (unsigned long)(arg12); \
+ __asm__ volatile( \
+ "subq $128,%%rsp\n\t" \
+ "pushq 96(%%rax)\n\t" \
+ "pushq 88(%%rax)\n\t" \
+ "pushq 80(%%rax)\n\t" \
+ "pushq 72(%%rax)\n\t" \
+ "pushq 64(%%rax)\n\t" \
+ "pushq 56(%%rax)\n\t" \
+ "movq 48(%%rax), %%r9\n\t" \
+ "movq 40(%%rax), %%r8\n\t" \
+ "movq 32(%%rax), %%rcx\n\t" \
+ "movq 24(%%rax), %%rdx\n\t" \
+ "movq 16(%%rax), %%rsi\n\t" \
+ "movq 8(%%rax), %%rdi\n\t" \
+ "movq (%%rax), %%rax\n\t" /* target->%rax */ \
+ VALGRIND_CALL_NOREDIR_RAX \
+ "addq $48, %%rsp\n" \
+ "addq $128,%%rsp\n\t" \
+ : /*out*/ "=a" (_res) \
+ : /*in*/ "a" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_amd64_linux */
+
+/* ------------------------ ppc32-linux ------------------------ */
+
+#if defined(PLAT_ppc32_linux)
+
+/* This is useful for finding out about the on-stack stuff:
+
+ extern int f9 ( int,int,int,int,int,int,int,int,int );
+ extern int f10 ( int,int,int,int,int,int,int,int,int,int );
+ extern int f11 ( int,int,int,int,int,int,int,int,int,int,int );
+ extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int );
+
+ int g9 ( void ) {
+ return f9(11,22,33,44,55,66,77,88,99);
+ }
+ int g10 ( void ) {
+ return f10(11,22,33,44,55,66,77,88,99,110);
+ }
+ int g11 ( void ) {
+ return f11(11,22,33,44,55,66,77,88,99,110,121);
+ }
+ int g12 ( void ) {
+ return f12(11,22,33,44,55,66,77,88,99,110,121,132);
+ }
+*/
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc32-linux,
+ sizeof(unsigned long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-16\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,16\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ _argvec[12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "addi 1,1,-32\n\t" \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,20(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,16(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,12(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,8(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3,4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4,8(11)\n\t" \
+ "lwz 5,12(11)\n\t" \
+ "lwz 6,16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7,20(11)\n\t" \
+ "lwz 8,24(11)\n\t" \
+ "lwz 9,28(11)\n\t" \
+ "lwz 10,32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11,0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "addi 1,1,32\n\t" \
+ "mr %0,3" \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[0]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_linux */
+
+/* ------------------------ ppc64-linux ------------------------ */
+
+#if defined(PLAT_ppc64_linux)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)" /* restore tocptr */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-128\n\t" /* expand stack frame */ \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,128" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "addi 1,1,-144\n\t" /* expand stack frame */ \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ "addi 1,1,144" /* restore frame */ \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_linux */
+
+/* ------------------------ ppc32-aix5 ------------------------- */
+
+#if defined(PLAT_ppc32_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "lwz 3," #_n_fr "(1)\n\t" \
+ "stw 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc32-aix5, sizeof(unsigned
+ long) == 4. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(64) \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(64) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "stw 2,-8(11)\n\t" /* save tocptr */ \
+ "lwz 2,-4(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(72) \
+ /* arg12 */ \
+ "lwz 3,48(11)\n\t" \
+ "stw 3,68(1)\n\t" \
+ /* arg11 */ \
+ "lwz 3,44(11)\n\t" \
+ "stw 3,64(1)\n\t" \
+ /* arg10 */ \
+ "lwz 3,40(11)\n\t" \
+ "stw 3,60(1)\n\t" \
+ /* arg9 */ \
+ "lwz 3,36(11)\n\t" \
+ "stw 3,56(1)\n\t" \
+ /* args1-8 */ \
+ "lwz 3, 4(11)\n\t" /* arg1->r3 */ \
+ "lwz 4, 8(11)\n\t" /* arg2->r4 */ \
+ "lwz 5, 12(11)\n\t" /* arg3->r5 */ \
+ "lwz 6, 16(11)\n\t" /* arg4->r6 */ \
+ "lwz 7, 20(11)\n\t" /* arg5->r7 */ \
+ "lwz 8, 24(11)\n\t" /* arg6->r8 */ \
+ "lwz 9, 28(11)\n\t" /* arg7->r9 */ \
+ "lwz 10, 32(11)\n\t" /* arg8->r10 */ \
+ "lwz 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "lwz 2,-8(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(72) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc32_aix5 */
+
+/* ------------------------ ppc64-aix5 ------------------------- */
+
+#if defined(PLAT_ppc64_aix5)
+
+/* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */
+
+/* These regs are trashed by the hidden call. */
+#define __CALLER_SAVED_REGS \
+ "lr", "ctr", "xer", \
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
+ "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \
+ "r11", "r12", "r13"
+
+/* Expand the stack frame, copying enough info that unwinding
+ still works. Trashes r3. */
+
+#define VG_EXPAND_FRAME_BY_trashes_r3(_n_fr) \
+ "addi 1,1,-" #_n_fr "\n\t" \
+ "ld 3," #_n_fr "(1)\n\t" \
+ "std 3,0(1)\n\t"
+
+#define VG_CONTRACT_FRAME_BY(_n_fr) \
+ "addi 1,1," #_n_fr "\n\t"
+
+/* These CALL_FN_ macros assume that on ppc64-aix5, sizeof(unsigned
+ long) == 8. */
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+0]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+1]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1,arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+2]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+3]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+4]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+5]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+6]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+7]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+8]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+9]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+10]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(128) \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(128) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+11]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \
+ arg7,arg8,arg9,arg10,arg11,arg12) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3+12]; \
+ volatile unsigned long _res; \
+ /* _argvec[0] holds current r2 across the call */ \
+ _argvec[1] = (unsigned long)_orig.r2; \
+ _argvec[2] = (unsigned long)_orig.nraddr; \
+ _argvec[2+1] = (unsigned long)arg1; \
+ _argvec[2+2] = (unsigned long)arg2; \
+ _argvec[2+3] = (unsigned long)arg3; \
+ _argvec[2+4] = (unsigned long)arg4; \
+ _argvec[2+5] = (unsigned long)arg5; \
+ _argvec[2+6] = (unsigned long)arg6; \
+ _argvec[2+7] = (unsigned long)arg7; \
+ _argvec[2+8] = (unsigned long)arg8; \
+ _argvec[2+9] = (unsigned long)arg9; \
+ _argvec[2+10] = (unsigned long)arg10; \
+ _argvec[2+11] = (unsigned long)arg11; \
+ _argvec[2+12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ "mr 11,%1\n\t" \
+ VG_EXPAND_FRAME_BY_trashes_r3(512) \
+ "std 2,-16(11)\n\t" /* save tocptr */ \
+ "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \
+ VG_EXPAND_FRAME_BY_trashes_r3(144) \
+ /* arg12 */ \
+ "ld 3,96(11)\n\t" \
+ "std 3,136(1)\n\t" \
+ /* arg11 */ \
+ "ld 3,88(11)\n\t" \
+ "std 3,128(1)\n\t" \
+ /* arg10 */ \
+ "ld 3,80(11)\n\t" \
+ "std 3,120(1)\n\t" \
+ /* arg9 */ \
+ "ld 3,72(11)\n\t" \
+ "std 3,112(1)\n\t" \
+ /* args1-8 */ \
+ "ld 3, 8(11)\n\t" /* arg1->r3 */ \
+ "ld 4, 16(11)\n\t" /* arg2->r4 */ \
+ "ld 5, 24(11)\n\t" /* arg3->r5 */ \
+ "ld 6, 32(11)\n\t" /* arg4->r6 */ \
+ "ld 7, 40(11)\n\t" /* arg5->r7 */ \
+ "ld 8, 48(11)\n\t" /* arg6->r8 */ \
+ "ld 9, 56(11)\n\t" /* arg7->r9 */ \
+ "ld 10, 64(11)\n\t" /* arg8->r10 */ \
+ "ld 11, 0(11)\n\t" /* target->r11 */ \
+ VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \
+ "mr 11,%1\n\t" \
+ "mr %0,3\n\t" \
+ "ld 2,-16(11)\n\t" /* restore tocptr */ \
+ VG_CONTRACT_FRAME_BY(144) \
+ VG_CONTRACT_FRAME_BY(512) \
+ : /*out*/ "=r" (_res) \
+ : /*in*/ "r" (&_argvec[2]) \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#endif /* PLAT_ppc64_aix5 */
+
+
+/* ------------------------------------------------------------------ */
+/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
+/* */
+/* ------------------------------------------------------------------ */
+
+/* Some request codes. There are many more of these, but most are not
+ exposed to end-user view. These are the public ones, all of the
+ form 0x1000 + small_number.
+
+ Core ones are in the range 0x00000000--0x0000ffff. The non-public
+ ones start at 0x2000.
+*/
+
+/* These macros are used by tools -- they must be public, but don't
+ embed them into other programs. */
+#define VG_USERREQ_TOOL_BASE(a,b) \
+ ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16))
+#define VG_IS_TOOL_USERREQ(a, b, v) \
+ (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000))
+
+/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
+ This enum comprises an ABI exported by Valgrind to programs
+ which use client requests. DO NOT CHANGE THE ORDER OF THESE
+ ENTRIES, NOR DELETE ANY -- add new ones at the end. */
+typedef
+ enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001,
+ VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002,
+
+ /* These allow any function to be called from the simulated
+ CPU but run on the real CPU. Nb: the first arg passed to
+ the function is always the ThreadId of the running
+ thread! So CLIENT_CALL0 actually requires a 1 arg
+ function, etc. */
+ VG_USERREQ__CLIENT_CALL0 = 0x1101,
+ VG_USERREQ__CLIENT_CALL1 = 0x1102,
+ VG_USERREQ__CLIENT_CALL2 = 0x1103,
+ VG_USERREQ__CLIENT_CALL3 = 0x1104,
+
+ /* Can be useful in regression testing suites -- eg. can
+ send Valgrind's output to /dev/null and still count
+ errors. */
+ VG_USERREQ__COUNT_ERRORS = 0x1201,
+
+ /* These are useful and can be interpreted by any tool that
+ tracks malloc() et al, by using vg_replace_malloc.c. */
+ VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301,
+ VG_USERREQ__FREELIKE_BLOCK = 0x1302,
+ /* Memory pool support. */
+ VG_USERREQ__CREATE_MEMPOOL = 0x1303,
+ VG_USERREQ__DESTROY_MEMPOOL = 0x1304,
+ VG_USERREQ__MEMPOOL_ALLOC = 0x1305,
+ VG_USERREQ__MEMPOOL_FREE = 0x1306,
+ VG_USERREQ__MEMPOOL_TRIM = 0x1307,
+ VG_USERREQ__MOVE_MEMPOOL = 0x1308,
+ VG_USERREQ__MEMPOOL_CHANGE = 0x1309,
+ VG_USERREQ__MEMPOOL_EXISTS = 0x130a,
+
+ /* Allow printfs to valgrind log. */
+ VG_USERREQ__PRINTF = 0x1401,
+ VG_USERREQ__PRINTF_BACKTRACE = 0x1402,
+
+ /* Stack support. */
+ VG_USERREQ__STACK_REGISTER = 0x1501,
+ VG_USERREQ__STACK_DEREGISTER = 0x1502,
+ VG_USERREQ__STACK_CHANGE = 0x1503,
+
+ /* Wine support */
+ VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601
+ } Vg_ClientRequest;
+
+#if !defined(__GNUC__)
+# define __extension__ /* */
+#endif
+
+/* Returns the number of Valgrinds this code is running under. That
+ is, 0 if running natively, 1 if running under Valgrind, 2 if
+ running under Valgrind which is running under another Valgrind,
+ etc. */
+#define RUNNING_ON_VALGRIND __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \
+ VG_USERREQ__RUNNING_ON_VALGRIND, \
+ 0, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+
+/* Discard translation of code in the range [_qzz_addr .. _qzz_addr +
+ _qzz_len - 1]. Useful if you are debugging a JITter or some such,
+ since it provides a way to make sure valgrind will retranslate the
+ invalidated area. Returns no value. */
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DISCARD_TRANSLATIONS, \
+ _qzz_addr, _qzz_len, 0, 0, 0); \
+ }
+
+
+/* These requests are for getting Valgrind itself to print something.
+ Possibly with a backtrace. This is a really ugly hack. */
+
+#if defined(NVALGRIND)
+
+# define VALGRIND_PRINTF(...)
+# define VALGRIND_PRINTF_BACKTRACE(...)
+
+#else /* NVALGRIND */
+
+/* Modern GCC will optimize the static routine out if unused,
+ and unused attribute will shut down warnings about it. */
+static int VALGRIND_PRINTF(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF,
+ (unsigned long)format, (unsigned long)vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+ __attribute__((format(__printf__, 1, 2), __unused__));
+static int
+VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+{
+ unsigned long _qzz_res;
+ va_list vargs;
+ va_start(vargs, format);
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE,
+ (unsigned long)format, (unsigned long)vargs,
+ 0, 0, 0);
+ va_end(vargs);
+ return (int)_qzz_res;
+}
+
+#endif /* NVALGRIND */
+
+
+/* These requests allow control to move from the simulated CPU to the
+ real CPU, calling an arbitary function.
+
+ Note that the current ThreadId is inserted as the first argument.
+ So this call:
+
+ VALGRIND_NON_SIMD_CALL2(f, arg1, arg2)
+
+ requires f to have this signature:
+
+ Word f(Word tid, Word arg1, Word arg2)
+
+ where "Word" is a word-sized type.
+
+ Note that these client requests are not entirely reliable. For example,
+ if you call a function with them that subsequently calls printf(),
+ there's a high chance Valgrind will 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.
+*/
+#define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL0, \
+ _qyy_fn, \
+ 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL1, \
+ _qyy_fn, \
+ _qyy_arg1, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL2, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, 0, 0); \
+ _qyy_res; \
+ })
+
+#define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \
+ __extension__ \
+ ({unsigned long _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__CLIENT_CALL3, \
+ _qyy_fn, \
+ _qyy_arg1, _qyy_arg2, \
+ _qyy_arg3, 0); \
+ _qyy_res; \
+ })
+
+
+/* Counts the number of errors that have been recorded by a tool. Nb:
+ the tool must record the errors with VG_(maybe_record_error)() or
+ VG_(unique_error)() for them to be counted. */
+#define VALGRIND_COUNT_ERRORS \
+ __extension__ \
+ ({unsigned int _qyy_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \
+ VG_USERREQ__COUNT_ERRORS, \
+ 0, 0, 0, 0, 0); \
+ _qyy_res; \
+ })
+
+/* Mark a block of memory as having been allocated by a malloc()-like
+ function. `addr' is the start of the usable block (ie. after any
+ redzone) `rzB' is redzone size if the allocator can apply redzones;
+ use '0' if not. Adding redzones makes it more likely Valgrind will spot
+ block overruns. `is_zeroed' indicates if the memory is zeroed, as it is
+ for calloc(). Put it immediately after the point where a block is
+ allocated.
+
+ If you're using Memcheck: If you're allocating memory via superblocks,
+ and then handing out small chunks of each superblock, if you don't have
+ redzones on your small blocks, it's worth marking the superblock with
+ VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are
+ detected. But if you can put redzones on, it's probably better to not do
+ this, so that messages for small overruns are described in terms of the
+ small block rather than the superblock (but if you have a big overrun
+ that skips over a redzone, you could miss an error this way). See
+ memcheck/tests/custom_alloc.c for an example.
+
+ WARNING: if your allocator uses malloc() or 'new' to allocate
+ superblocks, rather than mmap() or brk(), this will not work properly --
+ you'll likely get assertion failures during leak detection. This is
+ because Valgrind doesn't like seeing overlapping heap blocks. Sorry.
+
+ Nb: block must be freed via a free()-like function specified
+ with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */
+#define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MALLOCLIKE_BLOCK, \
+ addr, sizeB, rzB, is_zeroed, 0); \
+ }
+
+/* Mark a block of memory as having been freed by a free()-like function.
+ `rzB' is redzone size; it must match that given to
+ VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak
+ checker. Put it immediately after the point where the block is freed. */
+#define VALGRIND_FREELIKE_BLOCK(addr, rzB) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__FREELIKE_BLOCK, \
+ addr, rzB, 0, 0, 0); \
+ }
+
+/* Create a memory pool. */
+#define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__CREATE_MEMPOOL, \
+ pool, rzB, is_zeroed, 0, 0); \
+ }
+
+/* Destroy a memory pool. */
+#define VALGRIND_DESTROY_MEMPOOL(pool) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__DESTROY_MEMPOOL, \
+ pool, 0, 0, 0, 0); \
+ }
+
+/* Associate a piece of memory with a memory pool. */
+#define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_ALLOC, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Disassociate a piece of memory from a memory pool. */
+#define VALGRIND_MEMPOOL_FREE(pool, addr) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_FREE, \
+ pool, addr, 0, 0, 0); \
+ }
+
+/* Disassociate any pieces outside a particular range. */
+#define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_TRIM, \
+ pool, addr, size, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MOVE_MEMPOOL, \
+ poolA, poolB, 0, 0, 0); \
+ }
+
+/* Resize and/or move a piece associated with a memory pool. */
+#define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_CHANGE, \
+ pool, addrA, addrB, size, 0); \
+ }
+
+/* Return 1 if a mempool exists, else 0. */
+#define VALGRIND_MEMPOOL_EXISTS(pool) \
+ __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__MEMPOOL_EXISTS, \
+ pool, 0, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Mark a piece of memory as being a stack. Returns a stack id. */
+#define VALGRIND_STACK_REGISTER(start, end) \
+ __extension__ \
+ ({unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_REGISTER, \
+ start, end, 0, 0, 0); \
+ _qzz_res; \
+ })
+
+/* Unmark the piece of memory associated with a stack id as being a
+ stack. */
+#define VALGRIND_STACK_DEREGISTER(id) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_DEREGISTER, \
+ id, 0, 0, 0, 0); \
+ }
+
+/* Change the start and end address of the stack id. */
+#define VALGRIND_STACK_CHANGE(id, start, end) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__STACK_CHANGE, \
+ id, start, end, 0, 0); \
+ }
+
+/* Load PDB debug info for Wine PE image_map. */
+#define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \
+ {unsigned int _qzz_res; \
+ VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \
+ VG_USERREQ__LOAD_PDB_DEBUGINFO, \
+ fd, ptr, total_size, delta, 0); \
+ }
+
+
+#undef PLAT_x86_linux
+#undef PLAT_amd64_linux
+#undef PLAT_ppc32_linux
+#undef PLAT_ppc64_linux
+#undef PLAT_ppc32_aix5
+#undef PLAT_ppc64_aix5
+
+#endif /* __VALGRIND_H */