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