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