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