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