2 /*--------------------------------------------------------------------*/
3 /*--- Types and macros for writing syscall wrappers. ---*/
4 /*--- priv_types_n_macros.h ---*/
5 /*--------------------------------------------------------------------*/
8 This file is part of Valgrind, a dynamic binary instrumentation
11 Copyright (C) 2000-2017 Julian Seward
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
30 #ifndef __PRIV_TYPES_N_MACROS_H
31 #define __PRIV_TYPES_N_MACROS_H
33 #include "pub_core_basics.h" // Addr
35 /* requires #include "pub_core_options.h" */
36 /* requires #include "pub_core_signals.h" */
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
46 /* ---------------------------------------------------------------------
47 Types that are used in syscall wrappers.
48 ------------------------------------------------------------------ */
50 /* Arguments for a syscall. */
53 #if defined(VGO_freebsd)
68 /* Current status of a syscall being done on behalf of the client. */
70 struct SyscallStatus
{
72 /* call is complete, result is in 'res' */
74 /* syscall not yet completed; must be handed to the kernel */
76 /* not currently handling a syscall for this thread */
79 SysRes sres
; /* only meaningful for .what == SsComplete */
83 /* Guest state layout info for syscall args. */
86 // Note that, depending on the platform, arguments may be found in
87 // registers or on the stack. (See the comment at the top of
88 // syswrap-main.c for per-platform details.) For register arguments
89 // (which have o_arg field names) the o_arg value is the offset into
90 // the vex register state. For stack arguments (which have s_arg
91 // field names), the s_arg value is the offset from the stack pointer.
93 # if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
94 || defined(VGP_ppc32_linux) \
95 || defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
96 || defined(VGP_arm64_linux) \
97 || defined(VGP_nanomips_linux)
106 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
115 # elif defined(VGP_x86_freebsd)
124 # elif defined(VGP_amd64_freebsd)
130 // arg6 can either be a register or a stack
131 // depending on whether the syscall is 'syscall/__syscall'
132 // or any other syscall
140 # elif defined(VGP_mips32_linux)
149 # elif defined(VGP_x86_darwin) || defined(VGP_x86_solaris)
158 # elif defined(VGP_amd64_darwin) || defined(VGP_amd64_solaris)
167 # elif defined(VGP_mips64_linux)
177 # error "Unknown platform"
182 /* Flags describing syscall wrappers */
183 #define SfMayBlock (1U << 1U) /* may block */
184 #define SfPostOnFail (1U << 2U) /* call POST() function on failure */
185 #define SfPollAfter (1U << 3U) /* poll for signals on completion */
186 #define SfYieldAfter (1U << 4U) /* yield on completion */
187 #define SfNoWriteResult (1U << 5U) /* don't write result to guest state */
188 #define SfKernelRestart (1U << 6U) /* needs a manual restart */
191 /* ---------------------------------------------------------------------
193 ------------------------------------------------------------------ */
197 void (*before
) ( ThreadId
,
200 /*OUT*/SyscallStatus
*,
204 void (*after
) ( ThreadId
,
211 /* Syscall table entries bind __NR_xxx syscall numbers to the PRE/POST
212 wrappers for the relevant syscall used in the OS kernel for that
213 number. Note that the constant names don't always match the
214 wrapper names in a straightforward way. For example, on x86/Linux:
216 __NR_lchown --> sys_lchown16()
217 __NR_lchown32 --> sys_lchown()
218 __NR_select --> old_select()
219 __NR__newselect --> sys_select()
223 /* A function to find the syscall table entry for a given sysno. If
224 none is found, return NULL. This used to be done with a single
225 fixed sized table exposed to the caller, but that's too inflexible;
226 hence now use a function which can do arbitrary messing around to
227 find the required entry. */
229 #if defined(VGO_linux)
231 SyscallTableEntry
* ML_(get_linux_syscall_entry
)( UInt sysno
);
233 #elif defined(VGO_darwin)
234 /* XXX: Darwin still uses the old scheme of exposing the table
235 array(s) and size(s) directly to syswrap-main.c. This should be
238 extern const SyscallTableEntry
ML_(syscall_table
)[];
239 extern const UInt
ML_(syscall_table_size
);
241 #elif defined(VGO_solaris)
243 SyscallTableEntry
* ML_(get_solaris_syscall_entry
)( UInt sysno
);
245 #elif defined(VGO_freebsd)
247 const SyscallTableEntry
* ML_(get_freebsd_syscall_entry
)( UInt sysno
);
253 /* ---------------------------------------------------------------------
254 Declaring and defining wrappers.
255 ------------------------------------------------------------------ */
257 /* Templates for generating the PRE and POST macros -- that is, the
258 formal parameter lists for the definitions of wrapper functions.
260 Since these names exist in the global namespace, 'auxstr' should
261 give an auxiliary string, eg, "generic", "x86_linux", "linux", etc,
262 that ensures the names won't clash with other wrappers.
264 You should create corresponding global declarations using
265 DECL_TEMPLATE (indirectly) below.
267 Note. The silly name "arrghs" is used rather than just "args"
268 because a few wrappers declare the name "args" themselves, and
269 renaming those decls can change the name that comes out in error
270 messages (on scalar arg checks). Hence rename this instead.
273 #define DEFN_PRE_TEMPLATE(auxstr, name) \
274 void vgSysWrap_##auxstr##_##name##_before \
276 SyscallArgLayout* layout, \
277 /*MOD*/ SyscallArgs* arrghs, \
278 /*OUT*/ SyscallStatus* status, \
279 /*OUT*/ UWord* flags \
282 #define DEFN_POST_TEMPLATE(auxstr, name) \
283 void vgSysWrap_##auxstr##_##name##_after \
285 SyscallArgs* arrghs, \
286 SyscallStatus* status \
290 /* This macro generates declarations (prototypes) for wrappers. It
291 declares both the pre-wrapper and the post-wrapper, even though the
292 post-wrapper may not actually exist.
294 #define DECL_TEMPLATE(auxstr, name) \
296 void vgSysWrap_##auxstr##_##name##_before \
298 SyscallArgLayout* layout, \
299 /*MOD*/SyscallArgs* arrghs, \
300 /*OUT*/SyscallStatus* status, \
301 /*OUT*/UWord* flags \
304 void vgSysWrap_##auxstr##_##name##_after \
306 SyscallArgs* arrghs, \
307 SyscallStatus* status \
312 /* Macros for conveniently generating entries in the syscall
313 tables. This first pair are not used directly. */
315 #define WRAPPER_ENTRY_X_(auxstr, sysno, name) \
316 [sysno] = { vgSysWrap_##auxstr##_##name##_before, NULL }
317 #define WRAPPER_ENTRY_XY(auxstr, sysno, name) \
318 [sysno] = { vgSysWrap_##auxstr##_##name##_before, \
319 vgSysWrap_##auxstr##_##name##_after }
321 #define WRAPPER_PRE_NAME(auxstr, name) \
322 vgSysWrap_##auxstr##_##name##_before
323 #define WRAPPER_POST_NAME(auxstr, name) \
324 vgSysWrap_##auxstr##_##name##_after
326 /* Add a generic wrapper to a syscall table. */
327 #if defined(VGO_linux) || defined(VGO_solaris) || defined(VGO_freebsd)
328 # define GENX_(sysno, name) WRAPPER_ENTRY_X_(generic, sysno, name)
329 # define GENXY(sysno, name) WRAPPER_ENTRY_XY(generic, sysno, name)
330 #elif defined(VGO_darwin)
331 # define GENX_(sysno, name) WRAPPER_ENTRY_X_(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
332 # define GENXY(sysno, name) WRAPPER_ENTRY_XY(generic, VG_DARWIN_SYSNO_INDEX(sysno), name)
337 /* Add a Linux-specific, arch-independent wrapper to a syscall
339 #define LINX_(sysno, name) WRAPPER_ENTRY_X_(linux, sysno, name)
340 #define LINXY(sysno, name) WRAPPER_ENTRY_XY(linux, sysno, name)
342 /* Add a FreeBSD-specific, arch-independent wrapper to a syscall
344 #define BSDX_(sysno, name) WRAPPER_ENTRY_X_(freebsd, sysno, name)
345 #define BSDXY(sysno, name) WRAPPER_ENTRY_XY(freebsd, sysno, name)
348 /* ---------------------------------------------------------------------
349 Macros useful for writing wrappers concisely. These refer to the
350 parameters declared by DEFN_{PRE,POST}_TEMPLATE and so in a way do
351 not help clarity of understanding. But they are just too useful to
353 ------------------------------------------------------------------ */
355 /* Reference to the syscall's arguments -- the ones which the
356 pre-wrapper may have modified, not the original copy. */
357 #define SYSNO (arrghs->sysno)
358 #define ARG1 (arrghs->arg1)
359 #define ARG2 (arrghs->arg2)
360 #define ARG3 (arrghs->arg3)
361 #define ARG4 (arrghs->arg4)
362 #define ARG5 (arrghs->arg5)
363 #define ARG6 (arrghs->arg6)
364 #define ARG7 (arrghs->arg7)
365 #define ARG8 (arrghs->arg8)
366 #define RETVAL2 (arrghs->retval2)
368 /* Provide signed versions of the argument values */
369 #define SARG1 ((Word)ARG1)
370 #define SARG2 ((Word)ARG2)
371 #define SARG3 ((Word)ARG3)
372 #define SARG4 ((Word)ARG4)
373 #define SARG5 ((Word)ARG5)
374 #define SARG6 ((Word)ARG6)
375 #define SARG7 ((Word)ARG7)
376 #define SARG8 ((Word)ARG8)
378 /* Reference to the syscall's current result status/value. General
379 paranoia all round. */
380 #define SUCCESS (status->what == SsComplete && !sr_isError(status->sres))
381 #define FAILURE (status->what == SsComplete && sr_isError(status->sres))
382 #define SWHAT (status->what)
383 #define RES (getRES(status))
384 #define RESHI (getRESHI(status))
385 #define ERR (getERR(status))
387 static inline UWord
getRES ( SyscallStatus
* st
) {
388 vg_assert(st
->what
== SsComplete
);
389 vg_assert(!sr_isError(st
->sres
));
390 return sr_Res(st
->sres
);
393 #if defined(VGO_darwin) || defined(VGO_solaris) || defined(VGO_freebsd)
394 static inline UWord
getRESHI ( SyscallStatus
* st
) {
395 vg_assert(st
->what
== SsComplete
);
396 vg_assert(!sr_isError(st
->sres
));
397 return sr_ResHI(st
->sres
);
401 static inline UWord
getERR ( SyscallStatus
* st
) {
402 vg_assert(st
->what
== SsComplete
);
403 vg_assert(sr_isError(st
->sres
));
404 return sr_Err(st
->sres
);
408 /* Set the current result status/value in various ways. */
409 #define SET_STATUS_Success(zzz) \
410 do { status->what = SsComplete; \
411 status->sres = VG_(mk_SysRes_Success)(zzz); \
415 #define SET_STATUS_Success2(zzz, zzz2) \
416 do { status->what = SsComplete; \
417 status->sres = VG_(mk_SysRes_amd64_freebsd)(zzz, zzz2, False); \
421 #define SET_STATUS_Failure(zzz) \
422 do { Word wzz = (Word)(zzz); \
423 /* Catch out wildly bogus error values. */ \
424 vg_assert(wzz >= 0 && wzz < 10000); \
425 status->what = SsComplete; \
426 status->sres = VG_(mk_SysRes_Error)(wzz); \
429 #define SET_STATUS_from_SysRes(zzz) \
431 status->what = SsComplete; \
432 status->sres = (zzz); \
436 #define PRINT(format, args...) \
437 if (VG_(clo_trace_syscalls)) \
438 VG_(printf)(format, ## args)
440 #define FUSE_COMPATIBLE_MAY_BLOCK() \
441 if (SimHintiS(SimHint_fuse_compatible, VG_(clo_sim_hints))) \
445 /* Macros used to tell tools about uses of scalar arguments. Note,
446 these assume little-endianness. These can only be used in
447 pre-wrappers, and they refer to the layout parameter passed in. */
448 /* PRRSN == "pre-register-read-sysno"
449 PRRAn == "pre-register-read-argument"
450 PSRAn == "pre-stack-read-argument"
451 PRAn == "pre-read-argument"
454 #if defined(VGP_mips32_linux)
455 /* Up to 6 parameters, 4 in registers 2 on stack. */
456 # define PRA1(s,t,a) PRRAn(1,s,t,a)
457 # define PRA2(s,t,a) PRRAn(2,s,t,a)
458 # define PRA3(s,t,a) PRRAn(3,s,t,a)
459 # define PRA4(s,t,a) PRRAn(4,s,t,a)
460 # define PRA5(s,t,a) PSRAn(5,s,t,a)
461 # define PRA6(s,t,a) PSRAn(6,s,t,a)
462 # define PRA7(s,t,a) PSRAn(7,s,t,a)
464 #elif defined(VGO_linux) && !defined(VGP_mips32_linux)
465 /* Up to 6 parameters, all in registers. */
466 # define PRA1(s,t,a) PRRAn(1,s,t,a)
467 # define PRA2(s,t,a) PRRAn(2,s,t,a)
468 # define PRA3(s,t,a) PRRAn(3,s,t,a)
469 # define PRA4(s,t,a) PRRAn(4,s,t,a)
470 # define PRA5(s,t,a) PRRAn(5,s,t,a)
471 # define PRA6(s,t,a) PRRAn(6,s,t,a)
473 #elif defined(VGP_x86_freebsd)
474 /* Up to 8 parameters, all on the stack. */
475 # define PRA1(s,t,a) PSRAn(1,s,t,a)
476 # define PRA2(s,t,a) PSRAn(2,s,t,a)
477 # define PRA3(s,t,a) PSRAn(3,s,t,a)
478 # define PRA4(s,t,a) PSRAn(4,s,t,a)
479 # define PRA5(s,t,a) PSRAn(5,s,t,a)
480 # define PRA6(s,t,a) PSRAn(6,s,t,a)
481 # define PRA7(s,t,a) PSRAn(7,s,t,a)
482 # define PRA8(s,t,a) PSRAn(8,s,t,a)
484 #elif defined(VGP_amd64_freebsd)
485 /* Up to 8 parameters, 6 in registers, 2 on the stack. */
486 /* or 7 in registers and 3 on the stack */
487 # define PRA1(s,t,a) PRRAn(1,s,t,a)
488 # define PRA2(s,t,a) PRRAn(2,s,t,a)
489 # define PRA3(s,t,a) PRRAn(3,s,t,a)
490 # define PRA4(s,t,a) PRRAn(4,s,t,a)
491 # define PRA5(s,t,a) PRRAn(5,s,t,a)
492 # define PRA6(s,t,a) \
494 if (layout->arg6_is_reg) \
499 # define PRA7(s,t,a) PSRAn(7,s,t,a)
500 # define PRA8(s,t,a) PSRAn(8,s,t,a)
502 #elif defined(VGP_x86_darwin) || defined(VGP_x86_solaris)
503 /* Up to 8 parameters, all on the stack. */
504 # define PRA1(s,t,a) PSRAn(1,s,t,a)
505 # define PRA2(s,t,a) PSRAn(2,s,t,a)
506 # define PRA3(s,t,a) PSRAn(3,s,t,a)
507 # define PRA4(s,t,a) PSRAn(4,s,t,a)
508 # define PRA5(s,t,a) PSRAn(5,s,t,a)
509 # define PRA6(s,t,a) PSRAn(6,s,t,a)
510 # define PRA7(s,t,a) PSRAn(7,s,t,a)
511 # define PRA8(s,t,a) PSRAn(8,s,t,a)
513 #elif defined(VGP_amd64_darwin) || defined(VGP_amd64_solaris)
514 /* Up to 8 parameters, 6 in registers, 2 on the stack. */
515 # define PRA1(s,t,a) PRRAn(1,s,t,a)
516 # define PRA2(s,t,a) PRRAn(2,s,t,a)
517 # define PRA3(s,t,a) PRRAn(3,s,t,a)
518 # define PRA4(s,t,a) PRRAn(4,s,t,a)
519 # define PRA5(s,t,a) PRRAn(5,s,t,a)
520 # define PRA6(s,t,a) PRRAn(6,s,t,a)
521 # define PRA7(s,t,a) PSRAn(7,s,t,a)
522 # define PRA8(s,t,a) PSRAn(8,s,t,a)
525 # error Unknown platform
529 /* Tell the tool that the syscall number is being read. */
531 VG_(tdict).track_pre_reg_read(Vg_CoreSysCall, tid, "(syscallno)", \
532 layout->o_sysno, sizeof(RegWord));
534 /* REGISTER PARAMETERS */
536 /* PRRAn: Tell the tool that the register holding the n-th syscall
537 argument is being read, at type 't' which must be at most the size
538 of a register but can be smaller. In the latter case we need to be
539 careful about endianness. */
541 /* little-endian: the part of the guest state being read is
542 let here = offset_of_reg
543 in [here .. here + sizeof(t) - 1]
544 since the least significant parts of the guest register are stored
545 in memory at the lowest address.
547 #define PRRAn_LE(n,s,t,a) \
549 Int here = layout->o_arg##n; \
550 vg_assert(sizeof(t) <= sizeof(RegWord)); \
551 vg_assert(here >= 0); \
552 VG_(tdict).track_pre_reg_read( \
553 Vg_CoreSysCall, tid, s"("#a")", \
558 /* big-endian: the part of the guest state being read is
559 let next = offset_of_reg + sizeof(reg)
560 in [next - sizeof(t) .. next - 1]
561 since the least significant parts of the guest register are stored
562 in memory at the highest address.
564 #define PRRAn_BE(n,s,t,a) \
566 Int here = layout->o_arg##n; \
567 Int next = layout->o_arg##n + sizeof(RegWord); \
568 vg_assert(sizeof(t) <= sizeof(RegWord)); \
569 vg_assert(here >= 0); \
570 VG_(tdict).track_pre_reg_read( \
571 Vg_CoreSysCall, tid, s"("#a")", \
572 next-sizeof(t), sizeof(t) \
576 #if defined(VG_BIGENDIAN)
577 # define PRRAn(n,s,t,a) PRRAn_BE(n,s,t,a)
578 #elif defined(VG_LITTLEENDIAN)
579 # define PRRAn(n,s,t,a) PRRAn_LE(n,s,t,a)
581 # error "Unknown endianness"
585 /* STACK PARAMETERS */
587 /* PSRAn: Tell the tool that the memory holding the n-th syscall
588 argument is being read, at type 't' which must be at most the size
589 of a register but can be smaller. In the latter case we need to be
590 careful about endianness. */
592 /* little-endian: the part of the guest state being read is
593 let here = offset_of_reg
594 in [here .. here + sizeof(t) - 1]
595 since the least significant parts of the guest register are stored
596 in memory at the lowest address.
598 #define PSRAn_LE(n,s,t,a) \
600 Addr here = layout->s_arg##n + VG_(get_SP)(tid); \
601 vg_assert(sizeof(t) <= sizeof(RegWord)); \
602 VG_(tdict).track_pre_mem_read( \
603 Vg_CoreSysCallArgInMem, tid, s"("#a")", \
608 /* big-endian: the part of the guest state being read is
609 let next = offset_of_reg + sizeof(reg)
610 in [next - sizeof(t) .. next - 1]
611 since the least significant parts of the guest register are stored
612 in memory at the highest address.
614 #if (defined(VGP_mips32_linux) && defined (_MIPSEB))
615 #define PSRAn_BE(n,s,t,a) \
617 Addr next = layout->s_arg##n + sizeof(RegWord) + \
619 vg_assert(sizeof(t) <= sizeof(RegWord)); \
620 VG_(tdict).track_pre_mem_read( \
621 Vg_CoreSysCallArgInMem, tid, s"("#a")", \
622 next-sizeof(t), sizeof(t) \
626 #define PSRAn_BE(n,s,t,a) \
628 Addr next = layout->o_arg##n + sizeof(RegWord) + \
629 VG_(threads)[tid].arch.vex.VG_STACK_PTR; \
630 vg_assert(sizeof(t) <= sizeof(RegWord)); \
631 VG_(tdict).track_pre_mem_read( \
632 Vg_CoreSysCallArgInMem, tid, s"("#a")", \
633 next-sizeof(t), sizeof(t) \
638 #if defined(VG_BIGENDIAN)
639 # define PSRAn(n,s,t,a) PSRAn_BE(n,s,t,a)
640 #elif defined(VG_LITTLEENDIAN)
641 # define PSRAn(n,s,t,a) PSRAn_LE(n,s,t,a)
643 # error "Unknown endianness"
647 #define PRE_REG_READ0(tr, s) \
648 if (VG_(tdict).track_pre_reg_read) { \
651 #define PRE_REG_READ1(tr, s, t1, a1) \
652 if (VG_(tdict).track_pre_reg_read) { \
656 #define PRE_REG_READ2(tr, s, t1, a1, t2, a2) \
657 if (VG_(tdict).track_pre_reg_read) { \
659 PRA1(s,t1,a1); PRA2(s,t2,a2); \
661 #define PRE_REG_READ3(tr, s, t1, a1, t2, a2, t3, a3) \
662 if (VG_(tdict).track_pre_reg_read) { \
664 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
666 #define PRE_REG_READ4(tr, s, t1, a1, t2, a2, t3, a3, t4, a4) \
667 if (VG_(tdict).track_pre_reg_read) { \
669 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
672 #define PRE_REG_READ5(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
673 if (VG_(tdict).track_pre_reg_read) { \
675 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
676 PRA4(s,t4,a4); PRA5(s,t5,a5); \
678 #define PRE_REG_READ6(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
679 if (VG_(tdict).track_pre_reg_read) { \
681 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
682 PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6); \
684 #define PRE_REG_READ7(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7) \
685 if (VG_(tdict).track_pre_reg_read) { \
687 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
688 PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6); \
692 #define PRE_REG_READ8(tr, s, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6, t7, a7, t8, a8) \
693 if (VG_(tdict).track_pre_reg_read) { \
695 PRA1(s,t1,a1); PRA2(s,t2,a2); PRA3(s,t3,a3); \
696 PRA4(s,t4,a4); PRA5(s,t5,a5); PRA6(s,t6,a6); \
697 PRA7(s,t7,a7); PRA8(s,t8,a8); \
700 #define PRE_MEM_READ(zzname, zzaddr, zzlen) \
701 VG_TRACK( pre_mem_read, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
703 #define PRE_MEM_RASCIIZ(zzname, zzaddr) \
704 VG_TRACK( pre_mem_read_asciiz, Vg_CoreSysCall, tid, zzname, zzaddr)
706 #define PRE_MEM_WRITE(zzname, zzaddr, zzlen) \
707 VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid, zzname, zzaddr, zzlen)
709 #define POST_MEM_WRITE(zzaddr, zzlen) \
710 VG_TRACK( post_mem_write, Vg_CoreSysCall, tid, zzaddr, zzlen)
713 #define PRE_FIELD_READ(zzname, zzfield) \
714 PRE_MEM_READ(zzname, (UWord)&zzfield, sizeof(zzfield))
716 #define PRE_FIELD_WRITE(zzname, zzfield) \
717 PRE_MEM_WRITE(zzname, (UWord)&zzfield, sizeof(zzfield))
719 #define POST_FIELD_WRITE(zzfield) \
720 POST_MEM_WRITE((UWord)&zzfield, sizeof(zzfield))
722 // Macros to support 64-bit syscall args split into two 32 bit values
723 #define LOHI64(lo,hi) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
724 #if defined(VG_LITTLEENDIAN)
725 #define MERGE64(lo,hi) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
726 #define MERGE64_FIRST(name) name##_low
727 #define MERGE64_SECOND(name) name##_high
728 #elif defined(VG_BIGENDIAN)
729 #define MERGE64(hi,lo) ( ((ULong)(lo)) | (((ULong)(hi)) << 32) )
730 #define MERGE64_FIRST(name) name##_high
731 #define MERGE64_SECOND(name) name##_low
733 #error Unknown endianness
736 #endif // __PRIV_TYPES_N_MACROS_H
738 /*--------------------------------------------------------------------*/
740 /*--------------------------------------------------------------------*/