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