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