1 /* -*- c -*- 2 ---------------------------------------------------------------- 3 4 Notice that the following BSD-style license applies to this one 5 file (valgrind.h) only. The rest of Valgrind is licensed under the 6 terms of the GNU General Public License, version 2, unless 7 otherwise indicated. See the COPYING file in the source 8 distribution for details. 9 10 ---------------------------------------------------------------- 11 12 This file is part of Valgrind, a dynamic binary instrumentation 13 framework. 14 15 Copyright (C) 2000-2013 Julian Seward. All rights reserved. 16 17 Redistribution and use in source and binary forms, with or without 18 modification, are permitted provided that the following conditions 19 are met: 20 21 1. Redistributions of source code must retain the above copyright 22 notice, this list of conditions and the following disclaimer. 23 24 2. The origin of this software must not be misrepresented; you must 25 not claim that you wrote the original software. If you use this 26 software in a product, an acknowledgment in the product 27 documentation would be appreciated but is not required. 28 29 3. Altered source versions must be plainly marked as such, and must 30 not be misrepresented as being the original software. 31 32 4. The name of the author may not be used to endorse or promote 33 products derived from this software without specific prior written 34 permission. 35 36 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 37 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 38 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 40 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 41 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 42 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 43 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 44 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 45 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 46 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 48 ---------------------------------------------------------------- 49 50 Notice that the above BSD-style license applies to this one file 51 (valgrind.h) only. The entire rest of Valgrind is licensed under 52 the terms of the GNU General Public License, version 2. See the 53 COPYING file in the source distribution for details. 54 55 ---------------------------------------------------------------- 56 */ 57 58 59 /* This file is for inclusion into client (your!) code. 60 61 You can use these macros to manipulate and query Valgrind's 62 execution inside your own programs. 63 64 The resulting executables will still run without Valgrind, just a 65 little bit more slowly than they otherwise would, but otherwise 66 unchanged. When not running on valgrind, each client request 67 consumes very few (eg. 7) instructions, so the resulting performance 68 loss is negligible unless you plan to execute client requests 69 millions of times per second. Nevertheless, if that is still a 70 problem, you can compile with the NVALGRIND symbol defined (gcc 71 -DNVALGRIND) so that client requests are not even compiled in. */ 72 73 #ifndef __VALGRIND_H 74 #define __VALGRIND_H 75 76 77 /* ------------------------------------------------------------------ */ 78 /* VERSION NUMBER OF VALGRIND */ 79 /* ------------------------------------------------------------------ */ 80 81 /* Specify Valgrind's version number, so that user code can 82 conditionally compile based on our version number. Note that these 83 were introduced at version 3.6 and so do not exist in version 3.5 84 or earlier. The recommended way to use them to check for "version 85 X.Y or later" is (eg) 86 87 #if defined(__VALGRIND_MAJOR__) && defined(__VALGRIND_MINOR__) \ 88 && (__VALGRIND_MAJOR__ > 3 \ 89 || (__VALGRIND_MAJOR__ == 3 && __VALGRIND_MINOR__ >= 6)) 90 */ 91 #define __VALGRIND_MAJOR__ 3 92 #define __VALGRIND_MINOR__ 10 93 94 95 #include <stdarg.h> 96 97 /* Nb: this file might be included in a file compiled with -ansi. So 98 we can't use C++ style "//" comments nor the "asm" keyword (instead 99 use "__asm__"). */ 100 101 /* Derive some tags indicating what the target platform is. Note 102 that in this file we're using the compiler's CPP symbols for 103 identifying architectures, which are different to the ones we use 104 within the rest of Valgrind. Note, __powerpc__ is active for both 105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the 106 latter (on Linux, that is). 107 108 Misc note: how to find out what's predefined in gcc by default: 109 gcc -Wp,-dM somefile.c 110 */ 111 #undef PLAT_x86_darwin 112 #undef PLAT_amd64_darwin 113 #undef PLAT_x86_win32 114 #undef PLAT_amd64_win64 115 #undef PLAT_x86_linux 116 #undef PLAT_amd64_linux 117 #undef PLAT_ppc32_linux 118 #undef PLAT_ppc64_linux 119 #undef PLAT_arm_linux 120 #undef PLAT_arm64_linux 121 #undef PLAT_s390x_linux 122 #undef PLAT_mips32_linux 123 #undef PLAT_mips64_linux 124 125 126 #if defined(__APPLE__) && defined(__i386__) 127 # define PLAT_x86_darwin 1 128 #elif defined(__APPLE__) && defined(__x86_64__) 129 # define PLAT_amd64_darwin 1 130 #elif (defined(__MINGW32__) && !defined(__MINGW64__)) \ 131 || defined(__CYGWIN32__) \ 132 || (defined(_WIN32) && defined(_M_IX86)) 133 # define PLAT_x86_win32 1 134 #elif defined(__MINGW64__) \ 135 || (defined(_WIN64) && defined(_M_X64)) 136 # define PLAT_amd64_win64 1 137 #elif defined(__linux__) && defined(__i386__) 138 # define PLAT_x86_linux 1 139 #elif defined(__linux__) && defined(__x86_64__) 140 # define PLAT_amd64_linux 1 141 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) 142 # define PLAT_ppc32_linux 1 143 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) 144 # define PLAT_ppc64_linux 1 145 #elif defined(__linux__) && defined(__arm__) && !defined(__aarch64__) 146 # define PLAT_arm_linux 1 147 #elif defined(__linux__) && defined(__aarch64__) && !defined(__arm__) 148 # define PLAT_arm64_linux 1 149 #elif defined(__linux__) && defined(__s390__) && defined(__s390x__) 150 # define PLAT_s390x_linux 1 151 #elif defined(__linux__) && defined(__mips__) && (__mips==64) 152 # define PLAT_mips64_linux 1 153 #elif defined(__linux__) && defined(__mips__) && (__mips!=64) 154 # define PLAT_mips32_linux 1 155 #else 156 /* If we're not compiling for our target platform, don't generate 157 any inline asms. */ 158 # if !defined(NVALGRIND) 159 # define NVALGRIND 1 160 # endif 161 #endif 162 163 164 /* ------------------------------------------------------------------ */ 165 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ 166 /* in here of use to end-users -- skip to the next section. */ 167 /* ------------------------------------------------------------------ */ 168 169 /* 170 * VALGRIND_DO_CLIENT_REQUEST(): a statement that invokes a Valgrind client 171 * request. Accepts both pointers and integers as arguments. 172 * 173 * VALGRIND_DO_CLIENT_REQUEST_STMT(): a statement that invokes a Valgrind 174 * client request that does not return a value. 175 176 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind 177 * client request and whose value equals the client request result. Accepts 178 * both pointers and integers as arguments. Note that such calls are not 179 * necessarily pure functions -- they may have side effects. 180 */ 181 182 #define VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, \ 183 _zzq_request, _zzq_arg1, _zzq_arg2, \ 184 _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 185 do { (_zzq_rlval) = VALGRIND_DO_CLIENT_REQUEST_EXPR((_zzq_default), \ 186 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ 187 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) 188 189 #define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \ 190 _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 191 do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 192 (_zzq_request), (_zzq_arg1), (_zzq_arg2), \ 193 (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0) 194 195 #if defined(NVALGRIND) 196 197 /* Define NVALGRIND to completely remove the Valgrind magic sequence 198 from the compiled code (analogous to NDEBUG's effects on 199 assert()) */ 200 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 201 _zzq_default, _zzq_request, \ 202 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 203 (_zzq_default) 204 205 #else /* ! NVALGRIND */ 206 207 /* The following defines the magic code sequences which the JITter 208 spots and handles magically. Don't look too closely at them as 209 they will rot your brain. 210 211 The assembly code sequences for all architectures is in this one 212 file. This is because this file must be stand-alone, and we don't 213 want to have multiple files. 214 215 For VALGRIND_DO_CLIENT_REQUEST, we must ensure that the default 216 value gets put in the return slot, so that everything works when 217 this is executed not under Valgrind. Args are passed in a memory 218 block, and so there's no intrinsic limit to the number that could 219 be passed, but it's currently five. 220 221 The macro args are: 222 _zzq_rlval result lvalue 223 _zzq_default default value (result returned when running on real CPU) 224 _zzq_request request code 225 _zzq_arg1..5 request params 226 227 The other two macros are used to support function wrapping, and are 228 a lot simpler. VALGRIND_GET_NR_CONTEXT returns the value of the 229 guest's NRADDR pseudo-register and whatever other information is 230 needed to safely run the call original from the wrapper: on 231 ppc64-linux, the R2 value at the divert point is also needed. This 232 information is abstracted into a user-visible type, OrigFn. 233 234 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the 235 guest, but guarantees that the branch instruction will not be 236 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: 237 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a 238 complete inline asm, since it needs to be combined with more magic 239 inline asm stuff to be useful. 240 */ 241 242 /* ------------------------- x86-{linux,darwin} ---------------- */ 243 244 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ 245 || (defined(PLAT_x86_win32) && defined(__GNUC__)) 246 247 typedef 248 struct { 249 unsigned int nraddr; /* where's the code? */ 250 } 251 OrigFn; 252 253 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 254 "roll $3, %%edi ; roll $13, %%edi\n\t" \ 255 "roll $29, %%edi ; roll $19, %%edi\n\t" 256 257 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 258 _zzq_default, _zzq_request, \ 259 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 260 __extension__ \ 261 ({volatile unsigned int _zzq_args[6]; \ 262 volatile unsigned int _zzq_result; \ 263 _zzq_args[0] = (unsigned int)(_zzq_request); \ 264 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 265 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 266 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 267 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 268 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 269 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 270 /* %EDX = client_request ( %EAX ) */ \ 271 "xchgl %%ebx,%%ebx" \ 272 : "=d" (_zzq_result) \ 273 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 274 : "cc", "memory" \ 275 ); \ 276 _zzq_result; \ 277 }) 278 279 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 280 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 281 volatile unsigned int __addr; \ 282 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 283 /* %EAX = guest_NRADDR */ \ 284 "xchgl %%ecx,%%ecx" \ 285 : "=a" (__addr) \ 286 : \ 287 : "cc", "memory" \ 288 ); \ 289 _zzq_orig->nraddr = __addr; \ 290 } 291 292 #define VALGRIND_CALL_NOREDIR_EAX \ 293 __SPECIAL_INSTRUCTION_PREAMBLE \ 294 /* call-noredir *%EAX */ \ 295 "xchgl %%edx,%%edx\n\t" 296 297 #define VALGRIND_VEX_INJECT_IR() \ 298 do { \ 299 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 300 "xchgl %%edi,%%edi\n\t" \ 301 : : : "cc", "memory" \ 302 ); \ 303 } while (0) 304 305 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */ 306 307 /* ------------------------- x86-Win32 ------------------------- */ 308 309 #if defined(PLAT_x86_win32) && !defined(__GNUC__) 310 311 typedef 312 struct { 313 unsigned int nraddr; /* where's the code? */ 314 } 315 OrigFn; 316 317 #if defined(_MSC_VER) 318 319 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 320 __asm rol edi, 3 __asm rol edi, 13 \ 321 __asm rol edi, 29 __asm rol edi, 19 322 323 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 324 _zzq_default, _zzq_request, \ 325 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 326 valgrind_do_client_request_expr((uintptr_t)(_zzq_default), \ 327 (uintptr_t)(_zzq_request), (uintptr_t)(_zzq_arg1), \ 328 (uintptr_t)(_zzq_arg2), (uintptr_t)(_zzq_arg3), \ 329 (uintptr_t)(_zzq_arg4), (uintptr_t)(_zzq_arg5)) 330 331 static __inline uintptr_t 332 valgrind_do_client_request_expr(uintptr_t _zzq_default, uintptr_t _zzq_request, 333 uintptr_t _zzq_arg1, uintptr_t _zzq_arg2, 334 uintptr_t _zzq_arg3, uintptr_t _zzq_arg4, 335 uintptr_t _zzq_arg5) 336 { 337 volatile uintptr_t _zzq_args[6]; 338 volatile unsigned int _zzq_result; 339 _zzq_args[0] = (uintptr_t)(_zzq_request); 340 _zzq_args[1] = (uintptr_t)(_zzq_arg1); 341 _zzq_args[2] = (uintptr_t)(_zzq_arg2); 342 _zzq_args[3] = (uintptr_t)(_zzq_arg3); 343 _zzq_args[4] = (uintptr_t)(_zzq_arg4); 344 _zzq_args[5] = (uintptr_t)(_zzq_arg5); 345 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default 346 __SPECIAL_INSTRUCTION_PREAMBLE 347 /* %EDX = client_request ( %EAX ) */ 348 __asm xchg ebx,ebx 349 __asm mov _zzq_result, edx 350 } 351 return _zzq_result; 352 } 353 354 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 355 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 356 volatile unsigned int __addr; \ 357 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ 358 /* %EAX = guest_NRADDR */ \ 359 __asm xchg ecx,ecx \ 360 __asm mov __addr, eax \ 361 } \ 362 _zzq_orig->nraddr = __addr; \ 363 } 364 365 #define VALGRIND_CALL_NOREDIR_EAX ERROR 366 367 #define VALGRIND_VEX_INJECT_IR() \ 368 do { \ 369 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ 370 __asm xchg edi,edi \ 371 } \ 372 } while (0) 373 374 #else 375 #error Unsupported compiler. 376 #endif 377 378 #endif /* PLAT_x86_win32 */ 379 380 /* ------------------------ amd64-{linux,darwin} --------------- */ 381 382 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \ 383 || (defined(PLAT_amd64_win64) && defined(__GNUC__)) 384 385 typedef 386 struct { 387 unsigned long long int nraddr; /* where's the code? */ 388 } 389 OrigFn; 390 391 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 392 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ 393 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" 394 395 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 396 _zzq_default, _zzq_request, \ 397 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 398 __extension__ \ 399 ({ volatile unsigned long long int _zzq_args[6]; \ 400 volatile unsigned long long int _zzq_result; \ 401 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 402 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 403 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 404 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 405 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 406 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 407 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 408 /* %RDX = client_request ( %RAX ) */ \ 409 "xchgq %%rbx,%%rbx" \ 410 : "=d" (_zzq_result) \ 411 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 412 : "cc", "memory" \ 413 ); \ 414 _zzq_result; \ 415 }) 416 417 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 418 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 419 volatile unsigned long long int __addr; \ 420 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 421 /* %RAX = guest_NRADDR */ \ 422 "xchgq %%rcx,%%rcx" \ 423 : "=a" (__addr) \ 424 : \ 425 : "cc", "memory" \ 426 ); \ 427 _zzq_orig->nraddr = __addr; \ 428 } 429 430 #define VALGRIND_CALL_NOREDIR_RAX \ 431 __SPECIAL_INSTRUCTION_PREAMBLE \ 432 /* call-noredir *%RAX */ \ 433 "xchgq %%rdx,%%rdx\n\t" 434 435 #define VALGRIND_VEX_INJECT_IR() \ 436 do { \ 437 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 438 "xchgq %%rdi,%%rdi\n\t" \ 439 : : : "cc", "memory" \ 440 ); \ 441 } while (0) 442 443 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ 444 445 /* ------------------------- amd64-Win64 ------------------------- */ 446 447 #if defined(PLAT_amd64_win64) && !defined(__GNUC__) 448 449 #error Unsupported compiler. 450 451 #endif /* PLAT_amd64_win64 */ 452 453 /* ------------------------ ppc32-linux ------------------------ */ 454 455 #if defined(PLAT_ppc32_linux) 456 457 typedef 458 struct { 459 unsigned int nraddr; /* where's the code? */ 460 } 461 OrigFn; 462 463 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 464 "rlwinm 0,0,3,0,31 ; rlwinm 0,0,13,0,31\n\t" \ 465 "rlwinm 0,0,29,0,31 ; rlwinm 0,0,19,0,31\n\t" 466 467 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 468 _zzq_default, _zzq_request, \ 469 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 470 \ 471 __extension__ \ 472 ({ unsigned int _zzq_args[6]; \ 473 unsigned int _zzq_result; \ 474 unsigned int* _zzq_ptr; \ 475 _zzq_args[0] = (unsigned int)(_zzq_request); \ 476 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 477 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 478 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 479 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 480 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 481 _zzq_ptr = _zzq_args; \ 482 __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 483 "mr 4,%2\n\t" /*ptr*/ \ 484 __SPECIAL_INSTRUCTION_PREAMBLE \ 485 /* %R3 = client_request ( %R4 ) */ \ 486 "or 1,1,1\n\t" \ 487 "mr %0,3" /*result*/ \ 488 : "=b" (_zzq_result) \ 489 : "b" (_zzq_default), "b" (_zzq_ptr) \ 490 : "cc", "memory", "r3", "r4"); \ 491 _zzq_result; \ 492 }) 493 494 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 495 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 496 unsigned int __addr; \ 497 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 498 /* %R3 = guest_NRADDR */ \ 499 "or 2,2,2\n\t" \ 500 "mr %0,3" \ 501 : "=b" (__addr) \ 502 : \ 503 : "cc", "memory", "r3" \ 504 ); \ 505 _zzq_orig->nraddr = __addr; \ 506 } 507 508 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 509 __SPECIAL_INSTRUCTION_PREAMBLE \ 510 /* branch-and-link-to-noredir *%R11 */ \ 511 "or 3,3,3\n\t" 512 513 #define VALGRIND_VEX_INJECT_IR() \ 514 do { \ 515 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 516 "or 5,5,5\n\t" \ 517 ); \ 518 } while (0) 519 520 #endif /* PLAT_ppc32_linux */ 521 522 /* ------------------------ ppc64-linux ------------------------ */ 523 524 #if defined(PLAT_ppc64_linux) 525 526 typedef 527 struct { 528 unsigned long long int nraddr; /* where's the code? */ 529 unsigned long long int r2; /* what tocptr do we need? */ 530 } 531 OrigFn; 532 533 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 534 "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ 535 "rotldi 0,0,61 ; rotldi 0,0,51\n\t" 536 537 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 538 _zzq_default, _zzq_request, \ 539 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 540 \ 541 __extension__ \ 542 ({ unsigned long long int _zzq_args[6]; \ 543 unsigned long long int _zzq_result; \ 544 unsigned long long int* _zzq_ptr; \ 545 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 546 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 547 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 548 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 549 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 550 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 551 _zzq_ptr = _zzq_args; \ 552 __asm__ volatile("mr 3,%1\n\t" /*default*/ \ 553 "mr 4,%2\n\t" /*ptr*/ \ 554 __SPECIAL_INSTRUCTION_PREAMBLE \ 555 /* %R3 = client_request ( %R4 ) */ \ 556 "or 1,1,1\n\t" \ 557 "mr %0,3" /*result*/ \ 558 : "=b" (_zzq_result) \ 559 : "b" (_zzq_default), "b" (_zzq_ptr) \ 560 : "cc", "memory", "r3", "r4"); \ 561 _zzq_result; \ 562 }) 563 564 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 565 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 566 unsigned long long int __addr; \ 567 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 568 /* %R3 = guest_NRADDR */ \ 569 "or 2,2,2\n\t" \ 570 "mr %0,3" \ 571 : "=b" (__addr) \ 572 : \ 573 : "cc", "memory", "r3" \ 574 ); \ 575 _zzq_orig->nraddr = __addr; \ 576 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 577 /* %R3 = guest_NRADDR_GPR2 */ \ 578 "or 4,4,4\n\t" \ 579 "mr %0,3" \ 580 : "=b" (__addr) \ 581 : \ 582 : "cc", "memory", "r3" \ 583 ); \ 584 _zzq_orig->r2 = __addr; \ 585 } 586 587 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 588 __SPECIAL_INSTRUCTION_PREAMBLE \ 589 /* branch-and-link-to-noredir *%R11 */ \ 590 "or 3,3,3\n\t" 591 592 #define VALGRIND_VEX_INJECT_IR() \ 593 do { \ 594 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 595 "or 5,5,5\n\t" \ 596 ); \ 597 } while (0) 598 599 #endif /* PLAT_ppc64_linux */ 600 601 /* ------------------------- arm-linux ------------------------- */ 602 603 #if defined(PLAT_arm_linux) 604 605 typedef 606 struct { 607 unsigned int nraddr; /* where's the code? */ 608 } 609 OrigFn; 610 611 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 612 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ 613 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" 614 615 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 616 _zzq_default, _zzq_request, \ 617 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 618 \ 619 __extension__ \ 620 ({volatile unsigned int _zzq_args[6]; \ 621 volatile unsigned int _zzq_result; \ 622 _zzq_args[0] = (unsigned int)(_zzq_request); \ 623 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 624 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 625 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 626 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 627 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 628 __asm__ volatile("mov r3, %1\n\t" /*default*/ \ 629 "mov r4, %2\n\t" /*ptr*/ \ 630 __SPECIAL_INSTRUCTION_PREAMBLE \ 631 /* R3 = client_request ( R4 ) */ \ 632 "orr r10, r10, r10\n\t" \ 633 "mov %0, r3" /*result*/ \ 634 : "=r" (_zzq_result) \ 635 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ 636 : "cc","memory", "r3", "r4"); \ 637 _zzq_result; \ 638 }) 639 640 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 641 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 642 unsigned int __addr; \ 643 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 644 /* R3 = guest_NRADDR */ \ 645 "orr r11, r11, r11\n\t" \ 646 "mov %0, r3" \ 647 : "=r" (__addr) \ 648 : \ 649 : "cc", "memory", "r3" \ 650 ); \ 651 _zzq_orig->nraddr = __addr; \ 652 } 653 654 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 655 __SPECIAL_INSTRUCTION_PREAMBLE \ 656 /* branch-and-link-to-noredir *%R4 */ \ 657 "orr r12, r12, r12\n\t" 658 659 #define VALGRIND_VEX_INJECT_IR() \ 660 do { \ 661 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 662 "orr r9, r9, r9\n\t" \ 663 : : : "cc", "memory" \ 664 ); \ 665 } while (0) 666 667 #endif /* PLAT_arm_linux */ 668 669 /* ------------------------ arm64-linux ------------------------- */ 670 671 #if defined(PLAT_arm64_linux) 672 673 typedef 674 struct { 675 unsigned long long int nraddr; /* where's the code? */ 676 } 677 OrigFn; 678 679 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 680 "ror x12, x12, #3 ; ror x12, x12, #13 \n\t" \ 681 "ror x12, x12, #51 ; ror x12, x12, #61 \n\t" 682 683 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 684 _zzq_default, _zzq_request, \ 685 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 686 \ 687 __extension__ \ 688 ({volatile unsigned long long int _zzq_args[6]; \ 689 volatile unsigned long long int _zzq_result; \ 690 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 691 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 692 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 693 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 694 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 695 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 696 __asm__ volatile("mov x3, %1\n\t" /*default*/ \ 697 "mov x4, %2\n\t" /*ptr*/ \ 698 __SPECIAL_INSTRUCTION_PREAMBLE \ 699 /* X3 = client_request ( X4 ) */ \ 700 "orr x10, x10, x10\n\t" \ 701 "mov %0, x3" /*result*/ \ 702 : "=r" (_zzq_result) \ 703 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ 704 : "cc","memory", "x3", "x4"); \ 705 _zzq_result; \ 706 }) 707 708 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 709 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 710 unsigned long long int __addr; \ 711 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 712 /* X3 = guest_NRADDR */ \ 713 "orr x11, x11, x11\n\t" \ 714 "mov %0, x3" \ 715 : "=r" (__addr) \ 716 : \ 717 : "cc", "memory", "x3" \ 718 ); \ 719 _zzq_orig->nraddr = __addr; \ 720 } 721 722 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 723 __SPECIAL_INSTRUCTION_PREAMBLE \ 724 /* branch-and-link-to-noredir X8 */ \ 725 "orr x12, x12, x12\n\t" 726 727 #define VALGRIND_VEX_INJECT_IR() \ 728 do { \ 729 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 730 "orr x9, x9, x9\n\t" \ 731 : : : "cc", "memory" \ 732 ); \ 733 } while (0) 734 735 #endif /* PLAT_arm64_linux */ 736 737 /* ------------------------ s390x-linux ------------------------ */ 738 739 #if defined(PLAT_s390x_linux) 740 741 typedef 742 struct { 743 unsigned long long int nraddr; /* where's the code? */ 744 } 745 OrigFn; 746 747 /* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific 748 * code. This detection is implemented in platform specific toIR.c 749 * (e.g. VEX/priv/guest_s390_decoder.c). 750 */ 751 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 752 "lr 15,15\n\t" \ 753 "lr 1,1\n\t" \ 754 "lr 2,2\n\t" \ 755 "lr 3,3\n\t" 756 757 #define __CLIENT_REQUEST_CODE "lr 2,2\n\t" 758 #define __GET_NR_CONTEXT_CODE "lr 3,3\n\t" 759 #define __CALL_NO_REDIR_CODE "lr 4,4\n\t" 760 #define __VEX_INJECT_IR_CODE "lr 5,5\n\t" 761 762 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 763 _zzq_default, _zzq_request, \ 764 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 765 __extension__ \ 766 ({volatile unsigned long long int _zzq_args[6]; \ 767 volatile unsigned long long int _zzq_result; \ 768 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 769 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 770 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 771 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 772 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 773 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 774 __asm__ volatile(/* r2 = args */ \ 775 "lgr 2,%1\n\t" \ 776 /* r3 = default */ \ 777 "lgr 3,%2\n\t" \ 778 __SPECIAL_INSTRUCTION_PREAMBLE \ 779 __CLIENT_REQUEST_CODE \ 780 /* results = r3 */ \ 781 "lgr %0, 3\n\t" \ 782 : "=d" (_zzq_result) \ 783 : "a" (&_zzq_args[0]), "0" (_zzq_default) \ 784 : "cc", "2", "3", "memory" \ 785 ); \ 786 _zzq_result; \ 787 }) 788 789 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 790 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 791 volatile unsigned long long int __addr; \ 792 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 793 __GET_NR_CONTEXT_CODE \ 794 "lgr %0, 3\n\t" \ 795 : "=a" (__addr) \ 796 : \ 797 : "cc", "3", "memory" \ 798 ); \ 799 _zzq_orig->nraddr = __addr; \ 800 } 801 802 #define VALGRIND_CALL_NOREDIR_R1 \ 803 __SPECIAL_INSTRUCTION_PREAMBLE \ 804 __CALL_NO_REDIR_CODE 805 806 #define VALGRIND_VEX_INJECT_IR() \ 807 do { \ 808 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 809 __VEX_INJECT_IR_CODE); \ 810 } while (0) 811 812 #endif /* PLAT_s390x_linux */ 813 814 /* ------------------------- mips32-linux ---------------- */ 815 816 #if defined(PLAT_mips32_linux) 817 818 typedef 819 struct { 820 unsigned int nraddr; /* where's the code? */ 821 } 822 OrigFn; 823 824 /* .word 0x342 825 * .word 0x742 826 * .word 0xC2 827 * .word 0x4C2*/ 828 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 829 "srl $0, $0, 13\n\t" \ 830 "srl $0, $0, 29\n\t" \ 831 "srl $0, $0, 3\n\t" \ 832 "srl $0, $0, 19\n\t" 833 834 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 835 _zzq_default, _zzq_request, \ 836 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 837 __extension__ \ 838 ({ volatile unsigned int _zzq_args[6]; \ 839 volatile unsigned int _zzq_result; \ 840 _zzq_args[0] = (unsigned int)(_zzq_request); \ 841 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ 842 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ 843 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ 844 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ 845 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ 846 __asm__ volatile("move $11, %1\n\t" /*default*/ \ 847 "move $12, %2\n\t" /*ptr*/ \ 848 __SPECIAL_INSTRUCTION_PREAMBLE \ 849 /* T3 = client_request ( T4 ) */ \ 850 "or $13, $13, $13\n\t" \ 851 "move %0, $11\n\t" /*result*/ \ 852 : "=r" (_zzq_result) \ 853 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ 854 : "$11", "$12"); \ 855 _zzq_result; \ 856 }) 857 858 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 859 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 860 volatile unsigned int __addr; \ 861 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 862 /* %t9 = guest_NRADDR */ \ 863 "or $14, $14, $14\n\t" \ 864 "move %0, $11" /*result*/ \ 865 : "=r" (__addr) \ 866 : \ 867 : "$11" \ 868 ); \ 869 _zzq_orig->nraddr = __addr; \ 870 } 871 872 #define VALGRIND_CALL_NOREDIR_T9 \ 873 __SPECIAL_INSTRUCTION_PREAMBLE \ 874 /* call-noredir *%t9 */ \ 875 "or $15, $15, $15\n\t" 876 877 #define VALGRIND_VEX_INJECT_IR() \ 878 do { \ 879 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 880 "or $11, $11, $11\n\t" \ 881 ); \ 882 } while (0) 883 884 885 #endif /* PLAT_mips32_linux */ 886 887 /* ------------------------- mips64-linux ---------------- */ 888 889 #if defined(PLAT_mips64_linux) 890 891 typedef 892 struct { 893 unsigned long long nraddr; /* where's the code? */ 894 } 895 OrigFn; 896 897 /* dsll $0,$0, 3 898 * dsll $0,$0, 13 899 * dsll $0,$0, 29 900 * dsll $0,$0, 19*/ 901 #define __SPECIAL_INSTRUCTION_PREAMBLE \ 902 "dsll $0,$0, 3 ; dsll $0,$0,13\n\t" \ 903 "dsll $0,$0,29 ; dsll $0,$0,19\n\t" 904 905 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 906 _zzq_default, _zzq_request, \ 907 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ 908 __extension__ \ 909 ({ volatile unsigned long long int _zzq_args[6]; \ 910 volatile unsigned long long int _zzq_result; \ 911 _zzq_args[0] = (unsigned long long int)(_zzq_request); \ 912 _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ 913 _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ 914 _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ 915 _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ 916 _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \ 917 __asm__ volatile("move $11, %1\n\t" /*default*/ \ 918 "move $12, %2\n\t" /*ptr*/ \ 919 __SPECIAL_INSTRUCTION_PREAMBLE \ 920 /* $11 = client_request ( $12 ) */ \ 921 "or $13, $13, $13\n\t" \ 922 "move %0, $11\n\t" /*result*/ \ 923 : "=r" (_zzq_result) \ 924 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ 925 : "$11", "$12"); \ 926 _zzq_result; \ 927 }) 928 929 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ 930 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ 931 volatile unsigned long long int __addr; \ 932 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 933 /* $11 = guest_NRADDR */ \ 934 "or $14, $14, $14\n\t" \ 935 "move %0, $11" /*result*/ \ 936 : "=r" (__addr) \ 937 : \ 938 : "$11"); \ 939 _zzq_orig->nraddr = __addr; \ 940 } 941 942 #define VALGRIND_CALL_NOREDIR_T9 \ 943 __SPECIAL_INSTRUCTION_PREAMBLE \ 944 /* call-noredir $25 */ \ 945 "or $15, $15, $15\n\t" 946 947 #define VALGRIND_VEX_INJECT_IR() \ 948 do { \ 949 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ 950 "or $11, $11, $11\n\t" \ 951 ); \ 952 } while (0) 953 954 #endif /* PLAT_mips64_linux */ 955 956 /* Insert assembly code for other platforms here... */ 957 958 #endif /* NVALGRIND */ 959 960 961 /* ------------------------------------------------------------------ */ 962 /* PLATFORM SPECIFICS for FUNCTION WRAPPING. This is all very */ 963 /* ugly. It's the least-worst tradeoff I can think of. */ 964 /* ------------------------------------------------------------------ */ 965 966 /* This section defines magic (a.k.a appalling-hack) macros for doing 967 guaranteed-no-redirection macros, so as to get from function 968 wrappers to the functions they are wrapping. The whole point is to 969 construct standard call sequences, but to do the call itself with a 970 special no-redirect call pseudo-instruction that the JIT 971 understands and handles specially. This section is long and 972 repetitious, and I can't see a way to make it shorter. 973 974 The naming scheme is as follows: 975 976 CALL_FN_{W,v}_{v,W,WW,WWW,WWWW,5W,6W,7W,etc} 977 978 'W' stands for "word" and 'v' for "void". Hence there are 979 different macros for calling arity 0, 1, 2, 3, 4, etc, functions, 980 and for each, the possibility of returning a word-typed result, or 981 no result. 982 */ 983 984 /* Use these to write the name of your wrapper. NOTE: duplicates 985 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. NOTE also: inserts 986 the default behaviour equivalance class tag "0000" into the name. 987 See pub_tool_redir.h for details -- normally you don't need to 988 think about this, though. */ 989 990 /* Use an extra level of macroisation so as to ensure the soname/fnname 991 args are fully macro-expanded before pasting them together. */ 992 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd 993 994 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ 995 VG_CONCAT4(_vgw00000ZU_,soname,_,fnname) 996 997 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ 998 VG_CONCAT4(_vgw00000ZZ_,soname,_,fnname) 999 1000 /* Use this macro from within a wrapper function to collect the 1001 context (address and possibly other info) of the original function. 1002 Once you have that you can then use it in one of the CALL_FN_ 1003 macros. The type of the argument _lval is OrigFn. */ 1004 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) 1005 1006 /* Also provide end-user facilities for function replacement, rather 1007 than wrapping. A replacement function differs from a wrapper in 1008 that it has no way to get hold of the original function being 1009 called, and hence no way to call onwards to it. In a replacement 1010 function, VALGRIND_GET_ORIG_FN always returns zero. */ 1011 1012 #define I_REPLACE_SONAME_FNNAME_ZU(soname,fnname) \ 1013 VG_CONCAT4(_vgr00000ZU_,soname,_,fnname) 1014 1015 #define I_REPLACE_SONAME_FNNAME_ZZ(soname,fnname) \ 1016 VG_CONCAT4(_vgr00000ZZ_,soname,_,fnname) 1017 1018 /* Derivatives of the main macros below, for calling functions 1019 returning void. */ 1020 1021 #define CALL_FN_v_v(fnptr) \ 1022 do { volatile unsigned long _junk; \ 1023 CALL_FN_W_v(_junk,fnptr); } while (0) 1024 1025 #define CALL_FN_v_W(fnptr, arg1) \ 1026 do { volatile unsigned long _junk; \ 1027 CALL_FN_W_W(_junk,fnptr,arg1); } while (0) 1028 1029 #define CALL_FN_v_WW(fnptr, arg1,arg2) \ 1030 do { volatile unsigned long _junk; \ 1031 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) 1032 1033 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ 1034 do { volatile unsigned long _junk; \ 1035 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) 1036 1037 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ 1038 do { volatile unsigned long _junk; \ 1039 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) 1040 1041 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ 1042 do { volatile unsigned long _junk; \ 1043 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) 1044 1045 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ 1046 do { volatile unsigned long _junk; \ 1047 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) 1048 1049 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ 1050 do { volatile unsigned long _junk; \ 1051 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0) 1052 1053 /* ------------------------- x86-{linux,darwin} ---------------- */ 1054 1055 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) 1056 1057 /* These regs are trashed by the hidden call. No need to mention eax 1058 as gcc can already see that, plus causes gcc to bomb. */ 1059 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" 1060 1061 /* Macros to save and align the stack before making a function 1062 call and restore it afterwards as gcc may not keep the stack 1063 pointer aligned if it doesn't realise calls are being made 1064 to other functions. */ 1065 1066 #define VALGRIND_ALIGN_STACK \ 1067 "movl %%esp,%%edi\n\t" \ 1068 "andl $0xfffffff0,%%esp\n\t" 1069 #define VALGRIND_RESTORE_STACK \ 1070 "movl %%edi,%%esp\n\t" 1071 1072 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned 1073 long) == 4. */ 1074 1075 #define CALL_FN_W_v(lval, orig) \ 1076 do { \ 1077 volatile OrigFn _orig = (orig); \ 1078 volatile unsigned long _argvec[1]; \ 1079 volatile unsigned long _res; \ 1080 _argvec[0] = (unsigned long)_orig.nraddr; \ 1081 __asm__ volatile( \ 1082 VALGRIND_ALIGN_STACK \ 1083 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1084 VALGRIND_CALL_NOREDIR_EAX \ 1085 VALGRIND_RESTORE_STACK \ 1086 : /*out*/ "=a" (_res) \ 1087 : /*in*/ "a" (&_argvec[0]) \ 1088 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1089 ); \ 1090 lval = (__typeof__(lval)) _res; \ 1091 } while (0) 1092 1093 #define CALL_FN_W_W(lval, orig, arg1) \ 1094 do { \ 1095 volatile OrigFn _orig = (orig); \ 1096 volatile unsigned long _argvec[2]; \ 1097 volatile unsigned long _res; \ 1098 _argvec[0] = (unsigned long)_orig.nraddr; \ 1099 _argvec[1] = (unsigned long)(arg1); \ 1100 __asm__ volatile( \ 1101 VALGRIND_ALIGN_STACK \ 1102 "subl $12, %%esp\n\t" \ 1103 "pushl 4(%%eax)\n\t" \ 1104 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1105 VALGRIND_CALL_NOREDIR_EAX \ 1106 VALGRIND_RESTORE_STACK \ 1107 : /*out*/ "=a" (_res) \ 1108 : /*in*/ "a" (&_argvec[0]) \ 1109 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1110 ); \ 1111 lval = (__typeof__(lval)) _res; \ 1112 } while (0) 1113 1114 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1115 do { \ 1116 volatile OrigFn _orig = (orig); \ 1117 volatile unsigned long _argvec[3]; \ 1118 volatile unsigned long _res; \ 1119 _argvec[0] = (unsigned long)_orig.nraddr; \ 1120 _argvec[1] = (unsigned long)(arg1); \ 1121 _argvec[2] = (unsigned long)(arg2); \ 1122 __asm__ volatile( \ 1123 VALGRIND_ALIGN_STACK \ 1124 "subl $8, %%esp\n\t" \ 1125 "pushl 8(%%eax)\n\t" \ 1126 "pushl 4(%%eax)\n\t" \ 1127 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1128 VALGRIND_CALL_NOREDIR_EAX \ 1129 VALGRIND_RESTORE_STACK \ 1130 : /*out*/ "=a" (_res) \ 1131 : /*in*/ "a" (&_argvec[0]) \ 1132 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1133 ); \ 1134 lval = (__typeof__(lval)) _res; \ 1135 } while (0) 1136 1137 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1138 do { \ 1139 volatile OrigFn _orig = (orig); \ 1140 volatile unsigned long _argvec[4]; \ 1141 volatile unsigned long _res; \ 1142 _argvec[0] = (unsigned long)_orig.nraddr; \ 1143 _argvec[1] = (unsigned long)(arg1); \ 1144 _argvec[2] = (unsigned long)(arg2); \ 1145 _argvec[3] = (unsigned long)(arg3); \ 1146 __asm__ volatile( \ 1147 VALGRIND_ALIGN_STACK \ 1148 "subl $4, %%esp\n\t" \ 1149 "pushl 12(%%eax)\n\t" \ 1150 "pushl 8(%%eax)\n\t" \ 1151 "pushl 4(%%eax)\n\t" \ 1152 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1153 VALGRIND_CALL_NOREDIR_EAX \ 1154 VALGRIND_RESTORE_STACK \ 1155 : /*out*/ "=a" (_res) \ 1156 : /*in*/ "a" (&_argvec[0]) \ 1157 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1158 ); \ 1159 lval = (__typeof__(lval)) _res; \ 1160 } while (0) 1161 1162 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1163 do { \ 1164 volatile OrigFn _orig = (orig); \ 1165 volatile unsigned long _argvec[5]; \ 1166 volatile unsigned long _res; \ 1167 _argvec[0] = (unsigned long)_orig.nraddr; \ 1168 _argvec[1] = (unsigned long)(arg1); \ 1169 _argvec[2] = (unsigned long)(arg2); \ 1170 _argvec[3] = (unsigned long)(arg3); \ 1171 _argvec[4] = (unsigned long)(arg4); \ 1172 __asm__ volatile( \ 1173 VALGRIND_ALIGN_STACK \ 1174 "pushl 16(%%eax)\n\t" \ 1175 "pushl 12(%%eax)\n\t" \ 1176 "pushl 8(%%eax)\n\t" \ 1177 "pushl 4(%%eax)\n\t" \ 1178 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1179 VALGRIND_CALL_NOREDIR_EAX \ 1180 VALGRIND_RESTORE_STACK \ 1181 : /*out*/ "=a" (_res) \ 1182 : /*in*/ "a" (&_argvec[0]) \ 1183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1184 ); \ 1185 lval = (__typeof__(lval)) _res; \ 1186 } while (0) 1187 1188 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1189 do { \ 1190 volatile OrigFn _orig = (orig); \ 1191 volatile unsigned long _argvec[6]; \ 1192 volatile unsigned long _res; \ 1193 _argvec[0] = (unsigned long)_orig.nraddr; \ 1194 _argvec[1] = (unsigned long)(arg1); \ 1195 _argvec[2] = (unsigned long)(arg2); \ 1196 _argvec[3] = (unsigned long)(arg3); \ 1197 _argvec[4] = (unsigned long)(arg4); \ 1198 _argvec[5] = (unsigned long)(arg5); \ 1199 __asm__ volatile( \ 1200 VALGRIND_ALIGN_STACK \ 1201 "subl $12, %%esp\n\t" \ 1202 "pushl 20(%%eax)\n\t" \ 1203 "pushl 16(%%eax)\n\t" \ 1204 "pushl 12(%%eax)\n\t" \ 1205 "pushl 8(%%eax)\n\t" \ 1206 "pushl 4(%%eax)\n\t" \ 1207 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1208 VALGRIND_CALL_NOREDIR_EAX \ 1209 VALGRIND_RESTORE_STACK \ 1210 : /*out*/ "=a" (_res) \ 1211 : /*in*/ "a" (&_argvec[0]) \ 1212 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1213 ); \ 1214 lval = (__typeof__(lval)) _res; \ 1215 } while (0) 1216 1217 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1218 do { \ 1219 volatile OrigFn _orig = (orig); \ 1220 volatile unsigned long _argvec[7]; \ 1221 volatile unsigned long _res; \ 1222 _argvec[0] = (unsigned long)_orig.nraddr; \ 1223 _argvec[1] = (unsigned long)(arg1); \ 1224 _argvec[2] = (unsigned long)(arg2); \ 1225 _argvec[3] = (unsigned long)(arg3); \ 1226 _argvec[4] = (unsigned long)(arg4); \ 1227 _argvec[5] = (unsigned long)(arg5); \ 1228 _argvec[6] = (unsigned long)(arg6); \ 1229 __asm__ volatile( \ 1230 VALGRIND_ALIGN_STACK \ 1231 "subl $8, %%esp\n\t" \ 1232 "pushl 24(%%eax)\n\t" \ 1233 "pushl 20(%%eax)\n\t" \ 1234 "pushl 16(%%eax)\n\t" \ 1235 "pushl 12(%%eax)\n\t" \ 1236 "pushl 8(%%eax)\n\t" \ 1237 "pushl 4(%%eax)\n\t" \ 1238 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1239 VALGRIND_CALL_NOREDIR_EAX \ 1240 VALGRIND_RESTORE_STACK \ 1241 : /*out*/ "=a" (_res) \ 1242 : /*in*/ "a" (&_argvec[0]) \ 1243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1244 ); \ 1245 lval = (__typeof__(lval)) _res; \ 1246 } while (0) 1247 1248 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1249 arg7) \ 1250 do { \ 1251 volatile OrigFn _orig = (orig); \ 1252 volatile unsigned long _argvec[8]; \ 1253 volatile unsigned long _res; \ 1254 _argvec[0] = (unsigned long)_orig.nraddr; \ 1255 _argvec[1] = (unsigned long)(arg1); \ 1256 _argvec[2] = (unsigned long)(arg2); \ 1257 _argvec[3] = (unsigned long)(arg3); \ 1258 _argvec[4] = (unsigned long)(arg4); \ 1259 _argvec[5] = (unsigned long)(arg5); \ 1260 _argvec[6] = (unsigned long)(arg6); \ 1261 _argvec[7] = (unsigned long)(arg7); \ 1262 __asm__ volatile( \ 1263 VALGRIND_ALIGN_STACK \ 1264 "subl $4, %%esp\n\t" \ 1265 "pushl 28(%%eax)\n\t" \ 1266 "pushl 24(%%eax)\n\t" \ 1267 "pushl 20(%%eax)\n\t" \ 1268 "pushl 16(%%eax)\n\t" \ 1269 "pushl 12(%%eax)\n\t" \ 1270 "pushl 8(%%eax)\n\t" \ 1271 "pushl 4(%%eax)\n\t" \ 1272 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1273 VALGRIND_CALL_NOREDIR_EAX \ 1274 VALGRIND_RESTORE_STACK \ 1275 : /*out*/ "=a" (_res) \ 1276 : /*in*/ "a" (&_argvec[0]) \ 1277 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1278 ); \ 1279 lval = (__typeof__(lval)) _res; \ 1280 } while (0) 1281 1282 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1283 arg7,arg8) \ 1284 do { \ 1285 volatile OrigFn _orig = (orig); \ 1286 volatile unsigned long _argvec[9]; \ 1287 volatile unsigned long _res; \ 1288 _argvec[0] = (unsigned long)_orig.nraddr; \ 1289 _argvec[1] = (unsigned long)(arg1); \ 1290 _argvec[2] = (unsigned long)(arg2); \ 1291 _argvec[3] = (unsigned long)(arg3); \ 1292 _argvec[4] = (unsigned long)(arg4); \ 1293 _argvec[5] = (unsigned long)(arg5); \ 1294 _argvec[6] = (unsigned long)(arg6); \ 1295 _argvec[7] = (unsigned long)(arg7); \ 1296 _argvec[8] = (unsigned long)(arg8); \ 1297 __asm__ volatile( \ 1298 VALGRIND_ALIGN_STACK \ 1299 "pushl 32(%%eax)\n\t" \ 1300 "pushl 28(%%eax)\n\t" \ 1301 "pushl 24(%%eax)\n\t" \ 1302 "pushl 20(%%eax)\n\t" \ 1303 "pushl 16(%%eax)\n\t" \ 1304 "pushl 12(%%eax)\n\t" \ 1305 "pushl 8(%%eax)\n\t" \ 1306 "pushl 4(%%eax)\n\t" \ 1307 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1308 VALGRIND_CALL_NOREDIR_EAX \ 1309 VALGRIND_RESTORE_STACK \ 1310 : /*out*/ "=a" (_res) \ 1311 : /*in*/ "a" (&_argvec[0]) \ 1312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1313 ); \ 1314 lval = (__typeof__(lval)) _res; \ 1315 } while (0) 1316 1317 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1318 arg7,arg8,arg9) \ 1319 do { \ 1320 volatile OrigFn _orig = (orig); \ 1321 volatile unsigned long _argvec[10]; \ 1322 volatile unsigned long _res; \ 1323 _argvec[0] = (unsigned long)_orig.nraddr; \ 1324 _argvec[1] = (unsigned long)(arg1); \ 1325 _argvec[2] = (unsigned long)(arg2); \ 1326 _argvec[3] = (unsigned long)(arg3); \ 1327 _argvec[4] = (unsigned long)(arg4); \ 1328 _argvec[5] = (unsigned long)(arg5); \ 1329 _argvec[6] = (unsigned long)(arg6); \ 1330 _argvec[7] = (unsigned long)(arg7); \ 1331 _argvec[8] = (unsigned long)(arg8); \ 1332 _argvec[9] = (unsigned long)(arg9); \ 1333 __asm__ volatile( \ 1334 VALGRIND_ALIGN_STACK \ 1335 "subl $12, %%esp\n\t" \ 1336 "pushl 36(%%eax)\n\t" \ 1337 "pushl 32(%%eax)\n\t" \ 1338 "pushl 28(%%eax)\n\t" \ 1339 "pushl 24(%%eax)\n\t" \ 1340 "pushl 20(%%eax)\n\t" \ 1341 "pushl 16(%%eax)\n\t" \ 1342 "pushl 12(%%eax)\n\t" \ 1343 "pushl 8(%%eax)\n\t" \ 1344 "pushl 4(%%eax)\n\t" \ 1345 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1346 VALGRIND_CALL_NOREDIR_EAX \ 1347 VALGRIND_RESTORE_STACK \ 1348 : /*out*/ "=a" (_res) \ 1349 : /*in*/ "a" (&_argvec[0]) \ 1350 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1351 ); \ 1352 lval = (__typeof__(lval)) _res; \ 1353 } while (0) 1354 1355 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1356 arg7,arg8,arg9,arg10) \ 1357 do { \ 1358 volatile OrigFn _orig = (orig); \ 1359 volatile unsigned long _argvec[11]; \ 1360 volatile unsigned long _res; \ 1361 _argvec[0] = (unsigned long)_orig.nraddr; \ 1362 _argvec[1] = (unsigned long)(arg1); \ 1363 _argvec[2] = (unsigned long)(arg2); \ 1364 _argvec[3] = (unsigned long)(arg3); \ 1365 _argvec[4] = (unsigned long)(arg4); \ 1366 _argvec[5] = (unsigned long)(arg5); \ 1367 _argvec[6] = (unsigned long)(arg6); \ 1368 _argvec[7] = (unsigned long)(arg7); \ 1369 _argvec[8] = (unsigned long)(arg8); \ 1370 _argvec[9] = (unsigned long)(arg9); \ 1371 _argvec[10] = (unsigned long)(arg10); \ 1372 __asm__ volatile( \ 1373 VALGRIND_ALIGN_STACK \ 1374 "subl $8, %%esp\n\t" \ 1375 "pushl 40(%%eax)\n\t" \ 1376 "pushl 36(%%eax)\n\t" \ 1377 "pushl 32(%%eax)\n\t" \ 1378 "pushl 28(%%eax)\n\t" \ 1379 "pushl 24(%%eax)\n\t" \ 1380 "pushl 20(%%eax)\n\t" \ 1381 "pushl 16(%%eax)\n\t" \ 1382 "pushl 12(%%eax)\n\t" \ 1383 "pushl 8(%%eax)\n\t" \ 1384 "pushl 4(%%eax)\n\t" \ 1385 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1386 VALGRIND_CALL_NOREDIR_EAX \ 1387 VALGRIND_RESTORE_STACK \ 1388 : /*out*/ "=a" (_res) \ 1389 : /*in*/ "a" (&_argvec[0]) \ 1390 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1391 ); \ 1392 lval = (__typeof__(lval)) _res; \ 1393 } while (0) 1394 1395 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 1396 arg6,arg7,arg8,arg9,arg10, \ 1397 arg11) \ 1398 do { \ 1399 volatile OrigFn _orig = (orig); \ 1400 volatile unsigned long _argvec[12]; \ 1401 volatile unsigned long _res; \ 1402 _argvec[0] = (unsigned long)_orig.nraddr; \ 1403 _argvec[1] = (unsigned long)(arg1); \ 1404 _argvec[2] = (unsigned long)(arg2); \ 1405 _argvec[3] = (unsigned long)(arg3); \ 1406 _argvec[4] = (unsigned long)(arg4); \ 1407 _argvec[5] = (unsigned long)(arg5); \ 1408 _argvec[6] = (unsigned long)(arg6); \ 1409 _argvec[7] = (unsigned long)(arg7); \ 1410 _argvec[8] = (unsigned long)(arg8); \ 1411 _argvec[9] = (unsigned long)(arg9); \ 1412 _argvec[10] = (unsigned long)(arg10); \ 1413 _argvec[11] = (unsigned long)(arg11); \ 1414 __asm__ volatile( \ 1415 VALGRIND_ALIGN_STACK \ 1416 "subl $4, %%esp\n\t" \ 1417 "pushl 44(%%eax)\n\t" \ 1418 "pushl 40(%%eax)\n\t" \ 1419 "pushl 36(%%eax)\n\t" \ 1420 "pushl 32(%%eax)\n\t" \ 1421 "pushl 28(%%eax)\n\t" \ 1422 "pushl 24(%%eax)\n\t" \ 1423 "pushl 20(%%eax)\n\t" \ 1424 "pushl 16(%%eax)\n\t" \ 1425 "pushl 12(%%eax)\n\t" \ 1426 "pushl 8(%%eax)\n\t" \ 1427 "pushl 4(%%eax)\n\t" \ 1428 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1429 VALGRIND_CALL_NOREDIR_EAX \ 1430 VALGRIND_RESTORE_STACK \ 1431 : /*out*/ "=a" (_res) \ 1432 : /*in*/ "a" (&_argvec[0]) \ 1433 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1434 ); \ 1435 lval = (__typeof__(lval)) _res; \ 1436 } while (0) 1437 1438 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 1439 arg6,arg7,arg8,arg9,arg10, \ 1440 arg11,arg12) \ 1441 do { \ 1442 volatile OrigFn _orig = (orig); \ 1443 volatile unsigned long _argvec[13]; \ 1444 volatile unsigned long _res; \ 1445 _argvec[0] = (unsigned long)_orig.nraddr; \ 1446 _argvec[1] = (unsigned long)(arg1); \ 1447 _argvec[2] = (unsigned long)(arg2); \ 1448 _argvec[3] = (unsigned long)(arg3); \ 1449 _argvec[4] = (unsigned long)(arg4); \ 1450 _argvec[5] = (unsigned long)(arg5); \ 1451 _argvec[6] = (unsigned long)(arg6); \ 1452 _argvec[7] = (unsigned long)(arg7); \ 1453 _argvec[8] = (unsigned long)(arg8); \ 1454 _argvec[9] = (unsigned long)(arg9); \ 1455 _argvec[10] = (unsigned long)(arg10); \ 1456 _argvec[11] = (unsigned long)(arg11); \ 1457 _argvec[12] = (unsigned long)(arg12); \ 1458 __asm__ volatile( \ 1459 VALGRIND_ALIGN_STACK \ 1460 "pushl 48(%%eax)\n\t" \ 1461 "pushl 44(%%eax)\n\t" \ 1462 "pushl 40(%%eax)\n\t" \ 1463 "pushl 36(%%eax)\n\t" \ 1464 "pushl 32(%%eax)\n\t" \ 1465 "pushl 28(%%eax)\n\t" \ 1466 "pushl 24(%%eax)\n\t" \ 1467 "pushl 20(%%eax)\n\t" \ 1468 "pushl 16(%%eax)\n\t" \ 1469 "pushl 12(%%eax)\n\t" \ 1470 "pushl 8(%%eax)\n\t" \ 1471 "pushl 4(%%eax)\n\t" \ 1472 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ 1473 VALGRIND_CALL_NOREDIR_EAX \ 1474 VALGRIND_RESTORE_STACK \ 1475 : /*out*/ "=a" (_res) \ 1476 : /*in*/ "a" (&_argvec[0]) \ 1477 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "edi" \ 1478 ); \ 1479 lval = (__typeof__(lval)) _res; \ 1480 } while (0) 1481 1482 #endif /* PLAT_x86_linux || PLAT_x86_darwin */ 1483 1484 /* ------------------------ amd64-{linux,darwin} --------------- */ 1485 1486 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) 1487 1488 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ 1489 1490 /* These regs are trashed by the hidden call. */ 1491 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ 1492 "rdi", "r8", "r9", "r10", "r11" 1493 1494 /* This is all pretty complex. It's so as to make stack unwinding 1495 work reliably. See bug 243270. The basic problem is the sub and 1496 add of 128 of %rsp in all of the following macros. If gcc believes 1497 the CFA is in %rsp, then unwinding may fail, because what's at the 1498 CFA is not what gcc "expected" when it constructs the CFIs for the 1499 places where the macros are instantiated. 1500 1501 But we can't just add a CFI annotation to increase the CFA offset 1502 by 128, to match the sub of 128 from %rsp, because we don't know 1503 whether gcc has chosen %rsp as the CFA at that point, or whether it 1504 has chosen some other register (eg, %rbp). In the latter case, 1505 adding a CFI annotation to change the CFA offset is simply wrong. 1506 1507 So the solution is to get hold of the CFA using 1508 __builtin_dwarf_cfa(), put it in a known register, and add a 1509 CFI annotation to say what the register is. We choose %rbp for 1510 this (perhaps perversely), because: 1511 1512 (1) %rbp is already subject to unwinding. If a new register was 1513 chosen then the unwinder would have to unwind it in all stack 1514 traces, which is expensive, and 1515 1516 (2) %rbp is already subject to precise exception updates in the 1517 JIT. If a new register was chosen, we'd have to have precise 1518 exceptions for it too, which reduces performance of the 1519 generated code. 1520 1521 However .. one extra complication. We can't just whack the result 1522 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the 1523 list of trashed registers at the end of the inline assembly 1524 fragments; gcc won't allow %rbp to appear in that list. Hence 1525 instead we need to stash %rbp in %r15 for the duration of the asm, 1526 and say that %r15 is trashed instead. gcc seems happy to go with 1527 that. 1528 1529 Oh .. and this all needs to be conditionalised so that it is 1530 unchanged from before this commit, when compiled with older gccs 1531 that don't support __builtin_dwarf_cfa. Furthermore, since 1532 this header file is freestanding, it has to be independent of 1533 config.h, and so the following conditionalisation cannot depend on 1534 configure time checks. 1535 1536 Although it's not clear from 1537 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', 1538 this expression excludes Darwin. 1539 .cfi directives in Darwin assembly appear to be completely 1540 different and I haven't investigated how they work. 1541 1542 For even more entertainment value, note we have to use the 1543 completely undocumented __builtin_dwarf_cfa(), which appears to 1544 really compute the CFA, whereas __builtin_frame_address(0) claims 1545 to but actually doesn't. See 1546 https://bugs.kde.org/show_bug.cgi?id=243270#c47 1547 */ 1548 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) 1549 # define __FRAME_POINTER \ 1550 ,"r"(__builtin_dwarf_cfa()) 1551 # define VALGRIND_CFI_PROLOGUE \ 1552 "movq %%rbp, %%r15\n\t" \ 1553 "movq %2, %%rbp\n\t" \ 1554 ".cfi_remember_state\n\t" \ 1555 ".cfi_def_cfa rbp, 0\n\t" 1556 # define VALGRIND_CFI_EPILOGUE \ 1557 "movq %%r15, %%rbp\n\t" \ 1558 ".cfi_restore_state\n\t" 1559 #else 1560 # define __FRAME_POINTER 1561 # define VALGRIND_CFI_PROLOGUE 1562 # define VALGRIND_CFI_EPILOGUE 1563 #endif 1564 1565 /* Macros to save and align the stack before making a function 1566 call and restore it afterwards as gcc may not keep the stack 1567 pointer aligned if it doesn't realise calls are being made 1568 to other functions. */ 1569 1570 #define VALGRIND_ALIGN_STACK \ 1571 "movq %%rsp,%%r14\n\t" \ 1572 "andq $0xfffffffffffffff0,%%rsp\n\t" 1573 #define VALGRIND_RESTORE_STACK \ 1574 "movq %%r14,%%rsp\n\t" 1575 1576 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned 1577 long) == 8. */ 1578 1579 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ 1580 macros. In order not to trash the stack redzone, we need to drop 1581 %rsp by 128 before the hidden call, and restore afterwards. The 1582 nastyness is that it is only by luck that the stack still appears 1583 to be unwindable during the hidden call - since then the behaviour 1584 of any routine using this macro does not match what the CFI data 1585 says. Sigh. 1586 1587 Why is this important? Imagine that a wrapper has a stack 1588 allocated local, and passes to the hidden call, a pointer to it. 1589 Because gcc does not know about the hidden call, it may allocate 1590 that local in the redzone. Unfortunately the hidden call may then 1591 trash it before it comes to use it. So we must step clear of the 1592 redzone, for the duration of the hidden call, to make it safe. 1593 1594 Probably the same problem afflicts the other redzone-style ABIs too 1595 (ppc64-linux); but for those, the stack is 1596 self describing (none of this CFI nonsense) so at least messing 1597 with the stack pointer doesn't give a danger of non-unwindable 1598 stack. */ 1599 1600 #define CALL_FN_W_v(lval, orig) \ 1601 do { \ 1602 volatile OrigFn _orig = (orig); \ 1603 volatile unsigned long _argvec[1]; \ 1604 volatile unsigned long _res; \ 1605 _argvec[0] = (unsigned long)_orig.nraddr; \ 1606 __asm__ volatile( \ 1607 VALGRIND_CFI_PROLOGUE \ 1608 VALGRIND_ALIGN_STACK \ 1609 "subq $128,%%rsp\n\t" \ 1610 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1611 VALGRIND_CALL_NOREDIR_RAX \ 1612 VALGRIND_RESTORE_STACK \ 1613 VALGRIND_CFI_EPILOGUE \ 1614 : /*out*/ "=a" (_res) \ 1615 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1616 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1617 ); \ 1618 lval = (__typeof__(lval)) _res; \ 1619 } while (0) 1620 1621 #define CALL_FN_W_W(lval, orig, arg1) \ 1622 do { \ 1623 volatile OrigFn _orig = (orig); \ 1624 volatile unsigned long _argvec[2]; \ 1625 volatile unsigned long _res; \ 1626 _argvec[0] = (unsigned long)_orig.nraddr; \ 1627 _argvec[1] = (unsigned long)(arg1); \ 1628 __asm__ volatile( \ 1629 VALGRIND_CFI_PROLOGUE \ 1630 VALGRIND_ALIGN_STACK \ 1631 "subq $128,%%rsp\n\t" \ 1632 "movq 8(%%rax), %%rdi\n\t" \ 1633 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1634 VALGRIND_CALL_NOREDIR_RAX \ 1635 VALGRIND_RESTORE_STACK \ 1636 VALGRIND_CFI_EPILOGUE \ 1637 : /*out*/ "=a" (_res) \ 1638 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1639 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1640 ); \ 1641 lval = (__typeof__(lval)) _res; \ 1642 } while (0) 1643 1644 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 1645 do { \ 1646 volatile OrigFn _orig = (orig); \ 1647 volatile unsigned long _argvec[3]; \ 1648 volatile unsigned long _res; \ 1649 _argvec[0] = (unsigned long)_orig.nraddr; \ 1650 _argvec[1] = (unsigned long)(arg1); \ 1651 _argvec[2] = (unsigned long)(arg2); \ 1652 __asm__ volatile( \ 1653 VALGRIND_CFI_PROLOGUE \ 1654 VALGRIND_ALIGN_STACK \ 1655 "subq $128,%%rsp\n\t" \ 1656 "movq 16(%%rax), %%rsi\n\t" \ 1657 "movq 8(%%rax), %%rdi\n\t" \ 1658 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1659 VALGRIND_CALL_NOREDIR_RAX \ 1660 VALGRIND_RESTORE_STACK \ 1661 VALGRIND_CFI_EPILOGUE \ 1662 : /*out*/ "=a" (_res) \ 1663 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1664 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1665 ); \ 1666 lval = (__typeof__(lval)) _res; \ 1667 } while (0) 1668 1669 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 1670 do { \ 1671 volatile OrigFn _orig = (orig); \ 1672 volatile unsigned long _argvec[4]; \ 1673 volatile unsigned long _res; \ 1674 _argvec[0] = (unsigned long)_orig.nraddr; \ 1675 _argvec[1] = (unsigned long)(arg1); \ 1676 _argvec[2] = (unsigned long)(arg2); \ 1677 _argvec[3] = (unsigned long)(arg3); \ 1678 __asm__ volatile( \ 1679 VALGRIND_CFI_PROLOGUE \ 1680 VALGRIND_ALIGN_STACK \ 1681 "subq $128,%%rsp\n\t" \ 1682 "movq 24(%%rax), %%rdx\n\t" \ 1683 "movq 16(%%rax), %%rsi\n\t" \ 1684 "movq 8(%%rax), %%rdi\n\t" \ 1685 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1686 VALGRIND_CALL_NOREDIR_RAX \ 1687 VALGRIND_RESTORE_STACK \ 1688 VALGRIND_CFI_EPILOGUE \ 1689 : /*out*/ "=a" (_res) \ 1690 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1691 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1692 ); \ 1693 lval = (__typeof__(lval)) _res; \ 1694 } while (0) 1695 1696 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 1697 do { \ 1698 volatile OrigFn _orig = (orig); \ 1699 volatile unsigned long _argvec[5]; \ 1700 volatile unsigned long _res; \ 1701 _argvec[0] = (unsigned long)_orig.nraddr; \ 1702 _argvec[1] = (unsigned long)(arg1); \ 1703 _argvec[2] = (unsigned long)(arg2); \ 1704 _argvec[3] = (unsigned long)(arg3); \ 1705 _argvec[4] = (unsigned long)(arg4); \ 1706 __asm__ volatile( \ 1707 VALGRIND_CFI_PROLOGUE \ 1708 VALGRIND_ALIGN_STACK \ 1709 "subq $128,%%rsp\n\t" \ 1710 "movq 32(%%rax), %%rcx\n\t" \ 1711 "movq 24(%%rax), %%rdx\n\t" \ 1712 "movq 16(%%rax), %%rsi\n\t" \ 1713 "movq 8(%%rax), %%rdi\n\t" \ 1714 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1715 VALGRIND_CALL_NOREDIR_RAX \ 1716 VALGRIND_RESTORE_STACK \ 1717 VALGRIND_CFI_EPILOGUE \ 1718 : /*out*/ "=a" (_res) \ 1719 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1720 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1721 ); \ 1722 lval = (__typeof__(lval)) _res; \ 1723 } while (0) 1724 1725 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 1726 do { \ 1727 volatile OrigFn _orig = (orig); \ 1728 volatile unsigned long _argvec[6]; \ 1729 volatile unsigned long _res; \ 1730 _argvec[0] = (unsigned long)_orig.nraddr; \ 1731 _argvec[1] = (unsigned long)(arg1); \ 1732 _argvec[2] = (unsigned long)(arg2); \ 1733 _argvec[3] = (unsigned long)(arg3); \ 1734 _argvec[4] = (unsigned long)(arg4); \ 1735 _argvec[5] = (unsigned long)(arg5); \ 1736 __asm__ volatile( \ 1737 VALGRIND_CFI_PROLOGUE \ 1738 VALGRIND_ALIGN_STACK \ 1739 "subq $128,%%rsp\n\t" \ 1740 "movq 40(%%rax), %%r8\n\t" \ 1741 "movq 32(%%rax), %%rcx\n\t" \ 1742 "movq 24(%%rax), %%rdx\n\t" \ 1743 "movq 16(%%rax), %%rsi\n\t" \ 1744 "movq 8(%%rax), %%rdi\n\t" \ 1745 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1746 VALGRIND_CALL_NOREDIR_RAX \ 1747 VALGRIND_RESTORE_STACK \ 1748 VALGRIND_CFI_EPILOGUE \ 1749 : /*out*/ "=a" (_res) \ 1750 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1751 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1752 ); \ 1753 lval = (__typeof__(lval)) _res; \ 1754 } while (0) 1755 1756 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 1757 do { \ 1758 volatile OrigFn _orig = (orig); \ 1759 volatile unsigned long _argvec[7]; \ 1760 volatile unsigned long _res; \ 1761 _argvec[0] = (unsigned long)_orig.nraddr; \ 1762 _argvec[1] = (unsigned long)(arg1); \ 1763 _argvec[2] = (unsigned long)(arg2); \ 1764 _argvec[3] = (unsigned long)(arg3); \ 1765 _argvec[4] = (unsigned long)(arg4); \ 1766 _argvec[5] = (unsigned long)(arg5); \ 1767 _argvec[6] = (unsigned long)(arg6); \ 1768 __asm__ volatile( \ 1769 VALGRIND_CFI_PROLOGUE \ 1770 VALGRIND_ALIGN_STACK \ 1771 "subq $128,%%rsp\n\t" \ 1772 "movq 48(%%rax), %%r9\n\t" \ 1773 "movq 40(%%rax), %%r8\n\t" \ 1774 "movq 32(%%rax), %%rcx\n\t" \ 1775 "movq 24(%%rax), %%rdx\n\t" \ 1776 "movq 16(%%rax), %%rsi\n\t" \ 1777 "movq 8(%%rax), %%rdi\n\t" \ 1778 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1779 VALGRIND_CALL_NOREDIR_RAX \ 1780 VALGRIND_RESTORE_STACK \ 1781 VALGRIND_CFI_EPILOGUE \ 1782 : /*out*/ "=a" (_res) \ 1783 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1784 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1785 ); \ 1786 lval = (__typeof__(lval)) _res; \ 1787 } while (0) 1788 1789 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1790 arg7) \ 1791 do { \ 1792 volatile OrigFn _orig = (orig); \ 1793 volatile unsigned long _argvec[8]; \ 1794 volatile unsigned long _res; \ 1795 _argvec[0] = (unsigned long)_orig.nraddr; \ 1796 _argvec[1] = (unsigned long)(arg1); \ 1797 _argvec[2] = (unsigned long)(arg2); \ 1798 _argvec[3] = (unsigned long)(arg3); \ 1799 _argvec[4] = (unsigned long)(arg4); \ 1800 _argvec[5] = (unsigned long)(arg5); \ 1801 _argvec[6] = (unsigned long)(arg6); \ 1802 _argvec[7] = (unsigned long)(arg7); \ 1803 __asm__ volatile( \ 1804 VALGRIND_CFI_PROLOGUE \ 1805 VALGRIND_ALIGN_STACK \ 1806 "subq $136,%%rsp\n\t" \ 1807 "pushq 56(%%rax)\n\t" \ 1808 "movq 48(%%rax), %%r9\n\t" \ 1809 "movq 40(%%rax), %%r8\n\t" \ 1810 "movq 32(%%rax), %%rcx\n\t" \ 1811 "movq 24(%%rax), %%rdx\n\t" \ 1812 "movq 16(%%rax), %%rsi\n\t" \ 1813 "movq 8(%%rax), %%rdi\n\t" \ 1814 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1815 VALGRIND_CALL_NOREDIR_RAX \ 1816 VALGRIND_RESTORE_STACK \ 1817 VALGRIND_CFI_EPILOGUE \ 1818 : /*out*/ "=a" (_res) \ 1819 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1820 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1821 ); \ 1822 lval = (__typeof__(lval)) _res; \ 1823 } while (0) 1824 1825 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1826 arg7,arg8) \ 1827 do { \ 1828 volatile OrigFn _orig = (orig); \ 1829 volatile unsigned long _argvec[9]; \ 1830 volatile unsigned long _res; \ 1831 _argvec[0] = (unsigned long)_orig.nraddr; \ 1832 _argvec[1] = (unsigned long)(arg1); \ 1833 _argvec[2] = (unsigned long)(arg2); \ 1834 _argvec[3] = (unsigned long)(arg3); \ 1835 _argvec[4] = (unsigned long)(arg4); \ 1836 _argvec[5] = (unsigned long)(arg5); \ 1837 _argvec[6] = (unsigned long)(arg6); \ 1838 _argvec[7] = (unsigned long)(arg7); \ 1839 _argvec[8] = (unsigned long)(arg8); \ 1840 __asm__ volatile( \ 1841 VALGRIND_CFI_PROLOGUE \ 1842 VALGRIND_ALIGN_STACK \ 1843 "subq $128,%%rsp\n\t" \ 1844 "pushq 64(%%rax)\n\t" \ 1845 "pushq 56(%%rax)\n\t" \ 1846 "movq 48(%%rax), %%r9\n\t" \ 1847 "movq 40(%%rax), %%r8\n\t" \ 1848 "movq 32(%%rax), %%rcx\n\t" \ 1849 "movq 24(%%rax), %%rdx\n\t" \ 1850 "movq 16(%%rax), %%rsi\n\t" \ 1851 "movq 8(%%rax), %%rdi\n\t" \ 1852 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1853 VALGRIND_CALL_NOREDIR_RAX \ 1854 VALGRIND_RESTORE_STACK \ 1855 VALGRIND_CFI_EPILOGUE \ 1856 : /*out*/ "=a" (_res) \ 1857 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1859 ); \ 1860 lval = (__typeof__(lval)) _res; \ 1861 } while (0) 1862 1863 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1864 arg7,arg8,arg9) \ 1865 do { \ 1866 volatile OrigFn _orig = (orig); \ 1867 volatile unsigned long _argvec[10]; \ 1868 volatile unsigned long _res; \ 1869 _argvec[0] = (unsigned long)_orig.nraddr; \ 1870 _argvec[1] = (unsigned long)(arg1); \ 1871 _argvec[2] = (unsigned long)(arg2); \ 1872 _argvec[3] = (unsigned long)(arg3); \ 1873 _argvec[4] = (unsigned long)(arg4); \ 1874 _argvec[5] = (unsigned long)(arg5); \ 1875 _argvec[6] = (unsigned long)(arg6); \ 1876 _argvec[7] = (unsigned long)(arg7); \ 1877 _argvec[8] = (unsigned long)(arg8); \ 1878 _argvec[9] = (unsigned long)(arg9); \ 1879 __asm__ volatile( \ 1880 VALGRIND_CFI_PROLOGUE \ 1881 VALGRIND_ALIGN_STACK \ 1882 "subq $136,%%rsp\n\t" \ 1883 "pushq 72(%%rax)\n\t" \ 1884 "pushq 64(%%rax)\n\t" \ 1885 "pushq 56(%%rax)\n\t" \ 1886 "movq 48(%%rax), %%r9\n\t" \ 1887 "movq 40(%%rax), %%r8\n\t" \ 1888 "movq 32(%%rax), %%rcx\n\t" \ 1889 "movq 24(%%rax), %%rdx\n\t" \ 1890 "movq 16(%%rax), %%rsi\n\t" \ 1891 "movq 8(%%rax), %%rdi\n\t" \ 1892 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1893 VALGRIND_CALL_NOREDIR_RAX \ 1894 VALGRIND_RESTORE_STACK \ 1895 VALGRIND_CFI_EPILOGUE \ 1896 : /*out*/ "=a" (_res) \ 1897 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1898 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1899 ); \ 1900 lval = (__typeof__(lval)) _res; \ 1901 } while (0) 1902 1903 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1904 arg7,arg8,arg9,arg10) \ 1905 do { \ 1906 volatile OrigFn _orig = (orig); \ 1907 volatile unsigned long _argvec[11]; \ 1908 volatile unsigned long _res; \ 1909 _argvec[0] = (unsigned long)_orig.nraddr; \ 1910 _argvec[1] = (unsigned long)(arg1); \ 1911 _argvec[2] = (unsigned long)(arg2); \ 1912 _argvec[3] = (unsigned long)(arg3); \ 1913 _argvec[4] = (unsigned long)(arg4); \ 1914 _argvec[5] = (unsigned long)(arg5); \ 1915 _argvec[6] = (unsigned long)(arg6); \ 1916 _argvec[7] = (unsigned long)(arg7); \ 1917 _argvec[8] = (unsigned long)(arg8); \ 1918 _argvec[9] = (unsigned long)(arg9); \ 1919 _argvec[10] = (unsigned long)(arg10); \ 1920 __asm__ volatile( \ 1921 VALGRIND_CFI_PROLOGUE \ 1922 VALGRIND_ALIGN_STACK \ 1923 "subq $128,%%rsp\n\t" \ 1924 "pushq 80(%%rax)\n\t" \ 1925 "pushq 72(%%rax)\n\t" \ 1926 "pushq 64(%%rax)\n\t" \ 1927 "pushq 56(%%rax)\n\t" \ 1928 "movq 48(%%rax), %%r9\n\t" \ 1929 "movq 40(%%rax), %%r8\n\t" \ 1930 "movq 32(%%rax), %%rcx\n\t" \ 1931 "movq 24(%%rax), %%rdx\n\t" \ 1932 "movq 16(%%rax), %%rsi\n\t" \ 1933 "movq 8(%%rax), %%rdi\n\t" \ 1934 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1935 VALGRIND_CALL_NOREDIR_RAX \ 1936 VALGRIND_RESTORE_STACK \ 1937 VALGRIND_CFI_EPILOGUE \ 1938 : /*out*/ "=a" (_res) \ 1939 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1940 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1941 ); \ 1942 lval = (__typeof__(lval)) _res; \ 1943 } while (0) 1944 1945 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1946 arg7,arg8,arg9,arg10,arg11) \ 1947 do { \ 1948 volatile OrigFn _orig = (orig); \ 1949 volatile unsigned long _argvec[12]; \ 1950 volatile unsigned long _res; \ 1951 _argvec[0] = (unsigned long)_orig.nraddr; \ 1952 _argvec[1] = (unsigned long)(arg1); \ 1953 _argvec[2] = (unsigned long)(arg2); \ 1954 _argvec[3] = (unsigned long)(arg3); \ 1955 _argvec[4] = (unsigned long)(arg4); \ 1956 _argvec[5] = (unsigned long)(arg5); \ 1957 _argvec[6] = (unsigned long)(arg6); \ 1958 _argvec[7] = (unsigned long)(arg7); \ 1959 _argvec[8] = (unsigned long)(arg8); \ 1960 _argvec[9] = (unsigned long)(arg9); \ 1961 _argvec[10] = (unsigned long)(arg10); \ 1962 _argvec[11] = (unsigned long)(arg11); \ 1963 __asm__ volatile( \ 1964 VALGRIND_CFI_PROLOGUE \ 1965 VALGRIND_ALIGN_STACK \ 1966 "subq $136,%%rsp\n\t" \ 1967 "pushq 88(%%rax)\n\t" \ 1968 "pushq 80(%%rax)\n\t" \ 1969 "pushq 72(%%rax)\n\t" \ 1970 "pushq 64(%%rax)\n\t" \ 1971 "pushq 56(%%rax)\n\t" \ 1972 "movq 48(%%rax), %%r9\n\t" \ 1973 "movq 40(%%rax), %%r8\n\t" \ 1974 "movq 32(%%rax), %%rcx\n\t" \ 1975 "movq 24(%%rax), %%rdx\n\t" \ 1976 "movq 16(%%rax), %%rsi\n\t" \ 1977 "movq 8(%%rax), %%rdi\n\t" \ 1978 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 1979 VALGRIND_CALL_NOREDIR_RAX \ 1980 VALGRIND_RESTORE_STACK \ 1981 VALGRIND_CFI_EPILOGUE \ 1982 : /*out*/ "=a" (_res) \ 1983 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 1984 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 1985 ); \ 1986 lval = (__typeof__(lval)) _res; \ 1987 } while (0) 1988 1989 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 1990 arg7,arg8,arg9,arg10,arg11,arg12) \ 1991 do { \ 1992 volatile OrigFn _orig = (orig); \ 1993 volatile unsigned long _argvec[13]; \ 1994 volatile unsigned long _res; \ 1995 _argvec[0] = (unsigned long)_orig.nraddr; \ 1996 _argvec[1] = (unsigned long)(arg1); \ 1997 _argvec[2] = (unsigned long)(arg2); \ 1998 _argvec[3] = (unsigned long)(arg3); \ 1999 _argvec[4] = (unsigned long)(arg4); \ 2000 _argvec[5] = (unsigned long)(arg5); \ 2001 _argvec[6] = (unsigned long)(arg6); \ 2002 _argvec[7] = (unsigned long)(arg7); \ 2003 _argvec[8] = (unsigned long)(arg8); \ 2004 _argvec[9] = (unsigned long)(arg9); \ 2005 _argvec[10] = (unsigned long)(arg10); \ 2006 _argvec[11] = (unsigned long)(arg11); \ 2007 _argvec[12] = (unsigned long)(arg12); \ 2008 __asm__ volatile( \ 2009 VALGRIND_CFI_PROLOGUE \ 2010 VALGRIND_ALIGN_STACK \ 2011 "subq $128,%%rsp\n\t" \ 2012 "pushq 96(%%rax)\n\t" \ 2013 "pushq 88(%%rax)\n\t" \ 2014 "pushq 80(%%rax)\n\t" \ 2015 "pushq 72(%%rax)\n\t" \ 2016 "pushq 64(%%rax)\n\t" \ 2017 "pushq 56(%%rax)\n\t" \ 2018 "movq 48(%%rax), %%r9\n\t" \ 2019 "movq 40(%%rax), %%r8\n\t" \ 2020 "movq 32(%%rax), %%rcx\n\t" \ 2021 "movq 24(%%rax), %%rdx\n\t" \ 2022 "movq 16(%%rax), %%rsi\n\t" \ 2023 "movq 8(%%rax), %%rdi\n\t" \ 2024 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ 2025 VALGRIND_CALL_NOREDIR_RAX \ 2026 VALGRIND_RESTORE_STACK \ 2027 VALGRIND_CFI_EPILOGUE \ 2028 : /*out*/ "=a" (_res) \ 2029 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 2030 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r14", "r15" \ 2031 ); \ 2032 lval = (__typeof__(lval)) _res; \ 2033 } while (0) 2034 2035 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ 2036 2037 /* ------------------------ ppc32-linux ------------------------ */ 2038 2039 #if defined(PLAT_ppc32_linux) 2040 2041 /* This is useful for finding out about the on-stack stuff: 2042 2043 extern int f9 ( int,int,int,int,int,int,int,int,int ); 2044 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); 2045 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); 2046 extern int f12 ( int,int,int,int,int,int,int,int,int,int,int,int ); 2047 2048 int g9 ( void ) { 2049 return f9(11,22,33,44,55,66,77,88,99); 2050 } 2051 int g10 ( void ) { 2052 return f10(11,22,33,44,55,66,77,88,99,110); 2053 } 2054 int g11 ( void ) { 2055 return f11(11,22,33,44,55,66,77,88,99,110,121); 2056 } 2057 int g12 ( void ) { 2058 return f12(11,22,33,44,55,66,77,88,99,110,121,132); 2059 } 2060 */ 2061 2062 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 2063 2064 /* These regs are trashed by the hidden call. */ 2065 #define __CALLER_SAVED_REGS \ 2066 "lr", "ctr", "xer", \ 2067 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 2068 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 2069 "r11", "r12", "r13" 2070 2071 /* Macros to save and align the stack before making a function 2072 call and restore it afterwards as gcc may not keep the stack 2073 pointer aligned if it doesn't realise calls are being made 2074 to other functions. */ 2075 2076 #define VALGRIND_ALIGN_STACK \ 2077 "mr 28,1\n\t" \ 2078 "rlwinm 1,1,0,0,27\n\t" 2079 #define VALGRIND_RESTORE_STACK \ 2080 "mr 1,28\n\t" 2081 2082 /* These CALL_FN_ macros assume that on ppc32-linux, 2083 sizeof(unsigned long) == 4. */ 2084 2085 #define CALL_FN_W_v(lval, orig) \ 2086 do { \ 2087 volatile OrigFn _orig = (orig); \ 2088 volatile unsigned long _argvec[1]; \ 2089 volatile unsigned long _res; \ 2090 _argvec[0] = (unsigned long)_orig.nraddr; \ 2091 __asm__ volatile( \ 2092 VALGRIND_ALIGN_STACK \ 2093 "mr 11,%1\n\t" \ 2094 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2095 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2096 VALGRIND_RESTORE_STACK \ 2097 "mr %0,3" \ 2098 : /*out*/ "=r" (_res) \ 2099 : /*in*/ "r" (&_argvec[0]) \ 2100 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2101 ); \ 2102 lval = (__typeof__(lval)) _res; \ 2103 } while (0) 2104 2105 #define CALL_FN_W_W(lval, orig, arg1) \ 2106 do { \ 2107 volatile OrigFn _orig = (orig); \ 2108 volatile unsigned long _argvec[2]; \ 2109 volatile unsigned long _res; \ 2110 _argvec[0] = (unsigned long)_orig.nraddr; \ 2111 _argvec[1] = (unsigned long)arg1; \ 2112 __asm__ volatile( \ 2113 VALGRIND_ALIGN_STACK \ 2114 "mr 11,%1\n\t" \ 2115 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2116 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2117 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2118 VALGRIND_RESTORE_STACK \ 2119 "mr %0,3" \ 2120 : /*out*/ "=r" (_res) \ 2121 : /*in*/ "r" (&_argvec[0]) \ 2122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2123 ); \ 2124 lval = (__typeof__(lval)) _res; \ 2125 } while (0) 2126 2127 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 2128 do { \ 2129 volatile OrigFn _orig = (orig); \ 2130 volatile unsigned long _argvec[3]; \ 2131 volatile unsigned long _res; \ 2132 _argvec[0] = (unsigned long)_orig.nraddr; \ 2133 _argvec[1] = (unsigned long)arg1; \ 2134 _argvec[2] = (unsigned long)arg2; \ 2135 __asm__ volatile( \ 2136 VALGRIND_ALIGN_STACK \ 2137 "mr 11,%1\n\t" \ 2138 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2139 "lwz 4,8(11)\n\t" \ 2140 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2141 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2142 VALGRIND_RESTORE_STACK \ 2143 "mr %0,3" \ 2144 : /*out*/ "=r" (_res) \ 2145 : /*in*/ "r" (&_argvec[0]) \ 2146 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2147 ); \ 2148 lval = (__typeof__(lval)) _res; \ 2149 } while (0) 2150 2151 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2152 do { \ 2153 volatile OrigFn _orig = (orig); \ 2154 volatile unsigned long _argvec[4]; \ 2155 volatile unsigned long _res; \ 2156 _argvec[0] = (unsigned long)_orig.nraddr; \ 2157 _argvec[1] = (unsigned long)arg1; \ 2158 _argvec[2] = (unsigned long)arg2; \ 2159 _argvec[3] = (unsigned long)arg3; \ 2160 __asm__ volatile( \ 2161 VALGRIND_ALIGN_STACK \ 2162 "mr 11,%1\n\t" \ 2163 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2164 "lwz 4,8(11)\n\t" \ 2165 "lwz 5,12(11)\n\t" \ 2166 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2167 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2168 VALGRIND_RESTORE_STACK \ 2169 "mr %0,3" \ 2170 : /*out*/ "=r" (_res) \ 2171 : /*in*/ "r" (&_argvec[0]) \ 2172 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2173 ); \ 2174 lval = (__typeof__(lval)) _res; \ 2175 } while (0) 2176 2177 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2178 do { \ 2179 volatile OrigFn _orig = (orig); \ 2180 volatile unsigned long _argvec[5]; \ 2181 volatile unsigned long _res; \ 2182 _argvec[0] = (unsigned long)_orig.nraddr; \ 2183 _argvec[1] = (unsigned long)arg1; \ 2184 _argvec[2] = (unsigned long)arg2; \ 2185 _argvec[3] = (unsigned long)arg3; \ 2186 _argvec[4] = (unsigned long)arg4; \ 2187 __asm__ volatile( \ 2188 VALGRIND_ALIGN_STACK \ 2189 "mr 11,%1\n\t" \ 2190 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2191 "lwz 4,8(11)\n\t" \ 2192 "lwz 5,12(11)\n\t" \ 2193 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2194 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2195 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2196 VALGRIND_RESTORE_STACK \ 2197 "mr %0,3" \ 2198 : /*out*/ "=r" (_res) \ 2199 : /*in*/ "r" (&_argvec[0]) \ 2200 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2201 ); \ 2202 lval = (__typeof__(lval)) _res; \ 2203 } while (0) 2204 2205 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2206 do { \ 2207 volatile OrigFn _orig = (orig); \ 2208 volatile unsigned long _argvec[6]; \ 2209 volatile unsigned long _res; \ 2210 _argvec[0] = (unsigned long)_orig.nraddr; \ 2211 _argvec[1] = (unsigned long)arg1; \ 2212 _argvec[2] = (unsigned long)arg2; \ 2213 _argvec[3] = (unsigned long)arg3; \ 2214 _argvec[4] = (unsigned long)arg4; \ 2215 _argvec[5] = (unsigned long)arg5; \ 2216 __asm__ volatile( \ 2217 VALGRIND_ALIGN_STACK \ 2218 "mr 11,%1\n\t" \ 2219 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2220 "lwz 4,8(11)\n\t" \ 2221 "lwz 5,12(11)\n\t" \ 2222 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2223 "lwz 7,20(11)\n\t" \ 2224 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2225 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2226 VALGRIND_RESTORE_STACK \ 2227 "mr %0,3" \ 2228 : /*out*/ "=r" (_res) \ 2229 : /*in*/ "r" (&_argvec[0]) \ 2230 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2231 ); \ 2232 lval = (__typeof__(lval)) _res; \ 2233 } while (0) 2234 2235 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2236 do { \ 2237 volatile OrigFn _orig = (orig); \ 2238 volatile unsigned long _argvec[7]; \ 2239 volatile unsigned long _res; \ 2240 _argvec[0] = (unsigned long)_orig.nraddr; \ 2241 _argvec[1] = (unsigned long)arg1; \ 2242 _argvec[2] = (unsigned long)arg2; \ 2243 _argvec[3] = (unsigned long)arg3; \ 2244 _argvec[4] = (unsigned long)arg4; \ 2245 _argvec[5] = (unsigned long)arg5; \ 2246 _argvec[6] = (unsigned long)arg6; \ 2247 __asm__ volatile( \ 2248 VALGRIND_ALIGN_STACK \ 2249 "mr 11,%1\n\t" \ 2250 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2251 "lwz 4,8(11)\n\t" \ 2252 "lwz 5,12(11)\n\t" \ 2253 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2254 "lwz 7,20(11)\n\t" \ 2255 "lwz 8,24(11)\n\t" \ 2256 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2257 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2258 VALGRIND_RESTORE_STACK \ 2259 "mr %0,3" \ 2260 : /*out*/ "=r" (_res) \ 2261 : /*in*/ "r" (&_argvec[0]) \ 2262 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2263 ); \ 2264 lval = (__typeof__(lval)) _res; \ 2265 } while (0) 2266 2267 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2268 arg7) \ 2269 do { \ 2270 volatile OrigFn _orig = (orig); \ 2271 volatile unsigned long _argvec[8]; \ 2272 volatile unsigned long _res; \ 2273 _argvec[0] = (unsigned long)_orig.nraddr; \ 2274 _argvec[1] = (unsigned long)arg1; \ 2275 _argvec[2] = (unsigned long)arg2; \ 2276 _argvec[3] = (unsigned long)arg3; \ 2277 _argvec[4] = (unsigned long)arg4; \ 2278 _argvec[5] = (unsigned long)arg5; \ 2279 _argvec[6] = (unsigned long)arg6; \ 2280 _argvec[7] = (unsigned long)arg7; \ 2281 __asm__ volatile( \ 2282 VALGRIND_ALIGN_STACK \ 2283 "mr 11,%1\n\t" \ 2284 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2285 "lwz 4,8(11)\n\t" \ 2286 "lwz 5,12(11)\n\t" \ 2287 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2288 "lwz 7,20(11)\n\t" \ 2289 "lwz 8,24(11)\n\t" \ 2290 "lwz 9,28(11)\n\t" \ 2291 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2292 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2293 VALGRIND_RESTORE_STACK \ 2294 "mr %0,3" \ 2295 : /*out*/ "=r" (_res) \ 2296 : /*in*/ "r" (&_argvec[0]) \ 2297 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2298 ); \ 2299 lval = (__typeof__(lval)) _res; \ 2300 } while (0) 2301 2302 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2303 arg7,arg8) \ 2304 do { \ 2305 volatile OrigFn _orig = (orig); \ 2306 volatile unsigned long _argvec[9]; \ 2307 volatile unsigned long _res; \ 2308 _argvec[0] = (unsigned long)_orig.nraddr; \ 2309 _argvec[1] = (unsigned long)arg1; \ 2310 _argvec[2] = (unsigned long)arg2; \ 2311 _argvec[3] = (unsigned long)arg3; \ 2312 _argvec[4] = (unsigned long)arg4; \ 2313 _argvec[5] = (unsigned long)arg5; \ 2314 _argvec[6] = (unsigned long)arg6; \ 2315 _argvec[7] = (unsigned long)arg7; \ 2316 _argvec[8] = (unsigned long)arg8; \ 2317 __asm__ volatile( \ 2318 VALGRIND_ALIGN_STACK \ 2319 "mr 11,%1\n\t" \ 2320 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2321 "lwz 4,8(11)\n\t" \ 2322 "lwz 5,12(11)\n\t" \ 2323 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2324 "lwz 7,20(11)\n\t" \ 2325 "lwz 8,24(11)\n\t" \ 2326 "lwz 9,28(11)\n\t" \ 2327 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2328 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2330 VALGRIND_RESTORE_STACK \ 2331 "mr %0,3" \ 2332 : /*out*/ "=r" (_res) \ 2333 : /*in*/ "r" (&_argvec[0]) \ 2334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2335 ); \ 2336 lval = (__typeof__(lval)) _res; \ 2337 } while (0) 2338 2339 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2340 arg7,arg8,arg9) \ 2341 do { \ 2342 volatile OrigFn _orig = (orig); \ 2343 volatile unsigned long _argvec[10]; \ 2344 volatile unsigned long _res; \ 2345 _argvec[0] = (unsigned long)_orig.nraddr; \ 2346 _argvec[1] = (unsigned long)arg1; \ 2347 _argvec[2] = (unsigned long)arg2; \ 2348 _argvec[3] = (unsigned long)arg3; \ 2349 _argvec[4] = (unsigned long)arg4; \ 2350 _argvec[5] = (unsigned long)arg5; \ 2351 _argvec[6] = (unsigned long)arg6; \ 2352 _argvec[7] = (unsigned long)arg7; \ 2353 _argvec[8] = (unsigned long)arg8; \ 2354 _argvec[9] = (unsigned long)arg9; \ 2355 __asm__ volatile( \ 2356 VALGRIND_ALIGN_STACK \ 2357 "mr 11,%1\n\t" \ 2358 "addi 1,1,-16\n\t" \ 2359 /* arg9 */ \ 2360 "lwz 3,36(11)\n\t" \ 2361 "stw 3,8(1)\n\t" \ 2362 /* args1-8 */ \ 2363 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2364 "lwz 4,8(11)\n\t" \ 2365 "lwz 5,12(11)\n\t" \ 2366 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2367 "lwz 7,20(11)\n\t" \ 2368 "lwz 8,24(11)\n\t" \ 2369 "lwz 9,28(11)\n\t" \ 2370 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2371 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2372 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2373 VALGRIND_RESTORE_STACK \ 2374 "mr %0,3" \ 2375 : /*out*/ "=r" (_res) \ 2376 : /*in*/ "r" (&_argvec[0]) \ 2377 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2378 ); \ 2379 lval = (__typeof__(lval)) _res; \ 2380 } while (0) 2381 2382 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2383 arg7,arg8,arg9,arg10) \ 2384 do { \ 2385 volatile OrigFn _orig = (orig); \ 2386 volatile unsigned long _argvec[11]; \ 2387 volatile unsigned long _res; \ 2388 _argvec[0] = (unsigned long)_orig.nraddr; \ 2389 _argvec[1] = (unsigned long)arg1; \ 2390 _argvec[2] = (unsigned long)arg2; \ 2391 _argvec[3] = (unsigned long)arg3; \ 2392 _argvec[4] = (unsigned long)arg4; \ 2393 _argvec[5] = (unsigned long)arg5; \ 2394 _argvec[6] = (unsigned long)arg6; \ 2395 _argvec[7] = (unsigned long)arg7; \ 2396 _argvec[8] = (unsigned long)arg8; \ 2397 _argvec[9] = (unsigned long)arg9; \ 2398 _argvec[10] = (unsigned long)arg10; \ 2399 __asm__ volatile( \ 2400 VALGRIND_ALIGN_STACK \ 2401 "mr 11,%1\n\t" \ 2402 "addi 1,1,-16\n\t" \ 2403 /* arg10 */ \ 2404 "lwz 3,40(11)\n\t" \ 2405 "stw 3,12(1)\n\t" \ 2406 /* arg9 */ \ 2407 "lwz 3,36(11)\n\t" \ 2408 "stw 3,8(1)\n\t" \ 2409 /* args1-8 */ \ 2410 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2411 "lwz 4,8(11)\n\t" \ 2412 "lwz 5,12(11)\n\t" \ 2413 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2414 "lwz 7,20(11)\n\t" \ 2415 "lwz 8,24(11)\n\t" \ 2416 "lwz 9,28(11)\n\t" \ 2417 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2418 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2419 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2420 VALGRIND_RESTORE_STACK \ 2421 "mr %0,3" \ 2422 : /*out*/ "=r" (_res) \ 2423 : /*in*/ "r" (&_argvec[0]) \ 2424 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2425 ); \ 2426 lval = (__typeof__(lval)) _res; \ 2427 } while (0) 2428 2429 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2430 arg7,arg8,arg9,arg10,arg11) \ 2431 do { \ 2432 volatile OrigFn _orig = (orig); \ 2433 volatile unsigned long _argvec[12]; \ 2434 volatile unsigned long _res; \ 2435 _argvec[0] = (unsigned long)_orig.nraddr; \ 2436 _argvec[1] = (unsigned long)arg1; \ 2437 _argvec[2] = (unsigned long)arg2; \ 2438 _argvec[3] = (unsigned long)arg3; \ 2439 _argvec[4] = (unsigned long)arg4; \ 2440 _argvec[5] = (unsigned long)arg5; \ 2441 _argvec[6] = (unsigned long)arg6; \ 2442 _argvec[7] = (unsigned long)arg7; \ 2443 _argvec[8] = (unsigned long)arg8; \ 2444 _argvec[9] = (unsigned long)arg9; \ 2445 _argvec[10] = (unsigned long)arg10; \ 2446 _argvec[11] = (unsigned long)arg11; \ 2447 __asm__ volatile( \ 2448 VALGRIND_ALIGN_STACK \ 2449 "mr 11,%1\n\t" \ 2450 "addi 1,1,-32\n\t" \ 2451 /* arg11 */ \ 2452 "lwz 3,44(11)\n\t" \ 2453 "stw 3,16(1)\n\t" \ 2454 /* arg10 */ \ 2455 "lwz 3,40(11)\n\t" \ 2456 "stw 3,12(1)\n\t" \ 2457 /* arg9 */ \ 2458 "lwz 3,36(11)\n\t" \ 2459 "stw 3,8(1)\n\t" \ 2460 /* args1-8 */ \ 2461 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2462 "lwz 4,8(11)\n\t" \ 2463 "lwz 5,12(11)\n\t" \ 2464 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2465 "lwz 7,20(11)\n\t" \ 2466 "lwz 8,24(11)\n\t" \ 2467 "lwz 9,28(11)\n\t" \ 2468 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2469 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2470 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2471 VALGRIND_RESTORE_STACK \ 2472 "mr %0,3" \ 2473 : /*out*/ "=r" (_res) \ 2474 : /*in*/ "r" (&_argvec[0]) \ 2475 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2476 ); \ 2477 lval = (__typeof__(lval)) _res; \ 2478 } while (0) 2479 2480 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2481 arg7,arg8,arg9,arg10,arg11,arg12) \ 2482 do { \ 2483 volatile OrigFn _orig = (orig); \ 2484 volatile unsigned long _argvec[13]; \ 2485 volatile unsigned long _res; \ 2486 _argvec[0] = (unsigned long)_orig.nraddr; \ 2487 _argvec[1] = (unsigned long)arg1; \ 2488 _argvec[2] = (unsigned long)arg2; \ 2489 _argvec[3] = (unsigned long)arg3; \ 2490 _argvec[4] = (unsigned long)arg4; \ 2491 _argvec[5] = (unsigned long)arg5; \ 2492 _argvec[6] = (unsigned long)arg6; \ 2493 _argvec[7] = (unsigned long)arg7; \ 2494 _argvec[8] = (unsigned long)arg8; \ 2495 _argvec[9] = (unsigned long)arg9; \ 2496 _argvec[10] = (unsigned long)arg10; \ 2497 _argvec[11] = (unsigned long)arg11; \ 2498 _argvec[12] = (unsigned long)arg12; \ 2499 __asm__ volatile( \ 2500 VALGRIND_ALIGN_STACK \ 2501 "mr 11,%1\n\t" \ 2502 "addi 1,1,-32\n\t" \ 2503 /* arg12 */ \ 2504 "lwz 3,48(11)\n\t" \ 2505 "stw 3,20(1)\n\t" \ 2506 /* arg11 */ \ 2507 "lwz 3,44(11)\n\t" \ 2508 "stw 3,16(1)\n\t" \ 2509 /* arg10 */ \ 2510 "lwz 3,40(11)\n\t" \ 2511 "stw 3,12(1)\n\t" \ 2512 /* arg9 */ \ 2513 "lwz 3,36(11)\n\t" \ 2514 "stw 3,8(1)\n\t" \ 2515 /* args1-8 */ \ 2516 "lwz 3,4(11)\n\t" /* arg1->r3 */ \ 2517 "lwz 4,8(11)\n\t" \ 2518 "lwz 5,12(11)\n\t" \ 2519 "lwz 6,16(11)\n\t" /* arg4->r6 */ \ 2520 "lwz 7,20(11)\n\t" \ 2521 "lwz 8,24(11)\n\t" \ 2522 "lwz 9,28(11)\n\t" \ 2523 "lwz 10,32(11)\n\t" /* arg8->r10 */ \ 2524 "lwz 11,0(11)\n\t" /* target->r11 */ \ 2525 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2526 VALGRIND_RESTORE_STACK \ 2527 "mr %0,3" \ 2528 : /*out*/ "=r" (_res) \ 2529 : /*in*/ "r" (&_argvec[0]) \ 2530 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2531 ); \ 2532 lval = (__typeof__(lval)) _res; \ 2533 } while (0) 2534 2535 #endif /* PLAT_ppc32_linux */ 2536 2537 /* ------------------------ ppc64-linux ------------------------ */ 2538 2539 #if defined(PLAT_ppc64_linux) 2540 2541 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ 2542 2543 /* These regs are trashed by the hidden call. */ 2544 #define __CALLER_SAVED_REGS \ 2545 "lr", "ctr", "xer", \ 2546 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ 2547 "r0", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", \ 2548 "r11", "r12", "r13" 2549 2550 /* Macros to save and align the stack before making a function 2551 call and restore it afterwards as gcc may not keep the stack 2552 pointer aligned if it doesn't realise calls are being made 2553 to other functions. */ 2554 2555 #define VALGRIND_ALIGN_STACK \ 2556 "mr 28,1\n\t" \ 2557 "rldicr 1,1,0,59\n\t" 2558 #define VALGRIND_RESTORE_STACK \ 2559 "mr 1,28\n\t" 2560 2561 /* These CALL_FN_ macros assume that on ppc64-linux, sizeof(unsigned 2562 long) == 8. */ 2563 2564 #define CALL_FN_W_v(lval, orig) \ 2565 do { \ 2566 volatile OrigFn _orig = (orig); \ 2567 volatile unsigned long _argvec[3+0]; \ 2568 volatile unsigned long _res; \ 2569 /* _argvec[0] holds current r2 across the call */ \ 2570 _argvec[1] = (unsigned long)_orig.r2; \ 2571 _argvec[2] = (unsigned long)_orig.nraddr; \ 2572 __asm__ volatile( \ 2573 VALGRIND_ALIGN_STACK \ 2574 "mr 11,%1\n\t" \ 2575 "std 2,-16(11)\n\t" /* save tocptr */ \ 2576 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2577 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2578 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2579 "mr 11,%1\n\t" \ 2580 "mr %0,3\n\t" \ 2581 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2582 VALGRIND_RESTORE_STACK \ 2583 : /*out*/ "=r" (_res) \ 2584 : /*in*/ "r" (&_argvec[2]) \ 2585 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2586 ); \ 2587 lval = (__typeof__(lval)) _res; \ 2588 } while (0) 2589 2590 #define CALL_FN_W_W(lval, orig, arg1) \ 2591 do { \ 2592 volatile OrigFn _orig = (orig); \ 2593 volatile unsigned long _argvec[3+1]; \ 2594 volatile unsigned long _res; \ 2595 /* _argvec[0] holds current r2 across the call */ \ 2596 _argvec[1] = (unsigned long)_orig.r2; \ 2597 _argvec[2] = (unsigned long)_orig.nraddr; \ 2598 _argvec[2+1] = (unsigned long)arg1; \ 2599 __asm__ volatile( \ 2600 VALGRIND_ALIGN_STACK \ 2601 "mr 11,%1\n\t" \ 2602 "std 2,-16(11)\n\t" /* save tocptr */ \ 2603 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2604 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2605 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2606 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2607 "mr 11,%1\n\t" \ 2608 "mr %0,3\n\t" \ 2609 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2610 VALGRIND_RESTORE_STACK \ 2611 : /*out*/ "=r" (_res) \ 2612 : /*in*/ "r" (&_argvec[2]) \ 2613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2614 ); \ 2615 lval = (__typeof__(lval)) _res; \ 2616 } while (0) 2617 2618 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 2619 do { \ 2620 volatile OrigFn _orig = (orig); \ 2621 volatile unsigned long _argvec[3+2]; \ 2622 volatile unsigned long _res; \ 2623 /* _argvec[0] holds current r2 across the call */ \ 2624 _argvec[1] = (unsigned long)_orig.r2; \ 2625 _argvec[2] = (unsigned long)_orig.nraddr; \ 2626 _argvec[2+1] = (unsigned long)arg1; \ 2627 _argvec[2+2] = (unsigned long)arg2; \ 2628 __asm__ volatile( \ 2629 VALGRIND_ALIGN_STACK \ 2630 "mr 11,%1\n\t" \ 2631 "std 2,-16(11)\n\t" /* save tocptr */ \ 2632 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2633 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2634 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2635 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2636 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2637 "mr 11,%1\n\t" \ 2638 "mr %0,3\n\t" \ 2639 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2640 VALGRIND_RESTORE_STACK \ 2641 : /*out*/ "=r" (_res) \ 2642 : /*in*/ "r" (&_argvec[2]) \ 2643 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2644 ); \ 2645 lval = (__typeof__(lval)) _res; \ 2646 } while (0) 2647 2648 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 2649 do { \ 2650 volatile OrigFn _orig = (orig); \ 2651 volatile unsigned long _argvec[3+3]; \ 2652 volatile unsigned long _res; \ 2653 /* _argvec[0] holds current r2 across the call */ \ 2654 _argvec[1] = (unsigned long)_orig.r2; \ 2655 _argvec[2] = (unsigned long)_orig.nraddr; \ 2656 _argvec[2+1] = (unsigned long)arg1; \ 2657 _argvec[2+2] = (unsigned long)arg2; \ 2658 _argvec[2+3] = (unsigned long)arg3; \ 2659 __asm__ volatile( \ 2660 VALGRIND_ALIGN_STACK \ 2661 "mr 11,%1\n\t" \ 2662 "std 2,-16(11)\n\t" /* save tocptr */ \ 2663 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2664 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2665 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2666 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2667 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2668 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2669 "mr 11,%1\n\t" \ 2670 "mr %0,3\n\t" \ 2671 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2672 VALGRIND_RESTORE_STACK \ 2673 : /*out*/ "=r" (_res) \ 2674 : /*in*/ "r" (&_argvec[2]) \ 2675 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2676 ); \ 2677 lval = (__typeof__(lval)) _res; \ 2678 } while (0) 2679 2680 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 2681 do { \ 2682 volatile OrigFn _orig = (orig); \ 2683 volatile unsigned long _argvec[3+4]; \ 2684 volatile unsigned long _res; \ 2685 /* _argvec[0] holds current r2 across the call */ \ 2686 _argvec[1] = (unsigned long)_orig.r2; \ 2687 _argvec[2] = (unsigned long)_orig.nraddr; \ 2688 _argvec[2+1] = (unsigned long)arg1; \ 2689 _argvec[2+2] = (unsigned long)arg2; \ 2690 _argvec[2+3] = (unsigned long)arg3; \ 2691 _argvec[2+4] = (unsigned long)arg4; \ 2692 __asm__ volatile( \ 2693 VALGRIND_ALIGN_STACK \ 2694 "mr 11,%1\n\t" \ 2695 "std 2,-16(11)\n\t" /* save tocptr */ \ 2696 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2697 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2698 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2699 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2700 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2701 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2702 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2703 "mr 11,%1\n\t" \ 2704 "mr %0,3\n\t" \ 2705 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2706 VALGRIND_RESTORE_STACK \ 2707 : /*out*/ "=r" (_res) \ 2708 : /*in*/ "r" (&_argvec[2]) \ 2709 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2710 ); \ 2711 lval = (__typeof__(lval)) _res; \ 2712 } while (0) 2713 2714 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 2715 do { \ 2716 volatile OrigFn _orig = (orig); \ 2717 volatile unsigned long _argvec[3+5]; \ 2718 volatile unsigned long _res; \ 2719 /* _argvec[0] holds current r2 across the call */ \ 2720 _argvec[1] = (unsigned long)_orig.r2; \ 2721 _argvec[2] = (unsigned long)_orig.nraddr; \ 2722 _argvec[2+1] = (unsigned long)arg1; \ 2723 _argvec[2+2] = (unsigned long)arg2; \ 2724 _argvec[2+3] = (unsigned long)arg3; \ 2725 _argvec[2+4] = (unsigned long)arg4; \ 2726 _argvec[2+5] = (unsigned long)arg5; \ 2727 __asm__ volatile( \ 2728 VALGRIND_ALIGN_STACK \ 2729 "mr 11,%1\n\t" \ 2730 "std 2,-16(11)\n\t" /* save tocptr */ \ 2731 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2732 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2733 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2734 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2735 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2736 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2737 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2738 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2739 "mr 11,%1\n\t" \ 2740 "mr %0,3\n\t" \ 2741 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2742 VALGRIND_RESTORE_STACK \ 2743 : /*out*/ "=r" (_res) \ 2744 : /*in*/ "r" (&_argvec[2]) \ 2745 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2746 ); \ 2747 lval = (__typeof__(lval)) _res; \ 2748 } while (0) 2749 2750 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 2751 do { \ 2752 volatile OrigFn _orig = (orig); \ 2753 volatile unsigned long _argvec[3+6]; \ 2754 volatile unsigned long _res; \ 2755 /* _argvec[0] holds current r2 across the call */ \ 2756 _argvec[1] = (unsigned long)_orig.r2; \ 2757 _argvec[2] = (unsigned long)_orig.nraddr; \ 2758 _argvec[2+1] = (unsigned long)arg1; \ 2759 _argvec[2+2] = (unsigned long)arg2; \ 2760 _argvec[2+3] = (unsigned long)arg3; \ 2761 _argvec[2+4] = (unsigned long)arg4; \ 2762 _argvec[2+5] = (unsigned long)arg5; \ 2763 _argvec[2+6] = (unsigned long)arg6; \ 2764 __asm__ volatile( \ 2765 VALGRIND_ALIGN_STACK \ 2766 "mr 11,%1\n\t" \ 2767 "std 2,-16(11)\n\t" /* save tocptr */ \ 2768 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2769 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2770 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2771 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2772 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2773 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2774 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2775 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2776 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2777 "mr 11,%1\n\t" \ 2778 "mr %0,3\n\t" \ 2779 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2780 VALGRIND_RESTORE_STACK \ 2781 : /*out*/ "=r" (_res) \ 2782 : /*in*/ "r" (&_argvec[2]) \ 2783 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2784 ); \ 2785 lval = (__typeof__(lval)) _res; \ 2786 } while (0) 2787 2788 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2789 arg7) \ 2790 do { \ 2791 volatile OrigFn _orig = (orig); \ 2792 volatile unsigned long _argvec[3+7]; \ 2793 volatile unsigned long _res; \ 2794 /* _argvec[0] holds current r2 across the call */ \ 2795 _argvec[1] = (unsigned long)_orig.r2; \ 2796 _argvec[2] = (unsigned long)_orig.nraddr; \ 2797 _argvec[2+1] = (unsigned long)arg1; \ 2798 _argvec[2+2] = (unsigned long)arg2; \ 2799 _argvec[2+3] = (unsigned long)arg3; \ 2800 _argvec[2+4] = (unsigned long)arg4; \ 2801 _argvec[2+5] = (unsigned long)arg5; \ 2802 _argvec[2+6] = (unsigned long)arg6; \ 2803 _argvec[2+7] = (unsigned long)arg7; \ 2804 __asm__ volatile( \ 2805 VALGRIND_ALIGN_STACK \ 2806 "mr 11,%1\n\t" \ 2807 "std 2,-16(11)\n\t" /* save tocptr */ \ 2808 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2809 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2810 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2811 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2812 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2813 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2814 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2815 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2816 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2817 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2818 "mr 11,%1\n\t" \ 2819 "mr %0,3\n\t" \ 2820 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2821 VALGRIND_RESTORE_STACK \ 2822 : /*out*/ "=r" (_res) \ 2823 : /*in*/ "r" (&_argvec[2]) \ 2824 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2825 ); \ 2826 lval = (__typeof__(lval)) _res; \ 2827 } while (0) 2828 2829 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2830 arg7,arg8) \ 2831 do { \ 2832 volatile OrigFn _orig = (orig); \ 2833 volatile unsigned long _argvec[3+8]; \ 2834 volatile unsigned long _res; \ 2835 /* _argvec[0] holds current r2 across the call */ \ 2836 _argvec[1] = (unsigned long)_orig.r2; \ 2837 _argvec[2] = (unsigned long)_orig.nraddr; \ 2838 _argvec[2+1] = (unsigned long)arg1; \ 2839 _argvec[2+2] = (unsigned long)arg2; \ 2840 _argvec[2+3] = (unsigned long)arg3; \ 2841 _argvec[2+4] = (unsigned long)arg4; \ 2842 _argvec[2+5] = (unsigned long)arg5; \ 2843 _argvec[2+6] = (unsigned long)arg6; \ 2844 _argvec[2+7] = (unsigned long)arg7; \ 2845 _argvec[2+8] = (unsigned long)arg8; \ 2846 __asm__ volatile( \ 2847 VALGRIND_ALIGN_STACK \ 2848 "mr 11,%1\n\t" \ 2849 "std 2,-16(11)\n\t" /* save tocptr */ \ 2850 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2851 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2852 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2853 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2854 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2855 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2856 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2857 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2858 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2859 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2860 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2861 "mr 11,%1\n\t" \ 2862 "mr %0,3\n\t" \ 2863 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2864 VALGRIND_RESTORE_STACK \ 2865 : /*out*/ "=r" (_res) \ 2866 : /*in*/ "r" (&_argvec[2]) \ 2867 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2868 ); \ 2869 lval = (__typeof__(lval)) _res; \ 2870 } while (0) 2871 2872 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2873 arg7,arg8,arg9) \ 2874 do { \ 2875 volatile OrigFn _orig = (orig); \ 2876 volatile unsigned long _argvec[3+9]; \ 2877 volatile unsigned long _res; \ 2878 /* _argvec[0] holds current r2 across the call */ \ 2879 _argvec[1] = (unsigned long)_orig.r2; \ 2880 _argvec[2] = (unsigned long)_orig.nraddr; \ 2881 _argvec[2+1] = (unsigned long)arg1; \ 2882 _argvec[2+2] = (unsigned long)arg2; \ 2883 _argvec[2+3] = (unsigned long)arg3; \ 2884 _argvec[2+4] = (unsigned long)arg4; \ 2885 _argvec[2+5] = (unsigned long)arg5; \ 2886 _argvec[2+6] = (unsigned long)arg6; \ 2887 _argvec[2+7] = (unsigned long)arg7; \ 2888 _argvec[2+8] = (unsigned long)arg8; \ 2889 _argvec[2+9] = (unsigned long)arg9; \ 2890 __asm__ volatile( \ 2891 VALGRIND_ALIGN_STACK \ 2892 "mr 11,%1\n\t" \ 2893 "std 2,-16(11)\n\t" /* save tocptr */ \ 2894 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2895 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2896 /* arg9 */ \ 2897 "ld 3,72(11)\n\t" \ 2898 "std 3,112(1)\n\t" \ 2899 /* args1-8 */ \ 2900 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2901 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2902 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2903 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2904 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2905 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2906 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2907 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2908 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2909 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2910 "mr 11,%1\n\t" \ 2911 "mr %0,3\n\t" \ 2912 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2913 VALGRIND_RESTORE_STACK \ 2914 : /*out*/ "=r" (_res) \ 2915 : /*in*/ "r" (&_argvec[2]) \ 2916 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2917 ); \ 2918 lval = (__typeof__(lval)) _res; \ 2919 } while (0) 2920 2921 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2922 arg7,arg8,arg9,arg10) \ 2923 do { \ 2924 volatile OrigFn _orig = (orig); \ 2925 volatile unsigned long _argvec[3+10]; \ 2926 volatile unsigned long _res; \ 2927 /* _argvec[0] holds current r2 across the call */ \ 2928 _argvec[1] = (unsigned long)_orig.r2; \ 2929 _argvec[2] = (unsigned long)_orig.nraddr; \ 2930 _argvec[2+1] = (unsigned long)arg1; \ 2931 _argvec[2+2] = (unsigned long)arg2; \ 2932 _argvec[2+3] = (unsigned long)arg3; \ 2933 _argvec[2+4] = (unsigned long)arg4; \ 2934 _argvec[2+5] = (unsigned long)arg5; \ 2935 _argvec[2+6] = (unsigned long)arg6; \ 2936 _argvec[2+7] = (unsigned long)arg7; \ 2937 _argvec[2+8] = (unsigned long)arg8; \ 2938 _argvec[2+9] = (unsigned long)arg9; \ 2939 _argvec[2+10] = (unsigned long)arg10; \ 2940 __asm__ volatile( \ 2941 VALGRIND_ALIGN_STACK \ 2942 "mr 11,%1\n\t" \ 2943 "std 2,-16(11)\n\t" /* save tocptr */ \ 2944 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2945 "addi 1,1,-128\n\t" /* expand stack frame */ \ 2946 /* arg10 */ \ 2947 "ld 3,80(11)\n\t" \ 2948 "std 3,120(1)\n\t" \ 2949 /* arg9 */ \ 2950 "ld 3,72(11)\n\t" \ 2951 "std 3,112(1)\n\t" \ 2952 /* args1-8 */ \ 2953 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 2954 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 2955 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 2956 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 2957 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 2958 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 2959 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 2960 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 2961 "ld 11, 0(11)\n\t" /* target->r11 */ \ 2962 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 2963 "mr 11,%1\n\t" \ 2964 "mr %0,3\n\t" \ 2965 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 2966 VALGRIND_RESTORE_STACK \ 2967 : /*out*/ "=r" (_res) \ 2968 : /*in*/ "r" (&_argvec[2]) \ 2969 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 2970 ); \ 2971 lval = (__typeof__(lval)) _res; \ 2972 } while (0) 2973 2974 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 2975 arg7,arg8,arg9,arg10,arg11) \ 2976 do { \ 2977 volatile OrigFn _orig = (orig); \ 2978 volatile unsigned long _argvec[3+11]; \ 2979 volatile unsigned long _res; \ 2980 /* _argvec[0] holds current r2 across the call */ \ 2981 _argvec[1] = (unsigned long)_orig.r2; \ 2982 _argvec[2] = (unsigned long)_orig.nraddr; \ 2983 _argvec[2+1] = (unsigned long)arg1; \ 2984 _argvec[2+2] = (unsigned long)arg2; \ 2985 _argvec[2+3] = (unsigned long)arg3; \ 2986 _argvec[2+4] = (unsigned long)arg4; \ 2987 _argvec[2+5] = (unsigned long)arg5; \ 2988 _argvec[2+6] = (unsigned long)arg6; \ 2989 _argvec[2+7] = (unsigned long)arg7; \ 2990 _argvec[2+8] = (unsigned long)arg8; \ 2991 _argvec[2+9] = (unsigned long)arg9; \ 2992 _argvec[2+10] = (unsigned long)arg10; \ 2993 _argvec[2+11] = (unsigned long)arg11; \ 2994 __asm__ volatile( \ 2995 VALGRIND_ALIGN_STACK \ 2996 "mr 11,%1\n\t" \ 2997 "std 2,-16(11)\n\t" /* save tocptr */ \ 2998 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 2999 "addi 1,1,-144\n\t" /* expand stack frame */ \ 3000 /* arg11 */ \ 3001 "ld 3,88(11)\n\t" \ 3002 "std 3,128(1)\n\t" \ 3003 /* arg10 */ \ 3004 "ld 3,80(11)\n\t" \ 3005 "std 3,120(1)\n\t" \ 3006 /* arg9 */ \ 3007 "ld 3,72(11)\n\t" \ 3008 "std 3,112(1)\n\t" \ 3009 /* args1-8 */ \ 3010 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3011 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3012 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3013 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3014 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3015 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3016 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3017 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3018 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3019 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3020 "mr 11,%1\n\t" \ 3021 "mr %0,3\n\t" \ 3022 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3023 VALGRIND_RESTORE_STACK \ 3024 : /*out*/ "=r" (_res) \ 3025 : /*in*/ "r" (&_argvec[2]) \ 3026 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 3027 ); \ 3028 lval = (__typeof__(lval)) _res; \ 3029 } while (0) 3030 3031 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3032 arg7,arg8,arg9,arg10,arg11,arg12) \ 3033 do { \ 3034 volatile OrigFn _orig = (orig); \ 3035 volatile unsigned long _argvec[3+12]; \ 3036 volatile unsigned long _res; \ 3037 /* _argvec[0] holds current r2 across the call */ \ 3038 _argvec[1] = (unsigned long)_orig.r2; \ 3039 _argvec[2] = (unsigned long)_orig.nraddr; \ 3040 _argvec[2+1] = (unsigned long)arg1; \ 3041 _argvec[2+2] = (unsigned long)arg2; \ 3042 _argvec[2+3] = (unsigned long)arg3; \ 3043 _argvec[2+4] = (unsigned long)arg4; \ 3044 _argvec[2+5] = (unsigned long)arg5; \ 3045 _argvec[2+6] = (unsigned long)arg6; \ 3046 _argvec[2+7] = (unsigned long)arg7; \ 3047 _argvec[2+8] = (unsigned long)arg8; \ 3048 _argvec[2+9] = (unsigned long)arg9; \ 3049 _argvec[2+10] = (unsigned long)arg10; \ 3050 _argvec[2+11] = (unsigned long)arg11; \ 3051 _argvec[2+12] = (unsigned long)arg12; \ 3052 __asm__ volatile( \ 3053 VALGRIND_ALIGN_STACK \ 3054 "mr 11,%1\n\t" \ 3055 "std 2,-16(11)\n\t" /* save tocptr */ \ 3056 "ld 2,-8(11)\n\t" /* use nraddr's tocptr */ \ 3057 "addi 1,1,-144\n\t" /* expand stack frame */ \ 3058 /* arg12 */ \ 3059 "ld 3,96(11)\n\t" \ 3060 "std 3,136(1)\n\t" \ 3061 /* arg11 */ \ 3062 "ld 3,88(11)\n\t" \ 3063 "std 3,128(1)\n\t" \ 3064 /* arg10 */ \ 3065 "ld 3,80(11)\n\t" \ 3066 "std 3,120(1)\n\t" \ 3067 /* arg9 */ \ 3068 "ld 3,72(11)\n\t" \ 3069 "std 3,112(1)\n\t" \ 3070 /* args1-8 */ \ 3071 "ld 3, 8(11)\n\t" /* arg1->r3 */ \ 3072 "ld 4, 16(11)\n\t" /* arg2->r4 */ \ 3073 "ld 5, 24(11)\n\t" /* arg3->r5 */ \ 3074 "ld 6, 32(11)\n\t" /* arg4->r6 */ \ 3075 "ld 7, 40(11)\n\t" /* arg5->r7 */ \ 3076 "ld 8, 48(11)\n\t" /* arg6->r8 */ \ 3077 "ld 9, 56(11)\n\t" /* arg7->r9 */ \ 3078 "ld 10, 64(11)\n\t" /* arg8->r10 */ \ 3079 "ld 11, 0(11)\n\t" /* target->r11 */ \ 3080 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ 3081 "mr 11,%1\n\t" \ 3082 "mr %0,3\n\t" \ 3083 "ld 2,-16(11)\n\t" /* restore tocptr */ \ 3084 VALGRIND_RESTORE_STACK \ 3085 : /*out*/ "=r" (_res) \ 3086 : /*in*/ "r" (&_argvec[2]) \ 3087 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r28" \ 3088 ); \ 3089 lval = (__typeof__(lval)) _res; \ 3090 } while (0) 3091 3092 #endif /* PLAT_ppc64_linux */ 3093 3094 /* ------------------------- arm-linux ------------------------- */ 3095 3096 #if defined(PLAT_arm_linux) 3097 3098 /* These regs are trashed by the hidden call. */ 3099 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" 3100 3101 /* Macros to save and align the stack before making a function 3102 call and restore it afterwards as gcc may not keep the stack 3103 pointer aligned if it doesn't realise calls are being made 3104 to other functions. */ 3105 3106 /* This is a bit tricky. We store the original stack pointer in r10 3107 as it is callee-saves. gcc doesn't allow the use of r11 for some 3108 reason. Also, we can't directly "bic" the stack pointer in thumb 3109 mode since r13 isn't an allowed register number in that context. 3110 So use r4 as a temporary, since that is about to get trashed 3111 anyway, just after each use of this macro. Side effect is we need 3112 to be very careful about any future changes, since 3113 VALGRIND_ALIGN_STACK simply assumes r4 is usable. */ 3114 #define VALGRIND_ALIGN_STACK \ 3115 "mov r10, sp\n\t" \ 3116 "mov r4, sp\n\t" \ 3117 "bic r4, r4, #7\n\t" \ 3118 "mov sp, r4\n\t" 3119 #define VALGRIND_RESTORE_STACK \ 3120 "mov sp, r10\n\t" 3121 3122 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned 3123 long) == 4. */ 3124 3125 #define CALL_FN_W_v(lval, orig) \ 3126 do { \ 3127 volatile OrigFn _orig = (orig); \ 3128 volatile unsigned long _argvec[1]; \ 3129 volatile unsigned long _res; \ 3130 _argvec[0] = (unsigned long)_orig.nraddr; \ 3131 __asm__ volatile( \ 3132 VALGRIND_ALIGN_STACK \ 3133 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3134 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3135 VALGRIND_RESTORE_STACK \ 3136 "mov %0, r0\n" \ 3137 : /*out*/ "=r" (_res) \ 3138 : /*in*/ "0" (&_argvec[0]) \ 3139 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3140 ); \ 3141 lval = (__typeof__(lval)) _res; \ 3142 } while (0) 3143 3144 #define CALL_FN_W_W(lval, orig, arg1) \ 3145 do { \ 3146 volatile OrigFn _orig = (orig); \ 3147 volatile unsigned long _argvec[2]; \ 3148 volatile unsigned long _res; \ 3149 _argvec[0] = (unsigned long)_orig.nraddr; \ 3150 _argvec[1] = (unsigned long)(arg1); \ 3151 __asm__ volatile( \ 3152 VALGRIND_ALIGN_STACK \ 3153 "ldr r0, [%1, #4] \n\t" \ 3154 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3155 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3156 VALGRIND_RESTORE_STACK \ 3157 "mov %0, r0\n" \ 3158 : /*out*/ "=r" (_res) \ 3159 : /*in*/ "0" (&_argvec[0]) \ 3160 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3161 ); \ 3162 lval = (__typeof__(lval)) _res; \ 3163 } while (0) 3164 3165 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 3166 do { \ 3167 volatile OrigFn _orig = (orig); \ 3168 volatile unsigned long _argvec[3]; \ 3169 volatile unsigned long _res; \ 3170 _argvec[0] = (unsigned long)_orig.nraddr; \ 3171 _argvec[1] = (unsigned long)(arg1); \ 3172 _argvec[2] = (unsigned long)(arg2); \ 3173 __asm__ volatile( \ 3174 VALGRIND_ALIGN_STACK \ 3175 "ldr r0, [%1, #4] \n\t" \ 3176 "ldr r1, [%1, #8] \n\t" \ 3177 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3178 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3179 VALGRIND_RESTORE_STACK \ 3180 "mov %0, r0\n" \ 3181 : /*out*/ "=r" (_res) \ 3182 : /*in*/ "0" (&_argvec[0]) \ 3183 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3184 ); \ 3185 lval = (__typeof__(lval)) _res; \ 3186 } while (0) 3187 3188 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 3189 do { \ 3190 volatile OrigFn _orig = (orig); \ 3191 volatile unsigned long _argvec[4]; \ 3192 volatile unsigned long _res; \ 3193 _argvec[0] = (unsigned long)_orig.nraddr; \ 3194 _argvec[1] = (unsigned long)(arg1); \ 3195 _argvec[2] = (unsigned long)(arg2); \ 3196 _argvec[3] = (unsigned long)(arg3); \ 3197 __asm__ volatile( \ 3198 VALGRIND_ALIGN_STACK \ 3199 "ldr r0, [%1, #4] \n\t" \ 3200 "ldr r1, [%1, #8] \n\t" \ 3201 "ldr r2, [%1, #12] \n\t" \ 3202 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3203 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3204 VALGRIND_RESTORE_STACK \ 3205 "mov %0, r0\n" \ 3206 : /*out*/ "=r" (_res) \ 3207 : /*in*/ "0" (&_argvec[0]) \ 3208 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3209 ); \ 3210 lval = (__typeof__(lval)) _res; \ 3211 } while (0) 3212 3213 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 3214 do { \ 3215 volatile OrigFn _orig = (orig); \ 3216 volatile unsigned long _argvec[5]; \ 3217 volatile unsigned long _res; \ 3218 _argvec[0] = (unsigned long)_orig.nraddr; \ 3219 _argvec[1] = (unsigned long)(arg1); \ 3220 _argvec[2] = (unsigned long)(arg2); \ 3221 _argvec[3] = (unsigned long)(arg3); \ 3222 _argvec[4] = (unsigned long)(arg4); \ 3223 __asm__ volatile( \ 3224 VALGRIND_ALIGN_STACK \ 3225 "ldr r0, [%1, #4] \n\t" \ 3226 "ldr r1, [%1, #8] \n\t" \ 3227 "ldr r2, [%1, #12] \n\t" \ 3228 "ldr r3, [%1, #16] \n\t" \ 3229 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3230 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3231 VALGRIND_RESTORE_STACK \ 3232 "mov %0, r0" \ 3233 : /*out*/ "=r" (_res) \ 3234 : /*in*/ "0" (&_argvec[0]) \ 3235 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3236 ); \ 3237 lval = (__typeof__(lval)) _res; \ 3238 } while (0) 3239 3240 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 3241 do { \ 3242 volatile OrigFn _orig = (orig); \ 3243 volatile unsigned long _argvec[6]; \ 3244 volatile unsigned long _res; \ 3245 _argvec[0] = (unsigned long)_orig.nraddr; \ 3246 _argvec[1] = (unsigned long)(arg1); \ 3247 _argvec[2] = (unsigned long)(arg2); \ 3248 _argvec[3] = (unsigned long)(arg3); \ 3249 _argvec[4] = (unsigned long)(arg4); \ 3250 _argvec[5] = (unsigned long)(arg5); \ 3251 __asm__ volatile( \ 3252 VALGRIND_ALIGN_STACK \ 3253 "sub sp, sp, #4 \n\t" \ 3254 "ldr r0, [%1, #20] \n\t" \ 3255 "push {r0} \n\t" \ 3256 "ldr r0, [%1, #4] \n\t" \ 3257 "ldr r1, [%1, #8] \n\t" \ 3258 "ldr r2, [%1, #12] \n\t" \ 3259 "ldr r3, [%1, #16] \n\t" \ 3260 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3261 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3262 VALGRIND_RESTORE_STACK \ 3263 "mov %0, r0" \ 3264 : /*out*/ "=r" (_res) \ 3265 : /*in*/ "0" (&_argvec[0]) \ 3266 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3267 ); \ 3268 lval = (__typeof__(lval)) _res; \ 3269 } while (0) 3270 3271 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 3272 do { \ 3273 volatile OrigFn _orig = (orig); \ 3274 volatile unsigned long _argvec[7]; \ 3275 volatile unsigned long _res; \ 3276 _argvec[0] = (unsigned long)_orig.nraddr; \ 3277 _argvec[1] = (unsigned long)(arg1); \ 3278 _argvec[2] = (unsigned long)(arg2); \ 3279 _argvec[3] = (unsigned long)(arg3); \ 3280 _argvec[4] = (unsigned long)(arg4); \ 3281 _argvec[5] = (unsigned long)(arg5); \ 3282 _argvec[6] = (unsigned long)(arg6); \ 3283 __asm__ volatile( \ 3284 VALGRIND_ALIGN_STACK \ 3285 "ldr r0, [%1, #20] \n\t" \ 3286 "ldr r1, [%1, #24] \n\t" \ 3287 "push {r0, r1} \n\t" \ 3288 "ldr r0, [%1, #4] \n\t" \ 3289 "ldr r1, [%1, #8] \n\t" \ 3290 "ldr r2, [%1, #12] \n\t" \ 3291 "ldr r3, [%1, #16] \n\t" \ 3292 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3293 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3294 VALGRIND_RESTORE_STACK \ 3295 "mov %0, r0" \ 3296 : /*out*/ "=r" (_res) \ 3297 : /*in*/ "0" (&_argvec[0]) \ 3298 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3299 ); \ 3300 lval = (__typeof__(lval)) _res; \ 3301 } while (0) 3302 3303 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3304 arg7) \ 3305 do { \ 3306 volatile OrigFn _orig = (orig); \ 3307 volatile unsigned long _argvec[8]; \ 3308 volatile unsigned long _res; \ 3309 _argvec[0] = (unsigned long)_orig.nraddr; \ 3310 _argvec[1] = (unsigned long)(arg1); \ 3311 _argvec[2] = (unsigned long)(arg2); \ 3312 _argvec[3] = (unsigned long)(arg3); \ 3313 _argvec[4] = (unsigned long)(arg4); \ 3314 _argvec[5] = (unsigned long)(arg5); \ 3315 _argvec[6] = (unsigned long)(arg6); \ 3316 _argvec[7] = (unsigned long)(arg7); \ 3317 __asm__ volatile( \ 3318 VALGRIND_ALIGN_STACK \ 3319 "sub sp, sp, #4 \n\t" \ 3320 "ldr r0, [%1, #20] \n\t" \ 3321 "ldr r1, [%1, #24] \n\t" \ 3322 "ldr r2, [%1, #28] \n\t" \ 3323 "push {r0, r1, r2} \n\t" \ 3324 "ldr r0, [%1, #4] \n\t" \ 3325 "ldr r1, [%1, #8] \n\t" \ 3326 "ldr r2, [%1, #12] \n\t" \ 3327 "ldr r3, [%1, #16] \n\t" \ 3328 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3329 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3330 VALGRIND_RESTORE_STACK \ 3331 "mov %0, r0" \ 3332 : /*out*/ "=r" (_res) \ 3333 : /*in*/ "0" (&_argvec[0]) \ 3334 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3335 ); \ 3336 lval = (__typeof__(lval)) _res; \ 3337 } while (0) 3338 3339 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3340 arg7,arg8) \ 3341 do { \ 3342 volatile OrigFn _orig = (orig); \ 3343 volatile unsigned long _argvec[9]; \ 3344 volatile unsigned long _res; \ 3345 _argvec[0] = (unsigned long)_orig.nraddr; \ 3346 _argvec[1] = (unsigned long)(arg1); \ 3347 _argvec[2] = (unsigned long)(arg2); \ 3348 _argvec[3] = (unsigned long)(arg3); \ 3349 _argvec[4] = (unsigned long)(arg4); \ 3350 _argvec[5] = (unsigned long)(arg5); \ 3351 _argvec[6] = (unsigned long)(arg6); \ 3352 _argvec[7] = (unsigned long)(arg7); \ 3353 _argvec[8] = (unsigned long)(arg8); \ 3354 __asm__ volatile( \ 3355 VALGRIND_ALIGN_STACK \ 3356 "ldr r0, [%1, #20] \n\t" \ 3357 "ldr r1, [%1, #24] \n\t" \ 3358 "ldr r2, [%1, #28] \n\t" \ 3359 "ldr r3, [%1, #32] \n\t" \ 3360 "push {r0, r1, r2, r3} \n\t" \ 3361 "ldr r0, [%1, #4] \n\t" \ 3362 "ldr r1, [%1, #8] \n\t" \ 3363 "ldr r2, [%1, #12] \n\t" \ 3364 "ldr r3, [%1, #16] \n\t" \ 3365 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3366 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3367 VALGRIND_RESTORE_STACK \ 3368 "mov %0, r0" \ 3369 : /*out*/ "=r" (_res) \ 3370 : /*in*/ "0" (&_argvec[0]) \ 3371 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3372 ); \ 3373 lval = (__typeof__(lval)) _res; \ 3374 } while (0) 3375 3376 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3377 arg7,arg8,arg9) \ 3378 do { \ 3379 volatile OrigFn _orig = (orig); \ 3380 volatile unsigned long _argvec[10]; \ 3381 volatile unsigned long _res; \ 3382 _argvec[0] = (unsigned long)_orig.nraddr; \ 3383 _argvec[1] = (unsigned long)(arg1); \ 3384 _argvec[2] = (unsigned long)(arg2); \ 3385 _argvec[3] = (unsigned long)(arg3); \ 3386 _argvec[4] = (unsigned long)(arg4); \ 3387 _argvec[5] = (unsigned long)(arg5); \ 3388 _argvec[6] = (unsigned long)(arg6); \ 3389 _argvec[7] = (unsigned long)(arg7); \ 3390 _argvec[8] = (unsigned long)(arg8); \ 3391 _argvec[9] = (unsigned long)(arg9); \ 3392 __asm__ volatile( \ 3393 VALGRIND_ALIGN_STACK \ 3394 "sub sp, sp, #4 \n\t" \ 3395 "ldr r0, [%1, #20] \n\t" \ 3396 "ldr r1, [%1, #24] \n\t" \ 3397 "ldr r2, [%1, #28] \n\t" \ 3398 "ldr r3, [%1, #32] \n\t" \ 3399 "ldr r4, [%1, #36] \n\t" \ 3400 "push {r0, r1, r2, r3, r4} \n\t" \ 3401 "ldr r0, [%1, #4] \n\t" \ 3402 "ldr r1, [%1, #8] \n\t" \ 3403 "ldr r2, [%1, #12] \n\t" \ 3404 "ldr r3, [%1, #16] \n\t" \ 3405 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3406 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3407 VALGRIND_RESTORE_STACK \ 3408 "mov %0, r0" \ 3409 : /*out*/ "=r" (_res) \ 3410 : /*in*/ "0" (&_argvec[0]) \ 3411 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3412 ); \ 3413 lval = (__typeof__(lval)) _res; \ 3414 } while (0) 3415 3416 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3417 arg7,arg8,arg9,arg10) \ 3418 do { \ 3419 volatile OrigFn _orig = (orig); \ 3420 volatile unsigned long _argvec[11]; \ 3421 volatile unsigned long _res; \ 3422 _argvec[0] = (unsigned long)_orig.nraddr; \ 3423 _argvec[1] = (unsigned long)(arg1); \ 3424 _argvec[2] = (unsigned long)(arg2); \ 3425 _argvec[3] = (unsigned long)(arg3); \ 3426 _argvec[4] = (unsigned long)(arg4); \ 3427 _argvec[5] = (unsigned long)(arg5); \ 3428 _argvec[6] = (unsigned long)(arg6); \ 3429 _argvec[7] = (unsigned long)(arg7); \ 3430 _argvec[8] = (unsigned long)(arg8); \ 3431 _argvec[9] = (unsigned long)(arg9); \ 3432 _argvec[10] = (unsigned long)(arg10); \ 3433 __asm__ volatile( \ 3434 VALGRIND_ALIGN_STACK \ 3435 "ldr r0, [%1, #40] \n\t" \ 3436 "push {r0} \n\t" \ 3437 "ldr r0, [%1, #20] \n\t" \ 3438 "ldr r1, [%1, #24] \n\t" \ 3439 "ldr r2, [%1, #28] \n\t" \ 3440 "ldr r3, [%1, #32] \n\t" \ 3441 "ldr r4, [%1, #36] \n\t" \ 3442 "push {r0, r1, r2, r3, r4} \n\t" \ 3443 "ldr r0, [%1, #4] \n\t" \ 3444 "ldr r1, [%1, #8] \n\t" \ 3445 "ldr r2, [%1, #12] \n\t" \ 3446 "ldr r3, [%1, #16] \n\t" \ 3447 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3448 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3449 VALGRIND_RESTORE_STACK \ 3450 "mov %0, r0" \ 3451 : /*out*/ "=r" (_res) \ 3452 : /*in*/ "0" (&_argvec[0]) \ 3453 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3454 ); \ 3455 lval = (__typeof__(lval)) _res; \ 3456 } while (0) 3457 3458 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 3459 arg6,arg7,arg8,arg9,arg10, \ 3460 arg11) \ 3461 do { \ 3462 volatile OrigFn _orig = (orig); \ 3463 volatile unsigned long _argvec[12]; \ 3464 volatile unsigned long _res; \ 3465 _argvec[0] = (unsigned long)_orig.nraddr; \ 3466 _argvec[1] = (unsigned long)(arg1); \ 3467 _argvec[2] = (unsigned long)(arg2); \ 3468 _argvec[3] = (unsigned long)(arg3); \ 3469 _argvec[4] = (unsigned long)(arg4); \ 3470 _argvec[5] = (unsigned long)(arg5); \ 3471 _argvec[6] = (unsigned long)(arg6); \ 3472 _argvec[7] = (unsigned long)(arg7); \ 3473 _argvec[8] = (unsigned long)(arg8); \ 3474 _argvec[9] = (unsigned long)(arg9); \ 3475 _argvec[10] = (unsigned long)(arg10); \ 3476 _argvec[11] = (unsigned long)(arg11); \ 3477 __asm__ volatile( \ 3478 VALGRIND_ALIGN_STACK \ 3479 "sub sp, sp, #4 \n\t" \ 3480 "ldr r0, [%1, #40] \n\t" \ 3481 "ldr r1, [%1, #44] \n\t" \ 3482 "push {r0, r1} \n\t" \ 3483 "ldr r0, [%1, #20] \n\t" \ 3484 "ldr r1, [%1, #24] \n\t" \ 3485 "ldr r2, [%1, #28] \n\t" \ 3486 "ldr r3, [%1, #32] \n\t" \ 3487 "ldr r4, [%1, #36] \n\t" \ 3488 "push {r0, r1, r2, r3, r4} \n\t" \ 3489 "ldr r0, [%1, #4] \n\t" \ 3490 "ldr r1, [%1, #8] \n\t" \ 3491 "ldr r2, [%1, #12] \n\t" \ 3492 "ldr r3, [%1, #16] \n\t" \ 3493 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3494 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3495 VALGRIND_RESTORE_STACK \ 3496 "mov %0, r0" \ 3497 : /*out*/ "=r" (_res) \ 3498 : /*in*/ "0" (&_argvec[0]) \ 3499 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3500 ); \ 3501 lval = (__typeof__(lval)) _res; \ 3502 } while (0) 3503 3504 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 3505 arg6,arg7,arg8,arg9,arg10, \ 3506 arg11,arg12) \ 3507 do { \ 3508 volatile OrigFn _orig = (orig); \ 3509 volatile unsigned long _argvec[13]; \ 3510 volatile unsigned long _res; \ 3511 _argvec[0] = (unsigned long)_orig.nraddr; \ 3512 _argvec[1] = (unsigned long)(arg1); \ 3513 _argvec[2] = (unsigned long)(arg2); \ 3514 _argvec[3] = (unsigned long)(arg3); \ 3515 _argvec[4] = (unsigned long)(arg4); \ 3516 _argvec[5] = (unsigned long)(arg5); \ 3517 _argvec[6] = (unsigned long)(arg6); \ 3518 _argvec[7] = (unsigned long)(arg7); \ 3519 _argvec[8] = (unsigned long)(arg8); \ 3520 _argvec[9] = (unsigned long)(arg9); \ 3521 _argvec[10] = (unsigned long)(arg10); \ 3522 _argvec[11] = (unsigned long)(arg11); \ 3523 _argvec[12] = (unsigned long)(arg12); \ 3524 __asm__ volatile( \ 3525 VALGRIND_ALIGN_STACK \ 3526 "ldr r0, [%1, #40] \n\t" \ 3527 "ldr r1, [%1, #44] \n\t" \ 3528 "ldr r2, [%1, #48] \n\t" \ 3529 "push {r0, r1, r2} \n\t" \ 3530 "ldr r0, [%1, #20] \n\t" \ 3531 "ldr r1, [%1, #24] \n\t" \ 3532 "ldr r2, [%1, #28] \n\t" \ 3533 "ldr r3, [%1, #32] \n\t" \ 3534 "ldr r4, [%1, #36] \n\t" \ 3535 "push {r0, r1, r2, r3, r4} \n\t" \ 3536 "ldr r0, [%1, #4] \n\t" \ 3537 "ldr r1, [%1, #8] \n\t" \ 3538 "ldr r2, [%1, #12] \n\t" \ 3539 "ldr r3, [%1, #16] \n\t" \ 3540 "ldr r4, [%1] \n\t" /* target->r4 */ \ 3541 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ 3542 VALGRIND_RESTORE_STACK \ 3543 "mov %0, r0" \ 3544 : /*out*/ "=r" (_res) \ 3545 : /*in*/ "0" (&_argvec[0]) \ 3546 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r10" \ 3547 ); \ 3548 lval = (__typeof__(lval)) _res; \ 3549 } while (0) 3550 3551 #endif /* PLAT_arm_linux */ 3552 3553 /* ------------------------ arm64-linux ------------------------ */ 3554 3555 #if defined(PLAT_arm64_linux) 3556 3557 /* These regs are trashed by the hidden call. */ 3558 #define __CALLER_SAVED_REGS \ 3559 "x0", "x1", "x2", "x3","x4", "x5", "x6", "x7", "x8", "x9", \ 3560 "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", \ 3561 "x18", "x19", "x20", "x30", \ 3562 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \ 3563 "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", \ 3564 "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", \ 3565 "v26", "v27", "v28", "v29", "v30", "v31" 3566 3567 /* x21 is callee-saved, so we can use it to save and restore SP around 3568 the hidden call. */ 3569 #define VALGRIND_ALIGN_STACK \ 3570 "mov x21, sp\n\t" \ 3571 "bic sp, x21, #15\n\t" 3572 #define VALGRIND_RESTORE_STACK \ 3573 "mov sp, x21\n\t" 3574 3575 /* These CALL_FN_ macros assume that on arm64-linux, 3576 sizeof(unsigned long) == 8. */ 3577 3578 #define CALL_FN_W_v(lval, orig) \ 3579 do { \ 3580 volatile OrigFn _orig = (orig); \ 3581 volatile unsigned long _argvec[1]; \ 3582 volatile unsigned long _res; \ 3583 _argvec[0] = (unsigned long)_orig.nraddr; \ 3584 __asm__ volatile( \ 3585 VALGRIND_ALIGN_STACK \ 3586 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3587 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3588 VALGRIND_RESTORE_STACK \ 3589 "mov %0, x0\n" \ 3590 : /*out*/ "=r" (_res) \ 3591 : /*in*/ "0" (&_argvec[0]) \ 3592 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3593 ); \ 3594 lval = (__typeof__(lval)) _res; \ 3595 } while (0) 3596 3597 #define CALL_FN_W_W(lval, orig, arg1) \ 3598 do { \ 3599 volatile OrigFn _orig = (orig); \ 3600 volatile unsigned long _argvec[2]; \ 3601 volatile unsigned long _res; \ 3602 _argvec[0] = (unsigned long)_orig.nraddr; \ 3603 _argvec[1] = (unsigned long)(arg1); \ 3604 __asm__ volatile( \ 3605 VALGRIND_ALIGN_STACK \ 3606 "ldr x0, [%1, #8] \n\t" \ 3607 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3608 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3609 VALGRIND_RESTORE_STACK \ 3610 "mov %0, x0\n" \ 3611 : /*out*/ "=r" (_res) \ 3612 : /*in*/ "0" (&_argvec[0]) \ 3613 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3614 ); \ 3615 lval = (__typeof__(lval)) _res; \ 3616 } while (0) 3617 3618 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 3619 do { \ 3620 volatile OrigFn _orig = (orig); \ 3621 volatile unsigned long _argvec[3]; \ 3622 volatile unsigned long _res; \ 3623 _argvec[0] = (unsigned long)_orig.nraddr; \ 3624 _argvec[1] = (unsigned long)(arg1); \ 3625 _argvec[2] = (unsigned long)(arg2); \ 3626 __asm__ volatile( \ 3627 VALGRIND_ALIGN_STACK \ 3628 "ldr x0, [%1, #8] \n\t" \ 3629 "ldr x1, [%1, #16] \n\t" \ 3630 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3631 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3632 VALGRIND_RESTORE_STACK \ 3633 "mov %0, x0\n" \ 3634 : /*out*/ "=r" (_res) \ 3635 : /*in*/ "0" (&_argvec[0]) \ 3636 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3637 ); \ 3638 lval = (__typeof__(lval)) _res; \ 3639 } while (0) 3640 3641 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 3642 do { \ 3643 volatile OrigFn _orig = (orig); \ 3644 volatile unsigned long _argvec[4]; \ 3645 volatile unsigned long _res; \ 3646 _argvec[0] = (unsigned long)_orig.nraddr; \ 3647 _argvec[1] = (unsigned long)(arg1); \ 3648 _argvec[2] = (unsigned long)(arg2); \ 3649 _argvec[3] = (unsigned long)(arg3); \ 3650 __asm__ volatile( \ 3651 VALGRIND_ALIGN_STACK \ 3652 "ldr x0, [%1, #8] \n\t" \ 3653 "ldr x1, [%1, #16] \n\t" \ 3654 "ldr x2, [%1, #24] \n\t" \ 3655 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3656 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3657 VALGRIND_RESTORE_STACK \ 3658 "mov %0, x0\n" \ 3659 : /*out*/ "=r" (_res) \ 3660 : /*in*/ "0" (&_argvec[0]) \ 3661 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3662 ); \ 3663 lval = (__typeof__(lval)) _res; \ 3664 } while (0) 3665 3666 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 3667 do { \ 3668 volatile OrigFn _orig = (orig); \ 3669 volatile unsigned long _argvec[5]; \ 3670 volatile unsigned long _res; \ 3671 _argvec[0] = (unsigned long)_orig.nraddr; \ 3672 _argvec[1] = (unsigned long)(arg1); \ 3673 _argvec[2] = (unsigned long)(arg2); \ 3674 _argvec[3] = (unsigned long)(arg3); \ 3675 _argvec[4] = (unsigned long)(arg4); \ 3676 __asm__ volatile( \ 3677 VALGRIND_ALIGN_STACK \ 3678 "ldr x0, [%1, #8] \n\t" \ 3679 "ldr x1, [%1, #16] \n\t" \ 3680 "ldr x2, [%1, #24] \n\t" \ 3681 "ldr x3, [%1, #32] \n\t" \ 3682 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3683 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3684 VALGRIND_RESTORE_STACK \ 3685 "mov %0, x0" \ 3686 : /*out*/ "=r" (_res) \ 3687 : /*in*/ "0" (&_argvec[0]) \ 3688 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3689 ); \ 3690 lval = (__typeof__(lval)) _res; \ 3691 } while (0) 3692 3693 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 3694 do { \ 3695 volatile OrigFn _orig = (orig); \ 3696 volatile unsigned long _argvec[6]; \ 3697 volatile unsigned long _res; \ 3698 _argvec[0] = (unsigned long)_orig.nraddr; \ 3699 _argvec[1] = (unsigned long)(arg1); \ 3700 _argvec[2] = (unsigned long)(arg2); \ 3701 _argvec[3] = (unsigned long)(arg3); \ 3702 _argvec[4] = (unsigned long)(arg4); \ 3703 _argvec[5] = (unsigned long)(arg5); \ 3704 __asm__ volatile( \ 3705 VALGRIND_ALIGN_STACK \ 3706 "ldr x0, [%1, #8] \n\t" \ 3707 "ldr x1, [%1, #16] \n\t" \ 3708 "ldr x2, [%1, #24] \n\t" \ 3709 "ldr x3, [%1, #32] \n\t" \ 3710 "ldr x4, [%1, #40] \n\t" \ 3711 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3712 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3713 VALGRIND_RESTORE_STACK \ 3714 "mov %0, x0" \ 3715 : /*out*/ "=r" (_res) \ 3716 : /*in*/ "0" (&_argvec[0]) \ 3717 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3718 ); \ 3719 lval = (__typeof__(lval)) _res; \ 3720 } while (0) 3721 3722 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 3723 do { \ 3724 volatile OrigFn _orig = (orig); \ 3725 volatile unsigned long _argvec[7]; \ 3726 volatile unsigned long _res; \ 3727 _argvec[0] = (unsigned long)_orig.nraddr; \ 3728 _argvec[1] = (unsigned long)(arg1); \ 3729 _argvec[2] = (unsigned long)(arg2); \ 3730 _argvec[3] = (unsigned long)(arg3); \ 3731 _argvec[4] = (unsigned long)(arg4); \ 3732 _argvec[5] = (unsigned long)(arg5); \ 3733 _argvec[6] = (unsigned long)(arg6); \ 3734 __asm__ volatile( \ 3735 VALGRIND_ALIGN_STACK \ 3736 "ldr x0, [%1, #8] \n\t" \ 3737 "ldr x1, [%1, #16] \n\t" \ 3738 "ldr x2, [%1, #24] \n\t" \ 3739 "ldr x3, [%1, #32] \n\t" \ 3740 "ldr x4, [%1, #40] \n\t" \ 3741 "ldr x5, [%1, #48] \n\t" \ 3742 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3743 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3744 VALGRIND_RESTORE_STACK \ 3745 "mov %0, x0" \ 3746 : /*out*/ "=r" (_res) \ 3747 : /*in*/ "0" (&_argvec[0]) \ 3748 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3749 ); \ 3750 lval = (__typeof__(lval)) _res; \ 3751 } while (0) 3752 3753 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3754 arg7) \ 3755 do { \ 3756 volatile OrigFn _orig = (orig); \ 3757 volatile unsigned long _argvec[8]; \ 3758 volatile unsigned long _res; \ 3759 _argvec[0] = (unsigned long)_orig.nraddr; \ 3760 _argvec[1] = (unsigned long)(arg1); \ 3761 _argvec[2] = (unsigned long)(arg2); \ 3762 _argvec[3] = (unsigned long)(arg3); \ 3763 _argvec[4] = (unsigned long)(arg4); \ 3764 _argvec[5] = (unsigned long)(arg5); \ 3765 _argvec[6] = (unsigned long)(arg6); \ 3766 _argvec[7] = (unsigned long)(arg7); \ 3767 __asm__ volatile( \ 3768 VALGRIND_ALIGN_STACK \ 3769 "ldr x0, [%1, #8] \n\t" \ 3770 "ldr x1, [%1, #16] \n\t" \ 3771 "ldr x2, [%1, #24] \n\t" \ 3772 "ldr x3, [%1, #32] \n\t" \ 3773 "ldr x4, [%1, #40] \n\t" \ 3774 "ldr x5, [%1, #48] \n\t" \ 3775 "ldr x6, [%1, #56] \n\t" \ 3776 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3777 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3778 VALGRIND_RESTORE_STACK \ 3779 "mov %0, x0" \ 3780 : /*out*/ "=r" (_res) \ 3781 : /*in*/ "0" (&_argvec[0]) \ 3782 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3783 ); \ 3784 lval = (__typeof__(lval)) _res; \ 3785 } while (0) 3786 3787 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3788 arg7,arg8) \ 3789 do { \ 3790 volatile OrigFn _orig = (orig); \ 3791 volatile unsigned long _argvec[9]; \ 3792 volatile unsigned long _res; \ 3793 _argvec[0] = (unsigned long)_orig.nraddr; \ 3794 _argvec[1] = (unsigned long)(arg1); \ 3795 _argvec[2] = (unsigned long)(arg2); \ 3796 _argvec[3] = (unsigned long)(arg3); \ 3797 _argvec[4] = (unsigned long)(arg4); \ 3798 _argvec[5] = (unsigned long)(arg5); \ 3799 _argvec[6] = (unsigned long)(arg6); \ 3800 _argvec[7] = (unsigned long)(arg7); \ 3801 _argvec[8] = (unsigned long)(arg8); \ 3802 __asm__ volatile( \ 3803 VALGRIND_ALIGN_STACK \ 3804 "ldr x0, [%1, #8] \n\t" \ 3805 "ldr x1, [%1, #16] \n\t" \ 3806 "ldr x2, [%1, #24] \n\t" \ 3807 "ldr x3, [%1, #32] \n\t" \ 3808 "ldr x4, [%1, #40] \n\t" \ 3809 "ldr x5, [%1, #48] \n\t" \ 3810 "ldr x6, [%1, #56] \n\t" \ 3811 "ldr x7, [%1, #64] \n\t" \ 3812 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3813 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3814 VALGRIND_RESTORE_STACK \ 3815 "mov %0, x0" \ 3816 : /*out*/ "=r" (_res) \ 3817 : /*in*/ "0" (&_argvec[0]) \ 3818 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3819 ); \ 3820 lval = (__typeof__(lval)) _res; \ 3821 } while (0) 3822 3823 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3824 arg7,arg8,arg9) \ 3825 do { \ 3826 volatile OrigFn _orig = (orig); \ 3827 volatile unsigned long _argvec[10]; \ 3828 volatile unsigned long _res; \ 3829 _argvec[0] = (unsigned long)_orig.nraddr; \ 3830 _argvec[1] = (unsigned long)(arg1); \ 3831 _argvec[2] = (unsigned long)(arg2); \ 3832 _argvec[3] = (unsigned long)(arg3); \ 3833 _argvec[4] = (unsigned long)(arg4); \ 3834 _argvec[5] = (unsigned long)(arg5); \ 3835 _argvec[6] = (unsigned long)(arg6); \ 3836 _argvec[7] = (unsigned long)(arg7); \ 3837 _argvec[8] = (unsigned long)(arg8); \ 3838 _argvec[9] = (unsigned long)(arg9); \ 3839 __asm__ volatile( \ 3840 VALGRIND_ALIGN_STACK \ 3841 "sub sp, sp, #0x20 \n\t" \ 3842 "ldr x0, [%1, #8] \n\t" \ 3843 "ldr x1, [%1, #16] \n\t" \ 3844 "ldr x2, [%1, #24] \n\t" \ 3845 "ldr x3, [%1, #32] \n\t" \ 3846 "ldr x4, [%1, #40] \n\t" \ 3847 "ldr x5, [%1, #48] \n\t" \ 3848 "ldr x6, [%1, #56] \n\t" \ 3849 "ldr x7, [%1, #64] \n\t" \ 3850 "ldr x8, [%1, #72] \n\t" \ 3851 "str x8, [sp, #0] \n\t" \ 3852 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3853 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3854 VALGRIND_RESTORE_STACK \ 3855 "mov %0, x0" \ 3856 : /*out*/ "=r" (_res) \ 3857 : /*in*/ "0" (&_argvec[0]) \ 3858 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3859 ); \ 3860 lval = (__typeof__(lval)) _res; \ 3861 } while (0) 3862 3863 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3864 arg7,arg8,arg9,arg10) \ 3865 do { \ 3866 volatile OrigFn _orig = (orig); \ 3867 volatile unsigned long _argvec[11]; \ 3868 volatile unsigned long _res; \ 3869 _argvec[0] = (unsigned long)_orig.nraddr; \ 3870 _argvec[1] = (unsigned long)(arg1); \ 3871 _argvec[2] = (unsigned long)(arg2); \ 3872 _argvec[3] = (unsigned long)(arg3); \ 3873 _argvec[4] = (unsigned long)(arg4); \ 3874 _argvec[5] = (unsigned long)(arg5); \ 3875 _argvec[6] = (unsigned long)(arg6); \ 3876 _argvec[7] = (unsigned long)(arg7); \ 3877 _argvec[8] = (unsigned long)(arg8); \ 3878 _argvec[9] = (unsigned long)(arg9); \ 3879 _argvec[10] = (unsigned long)(arg10); \ 3880 __asm__ volatile( \ 3881 VALGRIND_ALIGN_STACK \ 3882 "sub sp, sp, #0x20 \n\t" \ 3883 "ldr x0, [%1, #8] \n\t" \ 3884 "ldr x1, [%1, #16] \n\t" \ 3885 "ldr x2, [%1, #24] \n\t" \ 3886 "ldr x3, [%1, #32] \n\t" \ 3887 "ldr x4, [%1, #40] \n\t" \ 3888 "ldr x5, [%1, #48] \n\t" \ 3889 "ldr x6, [%1, #56] \n\t" \ 3890 "ldr x7, [%1, #64] \n\t" \ 3891 "ldr x8, [%1, #72] \n\t" \ 3892 "str x8, [sp, #0] \n\t" \ 3893 "ldr x8, [%1, #80] \n\t" \ 3894 "str x8, [sp, #8] \n\t" \ 3895 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3896 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3897 VALGRIND_RESTORE_STACK \ 3898 "mov %0, x0" \ 3899 : /*out*/ "=r" (_res) \ 3900 : /*in*/ "0" (&_argvec[0]) \ 3901 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3902 ); \ 3903 lval = (__typeof__(lval)) _res; \ 3904 } while (0) 3905 3906 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3907 arg7,arg8,arg9,arg10,arg11) \ 3908 do { \ 3909 volatile OrigFn _orig = (orig); \ 3910 volatile unsigned long _argvec[12]; \ 3911 volatile unsigned long _res; \ 3912 _argvec[0] = (unsigned long)_orig.nraddr; \ 3913 _argvec[1] = (unsigned long)(arg1); \ 3914 _argvec[2] = (unsigned long)(arg2); \ 3915 _argvec[3] = (unsigned long)(arg3); \ 3916 _argvec[4] = (unsigned long)(arg4); \ 3917 _argvec[5] = (unsigned long)(arg5); \ 3918 _argvec[6] = (unsigned long)(arg6); \ 3919 _argvec[7] = (unsigned long)(arg7); \ 3920 _argvec[8] = (unsigned long)(arg8); \ 3921 _argvec[9] = (unsigned long)(arg9); \ 3922 _argvec[10] = (unsigned long)(arg10); \ 3923 _argvec[11] = (unsigned long)(arg11); \ 3924 __asm__ volatile( \ 3925 VALGRIND_ALIGN_STACK \ 3926 "sub sp, sp, #0x30 \n\t" \ 3927 "ldr x0, [%1, #8] \n\t" \ 3928 "ldr x1, [%1, #16] \n\t" \ 3929 "ldr x2, [%1, #24] \n\t" \ 3930 "ldr x3, [%1, #32] \n\t" \ 3931 "ldr x4, [%1, #40] \n\t" \ 3932 "ldr x5, [%1, #48] \n\t" \ 3933 "ldr x6, [%1, #56] \n\t" \ 3934 "ldr x7, [%1, #64] \n\t" \ 3935 "ldr x8, [%1, #72] \n\t" \ 3936 "str x8, [sp, #0] \n\t" \ 3937 "ldr x8, [%1, #80] \n\t" \ 3938 "str x8, [sp, #8] \n\t" \ 3939 "ldr x8, [%1, #88] \n\t" \ 3940 "str x8, [sp, #16] \n\t" \ 3941 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3942 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3943 VALGRIND_RESTORE_STACK \ 3944 "mov %0, x0" \ 3945 : /*out*/ "=r" (_res) \ 3946 : /*in*/ "0" (&_argvec[0]) \ 3947 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3948 ); \ 3949 lval = (__typeof__(lval)) _res; \ 3950 } while (0) 3951 3952 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 3953 arg7,arg8,arg9,arg10,arg11, \ 3954 arg12) \ 3955 do { \ 3956 volatile OrigFn _orig = (orig); \ 3957 volatile unsigned long _argvec[13]; \ 3958 volatile unsigned long _res; \ 3959 _argvec[0] = (unsigned long)_orig.nraddr; \ 3960 _argvec[1] = (unsigned long)(arg1); \ 3961 _argvec[2] = (unsigned long)(arg2); \ 3962 _argvec[3] = (unsigned long)(arg3); \ 3963 _argvec[4] = (unsigned long)(arg4); \ 3964 _argvec[5] = (unsigned long)(arg5); \ 3965 _argvec[6] = (unsigned long)(arg6); \ 3966 _argvec[7] = (unsigned long)(arg7); \ 3967 _argvec[8] = (unsigned long)(arg8); \ 3968 _argvec[9] = (unsigned long)(arg9); \ 3969 _argvec[10] = (unsigned long)(arg10); \ 3970 _argvec[11] = (unsigned long)(arg11); \ 3971 _argvec[12] = (unsigned long)(arg12); \ 3972 __asm__ volatile( \ 3973 VALGRIND_ALIGN_STACK \ 3974 "sub sp, sp, #0x30 \n\t" \ 3975 "ldr x0, [%1, #8] \n\t" \ 3976 "ldr x1, [%1, #16] \n\t" \ 3977 "ldr x2, [%1, #24] \n\t" \ 3978 "ldr x3, [%1, #32] \n\t" \ 3979 "ldr x4, [%1, #40] \n\t" \ 3980 "ldr x5, [%1, #48] \n\t" \ 3981 "ldr x6, [%1, #56] \n\t" \ 3982 "ldr x7, [%1, #64] \n\t" \ 3983 "ldr x8, [%1, #72] \n\t" \ 3984 "str x8, [sp, #0] \n\t" \ 3985 "ldr x8, [%1, #80] \n\t" \ 3986 "str x8, [sp, #8] \n\t" \ 3987 "ldr x8, [%1, #88] \n\t" \ 3988 "str x8, [sp, #16] \n\t" \ 3989 "ldr x8, [%1, #96] \n\t" \ 3990 "str x8, [sp, #24] \n\t" \ 3991 "ldr x8, [%1] \n\t" /* target->x8 */ \ 3992 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_X8 \ 3993 VALGRIND_RESTORE_STACK \ 3994 "mov %0, x0" \ 3995 : /*out*/ "=r" (_res) \ 3996 : /*in*/ "0" (&_argvec[0]) \ 3997 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "x21" \ 3998 ); \ 3999 lval = (__typeof__(lval)) _res; \ 4000 } while (0) 4001 4002 #endif /* PLAT_arm64_linux */ 4003 4004 /* ------------------------- s390x-linux ------------------------- */ 4005 4006 #if defined(PLAT_s390x_linux) 4007 4008 /* Similar workaround as amd64 (see above), but we use r11 as frame 4009 pointer and save the old r11 in r7. r11 might be used for 4010 argvec, therefore we copy argvec in r1 since r1 is clobbered 4011 after the call anyway. */ 4012 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) 4013 # define __FRAME_POINTER \ 4014 ,"d"(__builtin_dwarf_cfa()) 4015 # define VALGRIND_CFI_PROLOGUE \ 4016 ".cfi_remember_state\n\t" \ 4017 "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \ 4018 "lgr 7,11\n\t" \ 4019 "lgr 11,%2\n\t" \ 4020 ".cfi_def_cfa r11, 0\n\t" 4021 # define VALGRIND_CFI_EPILOGUE \ 4022 "lgr 11, 7\n\t" \ 4023 ".cfi_restore_state\n\t" 4024 #else 4025 # define __FRAME_POINTER 4026 # define VALGRIND_CFI_PROLOGUE \ 4027 "lgr 1,%1\n\t" 4028 # define VALGRIND_CFI_EPILOGUE 4029 #endif 4030 4031 /* Nb: On s390 the stack pointer is properly aligned *at all times* 4032 according to the s390 GCC maintainer. (The ABI specification is not 4033 precise in this regard.) Therefore, VALGRIND_ALIGN_STACK and 4034 VALGRIND_RESTORE_STACK are not defined here. */ 4035 4036 /* These regs are trashed by the hidden call. Note that we overwrite 4037 r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the 4038 function a proper return address. All others are ABI defined call 4039 clobbers. */ 4040 #define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \ 4041 "f0","f1","f2","f3","f4","f5","f6","f7" 4042 4043 /* Nb: Although r11 is modified in the asm snippets below (inside 4044 VALGRIND_CFI_PROLOGUE) it is not listed in the clobber section, for 4045 two reasons: 4046 (1) r11 is restored in VALGRIND_CFI_EPILOGUE, so effectively it is not 4047 modified 4048 (2) GCC will complain that r11 cannot appear inside a clobber section, 4049 when compiled with -O -fno-omit-frame-pointer 4050 */ 4051 4052 #define CALL_FN_W_v(lval, orig) \ 4053 do { \ 4054 volatile OrigFn _orig = (orig); \ 4055 volatile unsigned long _argvec[1]; \ 4056 volatile unsigned long _res; \ 4057 _argvec[0] = (unsigned long)_orig.nraddr; \ 4058 __asm__ volatile( \ 4059 VALGRIND_CFI_PROLOGUE \ 4060 "aghi 15,-160\n\t" \ 4061 "lg 1, 0(1)\n\t" /* target->r1 */ \ 4062 VALGRIND_CALL_NOREDIR_R1 \ 4063 "lgr %0, 2\n\t" \ 4064 "aghi 15,160\n\t" \ 4065 VALGRIND_CFI_EPILOGUE \ 4066 : /*out*/ "=d" (_res) \ 4067 : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \ 4068 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ 4069 ); \ 4070 lval = (__typeof__(lval)) _res; \ 4071 } while (0) 4072 4073 /* The call abi has the arguments in r2-r6 and stack */ 4074 #define CALL_FN_W_W(lval, orig, arg1) \ 4075 do { \ 4076 volatile OrigFn _orig = (orig); \ 4077 volatile unsigned long _argvec[2]; \ 4078 volatile unsigned long _res; \ 4079 _argvec[0] = (unsigned long)_orig.nraddr; \ 4080 _argvec[1] = (unsigned long)arg1; \ 4081 __asm__ volatile( \ 4082 VALGRIND_CFI_PROLOGUE \ 4083 "aghi 15,-160\n\t" \ 4084 "lg 2, 8(1)\n\t" \ 4085 "lg 1, 0(1)\n\t" \ 4086 VALGRIND_CALL_NOREDIR_R1 \ 4087 "lgr %0, 2\n\t" \ 4088 "aghi 15,160\n\t" \ 4089 VALGRIND_CFI_EPILOGUE \ 4090 : /*out*/ "=d" (_res) \ 4091 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4092 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ 4093 ); \ 4094 lval = (__typeof__(lval)) _res; \ 4095 } while (0) 4096 4097 #define CALL_FN_W_WW(lval, orig, arg1, arg2) \ 4098 do { \ 4099 volatile OrigFn _orig = (orig); \ 4100 volatile unsigned long _argvec[3]; \ 4101 volatile unsigned long _res; \ 4102 _argvec[0] = (unsigned long)_orig.nraddr; \ 4103 _argvec[1] = (unsigned long)arg1; \ 4104 _argvec[2] = (unsigned long)arg2; \ 4105 __asm__ volatile( \ 4106 VALGRIND_CFI_PROLOGUE \ 4107 "aghi 15,-160\n\t" \ 4108 "lg 2, 8(1)\n\t" \ 4109 "lg 3,16(1)\n\t" \ 4110 "lg 1, 0(1)\n\t" \ 4111 VALGRIND_CALL_NOREDIR_R1 \ 4112 "lgr %0, 2\n\t" \ 4113 "aghi 15,160\n\t" \ 4114 VALGRIND_CFI_EPILOGUE \ 4115 : /*out*/ "=d" (_res) \ 4116 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4117 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ 4118 ); \ 4119 lval = (__typeof__(lval)) _res; \ 4120 } while (0) 4121 4122 #define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \ 4123 do { \ 4124 volatile OrigFn _orig = (orig); \ 4125 volatile unsigned long _argvec[4]; \ 4126 volatile unsigned long _res; \ 4127 _argvec[0] = (unsigned long)_orig.nraddr; \ 4128 _argvec[1] = (unsigned long)arg1; \ 4129 _argvec[2] = (unsigned long)arg2; \ 4130 _argvec[3] = (unsigned long)arg3; \ 4131 __asm__ volatile( \ 4132 VALGRIND_CFI_PROLOGUE \ 4133 "aghi 15,-160\n\t" \ 4134 "lg 2, 8(1)\n\t" \ 4135 "lg 3,16(1)\n\t" \ 4136 "lg 4,24(1)\n\t" \ 4137 "lg 1, 0(1)\n\t" \ 4138 VALGRIND_CALL_NOREDIR_R1 \ 4139 "lgr %0, 2\n\t" \ 4140 "aghi 15,160\n\t" \ 4141 VALGRIND_CFI_EPILOGUE \ 4142 : /*out*/ "=d" (_res) \ 4143 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4144 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ 4145 ); \ 4146 lval = (__typeof__(lval)) _res; \ 4147 } while (0) 4148 4149 #define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \ 4150 do { \ 4151 volatile OrigFn _orig = (orig); \ 4152 volatile unsigned long _argvec[5]; \ 4153 volatile unsigned long _res; \ 4154 _argvec[0] = (unsigned long)_orig.nraddr; \ 4155 _argvec[1] = (unsigned long)arg1; \ 4156 _argvec[2] = (unsigned long)arg2; \ 4157 _argvec[3] = (unsigned long)arg3; \ 4158 _argvec[4] = (unsigned long)arg4; \ 4159 __asm__ volatile( \ 4160 VALGRIND_CFI_PROLOGUE \ 4161 "aghi 15,-160\n\t" \ 4162 "lg 2, 8(1)\n\t" \ 4163 "lg 3,16(1)\n\t" \ 4164 "lg 4,24(1)\n\t" \ 4165 "lg 5,32(1)\n\t" \ 4166 "lg 1, 0(1)\n\t" \ 4167 VALGRIND_CALL_NOREDIR_R1 \ 4168 "lgr %0, 2\n\t" \ 4169 "aghi 15,160\n\t" \ 4170 VALGRIND_CFI_EPILOGUE \ 4171 : /*out*/ "=d" (_res) \ 4172 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4173 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \ 4174 ); \ 4175 lval = (__typeof__(lval)) _res; \ 4176 } while (0) 4177 4178 #define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \ 4179 do { \ 4180 volatile OrigFn _orig = (orig); \ 4181 volatile unsigned long _argvec[6]; \ 4182 volatile unsigned long _res; \ 4183 _argvec[0] = (unsigned long)_orig.nraddr; \ 4184 _argvec[1] = (unsigned long)arg1; \ 4185 _argvec[2] = (unsigned long)arg2; \ 4186 _argvec[3] = (unsigned long)arg3; \ 4187 _argvec[4] = (unsigned long)arg4; \ 4188 _argvec[5] = (unsigned long)arg5; \ 4189 __asm__ volatile( \ 4190 VALGRIND_CFI_PROLOGUE \ 4191 "aghi 15,-160\n\t" \ 4192 "lg 2, 8(1)\n\t" \ 4193 "lg 3,16(1)\n\t" \ 4194 "lg 4,24(1)\n\t" \ 4195 "lg 5,32(1)\n\t" \ 4196 "lg 6,40(1)\n\t" \ 4197 "lg 1, 0(1)\n\t" \ 4198 VALGRIND_CALL_NOREDIR_R1 \ 4199 "lgr %0, 2\n\t" \ 4200 "aghi 15,160\n\t" \ 4201 VALGRIND_CFI_EPILOGUE \ 4202 : /*out*/ "=d" (_res) \ 4203 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4204 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4205 ); \ 4206 lval = (__typeof__(lval)) _res; \ 4207 } while (0) 4208 4209 #define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4210 arg6) \ 4211 do { \ 4212 volatile OrigFn _orig = (orig); \ 4213 volatile unsigned long _argvec[7]; \ 4214 volatile unsigned long _res; \ 4215 _argvec[0] = (unsigned long)_orig.nraddr; \ 4216 _argvec[1] = (unsigned long)arg1; \ 4217 _argvec[2] = (unsigned long)arg2; \ 4218 _argvec[3] = (unsigned long)arg3; \ 4219 _argvec[4] = (unsigned long)arg4; \ 4220 _argvec[5] = (unsigned long)arg5; \ 4221 _argvec[6] = (unsigned long)arg6; \ 4222 __asm__ volatile( \ 4223 VALGRIND_CFI_PROLOGUE \ 4224 "aghi 15,-168\n\t" \ 4225 "lg 2, 8(1)\n\t" \ 4226 "lg 3,16(1)\n\t" \ 4227 "lg 4,24(1)\n\t" \ 4228 "lg 5,32(1)\n\t" \ 4229 "lg 6,40(1)\n\t" \ 4230 "mvc 160(8,15), 48(1)\n\t" \ 4231 "lg 1, 0(1)\n\t" \ 4232 VALGRIND_CALL_NOREDIR_R1 \ 4233 "lgr %0, 2\n\t" \ 4234 "aghi 15,168\n\t" \ 4235 VALGRIND_CFI_EPILOGUE \ 4236 : /*out*/ "=d" (_res) \ 4237 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4238 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4239 ); \ 4240 lval = (__typeof__(lval)) _res; \ 4241 } while (0) 4242 4243 #define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4244 arg6, arg7) \ 4245 do { \ 4246 volatile OrigFn _orig = (orig); \ 4247 volatile unsigned long _argvec[8]; \ 4248 volatile unsigned long _res; \ 4249 _argvec[0] = (unsigned long)_orig.nraddr; \ 4250 _argvec[1] = (unsigned long)arg1; \ 4251 _argvec[2] = (unsigned long)arg2; \ 4252 _argvec[3] = (unsigned long)arg3; \ 4253 _argvec[4] = (unsigned long)arg4; \ 4254 _argvec[5] = (unsigned long)arg5; \ 4255 _argvec[6] = (unsigned long)arg6; \ 4256 _argvec[7] = (unsigned long)arg7; \ 4257 __asm__ volatile( \ 4258 VALGRIND_CFI_PROLOGUE \ 4259 "aghi 15,-176\n\t" \ 4260 "lg 2, 8(1)\n\t" \ 4261 "lg 3,16(1)\n\t" \ 4262 "lg 4,24(1)\n\t" \ 4263 "lg 5,32(1)\n\t" \ 4264 "lg 6,40(1)\n\t" \ 4265 "mvc 160(8,15), 48(1)\n\t" \ 4266 "mvc 168(8,15), 56(1)\n\t" \ 4267 "lg 1, 0(1)\n\t" \ 4268 VALGRIND_CALL_NOREDIR_R1 \ 4269 "lgr %0, 2\n\t" \ 4270 "aghi 15,176\n\t" \ 4271 VALGRIND_CFI_EPILOGUE \ 4272 : /*out*/ "=d" (_res) \ 4273 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4274 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4275 ); \ 4276 lval = (__typeof__(lval)) _res; \ 4277 } while (0) 4278 4279 #define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4280 arg6, arg7 ,arg8) \ 4281 do { \ 4282 volatile OrigFn _orig = (orig); \ 4283 volatile unsigned long _argvec[9]; \ 4284 volatile unsigned long _res; \ 4285 _argvec[0] = (unsigned long)_orig.nraddr; \ 4286 _argvec[1] = (unsigned long)arg1; \ 4287 _argvec[2] = (unsigned long)arg2; \ 4288 _argvec[3] = (unsigned long)arg3; \ 4289 _argvec[4] = (unsigned long)arg4; \ 4290 _argvec[5] = (unsigned long)arg5; \ 4291 _argvec[6] = (unsigned long)arg6; \ 4292 _argvec[7] = (unsigned long)arg7; \ 4293 _argvec[8] = (unsigned long)arg8; \ 4294 __asm__ volatile( \ 4295 VALGRIND_CFI_PROLOGUE \ 4296 "aghi 15,-184\n\t" \ 4297 "lg 2, 8(1)\n\t" \ 4298 "lg 3,16(1)\n\t" \ 4299 "lg 4,24(1)\n\t" \ 4300 "lg 5,32(1)\n\t" \ 4301 "lg 6,40(1)\n\t" \ 4302 "mvc 160(8,15), 48(1)\n\t" \ 4303 "mvc 168(8,15), 56(1)\n\t" \ 4304 "mvc 176(8,15), 64(1)\n\t" \ 4305 "lg 1, 0(1)\n\t" \ 4306 VALGRIND_CALL_NOREDIR_R1 \ 4307 "lgr %0, 2\n\t" \ 4308 "aghi 15,184\n\t" \ 4309 VALGRIND_CFI_EPILOGUE \ 4310 : /*out*/ "=d" (_res) \ 4311 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4312 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4313 ); \ 4314 lval = (__typeof__(lval)) _res; \ 4315 } while (0) 4316 4317 #define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4318 arg6, arg7 ,arg8, arg9) \ 4319 do { \ 4320 volatile OrigFn _orig = (orig); \ 4321 volatile unsigned long _argvec[10]; \ 4322 volatile unsigned long _res; \ 4323 _argvec[0] = (unsigned long)_orig.nraddr; \ 4324 _argvec[1] = (unsigned long)arg1; \ 4325 _argvec[2] = (unsigned long)arg2; \ 4326 _argvec[3] = (unsigned long)arg3; \ 4327 _argvec[4] = (unsigned long)arg4; \ 4328 _argvec[5] = (unsigned long)arg5; \ 4329 _argvec[6] = (unsigned long)arg6; \ 4330 _argvec[7] = (unsigned long)arg7; \ 4331 _argvec[8] = (unsigned long)arg8; \ 4332 _argvec[9] = (unsigned long)arg9; \ 4333 __asm__ volatile( \ 4334 VALGRIND_CFI_PROLOGUE \ 4335 "aghi 15,-192\n\t" \ 4336 "lg 2, 8(1)\n\t" \ 4337 "lg 3,16(1)\n\t" \ 4338 "lg 4,24(1)\n\t" \ 4339 "lg 5,32(1)\n\t" \ 4340 "lg 6,40(1)\n\t" \ 4341 "mvc 160(8,15), 48(1)\n\t" \ 4342 "mvc 168(8,15), 56(1)\n\t" \ 4343 "mvc 176(8,15), 64(1)\n\t" \ 4344 "mvc 184(8,15), 72(1)\n\t" \ 4345 "lg 1, 0(1)\n\t" \ 4346 VALGRIND_CALL_NOREDIR_R1 \ 4347 "lgr %0, 2\n\t" \ 4348 "aghi 15,192\n\t" \ 4349 VALGRIND_CFI_EPILOGUE \ 4350 : /*out*/ "=d" (_res) \ 4351 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4352 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4353 ); \ 4354 lval = (__typeof__(lval)) _res; \ 4355 } while (0) 4356 4357 #define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4358 arg6, arg7 ,arg8, arg9, arg10) \ 4359 do { \ 4360 volatile OrigFn _orig = (orig); \ 4361 volatile unsigned long _argvec[11]; \ 4362 volatile unsigned long _res; \ 4363 _argvec[0] = (unsigned long)_orig.nraddr; \ 4364 _argvec[1] = (unsigned long)arg1; \ 4365 _argvec[2] = (unsigned long)arg2; \ 4366 _argvec[3] = (unsigned long)arg3; \ 4367 _argvec[4] = (unsigned long)arg4; \ 4368 _argvec[5] = (unsigned long)arg5; \ 4369 _argvec[6] = (unsigned long)arg6; \ 4370 _argvec[7] = (unsigned long)arg7; \ 4371 _argvec[8] = (unsigned long)arg8; \ 4372 _argvec[9] = (unsigned long)arg9; \ 4373 _argvec[10] = (unsigned long)arg10; \ 4374 __asm__ volatile( \ 4375 VALGRIND_CFI_PROLOGUE \ 4376 "aghi 15,-200\n\t" \ 4377 "lg 2, 8(1)\n\t" \ 4378 "lg 3,16(1)\n\t" \ 4379 "lg 4,24(1)\n\t" \ 4380 "lg 5,32(1)\n\t" \ 4381 "lg 6,40(1)\n\t" \ 4382 "mvc 160(8,15), 48(1)\n\t" \ 4383 "mvc 168(8,15), 56(1)\n\t" \ 4384 "mvc 176(8,15), 64(1)\n\t" \ 4385 "mvc 184(8,15), 72(1)\n\t" \ 4386 "mvc 192(8,15), 80(1)\n\t" \ 4387 "lg 1, 0(1)\n\t" \ 4388 VALGRIND_CALL_NOREDIR_R1 \ 4389 "lgr %0, 2\n\t" \ 4390 "aghi 15,200\n\t" \ 4391 VALGRIND_CFI_EPILOGUE \ 4392 : /*out*/ "=d" (_res) \ 4393 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4394 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4395 ); \ 4396 lval = (__typeof__(lval)) _res; \ 4397 } while (0) 4398 4399 #define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4400 arg6, arg7 ,arg8, arg9, arg10, arg11) \ 4401 do { \ 4402 volatile OrigFn _orig = (orig); \ 4403 volatile unsigned long _argvec[12]; \ 4404 volatile unsigned long _res; \ 4405 _argvec[0] = (unsigned long)_orig.nraddr; \ 4406 _argvec[1] = (unsigned long)arg1; \ 4407 _argvec[2] = (unsigned long)arg2; \ 4408 _argvec[3] = (unsigned long)arg3; \ 4409 _argvec[4] = (unsigned long)arg4; \ 4410 _argvec[5] = (unsigned long)arg5; \ 4411 _argvec[6] = (unsigned long)arg6; \ 4412 _argvec[7] = (unsigned long)arg7; \ 4413 _argvec[8] = (unsigned long)arg8; \ 4414 _argvec[9] = (unsigned long)arg9; \ 4415 _argvec[10] = (unsigned long)arg10; \ 4416 _argvec[11] = (unsigned long)arg11; \ 4417 __asm__ volatile( \ 4418 VALGRIND_CFI_PROLOGUE \ 4419 "aghi 15,-208\n\t" \ 4420 "lg 2, 8(1)\n\t" \ 4421 "lg 3,16(1)\n\t" \ 4422 "lg 4,24(1)\n\t" \ 4423 "lg 5,32(1)\n\t" \ 4424 "lg 6,40(1)\n\t" \ 4425 "mvc 160(8,15), 48(1)\n\t" \ 4426 "mvc 168(8,15), 56(1)\n\t" \ 4427 "mvc 176(8,15), 64(1)\n\t" \ 4428 "mvc 184(8,15), 72(1)\n\t" \ 4429 "mvc 192(8,15), 80(1)\n\t" \ 4430 "mvc 200(8,15), 88(1)\n\t" \ 4431 "lg 1, 0(1)\n\t" \ 4432 VALGRIND_CALL_NOREDIR_R1 \ 4433 "lgr %0, 2\n\t" \ 4434 "aghi 15,208\n\t" \ 4435 VALGRIND_CFI_EPILOGUE \ 4436 : /*out*/ "=d" (_res) \ 4437 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4438 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4439 ); \ 4440 lval = (__typeof__(lval)) _res; \ 4441 } while (0) 4442 4443 #define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \ 4444 arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\ 4445 do { \ 4446 volatile OrigFn _orig = (orig); \ 4447 volatile unsigned long _argvec[13]; \ 4448 volatile unsigned long _res; \ 4449 _argvec[0] = (unsigned long)_orig.nraddr; \ 4450 _argvec[1] = (unsigned long)arg1; \ 4451 _argvec[2] = (unsigned long)arg2; \ 4452 _argvec[3] = (unsigned long)arg3; \ 4453 _argvec[4] = (unsigned long)arg4; \ 4454 _argvec[5] = (unsigned long)arg5; \ 4455 _argvec[6] = (unsigned long)arg6; \ 4456 _argvec[7] = (unsigned long)arg7; \ 4457 _argvec[8] = (unsigned long)arg8; \ 4458 _argvec[9] = (unsigned long)arg9; \ 4459 _argvec[10] = (unsigned long)arg10; \ 4460 _argvec[11] = (unsigned long)arg11; \ 4461 _argvec[12] = (unsigned long)arg12; \ 4462 __asm__ volatile( \ 4463 VALGRIND_CFI_PROLOGUE \ 4464 "aghi 15,-216\n\t" \ 4465 "lg 2, 8(1)\n\t" \ 4466 "lg 3,16(1)\n\t" \ 4467 "lg 4,24(1)\n\t" \ 4468 "lg 5,32(1)\n\t" \ 4469 "lg 6,40(1)\n\t" \ 4470 "mvc 160(8,15), 48(1)\n\t" \ 4471 "mvc 168(8,15), 56(1)\n\t" \ 4472 "mvc 176(8,15), 64(1)\n\t" \ 4473 "mvc 184(8,15), 72(1)\n\t" \ 4474 "mvc 192(8,15), 80(1)\n\t" \ 4475 "mvc 200(8,15), 88(1)\n\t" \ 4476 "mvc 208(8,15), 96(1)\n\t" \ 4477 "lg 1, 0(1)\n\t" \ 4478 VALGRIND_CALL_NOREDIR_R1 \ 4479 "lgr %0, 2\n\t" \ 4480 "aghi 15,216\n\t" \ 4481 VALGRIND_CFI_EPILOGUE \ 4482 : /*out*/ "=d" (_res) \ 4483 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ 4484 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \ 4485 ); \ 4486 lval = (__typeof__(lval)) _res; \ 4487 } while (0) 4488 4489 4490 #endif /* PLAT_s390x_linux */ 4491 4492 /* ------------------------- mips32-linux ----------------------- */ 4493 4494 #if defined(PLAT_mips32_linux) 4495 4496 /* These regs are trashed by the hidden call. */ 4497 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ 4498 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ 4499 "$25", "$31" 4500 4501 /* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned 4502 long) == 4. */ 4503 4504 #define CALL_FN_W_v(lval, orig) \ 4505 do { \ 4506 volatile OrigFn _orig = (orig); \ 4507 volatile unsigned long _argvec[1]; \ 4508 volatile unsigned long _res; \ 4509 _argvec[0] = (unsigned long)_orig.nraddr; \ 4510 __asm__ volatile( \ 4511 "subu $29, $29, 8 \n\t" \ 4512 "sw $28, 0($29) \n\t" \ 4513 "sw $31, 4($29) \n\t" \ 4514 "subu $29, $29, 16 \n\t" \ 4515 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4516 VALGRIND_CALL_NOREDIR_T9 \ 4517 "addu $29, $29, 16\n\t" \ 4518 "lw $28, 0($29) \n\t" \ 4519 "lw $31, 4($29) \n\t" \ 4520 "addu $29, $29, 8 \n\t" \ 4521 "move %0, $2\n" \ 4522 : /*out*/ "=r" (_res) \ 4523 : /*in*/ "0" (&_argvec[0]) \ 4524 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4525 ); \ 4526 lval = (__typeof__(lval)) _res; \ 4527 } while (0) 4528 4529 #define CALL_FN_W_W(lval, orig, arg1) \ 4530 do { \ 4531 volatile OrigFn _orig = (orig); \ 4532 volatile unsigned long _argvec[2]; \ 4533 volatile unsigned long _res; \ 4534 _argvec[0] = (unsigned long)_orig.nraddr; \ 4535 _argvec[1] = (unsigned long)(arg1); \ 4536 __asm__ volatile( \ 4537 "subu $29, $29, 8 \n\t" \ 4538 "sw $28, 0($29) \n\t" \ 4539 "sw $31, 4($29) \n\t" \ 4540 "subu $29, $29, 16 \n\t" \ 4541 "lw $4, 4(%1) \n\t" /* arg1*/ \ 4542 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4543 VALGRIND_CALL_NOREDIR_T9 \ 4544 "addu $29, $29, 16 \n\t" \ 4545 "lw $28, 0($29) \n\t" \ 4546 "lw $31, 4($29) \n\t" \ 4547 "addu $29, $29, 8 \n\t" \ 4548 "move %0, $2\n" \ 4549 : /*out*/ "=r" (_res) \ 4550 : /*in*/ "0" (&_argvec[0]) \ 4551 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4552 ); \ 4553 lval = (__typeof__(lval)) _res; \ 4554 } while (0) 4555 4556 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 4557 do { \ 4558 volatile OrigFn _orig = (orig); \ 4559 volatile unsigned long _argvec[3]; \ 4560 volatile unsigned long _res; \ 4561 _argvec[0] = (unsigned long)_orig.nraddr; \ 4562 _argvec[1] = (unsigned long)(arg1); \ 4563 _argvec[2] = (unsigned long)(arg2); \ 4564 __asm__ volatile( \ 4565 "subu $29, $29, 8 \n\t" \ 4566 "sw $28, 0($29) \n\t" \ 4567 "sw $31, 4($29) \n\t" \ 4568 "subu $29, $29, 16 \n\t" \ 4569 "lw $4, 4(%1) \n\t" \ 4570 "lw $5, 8(%1) \n\t" \ 4571 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4572 VALGRIND_CALL_NOREDIR_T9 \ 4573 "addu $29, $29, 16 \n\t" \ 4574 "lw $28, 0($29) \n\t" \ 4575 "lw $31, 4($29) \n\t" \ 4576 "addu $29, $29, 8 \n\t" \ 4577 "move %0, $2\n" \ 4578 : /*out*/ "=r" (_res) \ 4579 : /*in*/ "0" (&_argvec[0]) \ 4580 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4581 ); \ 4582 lval = (__typeof__(lval)) _res; \ 4583 } while (0) 4584 4585 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 4586 do { \ 4587 volatile OrigFn _orig = (orig); \ 4588 volatile unsigned long _argvec[4]; \ 4589 volatile unsigned long _res; \ 4590 _argvec[0] = (unsigned long)_orig.nraddr; \ 4591 _argvec[1] = (unsigned long)(arg1); \ 4592 _argvec[2] = (unsigned long)(arg2); \ 4593 _argvec[3] = (unsigned long)(arg3); \ 4594 __asm__ volatile( \ 4595 "subu $29, $29, 8 \n\t" \ 4596 "sw $28, 0($29) \n\t" \ 4597 "sw $31, 4($29) \n\t" \ 4598 "subu $29, $29, 16 \n\t" \ 4599 "lw $4, 4(%1) \n\t" \ 4600 "lw $5, 8(%1) \n\t" \ 4601 "lw $6, 12(%1) \n\t" \ 4602 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4603 VALGRIND_CALL_NOREDIR_T9 \ 4604 "addu $29, $29, 16 \n\t" \ 4605 "lw $28, 0($29) \n\t" \ 4606 "lw $31, 4($29) \n\t" \ 4607 "addu $29, $29, 8 \n\t" \ 4608 "move %0, $2\n" \ 4609 : /*out*/ "=r" (_res) \ 4610 : /*in*/ "0" (&_argvec[0]) \ 4611 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4612 ); \ 4613 lval = (__typeof__(lval)) _res; \ 4614 } while (0) 4615 4616 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 4617 do { \ 4618 volatile OrigFn _orig = (orig); \ 4619 volatile unsigned long _argvec[5]; \ 4620 volatile unsigned long _res; \ 4621 _argvec[0] = (unsigned long)_orig.nraddr; \ 4622 _argvec[1] = (unsigned long)(arg1); \ 4623 _argvec[2] = (unsigned long)(arg2); \ 4624 _argvec[3] = (unsigned long)(arg3); \ 4625 _argvec[4] = (unsigned long)(arg4); \ 4626 __asm__ volatile( \ 4627 "subu $29, $29, 8 \n\t" \ 4628 "sw $28, 0($29) \n\t" \ 4629 "sw $31, 4($29) \n\t" \ 4630 "subu $29, $29, 16 \n\t" \ 4631 "lw $4, 4(%1) \n\t" \ 4632 "lw $5, 8(%1) \n\t" \ 4633 "lw $6, 12(%1) \n\t" \ 4634 "lw $7, 16(%1) \n\t" \ 4635 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4636 VALGRIND_CALL_NOREDIR_T9 \ 4637 "addu $29, $29, 16 \n\t" \ 4638 "lw $28, 0($29) \n\t" \ 4639 "lw $31, 4($29) \n\t" \ 4640 "addu $29, $29, 8 \n\t" \ 4641 "move %0, $2\n" \ 4642 : /*out*/ "=r" (_res) \ 4643 : /*in*/ "0" (&_argvec[0]) \ 4644 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4645 ); \ 4646 lval = (__typeof__(lval)) _res; \ 4647 } while (0) 4648 4649 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 4650 do { \ 4651 volatile OrigFn _orig = (orig); \ 4652 volatile unsigned long _argvec[6]; \ 4653 volatile unsigned long _res; \ 4654 _argvec[0] = (unsigned long)_orig.nraddr; \ 4655 _argvec[1] = (unsigned long)(arg1); \ 4656 _argvec[2] = (unsigned long)(arg2); \ 4657 _argvec[3] = (unsigned long)(arg3); \ 4658 _argvec[4] = (unsigned long)(arg4); \ 4659 _argvec[5] = (unsigned long)(arg5); \ 4660 __asm__ volatile( \ 4661 "subu $29, $29, 8 \n\t" \ 4662 "sw $28, 0($29) \n\t" \ 4663 "sw $31, 4($29) \n\t" \ 4664 "lw $4, 20(%1) \n\t" \ 4665 "subu $29, $29, 24\n\t" \ 4666 "sw $4, 16($29) \n\t" \ 4667 "lw $4, 4(%1) \n\t" \ 4668 "lw $5, 8(%1) \n\t" \ 4669 "lw $6, 12(%1) \n\t" \ 4670 "lw $7, 16(%1) \n\t" \ 4671 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4672 VALGRIND_CALL_NOREDIR_T9 \ 4673 "addu $29, $29, 24 \n\t" \ 4674 "lw $28, 0($29) \n\t" \ 4675 "lw $31, 4($29) \n\t" \ 4676 "addu $29, $29, 8 \n\t" \ 4677 "move %0, $2\n" \ 4678 : /*out*/ "=r" (_res) \ 4679 : /*in*/ "0" (&_argvec[0]) \ 4680 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4681 ); \ 4682 lval = (__typeof__(lval)) _res; \ 4683 } while (0) 4684 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 4685 do { \ 4686 volatile OrigFn _orig = (orig); \ 4687 volatile unsigned long _argvec[7]; \ 4688 volatile unsigned long _res; \ 4689 _argvec[0] = (unsigned long)_orig.nraddr; \ 4690 _argvec[1] = (unsigned long)(arg1); \ 4691 _argvec[2] = (unsigned long)(arg2); \ 4692 _argvec[3] = (unsigned long)(arg3); \ 4693 _argvec[4] = (unsigned long)(arg4); \ 4694 _argvec[5] = (unsigned long)(arg5); \ 4695 _argvec[6] = (unsigned long)(arg6); \ 4696 __asm__ volatile( \ 4697 "subu $29, $29, 8 \n\t" \ 4698 "sw $28, 0($29) \n\t" \ 4699 "sw $31, 4($29) \n\t" \ 4700 "lw $4, 20(%1) \n\t" \ 4701 "subu $29, $29, 32\n\t" \ 4702 "sw $4, 16($29) \n\t" \ 4703 "lw $4, 24(%1) \n\t" \ 4704 "nop\n\t" \ 4705 "sw $4, 20($29) \n\t" \ 4706 "lw $4, 4(%1) \n\t" \ 4707 "lw $5, 8(%1) \n\t" \ 4708 "lw $6, 12(%1) \n\t" \ 4709 "lw $7, 16(%1) \n\t" \ 4710 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4711 VALGRIND_CALL_NOREDIR_T9 \ 4712 "addu $29, $29, 32 \n\t" \ 4713 "lw $28, 0($29) \n\t" \ 4714 "lw $31, 4($29) \n\t" \ 4715 "addu $29, $29, 8 \n\t" \ 4716 "move %0, $2\n" \ 4717 : /*out*/ "=r" (_res) \ 4718 : /*in*/ "0" (&_argvec[0]) \ 4719 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4720 ); \ 4721 lval = (__typeof__(lval)) _res; \ 4722 } while (0) 4723 4724 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4725 arg7) \ 4726 do { \ 4727 volatile OrigFn _orig = (orig); \ 4728 volatile unsigned long _argvec[8]; \ 4729 volatile unsigned long _res; \ 4730 _argvec[0] = (unsigned long)_orig.nraddr; \ 4731 _argvec[1] = (unsigned long)(arg1); \ 4732 _argvec[2] = (unsigned long)(arg2); \ 4733 _argvec[3] = (unsigned long)(arg3); \ 4734 _argvec[4] = (unsigned long)(arg4); \ 4735 _argvec[5] = (unsigned long)(arg5); \ 4736 _argvec[6] = (unsigned long)(arg6); \ 4737 _argvec[7] = (unsigned long)(arg7); \ 4738 __asm__ volatile( \ 4739 "subu $29, $29, 8 \n\t" \ 4740 "sw $28, 0($29) \n\t" \ 4741 "sw $31, 4($29) \n\t" \ 4742 "lw $4, 20(%1) \n\t" \ 4743 "subu $29, $29, 32\n\t" \ 4744 "sw $4, 16($29) \n\t" \ 4745 "lw $4, 24(%1) \n\t" \ 4746 "sw $4, 20($29) \n\t" \ 4747 "lw $4, 28(%1) \n\t" \ 4748 "sw $4, 24($29) \n\t" \ 4749 "lw $4, 4(%1) \n\t" \ 4750 "lw $5, 8(%1) \n\t" \ 4751 "lw $6, 12(%1) \n\t" \ 4752 "lw $7, 16(%1) \n\t" \ 4753 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4754 VALGRIND_CALL_NOREDIR_T9 \ 4755 "addu $29, $29, 32 \n\t" \ 4756 "lw $28, 0($29) \n\t" \ 4757 "lw $31, 4($29) \n\t" \ 4758 "addu $29, $29, 8 \n\t" \ 4759 "move %0, $2\n" \ 4760 : /*out*/ "=r" (_res) \ 4761 : /*in*/ "0" (&_argvec[0]) \ 4762 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4763 ); \ 4764 lval = (__typeof__(lval)) _res; \ 4765 } while (0) 4766 4767 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4768 arg7,arg8) \ 4769 do { \ 4770 volatile OrigFn _orig = (orig); \ 4771 volatile unsigned long _argvec[9]; \ 4772 volatile unsigned long _res; \ 4773 _argvec[0] = (unsigned long)_orig.nraddr; \ 4774 _argvec[1] = (unsigned long)(arg1); \ 4775 _argvec[2] = (unsigned long)(arg2); \ 4776 _argvec[3] = (unsigned long)(arg3); \ 4777 _argvec[4] = (unsigned long)(arg4); \ 4778 _argvec[5] = (unsigned long)(arg5); \ 4779 _argvec[6] = (unsigned long)(arg6); \ 4780 _argvec[7] = (unsigned long)(arg7); \ 4781 _argvec[8] = (unsigned long)(arg8); \ 4782 __asm__ volatile( \ 4783 "subu $29, $29, 8 \n\t" \ 4784 "sw $28, 0($29) \n\t" \ 4785 "sw $31, 4($29) \n\t" \ 4786 "lw $4, 20(%1) \n\t" \ 4787 "subu $29, $29, 40\n\t" \ 4788 "sw $4, 16($29) \n\t" \ 4789 "lw $4, 24(%1) \n\t" \ 4790 "sw $4, 20($29) \n\t" \ 4791 "lw $4, 28(%1) \n\t" \ 4792 "sw $4, 24($29) \n\t" \ 4793 "lw $4, 32(%1) \n\t" \ 4794 "sw $4, 28($29) \n\t" \ 4795 "lw $4, 4(%1) \n\t" \ 4796 "lw $5, 8(%1) \n\t" \ 4797 "lw $6, 12(%1) \n\t" \ 4798 "lw $7, 16(%1) \n\t" \ 4799 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4800 VALGRIND_CALL_NOREDIR_T9 \ 4801 "addu $29, $29, 40 \n\t" \ 4802 "lw $28, 0($29) \n\t" \ 4803 "lw $31, 4($29) \n\t" \ 4804 "addu $29, $29, 8 \n\t" \ 4805 "move %0, $2\n" \ 4806 : /*out*/ "=r" (_res) \ 4807 : /*in*/ "0" (&_argvec[0]) \ 4808 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4809 ); \ 4810 lval = (__typeof__(lval)) _res; \ 4811 } while (0) 4812 4813 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4814 arg7,arg8,arg9) \ 4815 do { \ 4816 volatile OrigFn _orig = (orig); \ 4817 volatile unsigned long _argvec[10]; \ 4818 volatile unsigned long _res; \ 4819 _argvec[0] = (unsigned long)_orig.nraddr; \ 4820 _argvec[1] = (unsigned long)(arg1); \ 4821 _argvec[2] = (unsigned long)(arg2); \ 4822 _argvec[3] = (unsigned long)(arg3); \ 4823 _argvec[4] = (unsigned long)(arg4); \ 4824 _argvec[5] = (unsigned long)(arg5); \ 4825 _argvec[6] = (unsigned long)(arg6); \ 4826 _argvec[7] = (unsigned long)(arg7); \ 4827 _argvec[8] = (unsigned long)(arg8); \ 4828 _argvec[9] = (unsigned long)(arg9); \ 4829 __asm__ volatile( \ 4830 "subu $29, $29, 8 \n\t" \ 4831 "sw $28, 0($29) \n\t" \ 4832 "sw $31, 4($29) \n\t" \ 4833 "lw $4, 20(%1) \n\t" \ 4834 "subu $29, $29, 40\n\t" \ 4835 "sw $4, 16($29) \n\t" \ 4836 "lw $4, 24(%1) \n\t" \ 4837 "sw $4, 20($29) \n\t" \ 4838 "lw $4, 28(%1) \n\t" \ 4839 "sw $4, 24($29) \n\t" \ 4840 "lw $4, 32(%1) \n\t" \ 4841 "sw $4, 28($29) \n\t" \ 4842 "lw $4, 36(%1) \n\t" \ 4843 "sw $4, 32($29) \n\t" \ 4844 "lw $4, 4(%1) \n\t" \ 4845 "lw $5, 8(%1) \n\t" \ 4846 "lw $6, 12(%1) \n\t" \ 4847 "lw $7, 16(%1) \n\t" \ 4848 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4849 VALGRIND_CALL_NOREDIR_T9 \ 4850 "addu $29, $29, 40 \n\t" \ 4851 "lw $28, 0($29) \n\t" \ 4852 "lw $31, 4($29) \n\t" \ 4853 "addu $29, $29, 8 \n\t" \ 4854 "move %0, $2\n" \ 4855 : /*out*/ "=r" (_res) \ 4856 : /*in*/ "0" (&_argvec[0]) \ 4857 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4858 ); \ 4859 lval = (__typeof__(lval)) _res; \ 4860 } while (0) 4861 4862 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 4863 arg7,arg8,arg9,arg10) \ 4864 do { \ 4865 volatile OrigFn _orig = (orig); \ 4866 volatile unsigned long _argvec[11]; \ 4867 volatile unsigned long _res; \ 4868 _argvec[0] = (unsigned long)_orig.nraddr; \ 4869 _argvec[1] = (unsigned long)(arg1); \ 4870 _argvec[2] = (unsigned long)(arg2); \ 4871 _argvec[3] = (unsigned long)(arg3); \ 4872 _argvec[4] = (unsigned long)(arg4); \ 4873 _argvec[5] = (unsigned long)(arg5); \ 4874 _argvec[6] = (unsigned long)(arg6); \ 4875 _argvec[7] = (unsigned long)(arg7); \ 4876 _argvec[8] = (unsigned long)(arg8); \ 4877 _argvec[9] = (unsigned long)(arg9); \ 4878 _argvec[10] = (unsigned long)(arg10); \ 4879 __asm__ volatile( \ 4880 "subu $29, $29, 8 \n\t" \ 4881 "sw $28, 0($29) \n\t" \ 4882 "sw $31, 4($29) \n\t" \ 4883 "lw $4, 20(%1) \n\t" \ 4884 "subu $29, $29, 48\n\t" \ 4885 "sw $4, 16($29) \n\t" \ 4886 "lw $4, 24(%1) \n\t" \ 4887 "sw $4, 20($29) \n\t" \ 4888 "lw $4, 28(%1) \n\t" \ 4889 "sw $4, 24($29) \n\t" \ 4890 "lw $4, 32(%1) \n\t" \ 4891 "sw $4, 28($29) \n\t" \ 4892 "lw $4, 36(%1) \n\t" \ 4893 "sw $4, 32($29) \n\t" \ 4894 "lw $4, 40(%1) \n\t" \ 4895 "sw $4, 36($29) \n\t" \ 4896 "lw $4, 4(%1) \n\t" \ 4897 "lw $5, 8(%1) \n\t" \ 4898 "lw $6, 12(%1) \n\t" \ 4899 "lw $7, 16(%1) \n\t" \ 4900 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4901 VALGRIND_CALL_NOREDIR_T9 \ 4902 "addu $29, $29, 48 \n\t" \ 4903 "lw $28, 0($29) \n\t" \ 4904 "lw $31, 4($29) \n\t" \ 4905 "addu $29, $29, 8 \n\t" \ 4906 "move %0, $2\n" \ 4907 : /*out*/ "=r" (_res) \ 4908 : /*in*/ "0" (&_argvec[0]) \ 4909 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4910 ); \ 4911 lval = (__typeof__(lval)) _res; \ 4912 } while (0) 4913 4914 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 4915 arg6,arg7,arg8,arg9,arg10, \ 4916 arg11) \ 4917 do { \ 4918 volatile OrigFn _orig = (orig); \ 4919 volatile unsigned long _argvec[12]; \ 4920 volatile unsigned long _res; \ 4921 _argvec[0] = (unsigned long)_orig.nraddr; \ 4922 _argvec[1] = (unsigned long)(arg1); \ 4923 _argvec[2] = (unsigned long)(arg2); \ 4924 _argvec[3] = (unsigned long)(arg3); \ 4925 _argvec[4] = (unsigned long)(arg4); \ 4926 _argvec[5] = (unsigned long)(arg5); \ 4927 _argvec[6] = (unsigned long)(arg6); \ 4928 _argvec[7] = (unsigned long)(arg7); \ 4929 _argvec[8] = (unsigned long)(arg8); \ 4930 _argvec[9] = (unsigned long)(arg9); \ 4931 _argvec[10] = (unsigned long)(arg10); \ 4932 _argvec[11] = (unsigned long)(arg11); \ 4933 __asm__ volatile( \ 4934 "subu $29, $29, 8 \n\t" \ 4935 "sw $28, 0($29) \n\t" \ 4936 "sw $31, 4($29) \n\t" \ 4937 "lw $4, 20(%1) \n\t" \ 4938 "subu $29, $29, 48\n\t" \ 4939 "sw $4, 16($29) \n\t" \ 4940 "lw $4, 24(%1) \n\t" \ 4941 "sw $4, 20($29) \n\t" \ 4942 "lw $4, 28(%1) \n\t" \ 4943 "sw $4, 24($29) \n\t" \ 4944 "lw $4, 32(%1) \n\t" \ 4945 "sw $4, 28($29) \n\t" \ 4946 "lw $4, 36(%1) \n\t" \ 4947 "sw $4, 32($29) \n\t" \ 4948 "lw $4, 40(%1) \n\t" \ 4949 "sw $4, 36($29) \n\t" \ 4950 "lw $4, 44(%1) \n\t" \ 4951 "sw $4, 40($29) \n\t" \ 4952 "lw $4, 4(%1) \n\t" \ 4953 "lw $5, 8(%1) \n\t" \ 4954 "lw $6, 12(%1) \n\t" \ 4955 "lw $7, 16(%1) \n\t" \ 4956 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 4957 VALGRIND_CALL_NOREDIR_T9 \ 4958 "addu $29, $29, 48 \n\t" \ 4959 "lw $28, 0($29) \n\t" \ 4960 "lw $31, 4($29) \n\t" \ 4961 "addu $29, $29, 8 \n\t" \ 4962 "move %0, $2\n" \ 4963 : /*out*/ "=r" (_res) \ 4964 : /*in*/ "0" (&_argvec[0]) \ 4965 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 4966 ); \ 4967 lval = (__typeof__(lval)) _res; \ 4968 } while (0) 4969 4970 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 4971 arg6,arg7,arg8,arg9,arg10, \ 4972 arg11,arg12) \ 4973 do { \ 4974 volatile OrigFn _orig = (orig); \ 4975 volatile unsigned long _argvec[13]; \ 4976 volatile unsigned long _res; \ 4977 _argvec[0] = (unsigned long)_orig.nraddr; \ 4978 _argvec[1] = (unsigned long)(arg1); \ 4979 _argvec[2] = (unsigned long)(arg2); \ 4980 _argvec[3] = (unsigned long)(arg3); \ 4981 _argvec[4] = (unsigned long)(arg4); \ 4982 _argvec[5] = (unsigned long)(arg5); \ 4983 _argvec[6] = (unsigned long)(arg6); \ 4984 _argvec[7] = (unsigned long)(arg7); \ 4985 _argvec[8] = (unsigned long)(arg8); \ 4986 _argvec[9] = (unsigned long)(arg9); \ 4987 _argvec[10] = (unsigned long)(arg10); \ 4988 _argvec[11] = (unsigned long)(arg11); \ 4989 _argvec[12] = (unsigned long)(arg12); \ 4990 __asm__ volatile( \ 4991 "subu $29, $29, 8 \n\t" \ 4992 "sw $28, 0($29) \n\t" \ 4993 "sw $31, 4($29) \n\t" \ 4994 "lw $4, 20(%1) \n\t" \ 4995 "subu $29, $29, 56\n\t" \ 4996 "sw $4, 16($29) \n\t" \ 4997 "lw $4, 24(%1) \n\t" \ 4998 "sw $4, 20($29) \n\t" \ 4999 "lw $4, 28(%1) \n\t" \ 5000 "sw $4, 24($29) \n\t" \ 5001 "lw $4, 32(%1) \n\t" \ 5002 "sw $4, 28($29) \n\t" \ 5003 "lw $4, 36(%1) \n\t" \ 5004 "sw $4, 32($29) \n\t" \ 5005 "lw $4, 40(%1) \n\t" \ 5006 "sw $4, 36($29) \n\t" \ 5007 "lw $4, 44(%1) \n\t" \ 5008 "sw $4, 40($29) \n\t" \ 5009 "lw $4, 48(%1) \n\t" \ 5010 "sw $4, 44($29) \n\t" \ 5011 "lw $4, 4(%1) \n\t" \ 5012 "lw $5, 8(%1) \n\t" \ 5013 "lw $6, 12(%1) \n\t" \ 5014 "lw $7, 16(%1) \n\t" \ 5015 "lw $25, 0(%1) \n\t" /* target->t9 */ \ 5016 VALGRIND_CALL_NOREDIR_T9 \ 5017 "addu $29, $29, 56 \n\t" \ 5018 "lw $28, 0($29) \n\t" \ 5019 "lw $31, 4($29) \n\t" \ 5020 "addu $29, $29, 8 \n\t" \ 5021 "move %0, $2\n" \ 5022 : /*out*/ "=r" (_res) \ 5023 : /*in*/ "r" (&_argvec[0]) \ 5024 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5025 ); \ 5026 lval = (__typeof__(lval)) _res; \ 5027 } while (0) 5028 5029 #endif /* PLAT_mips32_linux */ 5030 5031 /* ------------------------- mips64-linux ------------------------- */ 5032 5033 #if defined(PLAT_mips64_linux) 5034 5035 /* These regs are trashed by the hidden call. */ 5036 #define __CALLER_SAVED_REGS "$2", "$3", "$4", "$5", "$6", \ 5037 "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", \ 5038 "$25", "$31" 5039 5040 /* These CALL_FN_ macros assume that on mips-linux, sizeof(unsigned 5041 long) == 4. */ 5042 5043 #define CALL_FN_W_v(lval, orig) \ 5044 do { \ 5045 volatile OrigFn _orig = (orig); \ 5046 volatile unsigned long _argvec[1]; \ 5047 volatile unsigned long _res; \ 5048 _argvec[0] = (unsigned long)_orig.nraddr; \ 5049 __asm__ volatile( \ 5050 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5051 VALGRIND_CALL_NOREDIR_T9 \ 5052 "move %0, $2\n" \ 5053 : /*out*/ "=r" (_res) \ 5054 : /*in*/ "0" (&_argvec[0]) \ 5055 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5056 ); \ 5057 lval = (__typeof__(lval)) _res; \ 5058 } while (0) 5059 5060 #define CALL_FN_W_W(lval, orig, arg1) \ 5061 do { \ 5062 volatile OrigFn _orig = (orig); \ 5063 volatile unsigned long _argvec[2]; \ 5064 volatile unsigned long _res; \ 5065 _argvec[0] = (unsigned long)_orig.nraddr; \ 5066 _argvec[1] = (unsigned long)(arg1); \ 5067 __asm__ volatile( \ 5068 "ld $4, 8(%1)\n\t" /* arg1*/ \ 5069 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5070 VALGRIND_CALL_NOREDIR_T9 \ 5071 "move %0, $2\n" \ 5072 : /*out*/ "=r" (_res) \ 5073 : /*in*/ "r" (&_argvec[0]) \ 5074 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5075 ); \ 5076 lval = (__typeof__(lval)) _res; \ 5077 } while (0) 5078 5079 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ 5080 do { \ 5081 volatile OrigFn _orig = (orig); \ 5082 volatile unsigned long _argvec[3]; \ 5083 volatile unsigned long _res; \ 5084 _argvec[0] = (unsigned long)_orig.nraddr; \ 5085 _argvec[1] = (unsigned long)(arg1); \ 5086 _argvec[2] = (unsigned long)(arg2); \ 5087 __asm__ volatile( \ 5088 "ld $4, 8(%1)\n\t" \ 5089 "ld $5, 16(%1)\n\t" \ 5090 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5091 VALGRIND_CALL_NOREDIR_T9 \ 5092 "move %0, $2\n" \ 5093 : /*out*/ "=r" (_res) \ 5094 : /*in*/ "r" (&_argvec[0]) \ 5095 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5096 ); \ 5097 lval = (__typeof__(lval)) _res; \ 5098 } while (0) 5099 5100 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ 5101 do { \ 5102 volatile OrigFn _orig = (orig); \ 5103 volatile unsigned long _argvec[4]; \ 5104 volatile unsigned long _res; \ 5105 _argvec[0] = (unsigned long)_orig.nraddr; \ 5106 _argvec[1] = (unsigned long)(arg1); \ 5107 _argvec[2] = (unsigned long)(arg2); \ 5108 _argvec[3] = (unsigned long)(arg3); \ 5109 __asm__ volatile( \ 5110 "ld $4, 8(%1)\n\t" \ 5111 "ld $5, 16(%1)\n\t" \ 5112 "ld $6, 24(%1)\n\t" \ 5113 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5114 VALGRIND_CALL_NOREDIR_T9 \ 5115 "move %0, $2\n" \ 5116 : /*out*/ "=r" (_res) \ 5117 : /*in*/ "r" (&_argvec[0]) \ 5118 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5119 ); \ 5120 lval = (__typeof__(lval)) _res; \ 5121 } while (0) 5122 5123 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ 5124 do { \ 5125 volatile OrigFn _orig = (orig); \ 5126 volatile unsigned long _argvec[5]; \ 5127 volatile unsigned long _res; \ 5128 _argvec[0] = (unsigned long)_orig.nraddr; \ 5129 _argvec[1] = (unsigned long)(arg1); \ 5130 _argvec[2] = (unsigned long)(arg2); \ 5131 _argvec[3] = (unsigned long)(arg3); \ 5132 _argvec[4] = (unsigned long)(arg4); \ 5133 __asm__ volatile( \ 5134 "ld $4, 8(%1)\n\t" \ 5135 "ld $5, 16(%1)\n\t" \ 5136 "ld $6, 24(%1)\n\t" \ 5137 "ld $7, 32(%1)\n\t" \ 5138 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5139 VALGRIND_CALL_NOREDIR_T9 \ 5140 "move %0, $2\n" \ 5141 : /*out*/ "=r" (_res) \ 5142 : /*in*/ "r" (&_argvec[0]) \ 5143 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5144 ); \ 5145 lval = (__typeof__(lval)) _res; \ 5146 } while (0) 5147 5148 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ 5149 do { \ 5150 volatile OrigFn _orig = (orig); \ 5151 volatile unsigned long _argvec[6]; \ 5152 volatile unsigned long _res; \ 5153 _argvec[0] = (unsigned long)_orig.nraddr; \ 5154 _argvec[1] = (unsigned long)(arg1); \ 5155 _argvec[2] = (unsigned long)(arg2); \ 5156 _argvec[3] = (unsigned long)(arg3); \ 5157 _argvec[4] = (unsigned long)(arg4); \ 5158 _argvec[5] = (unsigned long)(arg5); \ 5159 __asm__ volatile( \ 5160 "ld $4, 8(%1)\n\t" \ 5161 "ld $5, 16(%1)\n\t" \ 5162 "ld $6, 24(%1)\n\t" \ 5163 "ld $7, 32(%1)\n\t" \ 5164 "ld $8, 40(%1)\n\t" \ 5165 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5166 VALGRIND_CALL_NOREDIR_T9 \ 5167 "move %0, $2\n" \ 5168 : /*out*/ "=r" (_res) \ 5169 : /*in*/ "r" (&_argvec[0]) \ 5170 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5171 ); \ 5172 lval = (__typeof__(lval)) _res; \ 5173 } while (0) 5174 5175 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ 5176 do { \ 5177 volatile OrigFn _orig = (orig); \ 5178 volatile unsigned long _argvec[7]; \ 5179 volatile unsigned long _res; \ 5180 _argvec[0] = (unsigned long)_orig.nraddr; \ 5181 _argvec[1] = (unsigned long)(arg1); \ 5182 _argvec[2] = (unsigned long)(arg2); \ 5183 _argvec[3] = (unsigned long)(arg3); \ 5184 _argvec[4] = (unsigned long)(arg4); \ 5185 _argvec[5] = (unsigned long)(arg5); \ 5186 _argvec[6] = (unsigned long)(arg6); \ 5187 __asm__ volatile( \ 5188 "ld $4, 8(%1)\n\t" \ 5189 "ld $5, 16(%1)\n\t" \ 5190 "ld $6, 24(%1)\n\t" \ 5191 "ld $7, 32(%1)\n\t" \ 5192 "ld $8, 40(%1)\n\t" \ 5193 "ld $9, 48(%1)\n\t" \ 5194 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5195 VALGRIND_CALL_NOREDIR_T9 \ 5196 "move %0, $2\n" \ 5197 : /*out*/ "=r" (_res) \ 5198 : /*in*/ "r" (&_argvec[0]) \ 5199 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5200 ); \ 5201 lval = (__typeof__(lval)) _res; \ 5202 } while (0) 5203 5204 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 5205 arg7) \ 5206 do { \ 5207 volatile OrigFn _orig = (orig); \ 5208 volatile unsigned long _argvec[8]; \ 5209 volatile unsigned long _res; \ 5210 _argvec[0] = (unsigned long)_orig.nraddr; \ 5211 _argvec[1] = (unsigned long)(arg1); \ 5212 _argvec[2] = (unsigned long)(arg2); \ 5213 _argvec[3] = (unsigned long)(arg3); \ 5214 _argvec[4] = (unsigned long)(arg4); \ 5215 _argvec[5] = (unsigned long)(arg5); \ 5216 _argvec[6] = (unsigned long)(arg6); \ 5217 _argvec[7] = (unsigned long)(arg7); \ 5218 __asm__ volatile( \ 5219 "ld $4, 8(%1)\n\t" \ 5220 "ld $5, 16(%1)\n\t" \ 5221 "ld $6, 24(%1)\n\t" \ 5222 "ld $7, 32(%1)\n\t" \ 5223 "ld $8, 40(%1)\n\t" \ 5224 "ld $9, 48(%1)\n\t" \ 5225 "ld $10, 56(%1)\n\t" \ 5226 "ld $25, 0(%1) \n\t" /* target->t9 */ \ 5227 VALGRIND_CALL_NOREDIR_T9 \ 5228 "move %0, $2\n" \ 5229 : /*out*/ "=r" (_res) \ 5230 : /*in*/ "r" (&_argvec[0]) \ 5231 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5232 ); \ 5233 lval = (__typeof__(lval)) _res; \ 5234 } while (0) 5235 5236 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 5237 arg7,arg8) \ 5238 do { \ 5239 volatile OrigFn _orig = (orig); \ 5240 volatile unsigned long _argvec[9]; \ 5241 volatile unsigned long _res; \ 5242 _argvec[0] = (unsigned long)_orig.nraddr; \ 5243 _argvec[1] = (unsigned long)(arg1); \ 5244 _argvec[2] = (unsigned long)(arg2); \ 5245 _argvec[3] = (unsigned long)(arg3); \ 5246 _argvec[4] = (unsigned long)(arg4); \ 5247 _argvec[5] = (unsigned long)(arg5); \ 5248 _argvec[6] = (unsigned long)(arg6); \ 5249 _argvec[7] = (unsigned long)(arg7); \ 5250 _argvec[8] = (unsigned long)(arg8); \ 5251 __asm__ volatile( \ 5252 "ld $4, 8(%1)\n\t" \ 5253 "ld $5, 16(%1)\n\t" \ 5254 "ld $6, 24(%1)\n\t" \ 5255 "ld $7, 32(%1)\n\t" \ 5256 "ld $8, 40(%1)\n\t" \ 5257 "ld $9, 48(%1)\n\t" \ 5258 "ld $10, 56(%1)\n\t" \ 5259 "ld $11, 64(%1)\n\t" \ 5260 "ld $25, 0(%1) \n\t" /* target->t9 */ \ 5261 VALGRIND_CALL_NOREDIR_T9 \ 5262 "move %0, $2\n" \ 5263 : /*out*/ "=r" (_res) \ 5264 : /*in*/ "r" (&_argvec[0]) \ 5265 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5266 ); \ 5267 lval = (__typeof__(lval)) _res; \ 5268 } while (0) 5269 5270 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 5271 arg7,arg8,arg9) \ 5272 do { \ 5273 volatile OrigFn _orig = (orig); \ 5274 volatile unsigned long _argvec[10]; \ 5275 volatile unsigned long _res; \ 5276 _argvec[0] = (unsigned long)_orig.nraddr; \ 5277 _argvec[1] = (unsigned long)(arg1); \ 5278 _argvec[2] = (unsigned long)(arg2); \ 5279 _argvec[3] = (unsigned long)(arg3); \ 5280 _argvec[4] = (unsigned long)(arg4); \ 5281 _argvec[5] = (unsigned long)(arg5); \ 5282 _argvec[6] = (unsigned long)(arg6); \ 5283 _argvec[7] = (unsigned long)(arg7); \ 5284 _argvec[8] = (unsigned long)(arg8); \ 5285 _argvec[9] = (unsigned long)(arg9); \ 5286 __asm__ volatile( \ 5287 "dsubu $29, $29, 8\n\t" \ 5288 "ld $4, 72(%1)\n\t" \ 5289 "sd $4, 0($29)\n\t" \ 5290 "ld $4, 8(%1)\n\t" \ 5291 "ld $5, 16(%1)\n\t" \ 5292 "ld $6, 24(%1)\n\t" \ 5293 "ld $7, 32(%1)\n\t" \ 5294 "ld $8, 40(%1)\n\t" \ 5295 "ld $9, 48(%1)\n\t" \ 5296 "ld $10, 56(%1)\n\t" \ 5297 "ld $11, 64(%1)\n\t" \ 5298 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5299 VALGRIND_CALL_NOREDIR_T9 \ 5300 "daddu $29, $29, 8\n\t" \ 5301 "move %0, $2\n" \ 5302 : /*out*/ "=r" (_res) \ 5303 : /*in*/ "r" (&_argvec[0]) \ 5304 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5305 ); \ 5306 lval = (__typeof__(lval)) _res; \ 5307 } while (0) 5308 5309 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ 5310 arg7,arg8,arg9,arg10) \ 5311 do { \ 5312 volatile OrigFn _orig = (orig); \ 5313 volatile unsigned long _argvec[11]; \ 5314 volatile unsigned long _res; \ 5315 _argvec[0] = (unsigned long)_orig.nraddr; \ 5316 _argvec[1] = (unsigned long)(arg1); \ 5317 _argvec[2] = (unsigned long)(arg2); \ 5318 _argvec[3] = (unsigned long)(arg3); \ 5319 _argvec[4] = (unsigned long)(arg4); \ 5320 _argvec[5] = (unsigned long)(arg5); \ 5321 _argvec[6] = (unsigned long)(arg6); \ 5322 _argvec[7] = (unsigned long)(arg7); \ 5323 _argvec[8] = (unsigned long)(arg8); \ 5324 _argvec[9] = (unsigned long)(arg9); \ 5325 _argvec[10] = (unsigned long)(arg10); \ 5326 __asm__ volatile( \ 5327 "dsubu $29, $29, 16\n\t" \ 5328 "ld $4, 72(%1)\n\t" \ 5329 "sd $4, 0($29)\n\t" \ 5330 "ld $4, 80(%1)\n\t" \ 5331 "sd $4, 8($29)\n\t" \ 5332 "ld $4, 8(%1)\n\t" \ 5333 "ld $5, 16(%1)\n\t" \ 5334 "ld $6, 24(%1)\n\t" \ 5335 "ld $7, 32(%1)\n\t" \ 5336 "ld $8, 40(%1)\n\t" \ 5337 "ld $9, 48(%1)\n\t" \ 5338 "ld $10, 56(%1)\n\t" \ 5339 "ld $11, 64(%1)\n\t" \ 5340 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5341 VALGRIND_CALL_NOREDIR_T9 \ 5342 "daddu $29, $29, 16\n\t" \ 5343 "move %0, $2\n" \ 5344 : /*out*/ "=r" (_res) \ 5345 : /*in*/ "r" (&_argvec[0]) \ 5346 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5347 ); \ 5348 lval = (__typeof__(lval)) _res; \ 5349 } while (0) 5350 5351 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 5352 arg6,arg7,arg8,arg9,arg10, \ 5353 arg11) \ 5354 do { \ 5355 volatile OrigFn _orig = (orig); \ 5356 volatile unsigned long _argvec[12]; \ 5357 volatile unsigned long _res; \ 5358 _argvec[0] = (unsigned long)_orig.nraddr; \ 5359 _argvec[1] = (unsigned long)(arg1); \ 5360 _argvec[2] = (unsigned long)(arg2); \ 5361 _argvec[3] = (unsigned long)(arg3); \ 5362 _argvec[4] = (unsigned long)(arg4); \ 5363 _argvec[5] = (unsigned long)(arg5); \ 5364 _argvec[6] = (unsigned long)(arg6); \ 5365 _argvec[7] = (unsigned long)(arg7); \ 5366 _argvec[8] = (unsigned long)(arg8); \ 5367 _argvec[9] = (unsigned long)(arg9); \ 5368 _argvec[10] = (unsigned long)(arg10); \ 5369 _argvec[11] = (unsigned long)(arg11); \ 5370 __asm__ volatile( \ 5371 "dsubu $29, $29, 24\n\t" \ 5372 "ld $4, 72(%1)\n\t" \ 5373 "sd $4, 0($29)\n\t" \ 5374 "ld $4, 80(%1)\n\t" \ 5375 "sd $4, 8($29)\n\t" \ 5376 "ld $4, 88(%1)\n\t" \ 5377 "sd $4, 16($29)\n\t" \ 5378 "ld $4, 8(%1)\n\t" \ 5379 "ld $5, 16(%1)\n\t" \ 5380 "ld $6, 24(%1)\n\t" \ 5381 "ld $7, 32(%1)\n\t" \ 5382 "ld $8, 40(%1)\n\t" \ 5383 "ld $9, 48(%1)\n\t" \ 5384 "ld $10, 56(%1)\n\t" \ 5385 "ld $11, 64(%1)\n\t" \ 5386 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5387 VALGRIND_CALL_NOREDIR_T9 \ 5388 "daddu $29, $29, 24\n\t" \ 5389 "move %0, $2\n" \ 5390 : /*out*/ "=r" (_res) \ 5391 : /*in*/ "r" (&_argvec[0]) \ 5392 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5393 ); \ 5394 lval = (__typeof__(lval)) _res; \ 5395 } while (0) 5396 5397 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ 5398 arg6,arg7,arg8,arg9,arg10, \ 5399 arg11,arg12) \ 5400 do { \ 5401 volatile OrigFn _orig = (orig); \ 5402 volatile unsigned long _argvec[13]; \ 5403 volatile unsigned long _res; \ 5404 _argvec[0] = (unsigned long)_orig.nraddr; \ 5405 _argvec[1] = (unsigned long)(arg1); \ 5406 _argvec[2] = (unsigned long)(arg2); \ 5407 _argvec[3] = (unsigned long)(arg3); \ 5408 _argvec[4] = (unsigned long)(arg4); \ 5409 _argvec[5] = (unsigned long)(arg5); \ 5410 _argvec[6] = (unsigned long)(arg6); \ 5411 _argvec[7] = (unsigned long)(arg7); \ 5412 _argvec[8] = (unsigned long)(arg8); \ 5413 _argvec[9] = (unsigned long)(arg9); \ 5414 _argvec[10] = (unsigned long)(arg10); \ 5415 _argvec[11] = (unsigned long)(arg11); \ 5416 _argvec[12] = (unsigned long)(arg12); \ 5417 __asm__ volatile( \ 5418 "dsubu $29, $29, 32\n\t" \ 5419 "ld $4, 72(%1)\n\t" \ 5420 "sd $4, 0($29)\n\t" \ 5421 "ld $4, 80(%1)\n\t" \ 5422 "sd $4, 8($29)\n\t" \ 5423 "ld $4, 88(%1)\n\t" \ 5424 "sd $4, 16($29)\n\t" \ 5425 "ld $4, 96(%1)\n\t" \ 5426 "sd $4, 24($29)\n\t" \ 5427 "ld $4, 8(%1)\n\t" \ 5428 "ld $5, 16(%1)\n\t" \ 5429 "ld $6, 24(%1)\n\t" \ 5430 "ld $7, 32(%1)\n\t" \ 5431 "ld $8, 40(%1)\n\t" \ 5432 "ld $9, 48(%1)\n\t" \ 5433 "ld $10, 56(%1)\n\t" \ 5434 "ld $11, 64(%1)\n\t" \ 5435 "ld $25, 0(%1)\n\t" /* target->t9 */ \ 5436 VALGRIND_CALL_NOREDIR_T9 \ 5437 "daddu $29, $29, 32\n\t" \ 5438 "move %0, $2\n" \ 5439 : /*out*/ "=r" (_res) \ 5440 : /*in*/ "r" (&_argvec[0]) \ 5441 : /*trash*/ "memory", __CALLER_SAVED_REGS \ 5442 ); \ 5443 lval = (__typeof__(lval)) _res; \ 5444 } while (0) 5445 5446 #endif /* PLAT_mips64_linux */ 5447 5448 5449 /* ------------------------------------------------------------------ */ 5450 /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */ 5451 /* */ 5452 /* ------------------------------------------------------------------ */ 5453 5454 /* Some request codes. There are many more of these, but most are not 5455 exposed to end-user view. These are the public ones, all of the 5456 form 0x1000 + small_number. 5457 5458 Core ones are in the range 0x00000000--0x0000ffff. The non-public 5459 ones start at 0x2000. 5460 */ 5461 5462 /* These macros are used by tools -- they must be public, but don't 5463 embed them into other programs. */ 5464 #define VG_USERREQ_TOOL_BASE(a,b) \ 5465 ((unsigned int)(((a)&0xff) << 24 | ((b)&0xff) << 16)) 5466 #define VG_IS_TOOL_USERREQ(a, b, v) \ 5467 (VG_USERREQ_TOOL_BASE(a,b) == ((v) & 0xffff0000)) 5468 5469 /* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !! 5470 This enum comprises an ABI exported by Valgrind to programs 5471 which use client requests. DO NOT CHANGE THE ORDER OF THESE 5472 ENTRIES, NOR DELETE ANY -- add new ones at the end. */ 5473 typedef 5474 enum { VG_USERREQ__RUNNING_ON_VALGRIND = 0x1001, 5475 VG_USERREQ__DISCARD_TRANSLATIONS = 0x1002, 5476 5477 /* These allow any function to be called from the simulated 5478 CPU but run on the real CPU. Nb: the first arg passed to 5479 the function is always the ThreadId of the running 5480 thread! So CLIENT_CALL0 actually requires a 1 arg 5481 function, etc. */ 5482 VG_USERREQ__CLIENT_CALL0 = 0x1101, 5483 VG_USERREQ__CLIENT_CALL1 = 0x1102, 5484 VG_USERREQ__CLIENT_CALL2 = 0x1103, 5485 VG_USERREQ__CLIENT_CALL3 = 0x1104, 5486 5487 /* Can be useful in regression testing suites -- eg. can 5488 send Valgrind's output to /dev/null and still count 5489 errors. */ 5490 VG_USERREQ__COUNT_ERRORS = 0x1201, 5491 5492 /* Allows the client program and/or gdbserver to execute a monitor 5493 command. */ 5494 VG_USERREQ__GDB_MONITOR_COMMAND = 0x1202, 5495 5496 /* These are useful and can be interpreted by any tool that 5497 tracks malloc() et al, by using vg_replace_malloc.c. */ 5498 VG_USERREQ__MALLOCLIKE_BLOCK = 0x1301, 5499 VG_USERREQ__RESIZEINPLACE_BLOCK = 0x130b, 5500 VG_USERREQ__FREELIKE_BLOCK = 0x1302, 5501 /* Memory pool support. */ 5502 VG_USERREQ__CREATE_MEMPOOL = 0x1303, 5503 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, 5504 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, 5505 VG_USERREQ__MEMPOOL_FREE = 0x1306, 5506 VG_USERREQ__MEMPOOL_TRIM = 0x1307, 5507 VG_USERREQ__MOVE_MEMPOOL = 0x1308, 5508 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, 5509 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, 5510 5511 /* Allow printfs to valgrind log. */ 5512 /* The first two pass the va_list argument by value, which 5513 assumes it is the same size as or smaller than a UWord, 5514 which generally isn't the case. Hence are deprecated. 5515 The second two pass the vargs by reference and so are 5516 immune to this problem. */ 5517 /* both :: char* fmt, va_list vargs (DEPRECATED) */ 5518 VG_USERREQ__PRINTF = 0x1401, 5519 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, 5520 /* both :: char* fmt, va_list* vargs */ 5521 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, 5522 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, 5523 5524 /* Stack support. */ 5525 VG_USERREQ__STACK_REGISTER = 0x1501, 5526 VG_USERREQ__STACK_DEREGISTER = 0x1502, 5527 VG_USERREQ__STACK_CHANGE = 0x1503, 5528 5529 /* Wine support */ 5530 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, 5531 5532 /* Querying of debug info. */ 5533 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701, 5534 5535 /* Disable/enable error reporting level. Takes a single 5536 Word arg which is the delta to this thread's error 5537 disablement indicator. Hence 1 disables or further 5538 disables errors, and -1 moves back towards enablement. 5539 Other values are not allowed. */ 5540 VG_USERREQ__CHANGE_ERR_DISABLEMENT = 0x1801, 5541 5542 /* Initialise IR injection */ 5543 VG_USERREQ__VEX_INIT_FOR_IRI = 0x1901 5544 } Vg_ClientRequest; 5545 5546 #if !defined(__GNUC__) 5547 # define __extension__ /* */ 5548 #endif 5549 5550 5551 /* Returns the number of Valgrinds this code is running under. That 5552 is, 0 if running natively, 1 if running under Valgrind, 2 if 5553 running under Valgrind which is running under another Valgrind, 5554 etc. */ 5555 #define RUNNING_ON_VALGRIND \ 5556 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ 5557 VG_USERREQ__RUNNING_ON_VALGRIND, \ 5558 0, 0, 0, 0, 0) \ 5559 5560 5561 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr + 5562 _qzz_len - 1]. Useful if you are debugging a JITter or some such, 5563 since it provides a way to make sure valgrind will retranslate the 5564 invalidated area. Returns no value. */ 5565 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ 5566 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \ 5567 _qzz_addr, _qzz_len, 0, 0, 0) 5568 5569 5570 /* These requests are for getting Valgrind itself to print something. 5571 Possibly with a backtrace. This is a really ugly hack. The return value 5572 is the number of characters printed, excluding the "**<pid>** " part at the 5573 start and the backtrace (if present). */ 5574 5575 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) 5576 /* Modern GCC will optimize the static routine out if unused, 5577 and unused attribute will shut down warnings about it. */ 5578 static int VALGRIND_PRINTF(const char *format, ...) 5579 __attribute__((format(__printf__, 1, 2), __unused__)); 5580 #endif 5581 static int 5582 #if defined(_MSC_VER) 5583 __inline 5584 #endif 5585 VALGRIND_PRINTF(const char *format, ...) 5586 { 5587 #if defined(NVALGRIND) 5588 return 0; 5589 #else /* NVALGRIND */ 5590 #if defined(_MSC_VER) || defined(__MINGW64__) 5591 uintptr_t _qzz_res; 5592 #else 5593 unsigned long _qzz_res; 5594 #endif 5595 va_list vargs; 5596 va_start(vargs, format); 5597 #if defined(_MSC_VER) || defined(__MINGW64__) 5598 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, 5599 VG_USERREQ__PRINTF_VALIST_BY_REF, 5600 (uintptr_t)format, 5601 (uintptr_t)&vargs, 5602 0, 0, 0); 5603 #else 5604 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, 5605 VG_USERREQ__PRINTF_VALIST_BY_REF, 5606 (unsigned long)format, 5607 (unsigned long)&vargs, 5608 0, 0, 0); 5609 #endif 5610 va_end(vargs); 5611 return (int)_qzz_res; 5612 #endif /* NVALGRIND */ 5613 } 5614 5615 #if defined(__GNUC__) || defined(__INTEL_COMPILER) && !defined(_MSC_VER) 5616 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 5617 __attribute__((format(__printf__, 1, 2), __unused__)); 5618 #endif 5619 static int 5620 #if defined(_MSC_VER) 5621 __inline 5622 #endif 5623 VALGRIND_PRINTF_BACKTRACE(const char *format, ...) 5624 { 5625 #if defined(NVALGRIND) 5626 return 0; 5627 #else /* NVALGRIND */ 5628 #if defined(_MSC_VER) || defined(__MINGW64__) 5629 uintptr_t _qzz_res; 5630 #else 5631 unsigned long _qzz_res; 5632 #endif 5633 va_list vargs; 5634 va_start(vargs, format); 5635 #if defined(_MSC_VER) || defined(__MINGW64__) 5636 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, 5637 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, 5638 (uintptr_t)format, 5639 (uintptr_t)&vargs, 5640 0, 0, 0); 5641 #else 5642 _qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0, 5643 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, 5644 (unsigned long)format, 5645 (unsigned long)&vargs, 5646 0, 0, 0); 5647 #endif 5648 va_end(vargs); 5649 return (int)_qzz_res; 5650 #endif /* NVALGRIND */ 5651 } 5652 5653 5654 /* These requests allow control to move from the simulated CPU to the 5655 real CPU, calling an arbitary function. 5656 5657 Note that the current ThreadId is inserted as the first argument. 5658 So this call: 5659 5660 VALGRIND_NON_SIMD_CALL2(f, arg1, arg2) 5661 5662 requires f to have this signature: 5663 5664 Word f(Word tid, Word arg1, Word arg2) 5665 5666 where "Word" is a word-sized type. 5667 5668 Note that these client requests are not entirely reliable. For example, 5669 if you call a function with them that subsequently calls printf(), 5670 there's a high chance Valgrind will crash. Generally, your prospects of 5671 these working are made higher if the called function does not refer to 5672 any global variables, and does not refer to any libc or other functions 5673 (printf et al). Any kind of entanglement with libc or dynamic linking is 5674 likely to have a bad outcome, for tricky reasons which we've grappled 5675 with a lot in the past. 5676 */ 5677 #define VALGRIND_NON_SIMD_CALL0(_qyy_fn) \ 5678 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ 5679 VG_USERREQ__CLIENT_CALL0, \ 5680 _qyy_fn, \ 5681 0, 0, 0, 0) 5682 5683 #define VALGRIND_NON_SIMD_CALL1(_qyy_fn, _qyy_arg1) \ 5684 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ 5685 VG_USERREQ__CLIENT_CALL1, \ 5686 _qyy_fn, \ 5687 _qyy_arg1, 0, 0, 0) 5688 5689 #define VALGRIND_NON_SIMD_CALL2(_qyy_fn, _qyy_arg1, _qyy_arg2) \ 5690 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ 5691 VG_USERREQ__CLIENT_CALL2, \ 5692 _qyy_fn, \ 5693 _qyy_arg1, _qyy_arg2, 0, 0) 5694 5695 #define VALGRIND_NON_SIMD_CALL3(_qyy_fn, _qyy_arg1, _qyy_arg2, _qyy_arg3) \ 5696 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \ 5697 VG_USERREQ__CLIENT_CALL3, \ 5698 _qyy_fn, \ 5699 _qyy_arg1, _qyy_arg2, \ 5700 _qyy_arg3, 0) 5701 5702 5703 /* Counts the number of errors that have been recorded by a tool. Nb: 5704 the tool must record the errors with VG_(maybe_record_error)() or 5705 VG_(unique_error)() for them to be counted. */ 5706 #define VALGRIND_COUNT_ERRORS \ 5707 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR( \ 5708 0 /* default return */, \ 5709 VG_USERREQ__COUNT_ERRORS, \ 5710 0, 0, 0, 0, 0) 5711 5712 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing 5713 when heap blocks are allocated in order to give accurate results. This 5714 happens automatically for the standard allocator functions such as 5715 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, 5716 delete[], etc. 5717 5718 But if your program uses a custom allocator, this doesn't automatically 5719 happen, and Valgrind will not do as well. For example, if you allocate 5720 superblocks with mmap() and then allocates chunks of the superblocks, all 5721 Valgrind's observations will be at the mmap() level and it won't know that 5722 the chunks should be considered separate entities. In Memcheck's case, 5723 that means you probably won't get heap block overrun detection (because 5724 there won't be redzones marked as unaddressable) and you definitely won't 5725 get any leak detection. 5726 5727 The following client requests allow a custom allocator to be annotated so 5728 that it can be handled accurately by Valgrind. 5729 5730 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated 5731 by a malloc()-like function. For Memcheck (an illustrative case), this 5732 does two things: 5733 5734 - It records that the block has been allocated. This means any addresses 5735 within the block mentioned in error messages will be 5736 identified as belonging to the block. It also means that if the block 5737 isn't freed it will be detected by the leak checker. 5738 5739 - It marks the block as being addressable and undefined (if 'is_zeroed' is 5740 not set), or addressable and defined (if 'is_zeroed' is set). This 5741 controls how accesses to the block by the program are handled. 5742 5743 'addr' is the start of the usable block (ie. after any 5744 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator 5745 can apply redzones -- these are blocks of padding at the start and end of 5746 each block. Adding redzones is recommended as it makes it much more likely 5747 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is 5748 zeroed (or filled with another predictable value), as is the case for 5749 calloc(). 5750 5751 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a 5752 heap block -- that will be used by the client program -- is allocated. 5753 It's best to put it at the outermost level of the allocator if possible; 5754 for example, if you have a function my_alloc() which calls 5755 internal_alloc(), and the client request is put inside internal_alloc(), 5756 stack traces relating to the heap block will contain entries for both 5757 my_alloc() and internal_alloc(), which is probably not what you want. 5758 5759 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out 5760 custom blocks from within a heap block, B, that has been allocated with 5761 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking 5762 -- the custom blocks will take precedence. 5763 5764 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For 5765 Memcheck, it does two things: 5766 5767 - It records that the block has been deallocated. This assumes that the 5768 block was annotated as having been allocated via 5769 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. 5770 5771 - It marks the block as being unaddressable. 5772 5773 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a 5774 heap block is deallocated. 5775 5776 VALGRIND_RESIZEINPLACE_BLOCK informs a tool about reallocation. For 5777 Memcheck, it does four things: 5778 5779 - It records that the size of a block has been changed. This assumes that 5780 the block was annotated as having been allocated via 5781 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. 5782 5783 - If the block shrunk, it marks the freed memory as being unaddressable. 5784 5785 - If the block grew, it marks the new area as undefined and defines a red 5786 zone past the end of the new block. 5787 5788 - The V-bits of the overlap between the old and the new block are preserved. 5789 5790 VALGRIND_RESIZEINPLACE_BLOCK should be put after allocation of the new block 5791 and before deallocation of the old block. 5792 5793 In many cases, these three client requests will not be enough to get your 5794 allocator working well with Memcheck. More specifically, if your allocator 5795 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call 5796 will be necessary to mark the memory as addressable just before the zeroing 5797 occurs, otherwise you'll get a lot of invalid write errors. For example, 5798 you'll need to do this if your allocator recycles freed blocks, but it 5799 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). 5800 Alternatively, if your allocator reuses freed blocks for allocator-internal 5801 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. 5802 5803 Really, what's happening is a blurring of the lines between the client 5804 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the 5805 memory should be considered unaddressable to the client program, but the 5806 allocator knows more than the rest of the client program and so may be able 5807 to safely access it. Extra client requests are necessary for Valgrind to 5808 understand the distinction between the allocator and the rest of the 5809 program. 5810 5811 Ignored if addr == 0. 5812 */ 5813 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ 5814 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MALLOCLIKE_BLOCK, \ 5815 addr, sizeB, rzB, is_zeroed, 0) 5816 5817 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. 5818 Ignored if addr == 0. 5819 */ 5820 #define VALGRIND_RESIZEINPLACE_BLOCK(addr, oldSizeB, newSizeB, rzB) \ 5821 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__RESIZEINPLACE_BLOCK, \ 5822 addr, oldSizeB, newSizeB, rzB, 0) 5823 5824 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. 5825 Ignored if addr == 0. 5826 */ 5827 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ 5828 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__FREELIKE_BLOCK, \ 5829 addr, rzB, 0, 0, 0) 5830 5831 /* Create a memory pool. */ 5832 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ 5833 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CREATE_MEMPOOL, \ 5834 pool, rzB, is_zeroed, 0, 0) 5835 5836 /* Destroy a memory pool. */ 5837 #define VALGRIND_DESTROY_MEMPOOL(pool) \ 5838 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DESTROY_MEMPOOL, \ 5839 pool, 0, 0, 0, 0) 5840 5841 /* Associate a piece of memory with a memory pool. */ 5842 #define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) \ 5843 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_ALLOC, \ 5844 pool, addr, size, 0, 0) 5845 5846 /* Disassociate a piece of memory from a memory pool. */ 5847 #define VALGRIND_MEMPOOL_FREE(pool, addr) \ 5848 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_FREE, \ 5849 pool, addr, 0, 0, 0) 5850 5851 /* Disassociate any pieces outside a particular range. */ 5852 #define VALGRIND_MEMPOOL_TRIM(pool, addr, size) \ 5853 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_TRIM, \ 5854 pool, addr, size, 0, 0) 5855 5856 /* Resize and/or move a piece associated with a memory pool. */ 5857 #define VALGRIND_MOVE_MEMPOOL(poolA, poolB) \ 5858 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MOVE_MEMPOOL, \ 5859 poolA, poolB, 0, 0, 0) 5860 5861 /* Resize and/or move a piece associated with a memory pool. */ 5862 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ 5863 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__MEMPOOL_CHANGE, \ 5864 pool, addrA, addrB, size, 0) 5865 5866 /* Return 1 if a mempool exists, else 0. */ 5867 #define VALGRIND_MEMPOOL_EXISTS(pool) \ 5868 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 5869 VG_USERREQ__MEMPOOL_EXISTS, \ 5870 pool, 0, 0, 0, 0) 5871 5872 /* Mark a piece of memory as being a stack. Returns a stack id. */ 5873 #define VALGRIND_STACK_REGISTER(start, end) \ 5874 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 5875 VG_USERREQ__STACK_REGISTER, \ 5876 start, end, 0, 0, 0) 5877 5878 /* Unmark the piece of memory associated with a stack id as being a 5879 stack. */ 5880 #define VALGRIND_STACK_DEREGISTER(id) \ 5881 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_DEREGISTER, \ 5882 id, 0, 0, 0, 0) 5883 5884 /* Change the start and end address of the stack id. */ 5885 #define VALGRIND_STACK_CHANGE(id, start, end) \ 5886 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__STACK_CHANGE, \ 5887 id, start, end, 0, 0) 5888 5889 /* Load PDB debug info for Wine PE image_map. */ 5890 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ 5891 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__LOAD_PDB_DEBUGINFO, \ 5892 fd, ptr, total_size, delta, 0) 5893 5894 /* Map a code address to a source file name and line number. buf64 5895 must point to a 64-byte buffer in the caller's address space. The 5896 result will be dumped in there and is guaranteed to be zero 5897 terminated. If no info is found, the first byte is set to zero. */ 5898 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ 5899 (unsigned)VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \ 5900 VG_USERREQ__MAP_IP_TO_SRCLOC, \ 5901 addr, buf64, 0, 0, 0) 5902 5903 /* Disable error reporting for this thread. Behaves in a stack like 5904 way, so you can safely call this multiple times provided that 5905 VALGRIND_ENABLE_ERROR_REPORTING is called the same number of times 5906 to re-enable reporting. The first call of this macro disables 5907 reporting. Subsequent calls have no effect except to increase the 5908 number of VALGRIND_ENABLE_ERROR_REPORTING calls needed to re-enable 5909 reporting. Child threads do not inherit this setting from their 5910 parents -- they are always created with reporting enabled. */ 5911 #define VALGRIND_DISABLE_ERROR_REPORTING \ 5912 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ 5913 1, 0, 0, 0, 0) 5914 5915 /* Re-enable error reporting, as per comments on 5916 VALGRIND_DISABLE_ERROR_REPORTING. */ 5917 #define VALGRIND_ENABLE_ERROR_REPORTING \ 5918 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__CHANGE_ERR_DISABLEMENT, \ 5919 -1, 0, 0, 0, 0) 5920 5921 /* Execute a monitor command from the client program. 5922 If a connection is opened with GDB, the output will be sent 5923 according to the output mode set for vgdb. 5924 If no connection is opened, output will go to the log output. 5925 Returns 1 if command not recognised, 0 otherwise. */ 5926 #define VALGRIND_MONITOR_COMMAND(command) \ 5927 VALGRIND_DO_CLIENT_REQUEST_EXPR(0, VG_USERREQ__GDB_MONITOR_COMMAND, \ 5928 command, 0, 0, 0, 0) 5929 5930 5931 #undef PLAT_x86_darwin 5932 #undef PLAT_amd64_darwin 5933 #undef PLAT_x86_win32 5934 #undef PLAT_amd64_win64 5935 #undef PLAT_x86_linux 5936 #undef PLAT_amd64_linux 5937 #undef PLAT_ppc32_linux 5938 #undef PLAT_ppc64_linux 5939 #undef PLAT_arm_linux 5940 #undef PLAT_s390x_linux 5941 #undef PLAT_mips32_linux 5942 #undef PLAT_mips64_linux 5943 5944 #endif /* __VALGRIND_H */ 5945