]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_syswrap/priv_types_n_macros.h
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_syswrap / priv_types_n_macros.h
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-2010 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. */
51 typedef
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. */
66 typedef
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. */
81 typedef
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_ppc32_aix5) || defined(VGP_ppc64_aix5)
102       Int o_arg1;
103       Int o_arg2;
104       Int o_arg3;
105       Int o_arg4;
106       Int o_arg5;
107       Int o_arg6;
108       Int o_arg7;
109       Int o_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 #     elif defined(VGP_x86_l4re)
129       Int o_arg1;
130       Int o_arg2;
131       Int o_arg3;
132       Int o_arg4;
133       Int o_arg5;
134       Int o_arg6;
135       Int o_arg7;
136       Int o_arg8;
137                 Int o_retval;
138 #     else
139 #       error "Unknown platform"
140 #     endif
141    }
142    SyscallArgLayout;
143
144 /* Flags describing syscall wrappers */
145 #define SfMayBlock      (1 << 1) /* may block                         */
146 #define SfPostOnFail    (1 << 2) /* call POST() function on failure   */
147 #define SfPollAfter     (1 << 3) /* poll for signals on completion    */
148 #define SfYieldAfter    (1 << 4) /* yield on completion               */
149 #define SfNoWriteResult (1 << 5) /* don't write result to guest state */
150
151
152 /* ---------------------------------------------------------------------
153    The syscall table.
154    ------------------------------------------------------------------ */
155
156 typedef
157    struct {
158       void (*before) ( ThreadId,
159                        SyscallArgLayout*,
160                        /*MOD*/SyscallArgs*,
161                        /*OUT*/SyscallStatus*,
162                        /*OUT*/UWord*
163                      );
164
165       void (*after)  ( ThreadId, 
166                        SyscallArgs*,
167                        SyscallStatus*
168                      );
169    }
170    SyscallTableEntry;
171
172 /* Syscall table entries bind __NR_xxx syscall numbers to the PRE/POST
173    wrappers for the relevant syscall used in the OS kernel for that
174    number.  Note that the constant names don't always match the
175    wrapper names in a straightforward way.  For example, on x86/Linux:
176       
177       __NR_lchown       --> sys_lchown16()
178       __NR_lchown32     --> sys_lchown()
179       __NR_select       --> old_select()
180       __NR__newselect   --> sys_select()
181 */
182
183
184 /* A function to find the syscall table entry for a given sysno.  If
185    none is found, return NULL.  This used to be done with a single
186    fixed sized table exposed to the caller, but that's too inflexible;
187    hence now use a function which can do arbitrary messing around to
188    find the required entry. */
189 #if defined(VGO_linux)
190 extern
191 SyscallTableEntry* ML_(get_linux_syscall_entry)( UInt sysno );
192
193 #elif defined(VGP_ppc32_aix5)
194 /* Same scheme on AIX5.  This is more complex than the simple fixed
195    table lookup typical for Linux, since the syscalls don't have fixed
196    numbers. */
197 extern
198 SyscallTableEntry* ML_(get_ppc32_aix5_syscall_entry) ( UInt sysno );
199
200 #elif defined(VGP_ppc64_aix5)
201 extern
202 SyscallTableEntry* ML_(get_ppc64_aix5_syscall_entry) ( UInt sysno );
203
204 #elif defined(VGO_darwin)
205 /* XXX: Darwin still uses the old scheme of exposing the table
206    array(s) and size(s) directly to syswrap-main.c.  This should be
207    fixed. */
208
209 extern const SyscallTableEntry ML_(syscall_table)[];
210 extern const UInt ML_(syscall_table_size);
211
212 #elif defined(VGO_l4re)
213 extern const SyscallTableEntry ML_(syscall_table)[];
214 extern const UInt ML_(syscall_table_size);
215
216 #else
217 #  error Unknown OS
218 #endif   
219
220 /* ---------------------------------------------------------------------
221    Declaring and defining wrappers.
222    ------------------------------------------------------------------ */
223
224 /* Templates for generating the PRE and POST macros -- that is, the
225    formal parameter lists for the definitions of wrapper functions.
226
227    Since these names exist in the global namespace, 'auxstr' should
228    give an auxiliary string, eg, "generic", "x86_linux", "linux", etc,
229    that ensures the names won't clash with other wrappers.
230
231    You should create corresponding global declarations using
232    DECL_TEMPLATE (indirectly) below.  
233
234    Note.  The silly name "arrghs" is used rather than just "args"
235    because a few wrappers declare the name "args" themselves, and
236    renaming those decls can change the name that comes out in error
237    messages (on scalar arg checks).  Hence rename this instead.
238 */
239
240 #define DEFN_PRE_TEMPLATE(auxstr, name)                          \
241    void vgSysWrap_##auxstr##_##name##_before                     \
242                                  ( ThreadId tid,                 \
243                                    SyscallArgLayout* layout,     \
244                                    /*MOD*/SyscallArgs* arrghs,   \
245                                    /*OUT*/SyscallStatus* status, \
246                                    /*OUT*/UWord* flags           \
247                                  )
248
249 #define DEFN_POST_TEMPLATE(auxstr, name)                         \
250    void vgSysWrap_##auxstr##_##name##_after                      \
251                                  ( ThreadId tid,                 \
252                                    SyscallArgs* arrghs,          \
253                                    SyscallStatus* status         \
254                                  )
255
256
257 /* This macro generates declarations (prototypes) for wrappers.  It
258    declares both the pre-wrapper and the post-wrapper, even though the
259    post-wrapper may not actually exist.
260 */
261 #define DECL_TEMPLATE(auxstr, name)                              \
262    extern                                                        \
263    void vgSysWrap_##auxstr##_##name##_before                     \
264                                  ( ThreadId tid,                 \
265                                    SyscallArgLayout* layout,     \
266                                    /*MOD*/SyscallArgs* arrghs,   \
267                                    /*OUT*/SyscallStatus* status, \
268                                    /*OUT*/UWord* flags           \
269                                  );                              \
270    extern                                                        \
271    void vgSysWrap_##auxstr##_##name##_after                      \
272                                  ( ThreadId tid,                 \
273                                    SyscallArgs* arrghs,          \
274                                    SyscallStatus* status         \
275                                  );
276
277
278
279 /* Macros for conveniently generating entries in the syscall
280    tables.  This first pair are not used directly. */
281
282 #define WRAPPER_ENTRY_X_(auxstr, sysno, name) \
283    [sysno] = { vgSysWrap_##auxstr##_##name##_before, NULL }
284 #define WRAPPER_ENTRY_XY(auxstr, sysno, name) \
285    [sysno] = { vgSysWrap_##auxstr##_##name##_before, \
286                vgSysWrap_##auxstr##_##name##_after }
287
288 #define WRAPPER_PRE_NAME(auxstr, name) \
289     vgSysWrap_##auxstr##_##name##_before
290 #define WRAPPER_POST_NAME(auxstr, name) \
291     vgSysWrap_##auxstr##_##name##_after
292
293 /* Add a generic wrapper to a syscall table. */
294 #if defined(VGO_linux) || defined(VGO_aix5) || defined(VGO_l4re)
295 #  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, sysno, name)
296 #  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, sysno, name)
297 #elif defined(VGO_darwin)
298 #  define GENX_(sysno, name)  WRAPPER_ENTRY_X_(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
299 #  define GENXY(sysno, name)  WRAPPER_ENTRY_XY(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
300 #else
301 #  error Unknown OS
302 #endif
303
304 /* Add a Linux-specific, arch-independent wrapper to a syscall
305    table. */
306 #define LINX_(sysno, name)    WRAPPER_ENTRY_X_(linux, sysno, name) 
307 #define LINXY(sysno, name)    WRAPPER_ENTRY_XY(linux, sysno, name)
308
309 /* Add an AIX5-specific, arch-independent wrapper to a syscall
310    table. */
311 #define AIXXY(sysno, name)                     \
312    { & sysno,                                  \
313      { & WRAPPER_PRE_NAME(aix5, name),         \
314        & WRAPPER_POST_NAME(aix5, name) }} 
315
316 #define AIXX_(sysno, name)                     \
317    { & sysno,                                  \
318      { & WRAPPER_PRE_NAME(aix5, name),         \
319        NULL }} 
320
321
322 /* ---------------------------------------------------------------------
323    Macros useful for writing wrappers concisely.  These refer to the
324    parameters declared by DEFN_{PRE,POST}_TEMPLATE and so in a way do
325    not help clarity of understanding.  But they are just too useful to
326    omit.
327    ------------------------------------------------------------------ */
328
329 /* Reference to the syscall's arguments -- the ones which the
330    pre-wrapper may have modified, not the original copy. */
331 #define SYSNO  (arrghs->sysno)
332 #define ARG1   (arrghs->arg1)
333 #define ARG2   (arrghs->arg2)
334 #define ARG3   (arrghs->arg3)
335 #define ARG4   (arrghs->arg4)
336 #define ARG5   (arrghs->arg5)
337 #define ARG6   (arrghs->arg6)
338 #define ARG7   (arrghs->arg7)
339 #define ARG8   (arrghs->arg8)
340
341 /* Reference to the syscall's current result status/value.  General
342    paranoia all round. */
343 #define SUCCESS       (status->what == SsComplete && !sr_isError(status->sres))
344 #define FAILURE       (status->what == SsComplete &&  sr_isError(status->sres))
345 #define SWHAT         (status->what)
346 #define RES           (getRES(status))
347 #define RESHI         (getRESHI(status))
348 #define ERR           (getERR(status))
349
350 static inline UWord getRES ( SyscallStatus* st ) {
351    vg_assert(st->what == SsComplete);
352    vg_assert(!sr_isError(st->sres));
353    return sr_Res(st->sres);
354 }
355
356 static inline UWord getRESHI ( SyscallStatus* st ) {
357    vg_assert(st->what == SsComplete);
358    vg_assert(!sr_isError(st->sres));
359    return sr_ResHI(st->sres);
360 }
361
362 static inline UWord getERR ( SyscallStatus* st ) {
363    vg_assert(st->what == SsComplete);
364    vg_assert(sr_isError(st->sres));
365    return sr_Err(st->sres);
366 }
367
368
369 /* Set the current result status/value in various ways. */
370 #define SET_STATUS_Success(zzz)                      \
371    do { status->what = SsComplete;                   \
372         status->sres = VG_(mk_SysRes_Success)(zzz);  \
373    } while (0)
374
375 #define SET_STATUS_Failure(zzz)                      \
376    do { Word wzz = (Word)(zzz);                      \
377         /* Catch out wildly bogus error values. */   \
378         vg_assert(wzz >= 0 && wzz < 10000);          \
379         status->what = SsComplete;                   \
380         status->sres = VG_(mk_SysRes_Error)(wzz);    \
381    } while (0)
382
383 #define SET_STATUS_from_SysRes(zzz)                  \
384    do {                                              \
385      status->what = SsComplete;                      \
386      status->sres = (zzz);                           \
387    } while (0)
388
389
390 #define PRINT(format, args...)                       \
391    if (VG_(clo_trace_syscalls))                      \
392       VG_(printf)(format, ## args)
393
394
395
396 /* Macros used to tell tools about uses of scalar arguments.  Note,
397    these assume little-endianness.  These can only be used in
398    pre-wrappers, and they refer to the layout parameter passed in. */
399 /* PRRSN == "pre-register-read-sysno"
400    PRRAn == "pre-register-read-argument"
401    PSRAn == "pre-stack-read-argument"
402    PRAn  == "pre-read-argument"
403 */
404
405 #if defined(VGO_linux) || defined(VGO_l4re)
406    /* Up to 6 parameters, all in registers. */
407 #  define PRA1(s,t,a) PRRAn(1,s,t,a)
408 #  define PRA2(s,t,a) PRRAn(2,s,t,a)
409 #  define PRA3(s,t,a) PRRAn(3,s,t,a)
410 #  define PRA4(s,t,a) PRRAn(4,s,t,a)
411 #  define PRA5(s,t,a) PRRAn(5,s,t,a)
412 #  define PRA6(s,t,a) PRRAn(6,s,t,a)
413
414 #elif defined(VGO_aix5)
415 #  error Need to fill this in for AIX5
416
417 #elif defined(VGP_x86_darwin)
418    /* Up to 8 parameters, all on the stack. */
419 #  define PRA1(s,t,a) PSRAn(1,s,t,a)
420 #  define PRA2(s,t,a) PSRAn(2,s,t,a)
421 #  define PRA3(s,t,a) PSRAn(3,s,t,a)
422 #  define PRA4(s,t,a) PSRAn(4,s,t,a)
423 #  define PRA5(s,t,a) PSRAn(5,s,t,a)
424 #  define PRA6(s,t,a) PSRAn(6,s,t,a)
425 #  define PRA7(s,t,a) PSRAn(7,s,t,a)
426 #  define PRA8(s,t,a) PSRAn(8,s,t,a)
427
428 #elif defined(VGP_amd64_darwin)
429    /* Up to 8 parameters, 6 in registers, 2 on the stack. */
430 #  define PRA1(s,t,a) PRRAn(1,s,t,a)
431 #  define PRA2(s,t,a) PRRAn(2,s,t,a)
432 #  define PRA3(s,t,a) PRRAn(3,s,t,a)
433 #  define PRA4(s,t,a) PRRAn(4,s,t,a)
434 #  define PRA5(s,t,a) PRRAn(5,s,t,a)
435 #  define PRA6(s,t,a) PRRAn(6,s,t,a)
436 #  define PRA7(s,t,a) PSRAn(7,s,t,a)
437 #  define PRA8(s,t,a) PSRAn(8,s,t,a)
438
439 #else
440 #  error Unknown platform
441 #endif
442
443
444 /* Tell the tool that the syscall number is being read. */
445 #define PRRSN \
446       VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \
447                                     layout->o_sysno, sizeof(UWord));
448
449 /* REGISTER PARAMETERS */
450
451 /* PRRAn: Tell the tool that the register holding the n-th syscall
452    argument is being read, at type 't' which must be at most the size
453    of a register but can be smaller.  In the latter case we need to be
454    careful about endianness. */
455
456 /* little-endian: the part of the guest state being read is
457       let here = offset_of_reg
458       in  [here .. here + sizeof(t) - 1]
459    since the least significant parts of the guest register are stored
460    in memory at the lowest address.
461 */
462 #define PRRAn_LE(n,s,t,a)                          \
463    do {                                            \
464       Int here = layout->o_arg##n;                 \
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          here, sizeof(t)                           \
470       );                                           \
471    } while (0)
472
473 /* big-endian: the part of the guest state being read is
474       let next = offset_of_reg + sizeof(reg) 
475       in  [next - sizeof(t) .. next - 1]
476    since the least significant parts of the guest register are stored
477    in memory at the highest address.
478 */
479 #define PRRAn_BE(n,s,t,a)                          \
480    do {                                            \
481       Int here = layout->o_arg##n;                 \
482       Int next = layout->o_arg##n + sizeof(UWord); \
483       vg_assert(sizeof(t) <= sizeof(UWord));       \
484       vg_assert(here >= 0);                        \
485       VG_(tdict).track_pre_reg_read(               \
486          Vg_CoreSysCall, tid, s"("#a")",           \
487          next-sizeof(t), sizeof(t)                 \
488       );                                           \
489    } while (0)
490
491 #if defined(VG_BIGENDIAN)
492 #  define PRRAn(n,s,t,a) PRRAn_BE(n,s,t,a)
493 #elif defined(VG_LITTLEENDIAN)
494 #  define PRRAn(n,s,t,a) PRRAn_LE(n,s,t,a)
495 #else
496 #  error "Unknown endianness"
497 #endif
498
499
500 /* STACK PARAMETERS */
501
502 /* PSRAn: Tell the tool that the memory holding the n-th syscall
503    argument is being read, at type 't' which must be at most the size
504    of a register but can be smaller.  In the latter case we need to be
505    careful about endianness. */
506
507 /* little-endian: the part of the guest state being read is
508       let here = offset_of_reg
509       in  [here .. here + sizeof(t) - 1]
510    since the least significant parts of the guest register are stored
511    in memory at the lowest address.
512 */
513 #define PSRAn_LE(n,s,t,a)                          \
514    do {                                            \
515       Addr here = layout->s_arg##n + 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          here, sizeof(t)                           \
520       );                                           \
521    } while (0)
522
523 /* big-endian: the part of the guest state being read is
524       let next = offset_of_reg + sizeof(reg) 
525       in  [next - sizeof(t) .. next - 1]
526    since the least significant parts of the guest register are stored
527    in memory at the highest address.
528 */
529 #define PSRAn_BE(n,s,t,a)                                         \
530    do {                                                           \
531       Addr next = layout->o_arg##n + sizeof(UWord) +              \
532                   VG_(threads)[tid].arch.vex.VG_STACK_PTR;        \
533       vg_assert(sizeof(t) <= sizeof(UWord));                      \
534       VG_(tdict).track_pre_mem_read(                              \
535          Vg_CoreSysCallArgInMem, tid, s"("#a")",                  \
536          next-sizeof(t), sizeof(t)                                \
537       );                                                          \
538    } while (0)
539
540 #if defined(VG_BIGENDIAN)
541 #  define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
542 #elif defined(VG_LITTLEENDIAN)
543 #  define PSRAn(n,s,t,a) PSRAn_LE(n,s,t,a)
544 #else
545 #  error "Unknown endianness"
546 #endif
547
548
549 #define PRE_REG_READ0(tr, s) \
550    if (VG_(tdict).track_pre_reg_read) { \
551       PRRSN; \
552    }
553 #define PRE_REG_READ1(tr, s, t1, a1) \
554    if (VG_(tdict).track_pre_reg_read) { \
555       PRRSN; \
556       PRA1(s,t1,a1);                            \
557    }
558 #define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
559    if (VG_(tdict).track_pre_reg_read) { \
560       PRRSN; \
561       PRA1(s,t1,a1); PRA2(s,t2,a2);           \
562    }
563 #define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
564    if (VG_(tdict).track_pre_reg_read) { \
565       PRRSN; \
566       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
567    }
568 #define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
569    if (VG_(tdict).track_pre_reg_read) { \
570       PRRSN; \
571       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
572       PRA4(s,t4,a4);                                    \
573    }
574 #define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
575    if (VG_(tdict).track_pre_reg_read) { \
576       PRRSN; \
577       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);  \
578       PRA4(s,t4,a4); PRA5(s,t5,a5);                   \
579    }
580 #define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
581    if (VG_(tdict).track_pre_reg_read) { \
582       PRRSN; \
583       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
584       PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
585    }
586 #define PRE_REG_READ7(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7) \
587    if (VG_(tdict).track_pre_reg_read) { \
588       PRRSN; \
589       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
590       PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
591       PRA7(s,t7,a7);                                     \
592    }
593
594 #define PRE_REG_READ8(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7, t8, a8) \
595    if (VG_(tdict).track_pre_reg_read) { \
596       PRRSN; \
597       PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3);   \
598       PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6);   \
599       PRA7(s,t7,a7); PRA8(s,t8,a8);                    \
600    }
601
602 #define PRE_MEM_READ(zzname, zzaddr, zzlen) \
603    VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
604
605 #define PRE_MEM_RASCIIZ(zzname, zzaddr) \
606    VG_TRACK( pre_mem_read_asciiz, Vg_CoreSysCall, tid, zzname, zzaddr)
607
608 #define PRE_MEM_WRITE(zzname, zzaddr, zzlen) \
609    VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
610
611 #define POST_MEM_WRITE(zzaddr, zzlen) \
612    VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, zzaddr, zzlen)
613
614
615 #define PRE_FIELD_READ(zzname, zzfield) \
616     PRE_MEM_READ(zzname, (UWord)&zzfield, sizeof(zzfield))
617
618 #define PRE_FIELD_WRITE(zzname, zzfield) \
619     PRE_MEM_WRITE(zzname, (UWord)&zzfield, sizeof(zzfield))
620
621 #define POST_FIELD_WRITE(zzfield) \
622     POST_MEM_WRITE((UWord)&zzfield, sizeof(zzfield))
623
624
625 #endif   // __PRIV_TYPES_N_MACROS_H
626
627 /*--------------------------------------------------------------------*/
628 /*--- end                                                          ---*/
629 /*--------------------------------------------------------------------*/