1
2/*--------------------------------------------------------------------*/
3/*--- Types and macros for writing syscall wrappers.               ---*/
4/*---                                        priv_types_n_macros.h ---*/
5/*--------------------------------------------------------------------*/
6
7/*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
10
11   Copyright (C) 2000-2012 Julian Seward
12      jseward@acm.org
13
14   This program is free software; you can redistribute it and/or
15   modify it under the terms of the GNU General Public License as
16   published by the Free Software Foundation; either version 2 of the
17   License, or (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful, but
20   WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22   General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program; if not, write to the Free Software
26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27   02111-1307, USA.
28
29   The GNU General Public License is contained in the file COPYING.
30*/
31
32#ifndef __PRIV_TYPES_N_MACROS_H
33#define __PRIV_TYPES_N_MACROS_H
34
35/* requires #include "pub_core_options.h" */
36/* requires #include "pub_core_signals.h" */
37
38/* This header defines types and macros which are useful for writing
39   syscall wrappers.  It does not give prototypes for any such
40   headers, though: that is the job of the priv_syswrap-*.h headers.
41   This header gets included in any file which defines or declares
42   wrappers, and as such should only contain stuff which is relevant
43   to all such files.
44*/
45
46/* ---------------------------------------------------------------------
47   Types that are used in syscall wrappers.
48   ------------------------------------------------------------------ */
49
50/* Arguments for a syscall. */
51typedef
52   struct SyscallArgs {
53      Word sysno;
54      UWord arg1;
55      UWord arg2;
56      UWord arg3;
57      UWord arg4;
58      UWord arg5;
59      UWord arg6;
60      UWord arg7;
61      UWord arg8;
62   }
63   SyscallArgs;
64
65/* Current status of a syscall being done on behalf of the client. */
66typedef
67   struct SyscallStatus {
68      enum {
69         /* call is complete, result is in 'res' */
70         SsComplete=1,
71         /* syscall not yet completed; must be handed to the kernel */
72         SsHandToKernel,
73         /* not currently handling a syscall for this thread */
74         SsIdle
75      } what;
76      SysRes sres; /* only meaningful for .what == SsComplete */
77   }
78   SyscallStatus;
79
80/* Guest state layout info for syscall args. */
81typedef
82   struct {
83      // Note that, depending on the platform, arguments may be found in
84      // registers or on the stack.  (See the comment at the top of
85      // syswrap-main.c for per-platform details.)  For register arguments
86      // (which have o_arg field names) the o_arg value is the offset into
87      // the vex register state.  For stack arguments (which have s_arg
88      // field names), the s_arg value is the offset from the stack pointer.
89      Int o_sysno;
90#     if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
91         || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
92         || defined(VGP_arm_linux) || defined(VGP_s390x_linux)
93      Int o_arg1;
94      Int o_arg2;
95      Int o_arg3;
96      Int o_arg4;
97      Int o_arg5;
98      Int o_arg6;
99      Int uu_arg7;
100      Int uu_arg8;
101#     elif defined(VGP_mips32_linux)
102      Int o_arg1;
103      Int o_arg2;
104      Int o_arg3;
105      Int o_arg4;
106      Int s_arg5;
107      Int s_arg6;
108      Int uu_arg7;
109      Int uu_arg8;
110#     elif defined(VGP_x86_darwin)
111      Int s_arg1;
112      Int s_arg2;
113      Int s_arg3;
114      Int s_arg4;
115      Int s_arg5;
116      Int s_arg6;
117      Int s_arg7;
118      Int s_arg8;
119#     elif defined(VGP_amd64_darwin)
120      Int o_arg1;
121      Int o_arg2;
122      Int o_arg3;
123      Int o_arg4;
124      Int o_arg5;
125      Int o_arg6;
126      Int s_arg7;
127      Int s_arg8;
128#     else
129#       error "Unknown platform"
130#     endif
131   }
132   SyscallArgLayout;
133
134/* Flags describing syscall wrappers */
135#define SfMayBlock      (1 << 1) /* may block                         */
136#define SfPostOnFail    (1 << 2) /* call POST() function on failure   */
137#define SfPollAfter     (1 << 3) /* poll for signals on completion    */
138#define SfYieldAfter    (1 << 4) /* yield on completion               */
139#define SfNoWriteResult (1 << 5) /* don't write result to guest state */
140
141
142/* ---------------------------------------------------------------------
143   The syscall table.
144   ------------------------------------------------------------------ */
145
146typedef
147   struct {
148      void (*before) ( ThreadId,
149                       SyscallArgLayout*,
150                       /*MOD*/SyscallArgs*,
151                       /*OUT*/SyscallStatus*,
152                       /*OUT*/UWord*
153                     );
154
155      void (*after)  ( ThreadId,
156                       SyscallArgs*,
157                       SyscallStatus*
158                     );
159   }
160   SyscallTableEntry;
161
162/* Syscall table entries bind __NR_xxx syscall numbers to the PRE/POST
163   wrappers for the relevant syscall used in the OS kernel for that
164   number.  Note that the constant names don't always match the
165   wrapper names in a straightforward way.  For example, on x86/Linux:
166
167      __NR_lchown       --> sys_lchown16()
168      __NR_lchown32     --> sys_lchown()
169      __NR_select       --> old_select()
170      __NR__newselect   --> sys_select()
171*/
172
173
174/* A function to find the syscall table entry for a given sysno.  If
175   none is found, return NULL.  This used to be done with a single
176   fixed sized table exposed to the caller, but that's too inflexible;
177   hence now use a function which can do arbitrary messing around to
178   find the required entry. */
179#if defined(VGP_mips32_linux)
180   /* Up to 6 parameters, 4 in registers 2 on stack. */
181#  define PRA1(s,t,a) PRRAn(1,s,t,a)
182#  define PRA2(s,t,a) PRRAn(2,s,t,a)
183#  define PRA3(s,t,a) PRRAn(3,s,t,a)
184#  define PRA4(s,t,a) PRRAn(4,s,t,a)
185#  define PRA5(s,t,a) PSRAn(5,s,t,a)
186#  define PRA6(s,t,a) PSRAn(6,s,t,a)
187
188#endif
189#if defined(VGO_linux)
190extern
191SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno );
192
193#elif defined(VGO_darwin)
194/* XXX: Darwin still uses the old scheme of exposing the table
195   array(s) and size(s) directly to syswrap-main.c.  This should be
196   fixed. */
197
198extern const SyscallTableEntry ML_(syscall_table)[];
199extern const UInt ML_(syscall_table_size);
200
201#else
202#  error Unknown OS
203#endif
204
205/* ---------------------------------------------------------------------
206   Declaring and defining wrappers.
207   ------------------------------------------------------------------ */
208
209/* Templates for generating the PRE and POST macros -- that is, the
210   formal parameter lists for the definitions of wrapper functions.
211
212   Since these names exist in the global namespace, 'auxstr' should
213   give an auxiliary string, eg, "generic", "x86_linux", "linux", etc,
214   that ensures the names won't clash with other wrappers.
215
216   You should create corresponding global declarations using
217   DECL_TEMPLATE (indirectly) below.
218
219   Note.  The silly name "arrghs" is used rather than just "args"
220   because a few wrappers declare the name "args" themselves, and
221   renaming those decls can change the name that comes out in error
222   messages (on scalar arg checks).  Hence rename this instead.
223*/
224
225#define DEFN_PRE_TEMPLATE(auxstr, name)                          \
226   void vgSysWrap_##auxstr##_##name##_before                     \
227                                 ( ThreadId tid,                 \
228                                   SyscallArgLayout* layout,     \
229                                   /*MOD*/SyscallArgs* arrghs,   \
230                                   /*OUT*/SyscallStatus* status, \
231                                   /*OUT*/UWord* flags           \
232                                 )
233
234#define DEFN_POST_TEMPLATE(auxstr, name)                         \
235   void vgSysWrap_##auxstr##_##name##_after                      \
236                                 ( ThreadId tid,                 \
237                                   SyscallArgs* arrghs,          \
238                                   SyscallStatus* status         \
239                                 )
240
241
242/* This macro generates declarations (prototypes) for wrappers.  It
243   declares both the pre-wrapper and the post-wrapper, even though the
244   post-wrapper may not actually exist.
245*/
246#define DECL_TEMPLATE(auxstr, name)                              \
247   extern                                                        \
248   void vgSysWrap_##auxstr##_##name##_before                     \
249                                 ( ThreadId tid,                 \
250                                   SyscallArgLayout* layout,     \
251                                   /*MOD*/SyscallArgs* arrghs,   \
252                                   /*OUT*/SyscallStatus* status, \
253                                   /*OUT*/UWord* flags           \
254                                 );                              \
255   extern                                                        \
256   void vgSysWrap_##auxstr##_##name##_after                      \
257                                 ( ThreadId tid,                 \
258                                   SyscallArgs* arrghs,          \
259                                   SyscallStatus* status         \
260                                 );
261
262
263
264/* Macros for conveniently generating entries in the syscall
265   tables.  This first pair are not used directly. */
266
267#define WRAPPER_ENTRY_X_(auxstr, sysno, name) \
268   [sysno] = { vgSysWrap_##auxstr##_##name##_before, NULL }
269#define WRAPPER_ENTRY_XY(auxstr, sysno, name) \
270   [sysno] = { vgSysWrap_##auxstr##_##name##_before, \
271               vgSysWrap_##auxstr##_##name##_after }
272
273#define WRAPPER_PRE_NAME(auxstr, name) \
274    vgSysWrap_##auxstr##_##name##_before
275#define WRAPPER_POST_NAME(auxstr, name) \
276    vgSysWrap_##auxstr##_##name##_after
277
278/* Add a generic wrapper to a syscall table. */
279#if defined(VGO_linux)
280#  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, sysno, name)
281#  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, sysno, name)
282#elif defined(VGO_darwin)
283#  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
284#  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
285#else
286#  error Unknown OS
287#endif
288
289/* Add a Linux-specific, arch-independent wrapper to a syscall
290   table. */
291#define LINX_(sysno, name)    WRAPPER_ENTRY_X_(linux, sysno, name)
292#define LINXY(sysno, name)    WRAPPER_ENTRY_XY(linux, sysno, name)
293
294
295/* ---------------------------------------------------------------------
296   Macros useful for writing wrappers concisely.  These refer to the
297   parameters declared by DEFN_{PRE,POST}_TEMPLATE and so in a way do
298   not help clarity of understanding.  But they are just too useful to
299   omit.
300   ------------------------------------------------------------------ */
301
302/* Reference to the syscall's arguments -- the ones which the
303   pre-wrapper may have modified, not the original copy. */
304#define SYSNO  (arrghs->sysno)
305#define ARG1   (arrghs->arg1)
306#define ARG2   (arrghs->arg2)
307#define ARG3   (arrghs->arg3)
308#define ARG4   (arrghs->arg4)
309#define ARG5   (arrghs->arg5)
310#define ARG6   (arrghs->arg6)
311#define ARG7   (arrghs->arg7)
312#define ARG8   (arrghs->arg8)
313
314/* Reference to the syscall's current result status/value.  General
315   paranoia all round. */
316#define SUCCESS       (status->what == SsComplete && !sr_isError(status->sres))
317#define FAILURE       (status->what == SsComplete &&  sr_isError(status->sres))
318#define SWHAT         (status->what)
319#define RES           (getRES(status))
320#define RESHI         (getRESHI(status))
321#define ERR           (getERR(status))
322
323static inline UWord getRES ( SyscallStatus* st ) {
324   vg_assert(st->what == SsComplete);
325   vg_assert(!sr_isError(st->sres));
326   return sr_Res(st->sres);
327}
328
329static inline UWord getRESHI ( SyscallStatus* st ) {
330   vg_assert(st->what == SsComplete);
331   vg_assert(!sr_isError(st->sres));
332   return sr_ResHI(st->sres);
333}
334
335static inline UWord getERR ( SyscallStatus* st ) {
336   vg_assert(st->what == SsComplete);
337   vg_assert(sr_isError(st->sres));
338   return sr_Err(st->sres);
339}
340
341
342/* Set the current result status/value in various ways. */
343#define SET_STATUS_Success(zzz)                      \
344   do { status->what = SsComplete;                   \
345        status->sres = VG_(mk_SysRes_Success)(zzz);  \
346   } while (0)
347
348#define SET_STATUS_Failure(zzz)                      \
349   do { Word wzz = (Word)(zzz);                      \
350        /* Catch out wildly bogus error values. */   \
351        vg_assert(wzz >= 0 && wzz < 10000);          \
352        status->what = SsComplete;                   \
353        status->sres = VG_(mk_SysRes_Error)(wzz);    \
354   } while (0)
355
356#define SET_STATUS_from_SysRes(zzz)                  \
357   do {                                              \
358     status->what = SsComplete;                      \
359     status->sres = (zzz);                           \
360   } while (0)
361
362
363#define PRINT(format, args...)                       \
364   if (VG_(clo_trace_syscalls))                      \
365      VG_(printf)(format, ## args)
366
367#define FUSE_COMPATIBLE_MAY_BLOCK()                       \
368   if (VG_(strstr)(VG_(clo_sim_hints),"fuse-compatible")) \
369      *flags |= SfMayBlock
370
371
372/* Macros used to tell tools about uses of scalar arguments.  Note,
373   these assume little-endianness.  These can only be used in
374   pre-wrappers, and they refer to the layout parameter passed in. */
375/* PRRSN == "pre-register-read-sysno"
376   PRRAn == "pre-register-read-argument"
377   PSRAn == "pre-stack-read-argument"
378   PRAn  == "pre-read-argument"
379*/
380
381#if defined(VGP_mips32_linux)
382   /* Up to 6 parameters, 4 in registers 2 on stack. */
383#  define PRA1(s,t,a) PRRAn(1,s,t,a)
384#  define PRA2(s,t,a) PRRAn(2,s,t,a)
385#  define PRA3(s,t,a) PRRAn(3,s,t,a)
386#  define PRA4(s,t,a) PRRAn(4,s,t,a)
387#  define PRA5(s,t,a) PSRAn(5,s,t,a)
388#  define PRA6(s,t,a) PSRAn(6,s,t,a)
389
390#elif defined(VGO_linux) && !defined(VGP_mips32_linux)
391   /* Up to 6 parameters, all in registers. */
392#  define PRA1(s,t,a) PRRAn(1,s,t,a)
393#  define PRA2(s,t,a) PRRAn(2,s,t,a)
394#  define PRA3(s,t,a) PRRAn(3,s,t,a)
395#  define PRA4(s,t,a) PRRAn(4,s,t,a)
396#  define PRA5(s,t,a) PRRAn(5,s,t,a)
397#  define PRA6(s,t,a) PRRAn(6,s,t,a)
398
399#elif defined(VGP_x86_darwin)
400   /* Up to 8 parameters, all on the stack. */
401#  define PRA1(s,t,a) PSRAn(1,s,t,a)
402#  define PRA2(s,t,a) PSRAn(2,s,t,a)
403#  define PRA3(s,t,a) PSRAn(3,s,t,a)
404#  define PRA4(s,t,a) PSRAn(4,s,t,a)
405#  define PRA5(s,t,a) PSRAn(5,s,t,a)
406#  define PRA6(s,t,a) PSRAn(6,s,t,a)
407#  define PRA7(s,t,a) PSRAn(7,s,t,a)
408#  define PRA8(s,t,a) PSRAn(8,s,t,a)
409
410#elif defined(VGP_amd64_darwin)
411   /* Up to 8 parameters, 6 in registers, 2 on the stack. */
412#  define PRA1(s,t,a) PRRAn(1,s,t,a)
413#  define PRA2(s,t,a) PRRAn(2,s,t,a)
414#  define PRA3(s,t,a) PRRAn(3,s,t,a)
415#  define PRA4(s,t,a) PRRAn(4,s,t,a)
416#  define PRA5(s,t,a) PRRAn(5,s,t,a)
417#  define PRA6(s,t,a) PRRAn(6,s,t,a)
418#  define PRA7(s,t,a) PSRAn(7,s,t,a)
419#  define PRA8(s,t,a) PSRAn(8,s,t,a)
420
421#else
422#  error Unknown platform
423#endif
424
425
426/* Tell the tool that the syscall number is being read. */
427#define PRRSN \
428      VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \
429                                    layout->o_sysno, sizeof(UWord));
430
431/* REGISTER PARAMETERS */
432
433/* PRRAn: Tell the tool that the register holding the n-th syscall
434   argument is being read, at type 't' which must be at most the size
435   of a register but can be smaller.  In the latter case we need to be
436   careful about endianness. */
437
438/* little-endian: the part of the guest state being read is
439      let here = offset_of_reg
440      in  [here .. here + sizeof(t) - 1]
441   since the least significant parts of the guest register are stored
442   in memory at the lowest address.
443*/
444#define PRRAn_LE(n,s,t,a)                          \
445   do {                                            \
446      Int here = layout->o_arg##n;                 \
447      vg_assert(sizeof(t) <= sizeof(UWord));       \
448      vg_assert(here >= 0);                        \
449      VG_(tdict).track_pre_reg_read(               \
450         Vg_CoreSysCall, tid, s"("#a")",           \
451         here, sizeof(t)                           \
452      );                                           \
453   } while (0)
454
455/* big-endian: the part of the guest state being read is
456      let next = offset_of_reg + sizeof(reg)
457      in  [next - sizeof(t) .. next - 1]
458   since the least significant parts of the guest register are stored
459   in memory at the highest address.
460*/
461#define PRRAn_BE(n,s,t,a)                          \
462   do {                                            \
463      Int here = layout->o_arg##n;                 \
464      Int next = layout->o_arg##n + sizeof(UWord); \
465      vg_assert(sizeof(t) <= sizeof(UWord));       \
466      vg_assert(here >= 0);                        \
467      VG_(tdict).track_pre_reg_read(               \
468         Vg_CoreSysCall, tid, s"("#a")",           \
469         next-sizeof(t), sizeof(t)                 \
470      );                                           \
471   } while (0)
472
473#if defined(VG_BIGENDIAN)
474#  define PRRAn(n,s,t,a) PRRAn_BE(n,s,t,a)
475#elif defined(VG_LITTLEENDIAN)
476#  define PRRAn(n,s,t,a) PRRAn_LE(n,s,t,a)
477#else
478#  error "Unknown endianness"
479#endif
480
481
482/* STACK PARAMETERS */
483
484/* PSRAn: Tell the tool that the memory holding the n-th syscall
485   argument is being read, at type 't' which must be at most the size
486   of a register but can be smaller.  In the latter case we need to be
487   careful about endianness. */
488
489/* little-endian: the part of the guest state being read is
490      let here = offset_of_reg
491      in  [here .. here + sizeof(t) - 1]
492   since the least significant parts of the guest register are stored
493   in memory at the lowest address.
494*/
495#define PSRAn_LE(n,s,t,a)                          \
496   do {                                            \
497      Addr here = layout->s_arg##n + VG_(get_SP)(tid); \
498      vg_assert(sizeof(t) <= sizeof(UWord));       \
499      VG_(tdict).track_pre_mem_read(               \
500         Vg_CoreSysCallArgInMem, tid, s"("#a")",   \
501         here, sizeof(t)                           \
502      );                                           \
503   } while (0)
504
505/* big-endian: the part of the guest state being read is
506      let next = offset_of_reg + sizeof(reg)
507      in  [next - sizeof(t) .. next - 1]
508   since the least significant parts of the guest register are stored
509   in memory at the highest address.
510*/
511#if (defined(VGP_mips32_linux) && defined (_MIPSEB))
512 #define PSRAn_BE(n,s,t,a)                                        \
513    do {                                                          \
514      Addr next = layout->s_arg##n + sizeof(UWord) +              \
515                  VG_(get_SP)(tid);                               \
516      vg_assert(sizeof(t) <= sizeof(UWord));                      \
517      VG_(tdict).track_pre_mem_read(                              \
518         Vg_CoreSysCallArgInMem, tid, s"("#a")",                  \
519         next-sizeof(t), sizeof(t)                                \
520      );                                                          \
521   } while (0)
522#else
523#define PSRAn_BE(n,s,t,a)                                         \
524   do {                                                           \
525      Addr next = layout->o_arg##n + sizeof(UWord) +              \
526                  VG_(threads)[tid].arch.vex.VG_STACK_PTR;        \
527      vg_assert(sizeof(t) <= sizeof(UWord));                      \
528      VG_(tdict).track_pre_mem_read(                              \
529         Vg_CoreSysCallArgInMem, tid, s"("#a")",                  \
530         next-sizeof(t), sizeof(t)                                \
531      );                                                          \
532   } while (0)
533#endif
534
535#if defined(VG_BIGENDIAN)
536#  define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
537#elif defined(VG_LITTLEENDIAN)
538#  define PSRAn(n,s,t,a) PSRAn_LE(n,s,t,a)
539#else
540#  error "Unknown endianness"
541#endif
542
543
544#define PRE_REG_READ0(tr, s) \
545   if (VG_(tdict).track_pre_reg_read) { \
546      PRRSN; \
547   }
548#define PRE_REG_READ1(tr, s, t1, a1) \
549   if (VG_(tdict).track_pre_reg_read) { \
550      PRRSN; \
551      PRA1(s,t1,a1);                            \
552   }
553#define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
554   if (VG_(tdict).track_pre_reg_read) { \
555      PRRSN; \
556      PRA1(s,t1,a1); PRA2(s,t2,a2);           \
557   }
558#define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
559   if (VG_(tdict).track_pre_reg_read) { \
560      PRRSN; \
561      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
562   }
563#define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
564   if (VG_(tdict).track_pre_reg_read) { \
565      PRRSN; \
566      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
567      PRA4(s,t4,a4);                                    \
568   }
569#define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
570   if (VG_(tdict).track_pre_reg_read) { \
571      PRRSN; \
572      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
573      PRA4(s,t4,a4); PRA5(s,t5,a5);                   \
574   }
575#define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
576   if (VG_(tdict).track_pre_reg_read) { \
577      PRRSN; \
578      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
579      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
580   }
581#define PRE_REG_READ7(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7) \
582   if (VG_(tdict).track_pre_reg_read) { \
583      PRRSN; \
584      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
585      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
586      PRA7(s,t7,a7);                                     \
587   }
588
589#define PRE_REG_READ8(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7, t8, a8) \
590   if (VG_(tdict).track_pre_reg_read) { \
591      PRRSN; \
592      PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
593      PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
594      PRA7(s,t7,a7); PRA8(s,t8,a8);                    \
595   }
596
597#define PRE_MEM_READ(zzname, zzaddr, zzlen) \
598   VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
599
600#define PRE_MEM_RASCIIZ(zzname, zzaddr) \
601   VG_TRACK( pre_mem_read_asciiz, Vg_CoreSysCall, tid, zzname, zzaddr)
602
603#define PRE_MEM_WRITE(zzname, zzaddr, zzlen) \
604   VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
605
606#define POST_MEM_WRITE(zzaddr, zzlen) \
607   VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, zzaddr, zzlen)
608
609
610#define PRE_FIELD_READ(zzname, zzfield) \
611    PRE_MEM_READ(zzname, (UWord)&zzfield, sizeof(zzfield))
612
613#define PRE_FIELD_WRITE(zzname, zzfield) \
614    PRE_MEM_WRITE(zzname, (UWord)&zzfield, sizeof(zzfield))
615
616#define POST_FIELD_WRITE(zzfield) \
617    POST_MEM_WRITE((UWord)&zzfield, sizeof(zzfield))
618
619
620#endif   // __PRIV_TYPES_N_MACROS_H
621
622/*--------------------------------------------------------------------*/
623/*--- end                                                          ---*/
624/*--------------------------------------------------------------------*/
625