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