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