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@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
getRES(SyscallStatus * st)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
getRESHI(SyscallStatus * st)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
getERR(SyscallStatus * st)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