| OLD | NEW |
| 1 /* -*- c -*- | 1 /* -*- c -*- |
| 2 ---------------------------------------------------------------- | 2 ---------------------------------------------------------------- |
| 3 | 3 |
| 4 Notice that the following BSD-style license applies to this one | 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 | 5 file (valgrind.h) only. The rest of Valgrind is licensed under the |
| 6 terms of the GNU General Public License, version 2, unless | 6 terms of the GNU General Public License, version 2, unless |
| 7 otherwise indicated. See the COPYING file in the source | 7 otherwise indicated. See the COPYING file in the source |
| 8 distribution for details. | 8 distribution for details. |
| 9 | 9 |
| 10 ---------------------------------------------------------------- | 10 ---------------------------------------------------------------- |
| 11 | 11 |
| 12 This file is part of Valgrind, a dynamic binary instrumentation | 12 This file is part of Valgrind, a dynamic binary instrumentation |
| 13 framework. | 13 framework. |
| 14 | 14 |
| 15 Copyright (C) 2000-2008 Julian Seward. All rights reserved. | 15 Copyright (C) 2000-2010 Julian Seward. All rights reserved. |
| 16 | 16 |
| 17 Redistribution and use in source and binary forms, with or without | 17 Redistribution and use in source and binary forms, with or without |
| 18 modification, are permitted provided that the following conditions | 18 modification, are permitted provided that the following conditions |
| 19 are met: | 19 are met: |
| 20 | 20 |
| 21 1. Redistributions of source code must retain the above copyright | 21 1. Redistributions of source code must retain the above copyright |
| 22 notice, this list of conditions and the following disclaimer. | 22 notice, this list of conditions and the following disclaimer. |
| 23 | 23 |
| 24 2. The origin of this software must not be misrepresented; you must | 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 | 25 not claim that you wrote the original software. If you use this |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 unchanged. When not running on valgrind, each client request | 66 unchanged. When not running on valgrind, each client request |
| 67 consumes very few (eg. 7) instructions, so the resulting performance | 67 consumes very few (eg. 7) instructions, so the resulting performance |
| 68 loss is negligible unless you plan to execute client requests | 68 loss is negligible unless you plan to execute client requests |
| 69 millions of times per second. Nevertheless, if that is still a | 69 millions of times per second. Nevertheless, if that is still a |
| 70 problem, you can compile with the NVALGRIND symbol defined (gcc | 70 problem, you can compile with the NVALGRIND symbol defined (gcc |
| 71 -DNVALGRIND) so that client requests are not even compiled in. */ | 71 -DNVALGRIND) so that client requests are not even compiled in. */ |
| 72 | 72 |
| 73 #ifndef __VALGRIND_H | 73 #ifndef __VALGRIND_H |
| 74 #define __VALGRIND_H | 74 #define __VALGRIND_H |
| 75 | 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__ 6 |
| 93 |
| 94 |
| 76 #include <stdarg.h> | 95 #include <stdarg.h> |
| 77 | 96 |
| 78 /* Nb: this file might be included in a file compiled with -ansi. So | 97 /* Nb: this file might be included in a file compiled with -ansi. So |
| 79 we can't use C++ style "//" comments nor the "asm" keyword (instead | 98 we can't use C++ style "//" comments nor the "asm" keyword (instead |
| 80 use "__asm__"). */ | 99 use "__asm__"). */ |
| 81 | 100 |
| 82 /* Derive some tags indicating what the target platform is. Note | 101 /* Derive some tags indicating what the target platform is. Note |
| 83 that in this file we're using the compiler's CPP symbols for | 102 that in this file we're using the compiler's CPP symbols for |
| 84 identifying architectures, which are different to the ones we use | 103 identifying architectures, which are different to the ones we use |
| 85 within the rest of Valgrind. Note, __powerpc__ is active for both | 104 within the rest of Valgrind. Note, __powerpc__ is active for both |
| 86 32 and 64-bit PPC, whereas __powerpc64__ is only active for the | 105 32 and 64-bit PPC, whereas __powerpc64__ is only active for the |
| 87 latter (on Linux, that is). */ | 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_ppc64_aix5 |
| 112 #undef PLAT_ppc32_aix5 |
| 113 #undef PLAT_x86_darwin |
| 114 #undef PLAT_amd64_darwin |
| 115 #undef PLAT_x86_win32 |
| 88 #undef PLAT_x86_linux | 116 #undef PLAT_x86_linux |
| 89 #undef PLAT_amd64_linux | 117 #undef PLAT_amd64_linux |
| 90 #undef PLAT_ppc32_linux | 118 #undef PLAT_ppc32_linux |
| 91 #undef PLAT_ppc64_linux | 119 #undef PLAT_ppc64_linux |
| 92 #undef PLAT_ppc32_aix5 | 120 #undef PLAT_arm_linux |
| 93 #undef PLAT_ppc64_aix5 | |
| 94 | 121 |
| 95 #if !defined(_AIX) && defined(__i386__) | 122 #if defined(_AIX) && defined(__64BIT__) |
| 96 # define PLAT_x86_linux 1 | |
| 97 #elif !defined(_AIX) && defined(__x86_64__) | |
| 98 # define PLAT_amd64_linux 1 | |
| 99 #elif !defined(_AIX) && defined(__powerpc__) && !defined(__powerpc64__) | |
| 100 # define PLAT_ppc32_linux 1 | |
| 101 #elif !defined(_AIX) && defined(__powerpc__) && defined(__powerpc64__) | |
| 102 # define PLAT_ppc64_linux 1 | |
| 103 #elif defined(_AIX) && defined(__64BIT__) | |
| 104 # define PLAT_ppc64_aix5 1 | 123 # define PLAT_ppc64_aix5 1 |
| 105 #elif defined(_AIX) && !defined(__64BIT__) | 124 #elif defined(_AIX) && !defined(__64BIT__) |
| 106 # define PLAT_ppc32_aix5 1 | 125 # define PLAT_ppc32_aix5 1 |
| 107 #endif | 126 #elif defined(__APPLE__) && defined(__i386__) |
| 108 | 127 # define PLAT_x86_darwin 1 |
| 109 | 128 #elif defined(__APPLE__) && defined(__x86_64__) |
| 129 # define PLAT_amd64_darwin 1 |
| 130 #elif defined(__MINGW32__) || defined(__CYGWIN32__) || defined(_WIN32) && define
d(_M_IX86) |
| 131 # define PLAT_x86_win32 1 |
| 132 #elif defined(__linux__) && defined(__i386__) |
| 133 # define PLAT_x86_linux 1 |
| 134 #elif defined(__linux__) && defined(__x86_64__) |
| 135 # define PLAT_amd64_linux 1 |
| 136 #elif defined(__linux__) && defined(__powerpc__) && !defined(__powerpc64__) |
| 137 # define PLAT_ppc32_linux 1 |
| 138 #elif defined(__linux__) && defined(__powerpc__) && defined(__powerpc64__) |
| 139 # define PLAT_ppc64_linux 1 |
| 140 #elif defined(__linux__) && defined(__arm__) |
| 141 # define PLAT_arm_linux 1 |
| 142 #else |
| 110 /* If we're not compiling for our target platform, don't generate | 143 /* If we're not compiling for our target platform, don't generate |
| 111 any inline asms. */ | 144 any inline asms. */ |
| 112 #if !defined(PLAT_x86_linux) && !defined(PLAT_amd64_linux) \ | |
| 113 && !defined(PLAT_ppc32_linux) && !defined(PLAT_ppc64_linux) \ | |
| 114 && !defined(PLAT_ppc32_aix5) && !defined(PLAT_ppc64_aix5) | |
| 115 # if !defined(NVALGRIND) | 145 # if !defined(NVALGRIND) |
| 116 # define NVALGRIND 1 | 146 # define NVALGRIND 1 |
| 117 # endif | 147 # endif |
| 118 #endif | 148 #endif |
| 119 | 149 |
| 120 | 150 |
| 121 /* ------------------------------------------------------------------ */ | 151 /* ------------------------------------------------------------------ */ |
| 122 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ | 152 /* ARCHITECTURE SPECIFICS for SPECIAL INSTRUCTIONS. There is nothing */ |
| 123 /* in here of use to end-users -- skip to the next section. */ | 153 /* in here of use to end-users -- skip to the next section. */ |
| 124 /* ------------------------------------------------------------------ */ | 154 /* ------------------------------------------------------------------ */ |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 information is abstracted into a user-visible type, OrigFn. | 195 information is abstracted into a user-visible type, OrigFn. |
| 166 | 196 |
| 167 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the | 197 VALGRIND_CALL_NOREDIR_* behaves the same as the following on the |
| 168 guest, but guarantees that the branch instruction will not be | 198 guest, but guarantees that the branch instruction will not be |
| 169 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: | 199 redirected: x86: call *%eax, amd64: call *%rax, ppc32/ppc64: |
| 170 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a | 200 branch-and-link-to-r11. VALGRIND_CALL_NOREDIR is just text, not a |
| 171 complete inline asm, since it needs to be combined with more magic | 201 complete inline asm, since it needs to be combined with more magic |
| 172 inline asm stuff to be useful. | 202 inline asm stuff to be useful. |
| 173 */ | 203 */ |
| 174 | 204 |
| 175 /* ------------------------- x86-linux ------------------------- */ | 205 /* ------------------------- x86-{linux,darwin} ---------------- */ |
| 176 | 206 |
| 177 #if defined(PLAT_x86_linux) | 207 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) \ |
| 208 || (defined(PLAT_x86_win32) && defined(__GNUC__)) |
| 178 | 209 |
| 179 typedef | 210 typedef |
| 180 struct { | 211 struct { |
| 181 unsigned int nraddr; /* where's the code? */ | 212 unsigned int nraddr; /* where's the code? */ |
| 182 } | 213 } |
| 183 OrigFn; | 214 OrigFn; |
| 184 | 215 |
| 185 #define __SPECIAL_INSTRUCTION_PREAMBLE \ | 216 #define __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 186 "roll $3, %%edi ; roll $13, %%edi\n\t" \ | 217 "roll $3, %%edi ; roll $13, %%edi\n\t" \ |
| 187 "roll $29, %%edi ; roll $19, %%edi\n\t" | 218 "roll $29, %%edi ; roll $19, %%edi\n\t" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 217 : \ | 248 : \ |
| 218 : "cc", "memory" \ | 249 : "cc", "memory" \ |
| 219 ); \ | 250 ); \ |
| 220 _zzq_orig->nraddr = __addr; \ | 251 _zzq_orig->nraddr = __addr; \ |
| 221 } | 252 } |
| 222 | 253 |
| 223 #define VALGRIND_CALL_NOREDIR_EAX \ | 254 #define VALGRIND_CALL_NOREDIR_EAX \ |
| 224 __SPECIAL_INSTRUCTION_PREAMBLE \ | 255 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 225 /* call-noredir *%EAX */ \ | 256 /* call-noredir *%EAX */ \ |
| 226 "xchgl %%edx,%%edx\n\t" | 257 "xchgl %%edx,%%edx\n\t" |
| 227 #endif /* PLAT_x86_linux */ | 258 #endif /* PLAT_x86_linux || PLAT_x86_darwin || (PLAT_x86_win32 && __GNUC__) */ |
| 228 | 259 |
| 229 /* ------------------------ amd64-linux ------------------------ */ | 260 /* ------------------------- x86-Win32 ------------------------- */ |
| 230 | 261 |
| 231 #if defined(PLAT_amd64_linux) | 262 #if defined(PLAT_x86_win32) && !defined(__GNUC__) |
| 263 |
| 264 typedef |
| 265 struct { |
| 266 unsigned int nraddr; /* where's the code? */ |
| 267 } |
| 268 OrigFn; |
| 269 |
| 270 #if defined(_MSC_VER) |
| 271 |
| 272 #define __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 273 __asm rol edi, 3 __asm rol edi, 13 \ |
| 274 __asm rol edi, 29 __asm rol edi, 19 |
| 275 |
| 276 #define VALGRIND_DO_CLIENT_REQUEST( \ |
| 277 _zzq_rlval, _zzq_default, _zzq_request, \ |
| 278 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 279 { volatile uintptr_t _zzq_args[6]; \ |
| 280 volatile unsigned int _zzq_result; \ |
| 281 _zzq_args[0] = (uintptr_t)(_zzq_request); \ |
| 282 _zzq_args[1] = (uintptr_t)(_zzq_arg1); \ |
| 283 _zzq_args[2] = (uintptr_t)(_zzq_arg2); \ |
| 284 _zzq_args[3] = (uintptr_t)(_zzq_arg3); \ |
| 285 _zzq_args[4] = (uintptr_t)(_zzq_arg4); \ |
| 286 _zzq_args[5] = (uintptr_t)(_zzq_arg5); \ |
| 287 __asm { __asm lea eax, _zzq_args __asm mov edx, _zzq_default \ |
| 288 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 289 /* %EDX = client_request ( %EAX ) */ \ |
| 290 __asm xchg ebx,ebx \ |
| 291 __asm mov _zzq_result, edx \ |
| 292 } \ |
| 293 _zzq_rlval = _zzq_result; \ |
| 294 } |
| 295 |
| 296 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ |
| 297 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ |
| 298 volatile unsigned int __addr; \ |
| 299 __asm { __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 300 /* %EAX = guest_NRADDR */ \ |
| 301 __asm xchg ecx,ecx \ |
| 302 __asm mov __addr, eax \ |
| 303 } \ |
| 304 _zzq_orig->nraddr = __addr; \ |
| 305 } |
| 306 |
| 307 #define VALGRIND_CALL_NOREDIR_EAX ERROR |
| 308 |
| 309 #else |
| 310 #error Unsupported compiler. |
| 311 #endif |
| 312 |
| 313 #endif /* PLAT_x86_win32 */ |
| 314 |
| 315 /* ------------------------ amd64-{linux,darwin} --------------- */ |
| 316 |
| 317 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) |
| 232 | 318 |
| 233 typedef | 319 typedef |
| 234 struct { | 320 struct { |
| 235 unsigned long long int nraddr; /* where's the code? */ | 321 unsigned long long int nraddr; /* where's the code? */ |
| 236 } | 322 } |
| 237 OrigFn; | 323 OrigFn; |
| 238 | 324 |
| 239 #define __SPECIAL_INSTRUCTION_PREAMBLE \ | 325 #define __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 240 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ | 326 "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ |
| 241 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" | 327 "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 271 : \ | 357 : \ |
| 272 : "cc", "memory" \ | 358 : "cc", "memory" \ |
| 273 ); \ | 359 ); \ |
| 274 _zzq_orig->nraddr = __addr; \ | 360 _zzq_orig->nraddr = __addr; \ |
| 275 } | 361 } |
| 276 | 362 |
| 277 #define VALGRIND_CALL_NOREDIR_RAX \ | 363 #define VALGRIND_CALL_NOREDIR_RAX \ |
| 278 __SPECIAL_INSTRUCTION_PREAMBLE \ | 364 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 279 /* call-noredir *%RAX */ \ | 365 /* call-noredir *%RAX */ \ |
| 280 "xchgq %%rdx,%%rdx\n\t" | 366 "xchgq %%rdx,%%rdx\n\t" |
| 281 #endif /* PLAT_amd64_linux */ | 367 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ |
| 282 | 368 |
| 283 /* ------------------------ ppc32-linux ------------------------ */ | 369 /* ------------------------ ppc32-linux ------------------------ */ |
| 284 | 370 |
| 285 #if defined(PLAT_ppc32_linux) | 371 #if defined(PLAT_ppc32_linux) |
| 286 | 372 |
| 287 typedef | 373 typedef |
| 288 struct { | 374 struct { |
| 289 unsigned int nraddr; /* where's the code? */ | 375 unsigned int nraddr; /* where's the code? */ |
| 290 } | 376 } |
| 291 OrigFn; | 377 OrigFn; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 399 _zzq_orig->r2 = __addr; \ | 485 _zzq_orig->r2 = __addr; \ |
| 400 } | 486 } |
| 401 | 487 |
| 402 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ | 488 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ |
| 403 __SPECIAL_INSTRUCTION_PREAMBLE \ | 489 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 404 /* branch-and-link-to-noredir *%R11 */ \ | 490 /* branch-and-link-to-noredir *%R11 */ \ |
| 405 "or 3,3,3\n\t" | 491 "or 3,3,3\n\t" |
| 406 | 492 |
| 407 #endif /* PLAT_ppc64_linux */ | 493 #endif /* PLAT_ppc64_linux */ |
| 408 | 494 |
| 495 /* ------------------------- arm-linux ------------------------- */ |
| 496 |
| 497 #if defined(PLAT_arm_linux) |
| 498 |
| 499 typedef |
| 500 struct { |
| 501 unsigned int nraddr; /* where's the code? */ |
| 502 } |
| 503 OrigFn; |
| 504 |
| 505 #define __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 506 "mov r12, r12, ror #3 ; mov r12, r12, ror #13 \n\t" \ |
| 507 "mov r12, r12, ror #29 ; mov r12, r12, ror #19 \n\t" |
| 508 |
| 509 #define VALGRIND_DO_CLIENT_REQUEST( \ |
| 510 _zzq_rlval, _zzq_default, _zzq_request, \ |
| 511 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 512 \ |
| 513 { volatile unsigned int _zzq_args[6]; \ |
| 514 volatile unsigned int _zzq_result; \ |
| 515 _zzq_args[0] = (unsigned int)(_zzq_request); \ |
| 516 _zzq_args[1] = (unsigned int)(_zzq_arg1); \ |
| 517 _zzq_args[2] = (unsigned int)(_zzq_arg2); \ |
| 518 _zzq_args[3] = (unsigned int)(_zzq_arg3); \ |
| 519 _zzq_args[4] = (unsigned int)(_zzq_arg4); \ |
| 520 _zzq_args[5] = (unsigned int)(_zzq_arg5); \ |
| 521 __asm__ volatile("mov r3, %1\n\t" /*default*/ \ |
| 522 "mov r4, %2\n\t" /*ptr*/ \ |
| 523 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 524 /* R3 = client_request ( R4 ) */ \ |
| 525 "orr r10, r10, r10\n\t" \ |
| 526 "mov %0, r3" /*result*/ \ |
| 527 : "=r" (_zzq_result) \ |
| 528 : "r" (_zzq_default), "r" (&_zzq_args[0]) \ |
| 529 : "cc","memory", "r3", "r4"); \ |
| 530 _zzq_rlval = _zzq_result; \ |
| 531 } |
| 532 |
| 533 #define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \ |
| 534 { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \ |
| 535 unsigned int __addr; \ |
| 536 __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ |
| 537 /* R3 = guest_NRADDR */ \ |
| 538 "orr r11, r11, r11\n\t" \ |
| 539 "mov %0, r3" \ |
| 540 : "=r" (__addr) \ |
| 541 : \ |
| 542 : "cc", "memory", "r3" \ |
| 543 ); \ |
| 544 _zzq_orig->nraddr = __addr; \ |
| 545 } |
| 546 |
| 547 #define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 548 __SPECIAL_INSTRUCTION_PREAMBLE \ |
| 549 /* branch-and-link-to-noredir *%R4 */ \ |
| 550 "orr r12, r12, r12\n\t" |
| 551 |
| 552 #endif /* PLAT_arm_linux */ |
| 553 |
| 409 /* ------------------------ ppc32-aix5 ------------------------- */ | 554 /* ------------------------ ppc32-aix5 ------------------------- */ |
| 410 | 555 |
| 411 #if defined(PLAT_ppc32_aix5) | 556 #if defined(PLAT_ppc32_aix5) |
| 412 | 557 |
| 413 typedef | 558 typedef |
| 414 struct { | 559 struct { |
| 415 unsigned int nraddr; /* where's the code? */ | 560 unsigned int nraddr; /* where's the code? */ |
| 416 unsigned int r2; /* what tocptr do we need? */ | 561 unsigned int r2; /* what tocptr do we need? */ |
| 417 } | 562 } |
| 418 OrigFn; | 563 OrigFn; |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 | 719 |
| 575 'W' stands for "word" and 'v' for "void". Hence there are | 720 'W' stands for "word" and 'v' for "void". Hence there are |
| 576 different macros for calling arity 0, 1, 2, 3, 4, etc, functions, | 721 different macros for calling arity 0, 1, 2, 3, 4, etc, functions, |
| 577 and for each, the possibility of returning a word-typed result, or | 722 and for each, the possibility of returning a word-typed result, or |
| 578 no result. | 723 no result. |
| 579 */ | 724 */ |
| 580 | 725 |
| 581 /* Use these to write the name of your wrapper. NOTE: duplicates | 726 /* Use these to write the name of your wrapper. NOTE: duplicates |
| 582 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ | 727 VG_WRAP_FUNCTION_Z{U,Z} in pub_tool_redir.h. */ |
| 583 | 728 |
| 729 /* Use an extra level of macroisation so as to ensure the soname/fnname |
| 730 args are fully macro-expanded before pasting them together. */ |
| 731 #define VG_CONCAT4(_aa,_bb,_cc,_dd) _aa##_bb##_cc##_dd |
| 732 |
| 584 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ | 733 #define I_WRAP_SONAME_FNNAME_ZU(soname,fnname) \ |
| 585 _vgwZU_##soname##_##fnname | 734 VG_CONCAT4(_vgwZU_,soname,_,fnname) |
| 586 | 735 |
| 587 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ | 736 #define I_WRAP_SONAME_FNNAME_ZZ(soname,fnname) \ |
| 588 _vgwZZ_##soname##_##fnname | 737 VG_CONCAT4(_vgwZZ_,soname,_,fnname) |
| 589 | 738 |
| 590 /* Use this macro from within a wrapper function to collect the | 739 /* Use this macro from within a wrapper function to collect the |
| 591 context (address and possibly other info) of the original function. | 740 context (address and possibly other info) of the original function. |
| 592 Once you have that you can then use it in one of the CALL_FN_ | 741 Once you have that you can then use it in one of the CALL_FN_ |
| 593 macros. The type of the argument _lval is OrigFn. */ | 742 macros. The type of the argument _lval is OrigFn. */ |
| 594 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) | 743 #define VALGRIND_GET_ORIG_FN(_lval) VALGRIND_GET_NR_CONTEXT(_lval) |
| 595 | 744 |
| 596 /* Derivatives of the main macros below, for calling functions | 745 /* Derivatives of the main macros below, for calling functions |
| 597 returning void. */ | 746 returning void. */ |
| 598 | 747 |
| 599 #define CALL_FN_v_v(fnptr) \ | 748 #define CALL_FN_v_v(fnptr) \ |
| 600 do { volatile unsigned long _junk; \ | 749 do { volatile unsigned long _junk; \ |
| 601 CALL_FN_W_v(_junk,fnptr); } while (0) | 750 CALL_FN_W_v(_junk,fnptr); } while (0) |
| 602 | 751 |
| 603 #define CALL_FN_v_W(fnptr, arg1) \ | 752 #define CALL_FN_v_W(fnptr, arg1) \ |
| 604 do { volatile unsigned long _junk; \ | 753 do { volatile unsigned long _junk; \ |
| 605 CALL_FN_W_W(_junk,fnptr,arg1); } while (0) | 754 CALL_FN_W_W(_junk,fnptr,arg1); } while (0) |
| 606 | 755 |
| 607 #define CALL_FN_v_WW(fnptr, arg1,arg2) \ | 756 #define CALL_FN_v_WW(fnptr, arg1,arg2) \ |
| 608 do { volatile unsigned long _junk; \ | 757 do { volatile unsigned long _junk; \ |
| 609 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) | 758 CALL_FN_W_WW(_junk,fnptr,arg1,arg2); } while (0) |
| 610 | 759 |
| 611 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ | 760 #define CALL_FN_v_WWW(fnptr, arg1,arg2,arg3) \ |
| 612 do { volatile unsigned long _junk; \ | 761 do { volatile unsigned long _junk; \ |
| 613 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) | 762 CALL_FN_W_WWW(_junk,fnptr,arg1,arg2,arg3); } while (0) |
| 614 | 763 |
| 615 /* ------------------------- x86-linux ------------------------- */ | 764 #define CALL_FN_v_WWWW(fnptr, arg1,arg2,arg3,arg4) \ |
| 765 do { volatile unsigned long _junk; \ |
| 766 CALL_FN_W_WWWW(_junk,fnptr,arg1,arg2,arg3,arg4); } while (0) |
| 616 | 767 |
| 617 #if defined(PLAT_x86_linux) | 768 #define CALL_FN_v_5W(fnptr, arg1,arg2,arg3,arg4,arg5) \ |
| 769 do { volatile unsigned long _junk; \ |
| 770 CALL_FN_W_5W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5); } while (0) |
| 771 |
| 772 #define CALL_FN_v_6W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6) \ |
| 773 do { volatile unsigned long _junk; \ |
| 774 CALL_FN_W_6W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6); } while (0) |
| 775 |
| 776 #define CALL_FN_v_7W(fnptr, arg1,arg2,arg3,arg4,arg5,arg6,arg7) \ |
| 777 do { volatile unsigned long _junk; \ |
| 778 CALL_FN_W_7W(_junk,fnptr,arg1,arg2,arg3,arg4,arg5,arg6,arg7); } while (0
) |
| 779 |
| 780 /* ------------------------- x86-{linux,darwin} ---------------- */ |
| 781 |
| 782 #if defined(PLAT_x86_linux) || defined(PLAT_x86_darwin) |
| 618 | 783 |
| 619 /* These regs are trashed by the hidden call. No need to mention eax | 784 /* These regs are trashed by the hidden call. No need to mention eax |
| 620 as gcc can already see that, plus causes gcc to bomb. */ | 785 as gcc can already see that, plus causes gcc to bomb. */ |
| 621 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" | 786 #define __CALLER_SAVED_REGS /*"eax"*/ "ecx", "edx" |
| 622 | 787 |
| 623 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned | 788 /* These CALL_FN_ macros assume that on x86-linux, sizeof(unsigned |
| 624 long) == 4. */ | 789 long) == 4. */ |
| 625 | 790 |
| 626 #define CALL_FN_W_v(lval, orig) \ | 791 #define CALL_FN_W_v(lval, orig) \ |
| 627 do { \ | 792 do { \ |
| (...skipping 12 matching lines...) Expand all Loading... |
| 640 } while (0) | 805 } while (0) |
| 641 | 806 |
| 642 #define CALL_FN_W_W(lval, orig, arg1) \ | 807 #define CALL_FN_W_W(lval, orig, arg1) \ |
| 643 do { \ | 808 do { \ |
| 644 volatile OrigFn _orig = (orig); \ | 809 volatile OrigFn _orig = (orig); \ |
| 645 volatile unsigned long _argvec[2]; \ | 810 volatile unsigned long _argvec[2]; \ |
| 646 volatile unsigned long _res; \ | 811 volatile unsigned long _res; \ |
| 647 _argvec[0] = (unsigned long)_orig.nraddr; \ | 812 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 648 _argvec[1] = (unsigned long)(arg1); \ | 813 _argvec[1] = (unsigned long)(arg1); \ |
| 649 __asm__ volatile( \ | 814 __asm__ volatile( \ |
| 815 "subl $12, %%esp\n\t" \ |
| 650 "pushl 4(%%eax)\n\t" \ | 816 "pushl 4(%%eax)\n\t" \ |
| 651 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 817 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 652 VALGRIND_CALL_NOREDIR_EAX \ | 818 VALGRIND_CALL_NOREDIR_EAX \ |
| 653 "addl $4, %%esp\n" \ | 819 "addl $16, %%esp\n" \ |
| 654 : /*out*/ "=a" (_res) \ | 820 : /*out*/ "=a" (_res) \ |
| 655 : /*in*/ "a" (&_argvec[0]) \ | 821 : /*in*/ "a" (&_argvec[0]) \ |
| 656 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 822 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 657 ); \ | 823 ); \ |
| 658 lval = (__typeof__(lval)) _res; \ | 824 lval = (__typeof__(lval)) _res; \ |
| 659 } while (0) | 825 } while (0) |
| 660 | 826 |
| 661 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ | 827 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ |
| 662 do { \ | 828 do { \ |
| 663 volatile OrigFn _orig = (orig); \ | 829 volatile OrigFn _orig = (orig); \ |
| 664 volatile unsigned long _argvec[3]; \ | 830 volatile unsigned long _argvec[3]; \ |
| 665 volatile unsigned long _res; \ | 831 volatile unsigned long _res; \ |
| 666 _argvec[0] = (unsigned long)_orig.nraddr; \ | 832 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 667 _argvec[1] = (unsigned long)(arg1); \ | 833 _argvec[1] = (unsigned long)(arg1); \ |
| 668 _argvec[2] = (unsigned long)(arg2); \ | 834 _argvec[2] = (unsigned long)(arg2); \ |
| 669 __asm__ volatile( \ | 835 __asm__ volatile( \ |
| 836 "subl $8, %%esp\n\t" \ |
| 670 "pushl 8(%%eax)\n\t" \ | 837 "pushl 8(%%eax)\n\t" \ |
| 671 "pushl 4(%%eax)\n\t" \ | 838 "pushl 4(%%eax)\n\t" \ |
| 672 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 839 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 673 VALGRIND_CALL_NOREDIR_EAX \ | 840 VALGRIND_CALL_NOREDIR_EAX \ |
| 674 "addl $8, %%esp\n" \ | 841 "addl $16, %%esp\n" \ |
| 675 : /*out*/ "=a" (_res) \ | 842 : /*out*/ "=a" (_res) \ |
| 676 : /*in*/ "a" (&_argvec[0]) \ | 843 : /*in*/ "a" (&_argvec[0]) \ |
| 677 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 844 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 678 ); \ | 845 ); \ |
| 679 lval = (__typeof__(lval)) _res; \ | 846 lval = (__typeof__(lval)) _res; \ |
| 680 } while (0) | 847 } while (0) |
| 681 | 848 |
| 682 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ | 849 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ |
| 683 do { \ | 850 do { \ |
| 684 volatile OrigFn _orig = (orig); \ | 851 volatile OrigFn _orig = (orig); \ |
| 685 volatile unsigned long _argvec[4]; \ | 852 volatile unsigned long _argvec[4]; \ |
| 686 volatile unsigned long _res; \ | 853 volatile unsigned long _res; \ |
| 687 _argvec[0] = (unsigned long)_orig.nraddr; \ | 854 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 688 _argvec[1] = (unsigned long)(arg1); \ | 855 _argvec[1] = (unsigned long)(arg1); \ |
| 689 _argvec[2] = (unsigned long)(arg2); \ | 856 _argvec[2] = (unsigned long)(arg2); \ |
| 690 _argvec[3] = (unsigned long)(arg3); \ | 857 _argvec[3] = (unsigned long)(arg3); \ |
| 691 __asm__ volatile( \ | 858 __asm__ volatile( \ |
| 859 "subl $4, %%esp\n\t" \ |
| 692 "pushl 12(%%eax)\n\t" \ | 860 "pushl 12(%%eax)\n\t" \ |
| 693 "pushl 8(%%eax)\n\t" \ | 861 "pushl 8(%%eax)\n\t" \ |
| 694 "pushl 4(%%eax)\n\t" \ | 862 "pushl 4(%%eax)\n\t" \ |
| 695 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 863 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 696 VALGRIND_CALL_NOREDIR_EAX \ | 864 VALGRIND_CALL_NOREDIR_EAX \ |
| 697 "addl $12, %%esp\n" \ | 865 "addl $16, %%esp\n" \ |
| 698 : /*out*/ "=a" (_res) \ | 866 : /*out*/ "=a" (_res) \ |
| 699 : /*in*/ "a" (&_argvec[0]) \ | 867 : /*in*/ "a" (&_argvec[0]) \ |
| 700 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 868 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 701 ); \ | 869 ); \ |
| 702 lval = (__typeof__(lval)) _res; \ | 870 lval = (__typeof__(lval)) _res; \ |
| 703 } while (0) | 871 } while (0) |
| 704 | 872 |
| 705 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ | 873 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ |
| 706 do { \ | 874 do { \ |
| 707 volatile OrigFn _orig = (orig); \ | 875 volatile OrigFn _orig = (orig); \ |
| (...skipping 24 matching lines...) Expand all Loading... |
| 732 volatile OrigFn _orig = (orig); \ | 900 volatile OrigFn _orig = (orig); \ |
| 733 volatile unsigned long _argvec[6]; \ | 901 volatile unsigned long _argvec[6]; \ |
| 734 volatile unsigned long _res; \ | 902 volatile unsigned long _res; \ |
| 735 _argvec[0] = (unsigned long)_orig.nraddr; \ | 903 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 736 _argvec[1] = (unsigned long)(arg1); \ | 904 _argvec[1] = (unsigned long)(arg1); \ |
| 737 _argvec[2] = (unsigned long)(arg2); \ | 905 _argvec[2] = (unsigned long)(arg2); \ |
| 738 _argvec[3] = (unsigned long)(arg3); \ | 906 _argvec[3] = (unsigned long)(arg3); \ |
| 739 _argvec[4] = (unsigned long)(arg4); \ | 907 _argvec[4] = (unsigned long)(arg4); \ |
| 740 _argvec[5] = (unsigned long)(arg5); \ | 908 _argvec[5] = (unsigned long)(arg5); \ |
| 741 __asm__ volatile( \ | 909 __asm__ volatile( \ |
| 910 "subl $12, %%esp\n\t" \ |
| 742 "pushl 20(%%eax)\n\t" \ | 911 "pushl 20(%%eax)\n\t" \ |
| 743 "pushl 16(%%eax)\n\t" \ | 912 "pushl 16(%%eax)\n\t" \ |
| 744 "pushl 12(%%eax)\n\t" \ | 913 "pushl 12(%%eax)\n\t" \ |
| 745 "pushl 8(%%eax)\n\t" \ | 914 "pushl 8(%%eax)\n\t" \ |
| 746 "pushl 4(%%eax)\n\t" \ | 915 "pushl 4(%%eax)\n\t" \ |
| 747 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 916 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 748 VALGRIND_CALL_NOREDIR_EAX \ | 917 VALGRIND_CALL_NOREDIR_EAX \ |
| 749 "addl $20, %%esp\n" \ | 918 "addl $32, %%esp\n" \ |
| 750 : /*out*/ "=a" (_res) \ | 919 : /*out*/ "=a" (_res) \ |
| 751 : /*in*/ "a" (&_argvec[0]) \ | 920 : /*in*/ "a" (&_argvec[0]) \ |
| 752 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 921 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 753 ); \ | 922 ); \ |
| 754 lval = (__typeof__(lval)) _res; \ | 923 lval = (__typeof__(lval)) _res; \ |
| 755 } while (0) | 924 } while (0) |
| 756 | 925 |
| 757 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ | 926 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ |
| 758 do { \ | 927 do { \ |
| 759 volatile OrigFn _orig = (orig); \ | 928 volatile OrigFn _orig = (orig); \ |
| 760 volatile unsigned long _argvec[7]; \ | 929 volatile unsigned long _argvec[7]; \ |
| 761 volatile unsigned long _res; \ | 930 volatile unsigned long _res; \ |
| 762 _argvec[0] = (unsigned long)_orig.nraddr; \ | 931 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 763 _argvec[1] = (unsigned long)(arg1); \ | 932 _argvec[1] = (unsigned long)(arg1); \ |
| 764 _argvec[2] = (unsigned long)(arg2); \ | 933 _argvec[2] = (unsigned long)(arg2); \ |
| 765 _argvec[3] = (unsigned long)(arg3); \ | 934 _argvec[3] = (unsigned long)(arg3); \ |
| 766 _argvec[4] = (unsigned long)(arg4); \ | 935 _argvec[4] = (unsigned long)(arg4); \ |
| 767 _argvec[5] = (unsigned long)(arg5); \ | 936 _argvec[5] = (unsigned long)(arg5); \ |
| 768 _argvec[6] = (unsigned long)(arg6); \ | 937 _argvec[6] = (unsigned long)(arg6); \ |
| 769 __asm__ volatile( \ | 938 __asm__ volatile( \ |
| 939 "subl $8, %%esp\n\t" \ |
| 770 "pushl 24(%%eax)\n\t" \ | 940 "pushl 24(%%eax)\n\t" \ |
| 771 "pushl 20(%%eax)\n\t" \ | 941 "pushl 20(%%eax)\n\t" \ |
| 772 "pushl 16(%%eax)\n\t" \ | 942 "pushl 16(%%eax)\n\t" \ |
| 773 "pushl 12(%%eax)\n\t" \ | 943 "pushl 12(%%eax)\n\t" \ |
| 774 "pushl 8(%%eax)\n\t" \ | 944 "pushl 8(%%eax)\n\t" \ |
| 775 "pushl 4(%%eax)\n\t" \ | 945 "pushl 4(%%eax)\n\t" \ |
| 776 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 946 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 777 VALGRIND_CALL_NOREDIR_EAX \ | 947 VALGRIND_CALL_NOREDIR_EAX \ |
| 778 "addl $24, %%esp\n" \ | 948 "addl $32, %%esp\n" \ |
| 779 : /*out*/ "=a" (_res) \ | 949 : /*out*/ "=a" (_res) \ |
| 780 : /*in*/ "a" (&_argvec[0]) \ | 950 : /*in*/ "a" (&_argvec[0]) \ |
| 781 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 951 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 782 ); \ | 952 ); \ |
| 783 lval = (__typeof__(lval)) _res; \ | 953 lval = (__typeof__(lval)) _res; \ |
| 784 } while (0) | 954 } while (0) |
| 785 | 955 |
| 786 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 956 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 787 arg7) \ | 957 arg7) \ |
| 788 do { \ | 958 do { \ |
| 789 volatile OrigFn _orig = (orig); \ | 959 volatile OrigFn _orig = (orig); \ |
| 790 volatile unsigned long _argvec[8]; \ | 960 volatile unsigned long _argvec[8]; \ |
| 791 volatile unsigned long _res; \ | 961 volatile unsigned long _res; \ |
| 792 _argvec[0] = (unsigned long)_orig.nraddr; \ | 962 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 793 _argvec[1] = (unsigned long)(arg1); \ | 963 _argvec[1] = (unsigned long)(arg1); \ |
| 794 _argvec[2] = (unsigned long)(arg2); \ | 964 _argvec[2] = (unsigned long)(arg2); \ |
| 795 _argvec[3] = (unsigned long)(arg3); \ | 965 _argvec[3] = (unsigned long)(arg3); \ |
| 796 _argvec[4] = (unsigned long)(arg4); \ | 966 _argvec[4] = (unsigned long)(arg4); \ |
| 797 _argvec[5] = (unsigned long)(arg5); \ | 967 _argvec[5] = (unsigned long)(arg5); \ |
| 798 _argvec[6] = (unsigned long)(arg6); \ | 968 _argvec[6] = (unsigned long)(arg6); \ |
| 799 _argvec[7] = (unsigned long)(arg7); \ | 969 _argvec[7] = (unsigned long)(arg7); \ |
| 800 __asm__ volatile( \ | 970 __asm__ volatile( \ |
| 971 "subl $4, %%esp\n\t" \ |
| 801 "pushl 28(%%eax)\n\t" \ | 972 "pushl 28(%%eax)\n\t" \ |
| 802 "pushl 24(%%eax)\n\t" \ | 973 "pushl 24(%%eax)\n\t" \ |
| 803 "pushl 20(%%eax)\n\t" \ | 974 "pushl 20(%%eax)\n\t" \ |
| 804 "pushl 16(%%eax)\n\t" \ | 975 "pushl 16(%%eax)\n\t" \ |
| 805 "pushl 12(%%eax)\n\t" \ | 976 "pushl 12(%%eax)\n\t" \ |
| 806 "pushl 8(%%eax)\n\t" \ | 977 "pushl 8(%%eax)\n\t" \ |
| 807 "pushl 4(%%eax)\n\t" \ | 978 "pushl 4(%%eax)\n\t" \ |
| 808 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 979 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 809 VALGRIND_CALL_NOREDIR_EAX \ | 980 VALGRIND_CALL_NOREDIR_EAX \ |
| 810 "addl $28, %%esp\n" \ | 981 "addl $32, %%esp\n" \ |
| 811 : /*out*/ "=a" (_res) \ | 982 : /*out*/ "=a" (_res) \ |
| 812 : /*in*/ "a" (&_argvec[0]) \ | 983 : /*in*/ "a" (&_argvec[0]) \ |
| 813 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 984 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 814 ); \ | 985 ); \ |
| 815 lval = (__typeof__(lval)) _res; \ | 986 lval = (__typeof__(lval)) _res; \ |
| 816 } while (0) | 987 } while (0) |
| 817 | 988 |
| 818 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 989 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 819 arg7,arg8) \ | 990 arg7,arg8) \ |
| 820 do { \ | 991 do { \ |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 _argvec[1] = (unsigned long)(arg1); \ | 1030 _argvec[1] = (unsigned long)(arg1); \ |
| 860 _argvec[2] = (unsigned long)(arg2); \ | 1031 _argvec[2] = (unsigned long)(arg2); \ |
| 861 _argvec[3] = (unsigned long)(arg3); \ | 1032 _argvec[3] = (unsigned long)(arg3); \ |
| 862 _argvec[4] = (unsigned long)(arg4); \ | 1033 _argvec[4] = (unsigned long)(arg4); \ |
| 863 _argvec[5] = (unsigned long)(arg5); \ | 1034 _argvec[5] = (unsigned long)(arg5); \ |
| 864 _argvec[6] = (unsigned long)(arg6); \ | 1035 _argvec[6] = (unsigned long)(arg6); \ |
| 865 _argvec[7] = (unsigned long)(arg7); \ | 1036 _argvec[7] = (unsigned long)(arg7); \ |
| 866 _argvec[8] = (unsigned long)(arg8); \ | 1037 _argvec[8] = (unsigned long)(arg8); \ |
| 867 _argvec[9] = (unsigned long)(arg9); \ | 1038 _argvec[9] = (unsigned long)(arg9); \ |
| 868 __asm__ volatile( \ | 1039 __asm__ volatile( \ |
| 1040 "subl $12, %%esp\n\t" \ |
| 869 "pushl 36(%%eax)\n\t" \ | 1041 "pushl 36(%%eax)\n\t" \ |
| 870 "pushl 32(%%eax)\n\t" \ | 1042 "pushl 32(%%eax)\n\t" \ |
| 871 "pushl 28(%%eax)\n\t" \ | 1043 "pushl 28(%%eax)\n\t" \ |
| 872 "pushl 24(%%eax)\n\t" \ | 1044 "pushl 24(%%eax)\n\t" \ |
| 873 "pushl 20(%%eax)\n\t" \ | 1045 "pushl 20(%%eax)\n\t" \ |
| 874 "pushl 16(%%eax)\n\t" \ | 1046 "pushl 16(%%eax)\n\t" \ |
| 875 "pushl 12(%%eax)\n\t" \ | 1047 "pushl 12(%%eax)\n\t" \ |
| 876 "pushl 8(%%eax)\n\t" \ | 1048 "pushl 8(%%eax)\n\t" \ |
| 877 "pushl 4(%%eax)\n\t" \ | 1049 "pushl 4(%%eax)\n\t" \ |
| 878 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 1050 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 879 VALGRIND_CALL_NOREDIR_EAX \ | 1051 VALGRIND_CALL_NOREDIR_EAX \ |
| 880 "addl $36, %%esp\n" \ | 1052 "addl $48, %%esp\n" \ |
| 881 : /*out*/ "=a" (_res) \ | 1053 : /*out*/ "=a" (_res) \ |
| 882 : /*in*/ "a" (&_argvec[0]) \ | 1054 : /*in*/ "a" (&_argvec[0]) \ |
| 883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1055 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 884 ); \ | 1056 ); \ |
| 885 lval = (__typeof__(lval)) _res; \ | 1057 lval = (__typeof__(lval)) _res; \ |
| 886 } while (0) | 1058 } while (0) |
| 887 | 1059 |
| 888 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1060 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 889 arg7,arg8,arg9,arg10) \ | 1061 arg7,arg8,arg9,arg10) \ |
| 890 do { \ | 1062 do { \ |
| 891 volatile OrigFn _orig = (orig); \ | 1063 volatile OrigFn _orig = (orig); \ |
| 892 volatile unsigned long _argvec[11]; \ | 1064 volatile unsigned long _argvec[11]; \ |
| 893 volatile unsigned long _res; \ | 1065 volatile unsigned long _res; \ |
| 894 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1066 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 895 _argvec[1] = (unsigned long)(arg1); \ | 1067 _argvec[1] = (unsigned long)(arg1); \ |
| 896 _argvec[2] = (unsigned long)(arg2); \ | 1068 _argvec[2] = (unsigned long)(arg2); \ |
| 897 _argvec[3] = (unsigned long)(arg3); \ | 1069 _argvec[3] = (unsigned long)(arg3); \ |
| 898 _argvec[4] = (unsigned long)(arg4); \ | 1070 _argvec[4] = (unsigned long)(arg4); \ |
| 899 _argvec[5] = (unsigned long)(arg5); \ | 1071 _argvec[5] = (unsigned long)(arg5); \ |
| 900 _argvec[6] = (unsigned long)(arg6); \ | 1072 _argvec[6] = (unsigned long)(arg6); \ |
| 901 _argvec[7] = (unsigned long)(arg7); \ | 1073 _argvec[7] = (unsigned long)(arg7); \ |
| 902 _argvec[8] = (unsigned long)(arg8); \ | 1074 _argvec[8] = (unsigned long)(arg8); \ |
| 903 _argvec[9] = (unsigned long)(arg9); \ | 1075 _argvec[9] = (unsigned long)(arg9); \ |
| 904 _argvec[10] = (unsigned long)(arg10); \ | 1076 _argvec[10] = (unsigned long)(arg10); \ |
| 905 __asm__ volatile( \ | 1077 __asm__ volatile( \ |
| 1078 "subl $8, %%esp\n\t" \ |
| 906 "pushl 40(%%eax)\n\t" \ | 1079 "pushl 40(%%eax)\n\t" \ |
| 907 "pushl 36(%%eax)\n\t" \ | 1080 "pushl 36(%%eax)\n\t" \ |
| 908 "pushl 32(%%eax)\n\t" \ | 1081 "pushl 32(%%eax)\n\t" \ |
| 909 "pushl 28(%%eax)\n\t" \ | 1082 "pushl 28(%%eax)\n\t" \ |
| 910 "pushl 24(%%eax)\n\t" \ | 1083 "pushl 24(%%eax)\n\t" \ |
| 911 "pushl 20(%%eax)\n\t" \ | 1084 "pushl 20(%%eax)\n\t" \ |
| 912 "pushl 16(%%eax)\n\t" \ | 1085 "pushl 16(%%eax)\n\t" \ |
| 913 "pushl 12(%%eax)\n\t" \ | 1086 "pushl 12(%%eax)\n\t" \ |
| 914 "pushl 8(%%eax)\n\t" \ | 1087 "pushl 8(%%eax)\n\t" \ |
| 915 "pushl 4(%%eax)\n\t" \ | 1088 "pushl 4(%%eax)\n\t" \ |
| 916 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 1089 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 917 VALGRIND_CALL_NOREDIR_EAX \ | 1090 VALGRIND_CALL_NOREDIR_EAX \ |
| 918 "addl $40, %%esp\n" \ | 1091 "addl $48, %%esp\n" \ |
| 919 : /*out*/ "=a" (_res) \ | 1092 : /*out*/ "=a" (_res) \ |
| 920 : /*in*/ "a" (&_argvec[0]) \ | 1093 : /*in*/ "a" (&_argvec[0]) \ |
| 921 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1094 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 922 ); \ | 1095 ); \ |
| 923 lval = (__typeof__(lval)) _res; \ | 1096 lval = (__typeof__(lval)) _res; \ |
| 924 } while (0) | 1097 } while (0) |
| 925 | 1098 |
| 926 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ | 1099 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ |
| 927 arg6,arg7,arg8,arg9,arg10, \ | 1100 arg6,arg7,arg8,arg9,arg10, \ |
| 928 arg11) \ | 1101 arg11) \ |
| 929 do { \ | 1102 do { \ |
| 930 volatile OrigFn _orig = (orig); \ | 1103 volatile OrigFn _orig = (orig); \ |
| 931 volatile unsigned long _argvec[12]; \ | 1104 volatile unsigned long _argvec[12]; \ |
| 932 volatile unsigned long _res; \ | 1105 volatile unsigned long _res; \ |
| 933 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1106 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 934 _argvec[1] = (unsigned long)(arg1); \ | 1107 _argvec[1] = (unsigned long)(arg1); \ |
| 935 _argvec[2] = (unsigned long)(arg2); \ | 1108 _argvec[2] = (unsigned long)(arg2); \ |
| 936 _argvec[3] = (unsigned long)(arg3); \ | 1109 _argvec[3] = (unsigned long)(arg3); \ |
| 937 _argvec[4] = (unsigned long)(arg4); \ | 1110 _argvec[4] = (unsigned long)(arg4); \ |
| 938 _argvec[5] = (unsigned long)(arg5); \ | 1111 _argvec[5] = (unsigned long)(arg5); \ |
| 939 _argvec[6] = (unsigned long)(arg6); \ | 1112 _argvec[6] = (unsigned long)(arg6); \ |
| 940 _argvec[7] = (unsigned long)(arg7); \ | 1113 _argvec[7] = (unsigned long)(arg7); \ |
| 941 _argvec[8] = (unsigned long)(arg8); \ | 1114 _argvec[8] = (unsigned long)(arg8); \ |
| 942 _argvec[9] = (unsigned long)(arg9); \ | 1115 _argvec[9] = (unsigned long)(arg9); \ |
| 943 _argvec[10] = (unsigned long)(arg10); \ | 1116 _argvec[10] = (unsigned long)(arg10); \ |
| 944 _argvec[11] = (unsigned long)(arg11); \ | 1117 _argvec[11] = (unsigned long)(arg11); \ |
| 945 __asm__ volatile( \ | 1118 __asm__ volatile( \ |
| 1119 "subl $4, %%esp\n\t" \ |
| 946 "pushl 44(%%eax)\n\t" \ | 1120 "pushl 44(%%eax)\n\t" \ |
| 947 "pushl 40(%%eax)\n\t" \ | 1121 "pushl 40(%%eax)\n\t" \ |
| 948 "pushl 36(%%eax)\n\t" \ | 1122 "pushl 36(%%eax)\n\t" \ |
| 949 "pushl 32(%%eax)\n\t" \ | 1123 "pushl 32(%%eax)\n\t" \ |
| 950 "pushl 28(%%eax)\n\t" \ | 1124 "pushl 28(%%eax)\n\t" \ |
| 951 "pushl 24(%%eax)\n\t" \ | 1125 "pushl 24(%%eax)\n\t" \ |
| 952 "pushl 20(%%eax)\n\t" \ | 1126 "pushl 20(%%eax)\n\t" \ |
| 953 "pushl 16(%%eax)\n\t" \ | 1127 "pushl 16(%%eax)\n\t" \ |
| 954 "pushl 12(%%eax)\n\t" \ | 1128 "pushl 12(%%eax)\n\t" \ |
| 955 "pushl 8(%%eax)\n\t" \ | 1129 "pushl 8(%%eax)\n\t" \ |
| 956 "pushl 4(%%eax)\n\t" \ | 1130 "pushl 4(%%eax)\n\t" \ |
| 957 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 1131 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 958 VALGRIND_CALL_NOREDIR_EAX \ | 1132 VALGRIND_CALL_NOREDIR_EAX \ |
| 959 "addl $44, %%esp\n" \ | 1133 "addl $48, %%esp\n" \ |
| 960 : /*out*/ "=a" (_res) \ | 1134 : /*out*/ "=a" (_res) \ |
| 961 : /*in*/ "a" (&_argvec[0]) \ | 1135 : /*in*/ "a" (&_argvec[0]) \ |
| 962 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1136 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 963 ); \ | 1137 ); \ |
| 964 lval = (__typeof__(lval)) _res; \ | 1138 lval = (__typeof__(lval)) _res; \ |
| 965 } while (0) | 1139 } while (0) |
| 966 | 1140 |
| 967 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ | 1141 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ |
| 968 arg6,arg7,arg8,arg9,arg10, \ | 1142 arg6,arg7,arg8,arg9,arg10, \ |
| 969 arg11,arg12) \ | 1143 arg11,arg12) \ |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1000 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ | 1174 "movl (%%eax), %%eax\n\t" /* target->%eax */ \ |
| 1001 VALGRIND_CALL_NOREDIR_EAX \ | 1175 VALGRIND_CALL_NOREDIR_EAX \ |
| 1002 "addl $48, %%esp\n" \ | 1176 "addl $48, %%esp\n" \ |
| 1003 : /*out*/ "=a" (_res) \ | 1177 : /*out*/ "=a" (_res) \ |
| 1004 : /*in*/ "a" (&_argvec[0]) \ | 1178 : /*in*/ "a" (&_argvec[0]) \ |
| 1005 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1179 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 1006 ); \ | 1180 ); \ |
| 1007 lval = (__typeof__(lval)) _res; \ | 1181 lval = (__typeof__(lval)) _res; \ |
| 1008 } while (0) | 1182 } while (0) |
| 1009 | 1183 |
| 1010 #endif /* PLAT_x86_linux */ | 1184 #endif /* PLAT_x86_linux || PLAT_x86_darwin */ |
| 1011 | 1185 |
| 1012 /* ------------------------ amd64-linux ------------------------ */ | 1186 /* ------------------------ amd64-{linux,darwin} --------------- */ |
| 1013 | 1187 |
| 1014 #if defined(PLAT_amd64_linux) | 1188 #if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) |
| 1015 | 1189 |
| 1016 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ | 1190 /* ARGREGS: rdi rsi rdx rcx r8 r9 (the rest on stack in R-to-L order) */ |
| 1017 | 1191 |
| 1018 /* These regs are trashed by the hidden call. */ | 1192 /* These regs are trashed by the hidden call. */ |
| 1019 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ | 1193 #define __CALLER_SAVED_REGS /*"rax",*/ "rcx", "rdx", "rsi", \ |
| 1020 "rdi", "r8", "r9", "r10", "r11" | 1194 "rdi", "r8", "r9", "r10", "r11" |
| 1021 | 1195 |
| 1196 /* This is all pretty complex. It's so as to make stack unwinding |
| 1197 work reliably. See bug 243270. The basic problem is the sub and |
| 1198 add of 128 of %rsp in all of the following macros. If gcc believes |
| 1199 the CFA is in %rsp, then unwinding may fail, because what's at the |
| 1200 CFA is not what gcc "expected" when it constructs the CFIs for the |
| 1201 places where the macros are instantiated. |
| 1202 |
| 1203 But we can't just add a CFI annotation to increase the CFA offset |
| 1204 by 128, to match the sub of 128 from %rsp, because we don't know |
| 1205 whether gcc has chosen %rsp as the CFA at that point, or whether it |
| 1206 has chosen some other register (eg, %rbp). In the latter case, |
| 1207 adding a CFI annotation to change the CFA offset is simply wrong. |
| 1208 |
| 1209 So the solution is to get hold of the CFA using |
| 1210 __builtin_dwarf_cfa(), put it in a known register, and add a |
| 1211 CFI annotation to say what the register is. We choose %rbp for |
| 1212 this (perhaps perversely), because: |
| 1213 |
| 1214 (1) %rbp is already subject to unwinding. If a new register was |
| 1215 chosen then the unwinder would have to unwind it in all stack |
| 1216 traces, which is expensive, and |
| 1217 |
| 1218 (2) %rbp is already subject to precise exception updates in the |
| 1219 JIT. If a new register was chosen, we'd have to have precise |
| 1220 exceptions for it too, which reduces performance of the |
| 1221 generated code. |
| 1222 |
| 1223 However .. one extra complication. We can't just whack the result |
| 1224 of __builtin_dwarf_cfa() into %rbp and then add %rbp to the |
| 1225 list of trashed registers at the end of the inline assembly |
| 1226 fragments; gcc won't allow %rbp to appear in that list. Hence |
| 1227 instead we need to stash %rbp in %r15 for the duration of the asm, |
| 1228 and say that %r15 is trashed instead. gcc seems happy to go with |
| 1229 that. |
| 1230 |
| 1231 Oh .. and this all needs to be conditionalised so that it is |
| 1232 unchanged from before this commit, when compiled with older gccs |
| 1233 that don't support __builtin_dwarf_cfa. Furthermore, since |
| 1234 this header file is freestanding, it has to be independent of |
| 1235 config.h, and so the following conditionalisation cannot depend on |
| 1236 configure time checks. |
| 1237 |
| 1238 Although it's not clear from |
| 1239 'defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)', |
| 1240 this expression excludes Darwin. |
| 1241 .cfi directives in Darwin assembly appear to be completely |
| 1242 different and I haven't investigated how they work. |
| 1243 |
| 1244 For even more entertainment value, note we have to use the |
| 1245 completely undocumented __builtin_dwarf_cfa(), which appears to |
| 1246 really compute the CFA, whereas __builtin_frame_address(0) claims |
| 1247 to but actually doesn't. See |
| 1248 https://bugs.kde.org/show_bug.cgi?id=243270#c47 |
| 1249 */ |
| 1250 #if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM) |
| 1251 # define __FRAME_POINTER \ |
| 1252 ,"r"(__builtin_dwarf_cfa()) |
| 1253 # define VALGRIND_CFI_PROLOGUE \ |
| 1254 "movq %%rbp, %%r15\n\t" \ |
| 1255 "movq %2, %%rbp\n\t" \ |
| 1256 ".cfi_remember_state\n\t" \ |
| 1257 ".cfi_def_cfa rbp, 0\n\t" |
| 1258 # define VALGRIND_CFI_EPILOGUE \ |
| 1259 "movq %%r15, %%rbp\n\t" \ |
| 1260 ".cfi_restore_state\n\t" |
| 1261 #else |
| 1262 # define __FRAME_POINTER |
| 1263 # define VALGRIND_CFI_PROLOGUE |
| 1264 # define VALGRIND_CFI_EPILOGUE |
| 1265 #endif |
| 1266 |
| 1267 |
| 1022 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned | 1268 /* These CALL_FN_ macros assume that on amd64-linux, sizeof(unsigned |
| 1023 long) == 8. */ | 1269 long) == 8. */ |
| 1024 | 1270 |
| 1025 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ | 1271 /* NB 9 Sept 07. There is a nasty kludge here in all these CALL_FN_ |
| 1026 macros. In order not to trash the stack redzone, we need to drop | 1272 macros. In order not to trash the stack redzone, we need to drop |
| 1027 %rsp by 128 before the hidden call, and restore afterwards. The | 1273 %rsp by 128 before the hidden call, and restore afterwards. The |
| 1028 nastyness is that it is only by luck that the stack still appears | 1274 nastyness is that it is only by luck that the stack still appears |
| 1029 to be unwindable during the hidden call - since then the behaviour | 1275 to be unwindable during the hidden call - since then the behaviour |
| 1030 of any routine using this macro does not match what the CFI data | 1276 of any routine using this macro does not match what the CFI data |
| 1031 says. Sigh. | 1277 says. Sigh. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1043 with the stack pointer doesn't give a danger of non-unwindable | 1289 with the stack pointer doesn't give a danger of non-unwindable |
| 1044 stack. */ | 1290 stack. */ |
| 1045 | 1291 |
| 1046 #define CALL_FN_W_v(lval, orig) \ | 1292 #define CALL_FN_W_v(lval, orig) \ |
| 1047 do { \ | 1293 do { \ |
| 1048 volatile OrigFn _orig = (orig); \ | 1294 volatile OrigFn _orig = (orig); \ |
| 1049 volatile unsigned long _argvec[1]; \ | 1295 volatile unsigned long _argvec[1]; \ |
| 1050 volatile unsigned long _res; \ | 1296 volatile unsigned long _res; \ |
| 1051 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1297 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1052 __asm__ volatile( \ | 1298 __asm__ volatile( \ |
| 1299 VALGRIND_CFI_PROLOGUE \ |
| 1053 "subq $128,%%rsp\n\t" \ | 1300 "subq $128,%%rsp\n\t" \ |
| 1054 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1301 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1055 VALGRIND_CALL_NOREDIR_RAX \ | 1302 VALGRIND_CALL_NOREDIR_RAX \ |
| 1056 "addq $128,%%rsp\n\t" \ | 1303 "addq $128,%%rsp\n\t" \ |
| 1304 VALGRIND_CFI_EPILOGUE \ |
| 1057 : /*out*/ "=a" (_res) \ | 1305 : /*out*/ "=a" (_res) \ |
| 1058 : /*in*/ "a" (&_argvec[0]) \ | 1306 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1059 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1307 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1060 ); \ | 1308 ); \ |
| 1061 lval = (__typeof__(lval)) _res; \ | 1309 lval = (__typeof__(lval)) _res; \ |
| 1062 } while (0) | 1310 } while (0) |
| 1063 | 1311 |
| 1064 #define CALL_FN_W_W(lval, orig, arg1) \ | 1312 #define CALL_FN_W_W(lval, orig, arg1) \ |
| 1065 do { \ | 1313 do { \ |
| 1066 volatile OrigFn _orig = (orig); \ | 1314 volatile OrigFn _orig = (orig); \ |
| 1067 volatile unsigned long _argvec[2]; \ | 1315 volatile unsigned long _argvec[2]; \ |
| 1068 volatile unsigned long _res; \ | 1316 volatile unsigned long _res; \ |
| 1069 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1317 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1070 _argvec[1] = (unsigned long)(arg1); \ | 1318 _argvec[1] = (unsigned long)(arg1); \ |
| 1071 __asm__ volatile( \ | 1319 __asm__ volatile( \ |
| 1320 VALGRIND_CFI_PROLOGUE \ |
| 1072 "subq $128,%%rsp\n\t" \ | 1321 "subq $128,%%rsp\n\t" \ |
| 1073 "movq 8(%%rax), %%rdi\n\t" \ | 1322 "movq 8(%%rax), %%rdi\n\t" \ |
| 1074 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1323 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1075 VALGRIND_CALL_NOREDIR_RAX \ | 1324 VALGRIND_CALL_NOREDIR_RAX \ |
| 1076 "addq $128,%%rsp\n\t" \ | 1325 "addq $128,%%rsp\n\t" \ |
| 1326 VALGRIND_CFI_EPILOGUE \ |
| 1077 : /*out*/ "=a" (_res) \ | 1327 : /*out*/ "=a" (_res) \ |
| 1078 : /*in*/ "a" (&_argvec[0]) \ | 1328 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1079 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1329 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1080 ); \ | 1330 ); \ |
| 1081 lval = (__typeof__(lval)) _res; \ | 1331 lval = (__typeof__(lval)) _res; \ |
| 1082 } while (0) | 1332 } while (0) |
| 1083 | 1333 |
| 1084 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ | 1334 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ |
| 1085 do { \ | 1335 do { \ |
| 1086 volatile OrigFn _orig = (orig); \ | 1336 volatile OrigFn _orig = (orig); \ |
| 1087 volatile unsigned long _argvec[3]; \ | 1337 volatile unsigned long _argvec[3]; \ |
| 1088 volatile unsigned long _res; \ | 1338 volatile unsigned long _res; \ |
| 1089 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1339 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1090 _argvec[1] = (unsigned long)(arg1); \ | 1340 _argvec[1] = (unsigned long)(arg1); \ |
| 1091 _argvec[2] = (unsigned long)(arg2); \ | 1341 _argvec[2] = (unsigned long)(arg2); \ |
| 1092 __asm__ volatile( \ | 1342 __asm__ volatile( \ |
| 1343 VALGRIND_CFI_PROLOGUE \ |
| 1093 "subq $128,%%rsp\n\t" \ | 1344 "subq $128,%%rsp\n\t" \ |
| 1094 "movq 16(%%rax), %%rsi\n\t" \ | 1345 "movq 16(%%rax), %%rsi\n\t" \ |
| 1095 "movq 8(%%rax), %%rdi\n\t" \ | 1346 "movq 8(%%rax), %%rdi\n\t" \ |
| 1096 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1347 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1097 VALGRIND_CALL_NOREDIR_RAX \ | 1348 VALGRIND_CALL_NOREDIR_RAX \ |
| 1098 "addq $128,%%rsp\n\t" \ | 1349 "addq $128,%%rsp\n\t" \ |
| 1350 VALGRIND_CFI_EPILOGUE \ |
| 1099 : /*out*/ "=a" (_res) \ | 1351 : /*out*/ "=a" (_res) \ |
| 1100 : /*in*/ "a" (&_argvec[0]) \ | 1352 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1101 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1353 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1102 ); \ | 1354 ); \ |
| 1103 lval = (__typeof__(lval)) _res; \ | 1355 lval = (__typeof__(lval)) _res; \ |
| 1104 } while (0) | 1356 } while (0) |
| 1105 | 1357 |
| 1106 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ | 1358 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ |
| 1107 do { \ | 1359 do { \ |
| 1108 volatile OrigFn _orig = (orig); \ | 1360 volatile OrigFn _orig = (orig); \ |
| 1109 volatile unsigned long _argvec[4]; \ | 1361 volatile unsigned long _argvec[4]; \ |
| 1110 volatile unsigned long _res; \ | 1362 volatile unsigned long _res; \ |
| 1111 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1363 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1112 _argvec[1] = (unsigned long)(arg1); \ | 1364 _argvec[1] = (unsigned long)(arg1); \ |
| 1113 _argvec[2] = (unsigned long)(arg2); \ | 1365 _argvec[2] = (unsigned long)(arg2); \ |
| 1114 _argvec[3] = (unsigned long)(arg3); \ | 1366 _argvec[3] = (unsigned long)(arg3); \ |
| 1115 __asm__ volatile( \ | 1367 __asm__ volatile( \ |
| 1368 VALGRIND_CFI_PROLOGUE \ |
| 1116 "subq $128,%%rsp\n\t" \ | 1369 "subq $128,%%rsp\n\t" \ |
| 1117 "movq 24(%%rax), %%rdx\n\t" \ | 1370 "movq 24(%%rax), %%rdx\n\t" \ |
| 1118 "movq 16(%%rax), %%rsi\n\t" \ | 1371 "movq 16(%%rax), %%rsi\n\t" \ |
| 1119 "movq 8(%%rax), %%rdi\n\t" \ | 1372 "movq 8(%%rax), %%rdi\n\t" \ |
| 1120 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1373 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1121 VALGRIND_CALL_NOREDIR_RAX \ | 1374 VALGRIND_CALL_NOREDIR_RAX \ |
| 1122 "addq $128,%%rsp\n\t" \ | 1375 "addq $128,%%rsp\n\t" \ |
| 1376 VALGRIND_CFI_EPILOGUE \ |
| 1123 : /*out*/ "=a" (_res) \ | 1377 : /*out*/ "=a" (_res) \ |
| 1124 : /*in*/ "a" (&_argvec[0]) \ | 1378 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1125 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1379 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1126 ); \ | 1380 ); \ |
| 1127 lval = (__typeof__(lval)) _res; \ | 1381 lval = (__typeof__(lval)) _res; \ |
| 1128 } while (0) | 1382 } while (0) |
| 1129 | 1383 |
| 1130 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ | 1384 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ |
| 1131 do { \ | 1385 do { \ |
| 1132 volatile OrigFn _orig = (orig); \ | 1386 volatile OrigFn _orig = (orig); \ |
| 1133 volatile unsigned long _argvec[5]; \ | 1387 volatile unsigned long _argvec[5]; \ |
| 1134 volatile unsigned long _res; \ | 1388 volatile unsigned long _res; \ |
| 1135 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1389 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1136 _argvec[1] = (unsigned long)(arg1); \ | 1390 _argvec[1] = (unsigned long)(arg1); \ |
| 1137 _argvec[2] = (unsigned long)(arg2); \ | 1391 _argvec[2] = (unsigned long)(arg2); \ |
| 1138 _argvec[3] = (unsigned long)(arg3); \ | 1392 _argvec[3] = (unsigned long)(arg3); \ |
| 1139 _argvec[4] = (unsigned long)(arg4); \ | 1393 _argvec[4] = (unsigned long)(arg4); \ |
| 1140 __asm__ volatile( \ | 1394 __asm__ volatile( \ |
| 1395 VALGRIND_CFI_PROLOGUE \ |
| 1141 "subq $128,%%rsp\n\t" \ | 1396 "subq $128,%%rsp\n\t" \ |
| 1142 "movq 32(%%rax), %%rcx\n\t" \ | 1397 "movq 32(%%rax), %%rcx\n\t" \ |
| 1143 "movq 24(%%rax), %%rdx\n\t" \ | 1398 "movq 24(%%rax), %%rdx\n\t" \ |
| 1144 "movq 16(%%rax), %%rsi\n\t" \ | 1399 "movq 16(%%rax), %%rsi\n\t" \ |
| 1145 "movq 8(%%rax), %%rdi\n\t" \ | 1400 "movq 8(%%rax), %%rdi\n\t" \ |
| 1146 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1401 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1147 VALGRIND_CALL_NOREDIR_RAX \ | 1402 VALGRIND_CALL_NOREDIR_RAX \ |
| 1148 "addq $128,%%rsp\n\t" \ | 1403 "addq $128,%%rsp\n\t" \ |
| 1404 VALGRIND_CFI_EPILOGUE \ |
| 1149 : /*out*/ "=a" (_res) \ | 1405 : /*out*/ "=a" (_res) \ |
| 1150 : /*in*/ "a" (&_argvec[0]) \ | 1406 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1151 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1407 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1152 ); \ | 1408 ); \ |
| 1153 lval = (__typeof__(lval)) _res; \ | 1409 lval = (__typeof__(lval)) _res; \ |
| 1154 } while (0) | 1410 } while (0) |
| 1155 | 1411 |
| 1156 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ | 1412 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ |
| 1157 do { \ | 1413 do { \ |
| 1158 volatile OrigFn _orig = (orig); \ | 1414 volatile OrigFn _orig = (orig); \ |
| 1159 volatile unsigned long _argvec[6]; \ | 1415 volatile unsigned long _argvec[6]; \ |
| 1160 volatile unsigned long _res; \ | 1416 volatile unsigned long _res; \ |
| 1161 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1417 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1162 _argvec[1] = (unsigned long)(arg1); \ | 1418 _argvec[1] = (unsigned long)(arg1); \ |
| 1163 _argvec[2] = (unsigned long)(arg2); \ | 1419 _argvec[2] = (unsigned long)(arg2); \ |
| 1164 _argvec[3] = (unsigned long)(arg3); \ | 1420 _argvec[3] = (unsigned long)(arg3); \ |
| 1165 _argvec[4] = (unsigned long)(arg4); \ | 1421 _argvec[4] = (unsigned long)(arg4); \ |
| 1166 _argvec[5] = (unsigned long)(arg5); \ | 1422 _argvec[5] = (unsigned long)(arg5); \ |
| 1167 __asm__ volatile( \ | 1423 __asm__ volatile( \ |
| 1424 VALGRIND_CFI_PROLOGUE \ |
| 1168 "subq $128,%%rsp\n\t" \ | 1425 "subq $128,%%rsp\n\t" \ |
| 1169 "movq 40(%%rax), %%r8\n\t" \ | 1426 "movq 40(%%rax), %%r8\n\t" \ |
| 1170 "movq 32(%%rax), %%rcx\n\t" \ | 1427 "movq 32(%%rax), %%rcx\n\t" \ |
| 1171 "movq 24(%%rax), %%rdx\n\t" \ | 1428 "movq 24(%%rax), %%rdx\n\t" \ |
| 1172 "movq 16(%%rax), %%rsi\n\t" \ | 1429 "movq 16(%%rax), %%rsi\n\t" \ |
| 1173 "movq 8(%%rax), %%rdi\n\t" \ | 1430 "movq 8(%%rax), %%rdi\n\t" \ |
| 1174 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1431 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1175 VALGRIND_CALL_NOREDIR_RAX \ | 1432 VALGRIND_CALL_NOREDIR_RAX \ |
| 1176 "addq $128,%%rsp\n\t" \ | 1433 "addq $128,%%rsp\n\t" \ |
| 1434 VALGRIND_CFI_EPILOGUE \ |
| 1177 : /*out*/ "=a" (_res) \ | 1435 : /*out*/ "=a" (_res) \ |
| 1178 : /*in*/ "a" (&_argvec[0]) \ | 1436 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1179 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1437 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1180 ); \ | 1438 ); \ |
| 1181 lval = (__typeof__(lval)) _res; \ | 1439 lval = (__typeof__(lval)) _res; \ |
| 1182 } while (0) | 1440 } while (0) |
| 1183 | 1441 |
| 1184 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ | 1442 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ |
| 1185 do { \ | 1443 do { \ |
| 1186 volatile OrigFn _orig = (orig); \ | 1444 volatile OrigFn _orig = (orig); \ |
| 1187 volatile unsigned long _argvec[7]; \ | 1445 volatile unsigned long _argvec[7]; \ |
| 1188 volatile unsigned long _res; \ | 1446 volatile unsigned long _res; \ |
| 1189 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1447 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1190 _argvec[1] = (unsigned long)(arg1); \ | 1448 _argvec[1] = (unsigned long)(arg1); \ |
| 1191 _argvec[2] = (unsigned long)(arg2); \ | 1449 _argvec[2] = (unsigned long)(arg2); \ |
| 1192 _argvec[3] = (unsigned long)(arg3); \ | 1450 _argvec[3] = (unsigned long)(arg3); \ |
| 1193 _argvec[4] = (unsigned long)(arg4); \ | 1451 _argvec[4] = (unsigned long)(arg4); \ |
| 1194 _argvec[5] = (unsigned long)(arg5); \ | 1452 _argvec[5] = (unsigned long)(arg5); \ |
| 1195 _argvec[6] = (unsigned long)(arg6); \ | 1453 _argvec[6] = (unsigned long)(arg6); \ |
| 1196 __asm__ volatile( \ | 1454 __asm__ volatile( \ |
| 1455 VALGRIND_CFI_PROLOGUE \ |
| 1197 "subq $128,%%rsp\n\t" \ | 1456 "subq $128,%%rsp\n\t" \ |
| 1198 "movq 48(%%rax), %%r9\n\t" \ | 1457 "movq 48(%%rax), %%r9\n\t" \ |
| 1199 "movq 40(%%rax), %%r8\n\t" \ | 1458 "movq 40(%%rax), %%r8\n\t" \ |
| 1200 "movq 32(%%rax), %%rcx\n\t" \ | 1459 "movq 32(%%rax), %%rcx\n\t" \ |
| 1201 "movq 24(%%rax), %%rdx\n\t" \ | 1460 "movq 24(%%rax), %%rdx\n\t" \ |
| 1202 "movq 16(%%rax), %%rsi\n\t" \ | 1461 "movq 16(%%rax), %%rsi\n\t" \ |
| 1203 "movq 8(%%rax), %%rdi\n\t" \ | 1462 "movq 8(%%rax), %%rdi\n\t" \ |
| 1204 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1463 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1464 VALGRIND_CALL_NOREDIR_RAX \ |
| 1205 "addq $128,%%rsp\n\t" \ | 1465 "addq $128,%%rsp\n\t" \ |
| 1206 VALGRIND_CALL_NOREDIR_RAX \ | 1466 VALGRIND_CFI_EPILOGUE \ |
| 1207 : /*out*/ "=a" (_res) \ | 1467 : /*out*/ "=a" (_res) \ |
| 1208 : /*in*/ "a" (&_argvec[0]) \ | 1468 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1209 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1469 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1210 ); \ | 1470 ); \ |
| 1211 lval = (__typeof__(lval)) _res; \ | 1471 lval = (__typeof__(lval)) _res; \ |
| 1212 } while (0) | 1472 } while (0) |
| 1213 | 1473 |
| 1214 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1474 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1215 arg7) \ | 1475 arg7) \ |
| 1216 do { \ | 1476 do { \ |
| 1217 volatile OrigFn _orig = (orig); \ | 1477 volatile OrigFn _orig = (orig); \ |
| 1218 volatile unsigned long _argvec[8]; \ | 1478 volatile unsigned long _argvec[8]; \ |
| 1219 volatile unsigned long _res; \ | 1479 volatile unsigned long _res; \ |
| 1220 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1480 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1221 _argvec[1] = (unsigned long)(arg1); \ | 1481 _argvec[1] = (unsigned long)(arg1); \ |
| 1222 _argvec[2] = (unsigned long)(arg2); \ | 1482 _argvec[2] = (unsigned long)(arg2); \ |
| 1223 _argvec[3] = (unsigned long)(arg3); \ | 1483 _argvec[3] = (unsigned long)(arg3); \ |
| 1224 _argvec[4] = (unsigned long)(arg4); \ | 1484 _argvec[4] = (unsigned long)(arg4); \ |
| 1225 _argvec[5] = (unsigned long)(arg5); \ | 1485 _argvec[5] = (unsigned long)(arg5); \ |
| 1226 _argvec[6] = (unsigned long)(arg6); \ | 1486 _argvec[6] = (unsigned long)(arg6); \ |
| 1227 _argvec[7] = (unsigned long)(arg7); \ | 1487 _argvec[7] = (unsigned long)(arg7); \ |
| 1228 __asm__ volatile( \ | 1488 __asm__ volatile( \ |
| 1229 "subq $128,%%rsp\n\t" \ | 1489 VALGRIND_CFI_PROLOGUE \ |
| 1490 "subq $136,%%rsp\n\t" \ |
| 1230 "pushq 56(%%rax)\n\t" \ | 1491 "pushq 56(%%rax)\n\t" \ |
| 1231 "movq 48(%%rax), %%r9\n\t" \ | 1492 "movq 48(%%rax), %%r9\n\t" \ |
| 1232 "movq 40(%%rax), %%r8\n\t" \ | 1493 "movq 40(%%rax), %%r8\n\t" \ |
| 1233 "movq 32(%%rax), %%rcx\n\t" \ | 1494 "movq 32(%%rax), %%rcx\n\t" \ |
| 1234 "movq 24(%%rax), %%rdx\n\t" \ | 1495 "movq 24(%%rax), %%rdx\n\t" \ |
| 1235 "movq 16(%%rax), %%rsi\n\t" \ | 1496 "movq 16(%%rax), %%rsi\n\t" \ |
| 1236 "movq 8(%%rax), %%rdi\n\t" \ | 1497 "movq 8(%%rax), %%rdi\n\t" \ |
| 1237 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1498 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1238 VALGRIND_CALL_NOREDIR_RAX \ | 1499 VALGRIND_CALL_NOREDIR_RAX \ |
| 1239 "addq $8, %%rsp\n" \ | 1500 "addq $8, %%rsp\n" \ |
| 1240 "addq $128,%%rsp\n\t" \ | 1501 "addq $136,%%rsp\n\t" \ |
| 1502 VALGRIND_CFI_EPILOGUE \ |
| 1241 : /*out*/ "=a" (_res) \ | 1503 : /*out*/ "=a" (_res) \ |
| 1242 : /*in*/ "a" (&_argvec[0]) \ | 1504 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1243 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1505 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1244 ); \ | 1506 ); \ |
| 1245 lval = (__typeof__(lval)) _res; \ | 1507 lval = (__typeof__(lval)) _res; \ |
| 1246 } while (0) | 1508 } while (0) |
| 1247 | 1509 |
| 1248 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1510 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1249 arg7,arg8) \ | 1511 arg7,arg8) \ |
| 1250 do { \ | 1512 do { \ |
| 1251 volatile OrigFn _orig = (orig); \ | 1513 volatile OrigFn _orig = (orig); \ |
| 1252 volatile unsigned long _argvec[9]; \ | 1514 volatile unsigned long _argvec[9]; \ |
| 1253 volatile unsigned long _res; \ | 1515 volatile unsigned long _res; \ |
| 1254 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1516 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1255 _argvec[1] = (unsigned long)(arg1); \ | 1517 _argvec[1] = (unsigned long)(arg1); \ |
| 1256 _argvec[2] = (unsigned long)(arg2); \ | 1518 _argvec[2] = (unsigned long)(arg2); \ |
| 1257 _argvec[3] = (unsigned long)(arg3); \ | 1519 _argvec[3] = (unsigned long)(arg3); \ |
| 1258 _argvec[4] = (unsigned long)(arg4); \ | 1520 _argvec[4] = (unsigned long)(arg4); \ |
| 1259 _argvec[5] = (unsigned long)(arg5); \ | 1521 _argvec[5] = (unsigned long)(arg5); \ |
| 1260 _argvec[6] = (unsigned long)(arg6); \ | 1522 _argvec[6] = (unsigned long)(arg6); \ |
| 1261 _argvec[7] = (unsigned long)(arg7); \ | 1523 _argvec[7] = (unsigned long)(arg7); \ |
| 1262 _argvec[8] = (unsigned long)(arg8); \ | 1524 _argvec[8] = (unsigned long)(arg8); \ |
| 1263 __asm__ volatile( \ | 1525 __asm__ volatile( \ |
| 1526 VALGRIND_CFI_PROLOGUE \ |
| 1264 "subq $128,%%rsp\n\t" \ | 1527 "subq $128,%%rsp\n\t" \ |
| 1265 "pushq 64(%%rax)\n\t" \ | 1528 "pushq 64(%%rax)\n\t" \ |
| 1266 "pushq 56(%%rax)\n\t" \ | 1529 "pushq 56(%%rax)\n\t" \ |
| 1267 "movq 48(%%rax), %%r9\n\t" \ | 1530 "movq 48(%%rax), %%r9\n\t" \ |
| 1268 "movq 40(%%rax), %%r8\n\t" \ | 1531 "movq 40(%%rax), %%r8\n\t" \ |
| 1269 "movq 32(%%rax), %%rcx\n\t" \ | 1532 "movq 32(%%rax), %%rcx\n\t" \ |
| 1270 "movq 24(%%rax), %%rdx\n\t" \ | 1533 "movq 24(%%rax), %%rdx\n\t" \ |
| 1271 "movq 16(%%rax), %%rsi\n\t" \ | 1534 "movq 16(%%rax), %%rsi\n\t" \ |
| 1272 "movq 8(%%rax), %%rdi\n\t" \ | 1535 "movq 8(%%rax), %%rdi\n\t" \ |
| 1273 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1536 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1274 VALGRIND_CALL_NOREDIR_RAX \ | 1537 VALGRIND_CALL_NOREDIR_RAX \ |
| 1275 "addq $16, %%rsp\n" \ | 1538 "addq $16, %%rsp\n" \ |
| 1276 "addq $128,%%rsp\n\t" \ | 1539 "addq $128,%%rsp\n\t" \ |
| 1540 VALGRIND_CFI_EPILOGUE \ |
| 1277 : /*out*/ "=a" (_res) \ | 1541 : /*out*/ "=a" (_res) \ |
| 1278 : /*in*/ "a" (&_argvec[0]) \ | 1542 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1279 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1543 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1280 ); \ | 1544 ); \ |
| 1281 lval = (__typeof__(lval)) _res; \ | 1545 lval = (__typeof__(lval)) _res; \ |
| 1282 } while (0) | 1546 } while (0) |
| 1283 | 1547 |
| 1284 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1548 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1285 arg7,arg8,arg9) \ | 1549 arg7,arg8,arg9) \ |
| 1286 do { \ | 1550 do { \ |
| 1287 volatile OrigFn _orig = (orig); \ | 1551 volatile OrigFn _orig = (orig); \ |
| 1288 volatile unsigned long _argvec[10]; \ | 1552 volatile unsigned long _argvec[10]; \ |
| 1289 volatile unsigned long _res; \ | 1553 volatile unsigned long _res; \ |
| 1290 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1554 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1291 _argvec[1] = (unsigned long)(arg1); \ | 1555 _argvec[1] = (unsigned long)(arg1); \ |
| 1292 _argvec[2] = (unsigned long)(arg2); \ | 1556 _argvec[2] = (unsigned long)(arg2); \ |
| 1293 _argvec[3] = (unsigned long)(arg3); \ | 1557 _argvec[3] = (unsigned long)(arg3); \ |
| 1294 _argvec[4] = (unsigned long)(arg4); \ | 1558 _argvec[4] = (unsigned long)(arg4); \ |
| 1295 _argvec[5] = (unsigned long)(arg5); \ | 1559 _argvec[5] = (unsigned long)(arg5); \ |
| 1296 _argvec[6] = (unsigned long)(arg6); \ | 1560 _argvec[6] = (unsigned long)(arg6); \ |
| 1297 _argvec[7] = (unsigned long)(arg7); \ | 1561 _argvec[7] = (unsigned long)(arg7); \ |
| 1298 _argvec[8] = (unsigned long)(arg8); \ | 1562 _argvec[8] = (unsigned long)(arg8); \ |
| 1299 _argvec[9] = (unsigned long)(arg9); \ | 1563 _argvec[9] = (unsigned long)(arg9); \ |
| 1300 __asm__ volatile( \ | 1564 __asm__ volatile( \ |
| 1301 "subq $128,%%rsp\n\t" \ | 1565 VALGRIND_CFI_PROLOGUE \ |
| 1566 "subq $136,%%rsp\n\t" \ |
| 1302 "pushq 72(%%rax)\n\t" \ | 1567 "pushq 72(%%rax)\n\t" \ |
| 1303 "pushq 64(%%rax)\n\t" \ | 1568 "pushq 64(%%rax)\n\t" \ |
| 1304 "pushq 56(%%rax)\n\t" \ | 1569 "pushq 56(%%rax)\n\t" \ |
| 1305 "movq 48(%%rax), %%r9\n\t" \ | 1570 "movq 48(%%rax), %%r9\n\t" \ |
| 1306 "movq 40(%%rax), %%r8\n\t" \ | 1571 "movq 40(%%rax), %%r8\n\t" \ |
| 1307 "movq 32(%%rax), %%rcx\n\t" \ | 1572 "movq 32(%%rax), %%rcx\n\t" \ |
| 1308 "movq 24(%%rax), %%rdx\n\t" \ | 1573 "movq 24(%%rax), %%rdx\n\t" \ |
| 1309 "movq 16(%%rax), %%rsi\n\t" \ | 1574 "movq 16(%%rax), %%rsi\n\t" \ |
| 1310 "movq 8(%%rax), %%rdi\n\t" \ | 1575 "movq 8(%%rax), %%rdi\n\t" \ |
| 1311 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1576 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1312 VALGRIND_CALL_NOREDIR_RAX \ | 1577 VALGRIND_CALL_NOREDIR_RAX \ |
| 1313 "addq $24, %%rsp\n" \ | 1578 "addq $24, %%rsp\n" \ |
| 1314 "addq $128,%%rsp\n\t" \ | 1579 "addq $136,%%rsp\n\t" \ |
| 1580 VALGRIND_CFI_EPILOGUE \ |
| 1315 : /*out*/ "=a" (_res) \ | 1581 : /*out*/ "=a" (_res) \ |
| 1316 : /*in*/ "a" (&_argvec[0]) \ | 1582 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1317 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1583 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1318 ); \ | 1584 ); \ |
| 1319 lval = (__typeof__(lval)) _res; \ | 1585 lval = (__typeof__(lval)) _res; \ |
| 1320 } while (0) | 1586 } while (0) |
| 1321 | 1587 |
| 1322 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1588 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1323 arg7,arg8,arg9,arg10) \ | 1589 arg7,arg8,arg9,arg10) \ |
| 1324 do { \ | 1590 do { \ |
| 1325 volatile OrigFn _orig = (orig); \ | 1591 volatile OrigFn _orig = (orig); \ |
| 1326 volatile unsigned long _argvec[11]; \ | 1592 volatile unsigned long _argvec[11]; \ |
| 1327 volatile unsigned long _res; \ | 1593 volatile unsigned long _res; \ |
| 1328 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1594 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1329 _argvec[1] = (unsigned long)(arg1); \ | 1595 _argvec[1] = (unsigned long)(arg1); \ |
| 1330 _argvec[2] = (unsigned long)(arg2); \ | 1596 _argvec[2] = (unsigned long)(arg2); \ |
| 1331 _argvec[3] = (unsigned long)(arg3); \ | 1597 _argvec[3] = (unsigned long)(arg3); \ |
| 1332 _argvec[4] = (unsigned long)(arg4); \ | 1598 _argvec[4] = (unsigned long)(arg4); \ |
| 1333 _argvec[5] = (unsigned long)(arg5); \ | 1599 _argvec[5] = (unsigned long)(arg5); \ |
| 1334 _argvec[6] = (unsigned long)(arg6); \ | 1600 _argvec[6] = (unsigned long)(arg6); \ |
| 1335 _argvec[7] = (unsigned long)(arg7); \ | 1601 _argvec[7] = (unsigned long)(arg7); \ |
| 1336 _argvec[8] = (unsigned long)(arg8); \ | 1602 _argvec[8] = (unsigned long)(arg8); \ |
| 1337 _argvec[9] = (unsigned long)(arg9); \ | 1603 _argvec[9] = (unsigned long)(arg9); \ |
| 1338 _argvec[10] = (unsigned long)(arg10); \ | 1604 _argvec[10] = (unsigned long)(arg10); \ |
| 1339 __asm__ volatile( \ | 1605 __asm__ volatile( \ |
| 1606 VALGRIND_CFI_PROLOGUE \ |
| 1340 "subq $128,%%rsp\n\t" \ | 1607 "subq $128,%%rsp\n\t" \ |
| 1341 "pushq 80(%%rax)\n\t" \ | 1608 "pushq 80(%%rax)\n\t" \ |
| 1342 "pushq 72(%%rax)\n\t" \ | 1609 "pushq 72(%%rax)\n\t" \ |
| 1343 "pushq 64(%%rax)\n\t" \ | 1610 "pushq 64(%%rax)\n\t" \ |
| 1344 "pushq 56(%%rax)\n\t" \ | 1611 "pushq 56(%%rax)\n\t" \ |
| 1345 "movq 48(%%rax), %%r9\n\t" \ | 1612 "movq 48(%%rax), %%r9\n\t" \ |
| 1346 "movq 40(%%rax), %%r8\n\t" \ | 1613 "movq 40(%%rax), %%r8\n\t" \ |
| 1347 "movq 32(%%rax), %%rcx\n\t" \ | 1614 "movq 32(%%rax), %%rcx\n\t" \ |
| 1348 "movq 24(%%rax), %%rdx\n\t" \ | 1615 "movq 24(%%rax), %%rdx\n\t" \ |
| 1349 "movq 16(%%rax), %%rsi\n\t" \ | 1616 "movq 16(%%rax), %%rsi\n\t" \ |
| 1350 "movq 8(%%rax), %%rdi\n\t" \ | 1617 "movq 8(%%rax), %%rdi\n\t" \ |
| 1351 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1618 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1352 VALGRIND_CALL_NOREDIR_RAX \ | 1619 VALGRIND_CALL_NOREDIR_RAX \ |
| 1353 "addq $32, %%rsp\n" \ | 1620 "addq $32, %%rsp\n" \ |
| 1354 "addq $128,%%rsp\n\t" \ | 1621 "addq $128,%%rsp\n\t" \ |
| 1622 VALGRIND_CFI_EPILOGUE \ |
| 1355 : /*out*/ "=a" (_res) \ | 1623 : /*out*/ "=a" (_res) \ |
| 1356 : /*in*/ "a" (&_argvec[0]) \ | 1624 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1357 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1625 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1358 ); \ | 1626 ); \ |
| 1359 lval = (__typeof__(lval)) _res; \ | 1627 lval = (__typeof__(lval)) _res; \ |
| 1360 } while (0) | 1628 } while (0) |
| 1361 | 1629 |
| 1362 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1630 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1363 arg7,arg8,arg9,arg10,arg11) \ | 1631 arg7,arg8,arg9,arg10,arg11) \ |
| 1364 do { \ | 1632 do { \ |
| 1365 volatile OrigFn _orig = (orig); \ | 1633 volatile OrigFn _orig = (orig); \ |
| 1366 volatile unsigned long _argvec[12]; \ | 1634 volatile unsigned long _argvec[12]; \ |
| 1367 volatile unsigned long _res; \ | 1635 volatile unsigned long _res; \ |
| 1368 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1636 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1369 _argvec[1] = (unsigned long)(arg1); \ | 1637 _argvec[1] = (unsigned long)(arg1); \ |
| 1370 _argvec[2] = (unsigned long)(arg2); \ | 1638 _argvec[2] = (unsigned long)(arg2); \ |
| 1371 _argvec[3] = (unsigned long)(arg3); \ | 1639 _argvec[3] = (unsigned long)(arg3); \ |
| 1372 _argvec[4] = (unsigned long)(arg4); \ | 1640 _argvec[4] = (unsigned long)(arg4); \ |
| 1373 _argvec[5] = (unsigned long)(arg5); \ | 1641 _argvec[5] = (unsigned long)(arg5); \ |
| 1374 _argvec[6] = (unsigned long)(arg6); \ | 1642 _argvec[6] = (unsigned long)(arg6); \ |
| 1375 _argvec[7] = (unsigned long)(arg7); \ | 1643 _argvec[7] = (unsigned long)(arg7); \ |
| 1376 _argvec[8] = (unsigned long)(arg8); \ | 1644 _argvec[8] = (unsigned long)(arg8); \ |
| 1377 _argvec[9] = (unsigned long)(arg9); \ | 1645 _argvec[9] = (unsigned long)(arg9); \ |
| 1378 _argvec[10] = (unsigned long)(arg10); \ | 1646 _argvec[10] = (unsigned long)(arg10); \ |
| 1379 _argvec[11] = (unsigned long)(arg11); \ | 1647 _argvec[11] = (unsigned long)(arg11); \ |
| 1380 __asm__ volatile( \ | 1648 __asm__ volatile( \ |
| 1381 "subq $128,%%rsp\n\t" \ | 1649 VALGRIND_CFI_PROLOGUE \ |
| 1650 "subq $136,%%rsp\n\t" \ |
| 1382 "pushq 88(%%rax)\n\t" \ | 1651 "pushq 88(%%rax)\n\t" \ |
| 1383 "pushq 80(%%rax)\n\t" \ | 1652 "pushq 80(%%rax)\n\t" \ |
| 1384 "pushq 72(%%rax)\n\t" \ | 1653 "pushq 72(%%rax)\n\t" \ |
| 1385 "pushq 64(%%rax)\n\t" \ | 1654 "pushq 64(%%rax)\n\t" \ |
| 1386 "pushq 56(%%rax)\n\t" \ | 1655 "pushq 56(%%rax)\n\t" \ |
| 1387 "movq 48(%%rax), %%r9\n\t" \ | 1656 "movq 48(%%rax), %%r9\n\t" \ |
| 1388 "movq 40(%%rax), %%r8\n\t" \ | 1657 "movq 40(%%rax), %%r8\n\t" \ |
| 1389 "movq 32(%%rax), %%rcx\n\t" \ | 1658 "movq 32(%%rax), %%rcx\n\t" \ |
| 1390 "movq 24(%%rax), %%rdx\n\t" \ | 1659 "movq 24(%%rax), %%rdx\n\t" \ |
| 1391 "movq 16(%%rax), %%rsi\n\t" \ | 1660 "movq 16(%%rax), %%rsi\n\t" \ |
| 1392 "movq 8(%%rax), %%rdi\n\t" \ | 1661 "movq 8(%%rax), %%rdi\n\t" \ |
| 1393 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1662 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1394 VALGRIND_CALL_NOREDIR_RAX \ | 1663 VALGRIND_CALL_NOREDIR_RAX \ |
| 1395 "addq $40, %%rsp\n" \ | 1664 "addq $40, %%rsp\n" \ |
| 1396 "addq $128,%%rsp\n\t" \ | 1665 "addq $136,%%rsp\n\t" \ |
| 1666 VALGRIND_CFI_EPILOGUE \ |
| 1397 : /*out*/ "=a" (_res) \ | 1667 : /*out*/ "=a" (_res) \ |
| 1398 : /*in*/ "a" (&_argvec[0]) \ | 1668 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1399 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1669 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1400 ); \ | 1670 ); \ |
| 1401 lval = (__typeof__(lval)) _res; \ | 1671 lval = (__typeof__(lval)) _res; \ |
| 1402 } while (0) | 1672 } while (0) |
| 1403 | 1673 |
| 1404 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ | 1674 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 1405 arg7,arg8,arg9,arg10,arg11,arg12) \ | 1675 arg7,arg8,arg9,arg10,arg11,arg12) \ |
| 1406 do { \ | 1676 do { \ |
| 1407 volatile OrigFn _orig = (orig); \ | 1677 volatile OrigFn _orig = (orig); \ |
| 1408 volatile unsigned long _argvec[13]; \ | 1678 volatile unsigned long _argvec[13]; \ |
| 1409 volatile unsigned long _res; \ | 1679 volatile unsigned long _res; \ |
| 1410 _argvec[0] = (unsigned long)_orig.nraddr; \ | 1680 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 1411 _argvec[1] = (unsigned long)(arg1); \ | 1681 _argvec[1] = (unsigned long)(arg1); \ |
| 1412 _argvec[2] = (unsigned long)(arg2); \ | 1682 _argvec[2] = (unsigned long)(arg2); \ |
| 1413 _argvec[3] = (unsigned long)(arg3); \ | 1683 _argvec[3] = (unsigned long)(arg3); \ |
| 1414 _argvec[4] = (unsigned long)(arg4); \ | 1684 _argvec[4] = (unsigned long)(arg4); \ |
| 1415 _argvec[5] = (unsigned long)(arg5); \ | 1685 _argvec[5] = (unsigned long)(arg5); \ |
| 1416 _argvec[6] = (unsigned long)(arg6); \ | 1686 _argvec[6] = (unsigned long)(arg6); \ |
| 1417 _argvec[7] = (unsigned long)(arg7); \ | 1687 _argvec[7] = (unsigned long)(arg7); \ |
| 1418 _argvec[8] = (unsigned long)(arg8); \ | 1688 _argvec[8] = (unsigned long)(arg8); \ |
| 1419 _argvec[9] = (unsigned long)(arg9); \ | 1689 _argvec[9] = (unsigned long)(arg9); \ |
| 1420 _argvec[10] = (unsigned long)(arg10); \ | 1690 _argvec[10] = (unsigned long)(arg10); \ |
| 1421 _argvec[11] = (unsigned long)(arg11); \ | 1691 _argvec[11] = (unsigned long)(arg11); \ |
| 1422 _argvec[12] = (unsigned long)(arg12); \ | 1692 _argvec[12] = (unsigned long)(arg12); \ |
| 1423 __asm__ volatile( \ | 1693 __asm__ volatile( \ |
| 1694 VALGRIND_CFI_PROLOGUE \ |
| 1424 "subq $128,%%rsp\n\t" \ | 1695 "subq $128,%%rsp\n\t" \ |
| 1425 "pushq 96(%%rax)\n\t" \ | 1696 "pushq 96(%%rax)\n\t" \ |
| 1426 "pushq 88(%%rax)\n\t" \ | 1697 "pushq 88(%%rax)\n\t" \ |
| 1427 "pushq 80(%%rax)\n\t" \ | 1698 "pushq 80(%%rax)\n\t" \ |
| 1428 "pushq 72(%%rax)\n\t" \ | 1699 "pushq 72(%%rax)\n\t" \ |
| 1429 "pushq 64(%%rax)\n\t" \ | 1700 "pushq 64(%%rax)\n\t" \ |
| 1430 "pushq 56(%%rax)\n\t" \ | 1701 "pushq 56(%%rax)\n\t" \ |
| 1431 "movq 48(%%rax), %%r9\n\t" \ | 1702 "movq 48(%%rax), %%r9\n\t" \ |
| 1432 "movq 40(%%rax), %%r8\n\t" \ | 1703 "movq 40(%%rax), %%r8\n\t" \ |
| 1433 "movq 32(%%rax), %%rcx\n\t" \ | 1704 "movq 32(%%rax), %%rcx\n\t" \ |
| 1434 "movq 24(%%rax), %%rdx\n\t" \ | 1705 "movq 24(%%rax), %%rdx\n\t" \ |
| 1435 "movq 16(%%rax), %%rsi\n\t" \ | 1706 "movq 16(%%rax), %%rsi\n\t" \ |
| 1436 "movq 8(%%rax), %%rdi\n\t" \ | 1707 "movq 8(%%rax), %%rdi\n\t" \ |
| 1437 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ | 1708 "movq (%%rax), %%rax\n\t" /* target->%rax */ \ |
| 1438 VALGRIND_CALL_NOREDIR_RAX \ | 1709 VALGRIND_CALL_NOREDIR_RAX \ |
| 1439 "addq $48, %%rsp\n" \ | 1710 "addq $48, %%rsp\n" \ |
| 1440 "addq $128,%%rsp\n\t" \ | 1711 "addq $128,%%rsp\n\t" \ |
| 1712 VALGRIND_CFI_EPILOGUE \ |
| 1441 : /*out*/ "=a" (_res) \ | 1713 : /*out*/ "=a" (_res) \ |
| 1442 : /*in*/ "a" (&_argvec[0]) \ | 1714 : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \ |
| 1443 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 1715 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS, "r15" \ |
| 1444 ); \ | 1716 ); \ |
| 1445 lval = (__typeof__(lval)) _res; \ | 1717 lval = (__typeof__(lval)) _res; \ |
| 1446 } while (0) | 1718 } while (0) |
| 1447 | 1719 |
| 1448 #endif /* PLAT_amd64_linux */ | 1720 #endif /* PLAT_amd64_linux || PLAT_amd64_darwin */ |
| 1449 | 1721 |
| 1450 /* ------------------------ ppc32-linux ------------------------ */ | 1722 /* ------------------------ ppc32-linux ------------------------ */ |
| 1451 | 1723 |
| 1452 #if defined(PLAT_ppc32_linux) | 1724 #if defined(PLAT_ppc32_linux) |
| 1453 | 1725 |
| 1454 /* This is useful for finding out about the on-stack stuff: | 1726 /* This is useful for finding out about the on-stack stuff: |
| 1455 | 1727 |
| 1456 extern int f9 ( int,int,int,int,int,int,int,int,int ); | 1728 extern int f9 ( int,int,int,int,int,int,int,int,int ); |
| 1457 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); | 1729 extern int f10 ( int,int,int,int,int,int,int,int,int,int ); |
| 1458 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); | 1730 extern int f11 ( int,int,int,int,int,int,int,int,int,int,int ); |
| (...skipping 972 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2431 "addi 1,1,144" /* restore frame */ \ | 2703 "addi 1,1,144" /* restore frame */ \ |
| 2432 : /*out*/ "=r" (_res) \ | 2704 : /*out*/ "=r" (_res) \ |
| 2433 : /*in*/ "r" (&_argvec[2]) \ | 2705 : /*in*/ "r" (&_argvec[2]) \ |
| 2434 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ | 2706 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2435 ); \ | 2707 ); \ |
| 2436 lval = (__typeof__(lval)) _res; \ | 2708 lval = (__typeof__(lval)) _res; \ |
| 2437 } while (0) | 2709 } while (0) |
| 2438 | 2710 |
| 2439 #endif /* PLAT_ppc64_linux */ | 2711 #endif /* PLAT_ppc64_linux */ |
| 2440 | 2712 |
| 2713 /* ------------------------- arm-linux ------------------------- */ |
| 2714 |
| 2715 #if defined(PLAT_arm_linux) |
| 2716 |
| 2717 /* These regs are trashed by the hidden call. */ |
| 2718 #define __CALLER_SAVED_REGS "r0", "r1", "r2", "r3","r4","r14" |
| 2719 |
| 2720 /* These CALL_FN_ macros assume that on arm-linux, sizeof(unsigned |
| 2721 long) == 4. */ |
| 2722 |
| 2723 #define CALL_FN_W_v(lval, orig) \ |
| 2724 do { \ |
| 2725 volatile OrigFn _orig = (orig); \ |
| 2726 volatile unsigned long _argvec[1]; \ |
| 2727 volatile unsigned long _res; \ |
| 2728 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2729 __asm__ volatile( \ |
| 2730 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2731 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2732 "mov %0, r0\n" \ |
| 2733 : /*out*/ "=r" (_res) \ |
| 2734 : /*in*/ "0" (&_argvec[0]) \ |
| 2735 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2736 ); \ |
| 2737 lval = (__typeof__(lval)) _res; \ |
| 2738 } while (0) |
| 2739 |
| 2740 #define CALL_FN_W_W(lval, orig, arg1) \ |
| 2741 do { \ |
| 2742 volatile OrigFn _orig = (orig); \ |
| 2743 volatile unsigned long _argvec[2]; \ |
| 2744 volatile unsigned long _res; \ |
| 2745 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2746 _argvec[1] = (unsigned long)(arg1); \ |
| 2747 __asm__ volatile( \ |
| 2748 "ldr r0, [%1, #4] \n\t" \ |
| 2749 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2750 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2751 "mov %0, r0\n" \ |
| 2752 : /*out*/ "=r" (_res) \ |
| 2753 : /*in*/ "0" (&_argvec[0]) \ |
| 2754 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2755 ); \ |
| 2756 lval = (__typeof__(lval)) _res; \ |
| 2757 } while (0) |
| 2758 |
| 2759 #define CALL_FN_W_WW(lval, orig, arg1,arg2) \ |
| 2760 do { \ |
| 2761 volatile OrigFn _orig = (orig); \ |
| 2762 volatile unsigned long _argvec[3]; \ |
| 2763 volatile unsigned long _res; \ |
| 2764 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2765 _argvec[1] = (unsigned long)(arg1); \ |
| 2766 _argvec[2] = (unsigned long)(arg2); \ |
| 2767 __asm__ volatile( \ |
| 2768 "ldr r0, [%1, #4] \n\t" \ |
| 2769 "ldr r1, [%1, #8] \n\t" \ |
| 2770 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2771 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2772 "mov %0, r0\n" \ |
| 2773 : /*out*/ "=r" (_res) \ |
| 2774 : /*in*/ "0" (&_argvec[0]) \ |
| 2775 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2776 ); \ |
| 2777 lval = (__typeof__(lval)) _res; \ |
| 2778 } while (0) |
| 2779 |
| 2780 #define CALL_FN_W_WWW(lval, orig, arg1,arg2,arg3) \ |
| 2781 do { \ |
| 2782 volatile OrigFn _orig = (orig); \ |
| 2783 volatile unsigned long _argvec[4]; \ |
| 2784 volatile unsigned long _res; \ |
| 2785 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2786 _argvec[1] = (unsigned long)(arg1); \ |
| 2787 _argvec[2] = (unsigned long)(arg2); \ |
| 2788 _argvec[3] = (unsigned long)(arg3); \ |
| 2789 __asm__ volatile( \ |
| 2790 "ldr r0, [%1, #4] \n\t" \ |
| 2791 "ldr r1, [%1, #8] \n\t" \ |
| 2792 "ldr r2, [%1, #12] \n\t" \ |
| 2793 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2794 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2795 "mov %0, r0\n" \ |
| 2796 : /*out*/ "=r" (_res) \ |
| 2797 : /*in*/ "0" (&_argvec[0]) \ |
| 2798 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2799 ); \ |
| 2800 lval = (__typeof__(lval)) _res; \ |
| 2801 } while (0) |
| 2802 |
| 2803 #define CALL_FN_W_WWWW(lval, orig, arg1,arg2,arg3,arg4) \ |
| 2804 do { \ |
| 2805 volatile OrigFn _orig = (orig); \ |
| 2806 volatile unsigned long _argvec[5]; \ |
| 2807 volatile unsigned long _res; \ |
| 2808 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2809 _argvec[1] = (unsigned long)(arg1); \ |
| 2810 _argvec[2] = (unsigned long)(arg2); \ |
| 2811 _argvec[3] = (unsigned long)(arg3); \ |
| 2812 _argvec[4] = (unsigned long)(arg4); \ |
| 2813 __asm__ volatile( \ |
| 2814 "ldr r0, [%1, #4] \n\t" \ |
| 2815 "ldr r1, [%1, #8] \n\t" \ |
| 2816 "ldr r2, [%1, #12] \n\t" \ |
| 2817 "ldr r3, [%1, #16] \n\t" \ |
| 2818 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2819 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2820 "mov %0, r0" \ |
| 2821 : /*out*/ "=r" (_res) \ |
| 2822 : /*in*/ "0" (&_argvec[0]) \ |
| 2823 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2824 ); \ |
| 2825 lval = (__typeof__(lval)) _res; \ |
| 2826 } while (0) |
| 2827 |
| 2828 #define CALL_FN_W_5W(lval, orig, arg1,arg2,arg3,arg4,arg5) \ |
| 2829 do { \ |
| 2830 volatile OrigFn _orig = (orig); \ |
| 2831 volatile unsigned long _argvec[6]; \ |
| 2832 volatile unsigned long _res; \ |
| 2833 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2834 _argvec[1] = (unsigned long)(arg1); \ |
| 2835 _argvec[2] = (unsigned long)(arg2); \ |
| 2836 _argvec[3] = (unsigned long)(arg3); \ |
| 2837 _argvec[4] = (unsigned long)(arg4); \ |
| 2838 _argvec[5] = (unsigned long)(arg5); \ |
| 2839 __asm__ volatile( \ |
| 2840 "ldr r0, [%1, #20] \n\t" \ |
| 2841 "push {r0} \n\t" \ |
| 2842 "ldr r0, [%1, #4] \n\t" \ |
| 2843 "ldr r1, [%1, #8] \n\t" \ |
| 2844 "ldr r2, [%1, #12] \n\t" \ |
| 2845 "ldr r3, [%1, #16] \n\t" \ |
| 2846 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2847 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2848 "add sp, sp, #4 \n\t" \ |
| 2849 "mov %0, r0" \ |
| 2850 : /*out*/ "=r" (_res) \ |
| 2851 : /*in*/ "0" (&_argvec[0]) \ |
| 2852 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2853 ); \ |
| 2854 lval = (__typeof__(lval)) _res; \ |
| 2855 } while (0) |
| 2856 |
| 2857 #define CALL_FN_W_6W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6) \ |
| 2858 do { \ |
| 2859 volatile OrigFn _orig = (orig); \ |
| 2860 volatile unsigned long _argvec[7]; \ |
| 2861 volatile unsigned long _res; \ |
| 2862 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2863 _argvec[1] = (unsigned long)(arg1); \ |
| 2864 _argvec[2] = (unsigned long)(arg2); \ |
| 2865 _argvec[3] = (unsigned long)(arg3); \ |
| 2866 _argvec[4] = (unsigned long)(arg4); \ |
| 2867 _argvec[5] = (unsigned long)(arg5); \ |
| 2868 _argvec[6] = (unsigned long)(arg6); \ |
| 2869 __asm__ volatile( \ |
| 2870 "ldr r0, [%1, #20] \n\t" \ |
| 2871 "ldr r1, [%1, #24] \n\t" \ |
| 2872 "push {r0, r1} \n\t" \ |
| 2873 "ldr r0, [%1, #4] \n\t" \ |
| 2874 "ldr r1, [%1, #8] \n\t" \ |
| 2875 "ldr r2, [%1, #12] \n\t" \ |
| 2876 "ldr r3, [%1, #16] \n\t" \ |
| 2877 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2878 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2879 "add sp, sp, #8 \n\t" \ |
| 2880 "mov %0, r0" \ |
| 2881 : /*out*/ "=r" (_res) \ |
| 2882 : /*in*/ "0" (&_argvec[0]) \ |
| 2883 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2884 ); \ |
| 2885 lval = (__typeof__(lval)) _res; \ |
| 2886 } while (0) |
| 2887 |
| 2888 #define CALL_FN_W_7W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 2889 arg7) \ |
| 2890 do { \ |
| 2891 volatile OrigFn _orig = (orig); \ |
| 2892 volatile unsigned long _argvec[8]; \ |
| 2893 volatile unsigned long _res; \ |
| 2894 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2895 _argvec[1] = (unsigned long)(arg1); \ |
| 2896 _argvec[2] = (unsigned long)(arg2); \ |
| 2897 _argvec[3] = (unsigned long)(arg3); \ |
| 2898 _argvec[4] = (unsigned long)(arg4); \ |
| 2899 _argvec[5] = (unsigned long)(arg5); \ |
| 2900 _argvec[6] = (unsigned long)(arg6); \ |
| 2901 _argvec[7] = (unsigned long)(arg7); \ |
| 2902 __asm__ volatile( \ |
| 2903 "ldr r0, [%1, #20] \n\t" \ |
| 2904 "ldr r1, [%1, #24] \n\t" \ |
| 2905 "ldr r2, [%1, #28] \n\t" \ |
| 2906 "push {r0, r1, r2} \n\t" \ |
| 2907 "ldr r0, [%1, #4] \n\t" \ |
| 2908 "ldr r1, [%1, #8] \n\t" \ |
| 2909 "ldr r2, [%1, #12] \n\t" \ |
| 2910 "ldr r3, [%1, #16] \n\t" \ |
| 2911 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2912 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2913 "add sp, sp, #12 \n\t" \ |
| 2914 "mov %0, r0" \ |
| 2915 : /*out*/ "=r" (_res) \ |
| 2916 : /*in*/ "0" (&_argvec[0]) \ |
| 2917 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2918 ); \ |
| 2919 lval = (__typeof__(lval)) _res; \ |
| 2920 } while (0) |
| 2921 |
| 2922 #define CALL_FN_W_8W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 2923 arg7,arg8) \ |
| 2924 do { \ |
| 2925 volatile OrigFn _orig = (orig); \ |
| 2926 volatile unsigned long _argvec[9]; \ |
| 2927 volatile unsigned long _res; \ |
| 2928 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2929 _argvec[1] = (unsigned long)(arg1); \ |
| 2930 _argvec[2] = (unsigned long)(arg2); \ |
| 2931 _argvec[3] = (unsigned long)(arg3); \ |
| 2932 _argvec[4] = (unsigned long)(arg4); \ |
| 2933 _argvec[5] = (unsigned long)(arg5); \ |
| 2934 _argvec[6] = (unsigned long)(arg6); \ |
| 2935 _argvec[7] = (unsigned long)(arg7); \ |
| 2936 _argvec[8] = (unsigned long)(arg8); \ |
| 2937 __asm__ volatile( \ |
| 2938 "ldr r0, [%1, #20] \n\t" \ |
| 2939 "ldr r1, [%1, #24] \n\t" \ |
| 2940 "ldr r2, [%1, #28] \n\t" \ |
| 2941 "ldr r3, [%1, #32] \n\t" \ |
| 2942 "push {r0, r1, r2, r3} \n\t" \ |
| 2943 "ldr r0, [%1, #4] \n\t" \ |
| 2944 "ldr r1, [%1, #8] \n\t" \ |
| 2945 "ldr r2, [%1, #12] \n\t" \ |
| 2946 "ldr r3, [%1, #16] \n\t" \ |
| 2947 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2948 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2949 "add sp, sp, #16 \n\t" \ |
| 2950 "mov %0, r0" \ |
| 2951 : /*out*/ "=r" (_res) \ |
| 2952 : /*in*/ "0" (&_argvec[0]) \ |
| 2953 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2954 ); \ |
| 2955 lval = (__typeof__(lval)) _res; \ |
| 2956 } while (0) |
| 2957 |
| 2958 #define CALL_FN_W_9W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 2959 arg7,arg8,arg9) \ |
| 2960 do { \ |
| 2961 volatile OrigFn _orig = (orig); \ |
| 2962 volatile unsigned long _argvec[10]; \ |
| 2963 volatile unsigned long _res; \ |
| 2964 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 2965 _argvec[1] = (unsigned long)(arg1); \ |
| 2966 _argvec[2] = (unsigned long)(arg2); \ |
| 2967 _argvec[3] = (unsigned long)(arg3); \ |
| 2968 _argvec[4] = (unsigned long)(arg4); \ |
| 2969 _argvec[5] = (unsigned long)(arg5); \ |
| 2970 _argvec[6] = (unsigned long)(arg6); \ |
| 2971 _argvec[7] = (unsigned long)(arg7); \ |
| 2972 _argvec[8] = (unsigned long)(arg8); \ |
| 2973 _argvec[9] = (unsigned long)(arg9); \ |
| 2974 __asm__ volatile( \ |
| 2975 "ldr r0, [%1, #20] \n\t" \ |
| 2976 "ldr r1, [%1, #24] \n\t" \ |
| 2977 "ldr r2, [%1, #28] \n\t" \ |
| 2978 "ldr r3, [%1, #32] \n\t" \ |
| 2979 "ldr r4, [%1, #36] \n\t" \ |
| 2980 "push {r0, r1, r2, r3, r4} \n\t" \ |
| 2981 "ldr r0, [%1, #4] \n\t" \ |
| 2982 "ldr r1, [%1, #8] \n\t" \ |
| 2983 "ldr r2, [%1, #12] \n\t" \ |
| 2984 "ldr r3, [%1, #16] \n\t" \ |
| 2985 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 2986 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 2987 "add sp, sp, #20 \n\t" \ |
| 2988 "mov %0, r0" \ |
| 2989 : /*out*/ "=r" (_res) \ |
| 2990 : /*in*/ "0" (&_argvec[0]) \ |
| 2991 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 2992 ); \ |
| 2993 lval = (__typeof__(lval)) _res; \ |
| 2994 } while (0) |
| 2995 |
| 2996 #define CALL_FN_W_10W(lval, orig, arg1,arg2,arg3,arg4,arg5,arg6, \ |
| 2997 arg7,arg8,arg9,arg10) \ |
| 2998 do { \ |
| 2999 volatile OrigFn _orig = (orig); \ |
| 3000 volatile unsigned long _argvec[11]; \ |
| 3001 volatile unsigned long _res; \ |
| 3002 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 3003 _argvec[1] = (unsigned long)(arg1); \ |
| 3004 _argvec[2] = (unsigned long)(arg2); \ |
| 3005 _argvec[3] = (unsigned long)(arg3); \ |
| 3006 _argvec[4] = (unsigned long)(arg4); \ |
| 3007 _argvec[5] = (unsigned long)(arg5); \ |
| 3008 _argvec[6] = (unsigned long)(arg6); \ |
| 3009 _argvec[7] = (unsigned long)(arg7); \ |
| 3010 _argvec[8] = (unsigned long)(arg8); \ |
| 3011 _argvec[9] = (unsigned long)(arg9); \ |
| 3012 _argvec[10] = (unsigned long)(arg10); \ |
| 3013 __asm__ volatile( \ |
| 3014 "ldr r0, [%1, #40] \n\t" \ |
| 3015 "push {r0} \n\t" \ |
| 3016 "ldr r0, [%1, #20] \n\t" \ |
| 3017 "ldr r1, [%1, #24] \n\t" \ |
| 3018 "ldr r2, [%1, #28] \n\t" \ |
| 3019 "ldr r3, [%1, #32] \n\t" \ |
| 3020 "ldr r4, [%1, #36] \n\t" \ |
| 3021 "push {r0, r1, r2, r3, r4} \n\t" \ |
| 3022 "ldr r0, [%1, #4] \n\t" \ |
| 3023 "ldr r1, [%1, #8] \n\t" \ |
| 3024 "ldr r2, [%1, #12] \n\t" \ |
| 3025 "ldr r3, [%1, #16] \n\t" \ |
| 3026 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 3027 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 3028 "add sp, sp, #24 \n\t" \ |
| 3029 "mov %0, r0" \ |
| 3030 : /*out*/ "=r" (_res) \ |
| 3031 : /*in*/ "0" (&_argvec[0]) \ |
| 3032 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 3033 ); \ |
| 3034 lval = (__typeof__(lval)) _res; \ |
| 3035 } while (0) |
| 3036 |
| 3037 #define CALL_FN_W_11W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ |
| 3038 arg6,arg7,arg8,arg9,arg10, \ |
| 3039 arg11) \ |
| 3040 do { \ |
| 3041 volatile OrigFn _orig = (orig); \ |
| 3042 volatile unsigned long _argvec[12]; \ |
| 3043 volatile unsigned long _res; \ |
| 3044 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 3045 _argvec[1] = (unsigned long)(arg1); \ |
| 3046 _argvec[2] = (unsigned long)(arg2); \ |
| 3047 _argvec[3] = (unsigned long)(arg3); \ |
| 3048 _argvec[4] = (unsigned long)(arg4); \ |
| 3049 _argvec[5] = (unsigned long)(arg5); \ |
| 3050 _argvec[6] = (unsigned long)(arg6); \ |
| 3051 _argvec[7] = (unsigned long)(arg7); \ |
| 3052 _argvec[8] = (unsigned long)(arg8); \ |
| 3053 _argvec[9] = (unsigned long)(arg9); \ |
| 3054 _argvec[10] = (unsigned long)(arg10); \ |
| 3055 _argvec[11] = (unsigned long)(arg11); \ |
| 3056 __asm__ volatile( \ |
| 3057 "ldr r0, [%1, #40] \n\t" \ |
| 3058 "ldr r1, [%1, #44] \n\t" \ |
| 3059 "push {r0, r1} \n\t" \ |
| 3060 "ldr r0, [%1, #20] \n\t" \ |
| 3061 "ldr r1, [%1, #24] \n\t" \ |
| 3062 "ldr r2, [%1, #28] \n\t" \ |
| 3063 "ldr r3, [%1, #32] \n\t" \ |
| 3064 "ldr r4, [%1, #36] \n\t" \ |
| 3065 "push {r0, r1, r2, r3, r4} \n\t" \ |
| 3066 "ldr r0, [%1, #4] \n\t" \ |
| 3067 "ldr r1, [%1, #8] \n\t" \ |
| 3068 "ldr r2, [%1, #12] \n\t" \ |
| 3069 "ldr r3, [%1, #16] \n\t" \ |
| 3070 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 3071 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 3072 "add sp, sp, #28 \n\t" \ |
| 3073 "mov %0, r0" \ |
| 3074 : /*out*/ "=r" (_res) \ |
| 3075 : /*in*/ "0" (&_argvec[0]) \ |
| 3076 : /*trash*/ "cc", "memory",__CALLER_SAVED_REGS \ |
| 3077 ); \ |
| 3078 lval = (__typeof__(lval)) _res; \ |
| 3079 } while (0) |
| 3080 |
| 3081 #define CALL_FN_W_12W(lval, orig, arg1,arg2,arg3,arg4,arg5, \ |
| 3082 arg6,arg7,arg8,arg9,arg10, \ |
| 3083 arg11,arg12) \ |
| 3084 do { \ |
| 3085 volatile OrigFn _orig = (orig); \ |
| 3086 volatile unsigned long _argvec[13]; \ |
| 3087 volatile unsigned long _res; \ |
| 3088 _argvec[0] = (unsigned long)_orig.nraddr; \ |
| 3089 _argvec[1] = (unsigned long)(arg1); \ |
| 3090 _argvec[2] = (unsigned long)(arg2); \ |
| 3091 _argvec[3] = (unsigned long)(arg3); \ |
| 3092 _argvec[4] = (unsigned long)(arg4); \ |
| 3093 _argvec[5] = (unsigned long)(arg5); \ |
| 3094 _argvec[6] = (unsigned long)(arg6); \ |
| 3095 _argvec[7] = (unsigned long)(arg7); \ |
| 3096 _argvec[8] = (unsigned long)(arg8); \ |
| 3097 _argvec[9] = (unsigned long)(arg9); \ |
| 3098 _argvec[10] = (unsigned long)(arg10); \ |
| 3099 _argvec[11] = (unsigned long)(arg11); \ |
| 3100 _argvec[12] = (unsigned long)(arg12); \ |
| 3101 __asm__ volatile( \ |
| 3102 "ldr r0, [%1, #40] \n\t" \ |
| 3103 "ldr r1, [%1, #44] \n\t" \ |
| 3104 "ldr r2, [%1, #48] \n\t" \ |
| 3105 "push {r0, r1, r2} \n\t" \ |
| 3106 "ldr r0, [%1, #20] \n\t" \ |
| 3107 "ldr r1, [%1, #24] \n\t" \ |
| 3108 "ldr r2, [%1, #28] \n\t" \ |
| 3109 "ldr r3, [%1, #32] \n\t" \ |
| 3110 "ldr r4, [%1, #36] \n\t" \ |
| 3111 "push {r0, r1, r2, r3, r4} \n\t" \ |
| 3112 "ldr r0, [%1, #4] \n\t" \ |
| 3113 "ldr r1, [%1, #8] \n\t" \ |
| 3114 "ldr r2, [%1, #12] \n\t" \ |
| 3115 "ldr r3, [%1, #16] \n\t" \ |
| 3116 "ldr r4, [%1] \n\t" /* target->r4 */ \ |
| 3117 VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R4 \ |
| 3118 "add sp, sp, #32 \n\t" \ |
| 3119 "mov %0, r0" \ |
| 3120 : /*out*/ "=r" (_res) \ |
| 3121 : /*in*/ "0" (&_argvec[0]) \ |
| 3122 : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS \ |
| 3123 ); \ |
| 3124 lval = (__typeof__(lval)) _res; \ |
| 3125 } while (0) |
| 3126 |
| 3127 #endif /* PLAT_arm_linux */ |
| 3128 |
| 2441 /* ------------------------ ppc32-aix5 ------------------------- */ | 3129 /* ------------------------ ppc32-aix5 ------------------------- */ |
| 2442 | 3130 |
| 2443 #if defined(PLAT_ppc32_aix5) | 3131 #if defined(PLAT_ppc32_aix5) |
| 2444 | 3132 |
| 2445 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ | 3133 /* ARGREGS: r3 r4 r5 r6 r7 r8 r9 r10 (the rest on stack somewhere) */ |
| 2446 | 3134 |
| 2447 /* These regs are trashed by the hidden call. */ | 3135 /* These regs are trashed by the hidden call. */ |
| 2448 #define __CALLER_SAVED_REGS \ | 3136 #define __CALLER_SAVED_REGS \ |
| 2449 "lr", "ctr", "xer", \ | 3137 "lr", "ctr", "xer", \ |
| 2450 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ | 3138 "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \ |
| (...skipping 1161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3612 VG_USERREQ__CREATE_MEMPOOL = 0x1303, | 4300 VG_USERREQ__CREATE_MEMPOOL = 0x1303, |
| 3613 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, | 4301 VG_USERREQ__DESTROY_MEMPOOL = 0x1304, |
| 3614 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, | 4302 VG_USERREQ__MEMPOOL_ALLOC = 0x1305, |
| 3615 VG_USERREQ__MEMPOOL_FREE = 0x1306, | 4303 VG_USERREQ__MEMPOOL_FREE = 0x1306, |
| 3616 VG_USERREQ__MEMPOOL_TRIM = 0x1307, | 4304 VG_USERREQ__MEMPOOL_TRIM = 0x1307, |
| 3617 VG_USERREQ__MOVE_MEMPOOL = 0x1308, | 4305 VG_USERREQ__MOVE_MEMPOOL = 0x1308, |
| 3618 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, | 4306 VG_USERREQ__MEMPOOL_CHANGE = 0x1309, |
| 3619 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, | 4307 VG_USERREQ__MEMPOOL_EXISTS = 0x130a, |
| 3620 | 4308 |
| 3621 /* Allow printfs to valgrind log. */ | 4309 /* Allow printfs to valgrind log. */ |
| 4310 /* The first two pass the va_list argument by value, which |
| 4311 assumes it is the same size as or smaller than a UWord, |
| 4312 which generally isn't the case. Hence are deprecated. |
| 4313 The second two pass the vargs by reference and so are |
| 4314 immune to this problem. */ |
| 4315 /* both :: char* fmt, va_list vargs (DEPRECATED) */ |
| 3622 VG_USERREQ__PRINTF = 0x1401, | 4316 VG_USERREQ__PRINTF = 0x1401, |
| 3623 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, | 4317 VG_USERREQ__PRINTF_BACKTRACE = 0x1402, |
| 4318 /* both :: char* fmt, va_list* vargs */ |
| 4319 VG_USERREQ__PRINTF_VALIST_BY_REF = 0x1403, |
| 4320 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF = 0x1404, |
| 3624 | 4321 |
| 3625 /* Stack support. */ | 4322 /* Stack support. */ |
| 3626 VG_USERREQ__STACK_REGISTER = 0x1501, | 4323 VG_USERREQ__STACK_REGISTER = 0x1501, |
| 3627 VG_USERREQ__STACK_DEREGISTER = 0x1502, | 4324 VG_USERREQ__STACK_DEREGISTER = 0x1502, |
| 3628 VG_USERREQ__STACK_CHANGE = 0x1503 | 4325 VG_USERREQ__STACK_CHANGE = 0x1503, |
| 4326 |
| 4327 /* Wine support */ |
| 4328 VG_USERREQ__LOAD_PDB_DEBUGINFO = 0x1601, |
| 4329 |
| 4330 /* Querying of debug info. */ |
| 4331 VG_USERREQ__MAP_IP_TO_SRCLOC = 0x1701 |
| 3629 } Vg_ClientRequest; | 4332 } Vg_ClientRequest; |
| 3630 | 4333 |
| 3631 #if !defined(__GNUC__) | 4334 #if !defined(__GNUC__) |
| 3632 # define __extension__ /* */ | 4335 # define __extension__ /* */ |
| 3633 #endif | 4336 #endif |
| 3634 | 4337 |
| 4338 |
| 4339 /* |
| 4340 * VALGRIND_DO_CLIENT_REQUEST_EXPR(): a C expression that invokes a Valgrind |
| 4341 * client request and whose value equals the client request result. |
| 4342 */ |
| 4343 |
| 4344 #if defined(NVALGRIND) |
| 4345 |
| 4346 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ |
| 4347 _zzq_default, _zzq_request, \ |
| 4348 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 4349 (_zzq_default) |
| 4350 |
| 4351 #else /*defined(NVALGRIND)*/ |
| 4352 |
| 4353 #if defined(_MSC_VER) |
| 4354 |
| 4355 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ |
| 4356 _zzq_default, _zzq_request, \ |
| 4357 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 4358 (vg_VALGRIND_DO_CLIENT_REQUEST_EXPR((uintptr_t)(_zzq_default), \ |
| 4359 (_zzq_request), (uintptr_t)(_zzq_arg1), (uintptr_t)(_zzq_arg2), \ |
| 4360 (uintptr_t)(_zzq_arg3), (uintptr_t)(_zzq_arg4), \ |
| 4361 (uintptr_t)(_zzq_arg5))) |
| 4362 |
| 4363 static __inline unsigned |
| 4364 vg_VALGRIND_DO_CLIENT_REQUEST_EXPR(uintptr_t _zzq_default, |
| 4365 unsigned _zzq_request, uintptr_t _zzq_arg1, |
| 4366 uintptr_t _zzq_arg2, uintptr_t _zzq_arg3, |
| 4367 uintptr_t _zzq_arg4, uintptr_t _zzq_arg5) |
| 4368 { |
| 4369 unsigned _zzq_rlval; |
| 4370 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, |
| 4371 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5); |
| 4372 return _zzq_rlval; |
| 4373 } |
| 4374 |
| 4375 #else /*defined(_MSC_VER)*/ |
| 4376 |
| 4377 #define VALGRIND_DO_CLIENT_REQUEST_EXPR( \ |
| 4378 _zzq_default, _zzq_request, \ |
| 4379 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 4380 (__extension__({unsigned int _zzq_rlval; \ |
| 4381 VALGRIND_DO_CLIENT_REQUEST(_zzq_rlval, _zzq_default, _zzq_request, \ |
| 4382 _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \ |
| 4383 _zzq_rlval; \ |
| 4384 })) |
| 4385 |
| 4386 #endif /*defined(_MSC_VER)*/ |
| 4387 |
| 4388 #endif /*defined(NVALGRIND)*/ |
| 4389 |
| 4390 |
| 3635 /* Returns the number of Valgrinds this code is running under. That | 4391 /* Returns the number of Valgrinds this code is running under. That |
| 3636 is, 0 if running natively, 1 if running under Valgrind, 2 if | 4392 is, 0 if running natively, 1 if running under Valgrind, 2 if |
| 3637 running under Valgrind which is running under another Valgrind, | 4393 running under Valgrind which is running under another Valgrind, |
| 3638 etc. */ | 4394 etc. */ |
| 3639 #define RUNNING_ON_VALGRIND __extension__ \ | 4395 #define RUNNING_ON_VALGRIND \ |
| 3640 ({unsigned int _qzz_res; \ | 4396 VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* if not */, \ |
| 3641 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0 /* if not */, \ | 4397 VG_USERREQ__RUNNING_ON_VALGRIND, \ |
| 3642 VG_USERREQ__RUNNING_ON_VALGRIND, \ | 4398 0, 0, 0, 0, 0) \ |
| 3643 0, 0, 0, 0, 0); \ | |
| 3644 _qzz_res; \ | |
| 3645 }) | |
| 3646 | 4399 |
| 3647 | 4400 |
| 3648 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr + | 4401 /* Discard translation of code in the range [_qzz_addr .. _qzz_addr + |
| 3649 _qzz_len - 1]. Useful if you are debugging a JITter or some such, | 4402 _qzz_len - 1]. Useful if you are debugging a JITter or some such, |
| 3650 since it provides a way to make sure valgrind will retranslate the | 4403 since it provides a way to make sure valgrind will retranslate the |
| 3651 invalidated area. Returns no value. */ | 4404 invalidated area. Returns no value. */ |
| 3652 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ | 4405 #define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \ |
| 3653 {unsigned int _qzz_res; \ | 4406 {unsigned int _qzz_res; \ |
| 3654 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4407 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3655 VG_USERREQ__DISCARD_TRANSLATIONS, \ | 4408 VG_USERREQ__DISCARD_TRANSLATIONS, \ |
| 3656 _qzz_addr, _qzz_len, 0, 0, 0); \ | 4409 _qzz_addr, _qzz_len, 0, 0, 0); \ |
| 3657 } | 4410 } |
| 3658 | 4411 |
| 3659 | 4412 |
| 3660 /* These requests are for getting Valgrind itself to print something. | 4413 /* These requests are for getting Valgrind itself to print something. |
| 3661 Possibly with a backtrace. This is a really ugly hack. */ | 4414 Possibly with a backtrace. This is a really ugly hack. The return value |
| 4415 is the number of characters printed, excluding the "**<pid>** " part at the |
| 4416 start and the backtrace (if present). */ |
| 3662 | 4417 |
| 3663 #if defined(NVALGRIND) | 4418 #if defined(NVALGRIND) |
| 3664 | 4419 |
| 3665 # define VALGRIND_PRINTF(...) | 4420 # define VALGRIND_PRINTF(...) |
| 3666 # define VALGRIND_PRINTF_BACKTRACE(...) | 4421 # define VALGRIND_PRINTF_BACKTRACE(...) |
| 3667 | 4422 |
| 3668 #else /* NVALGRIND */ | 4423 #else /* NVALGRIND */ |
| 3669 | 4424 |
| 4425 #if !defined(_MSC_VER) |
| 3670 /* Modern GCC will optimize the static routine out if unused, | 4426 /* Modern GCC will optimize the static routine out if unused, |
| 3671 and unused attribute will shut down warnings about it. */ | 4427 and unused attribute will shut down warnings about it. */ |
| 3672 static int VALGRIND_PRINTF(const char *format, ...) | 4428 static int VALGRIND_PRINTF(const char *format, ...) |
| 3673 __attribute__((format(__printf__, 1, 2), __unused__)); | 4429 __attribute__((format(__printf__, 1, 2), __unused__)); |
| 4430 #endif |
| 3674 static int | 4431 static int |
| 4432 #if defined(_MSC_VER) |
| 4433 __inline |
| 4434 #endif |
| 3675 VALGRIND_PRINTF(const char *format, ...) | 4435 VALGRIND_PRINTF(const char *format, ...) |
| 3676 { | 4436 { |
| 3677 unsigned long _qzz_res; | 4437 unsigned long _qzz_res; |
| 3678 va_list vargs; | 4438 va_list vargs; |
| 3679 va_start(vargs, format); | 4439 va_start(vargs, format); |
| 3680 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF, | 4440 #if defined(_MSC_VER) |
| 3681 (unsigned long)format, (unsigned long)vargs, | 4441 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, |
| 4442 VG_USERREQ__PRINTF_VALIST_BY_REF, |
| 4443 (uintptr_t)format, |
| 4444 (uintptr_t)&vargs, |
| 3682 0, 0, 0); | 4445 0, 0, 0); |
| 4446 #else |
| 4447 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, |
| 4448 VG_USERREQ__PRINTF_VALIST_BY_REF, |
| 4449 (unsigned long)format, |
| 4450 (unsigned long)&vargs, |
| 4451 0, 0, 0); |
| 4452 #endif |
| 3683 va_end(vargs); | 4453 va_end(vargs); |
| 3684 return (int)_qzz_res; | 4454 return (int)_qzz_res; |
| 3685 } | 4455 } |
| 3686 | 4456 |
| 4457 #if !defined(_MSC_VER) |
| 3687 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) | 4458 static int VALGRIND_PRINTF_BACKTRACE(const char *format, ...) |
| 3688 __attribute__((format(__printf__, 1, 2), __unused__)); | 4459 __attribute__((format(__printf__, 1, 2), __unused__)); |
| 4460 #endif |
| 3689 static int | 4461 static int |
| 4462 #if defined(_MSC_VER) |
| 4463 __inline |
| 4464 #endif |
| 3690 VALGRIND_PRINTF_BACKTRACE(const char *format, ...) | 4465 VALGRIND_PRINTF_BACKTRACE(const char *format, ...) |
| 3691 { | 4466 { |
| 3692 unsigned long _qzz_res; | 4467 unsigned long _qzz_res; |
| 3693 va_list vargs; | 4468 va_list vargs; |
| 3694 va_start(vargs, format); | 4469 va_start(vargs, format); |
| 3695 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, VG_USERREQ__PRINTF_BACKTRACE, | 4470 #if defined(_MSC_VER) |
| 3696 (unsigned long)format, (unsigned long)vargs, | 4471 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, |
| 4472 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, |
| 4473 (uintptr_t)format, |
| 4474 (uintptr_t)&vargs, |
| 3697 0, 0, 0); | 4475 0, 0, 0); |
| 4476 #else |
| 4477 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, |
| 4478 VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF, |
| 4479 (unsigned long)format, |
| 4480 (unsigned long)&vargs, |
| 4481 0, 0, 0); |
| 4482 #endif |
| 3698 va_end(vargs); | 4483 va_end(vargs); |
| 3699 return (int)_qzz_res; | 4484 return (int)_qzz_res; |
| 3700 } | 4485 } |
| 3701 | 4486 |
| 3702 #endif /* NVALGRIND */ | 4487 #endif /* NVALGRIND */ |
| 3703 | 4488 |
| 3704 | 4489 |
| 3705 /* These requests allow control to move from the simulated CPU to the | 4490 /* These requests allow control to move from the simulated CPU to the |
| 3706 real CPU, calling an arbitary function. | 4491 real CPU, calling an arbitary function. |
| 3707 | 4492 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3772 VG_(unique_error)() for them to be counted. */ | 4557 VG_(unique_error)() for them to be counted. */ |
| 3773 #define VALGRIND_COUNT_ERRORS \ | 4558 #define VALGRIND_COUNT_ERRORS \ |
| 3774 __extension__ \ | 4559 __extension__ \ |
| 3775 ({unsigned int _qyy_res; \ | 4560 ({unsigned int _qyy_res; \ |
| 3776 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ | 4561 VALGRIND_DO_CLIENT_REQUEST(_qyy_res, 0 /* default return */, \ |
| 3777 VG_USERREQ__COUNT_ERRORS, \ | 4562 VG_USERREQ__COUNT_ERRORS, \ |
| 3778 0, 0, 0, 0, 0); \ | 4563 0, 0, 0, 0, 0); \ |
| 3779 _qyy_res; \ | 4564 _qyy_res; \ |
| 3780 }) | 4565 }) |
| 3781 | 4566 |
| 3782 /* Mark a block of memory as having been allocated by a malloc()-like | 4567 /* Several Valgrind tools (Memcheck, Massif, Helgrind, DRD) rely on knowing |
| 3783 function. `addr' is the start of the usable block (ie. after any | 4568 when heap blocks are allocated in order to give accurate results. This |
| 3784 redzone) `rzB' is redzone size if the allocator can apply redzones; | 4569 happens automatically for the standard allocator functions such as |
| 3785 use '0' if not. Adding redzones makes it more likely Valgrind will spot | 4570 malloc(), calloc(), realloc(), memalign(), new, new[], free(), delete, |
| 3786 block overruns. `is_zeroed' indicates if the memory is zeroed, as it is | 4571 delete[], etc. |
| 3787 for calloc(). Put it immediately after the point where a block is | 4572 |
| 3788 allocated. | 4573 But if your program uses a custom allocator, this doesn't automatically |
| 4574 happen, and Valgrind will not do as well. For example, if you allocate |
| 4575 superblocks with mmap() and then allocates chunks of the superblocks, all |
| 4576 Valgrind's observations will be at the mmap() level and it won't know that |
| 4577 the chunks should be considered separate entities. In Memcheck's case, |
| 4578 that means you probably won't get heap block overrun detection (because |
| 4579 there won't be redzones marked as unaddressable) and you definitely won't |
| 4580 get any leak detection. |
| 4581 |
| 4582 The following client requests allow a custom allocator to be annotated so |
| 4583 that it can be handled accurately by Valgrind. |
| 4584 |
| 4585 VALGRIND_MALLOCLIKE_BLOCK marks a region of memory as having been allocated |
| 4586 by a malloc()-like function. For Memcheck (an illustrative case), this |
| 4587 does two things: |
| 4588 |
| 4589 - It records that the block has been allocated. This means any addresses |
| 4590 within the block mentioned in error messages will be |
| 4591 identified as belonging to the block. It also means that if the block |
| 4592 isn't freed it will be detected by the leak checker. |
| 4593 |
| 4594 - It marks the block as being addressable and undefined (if 'is_zeroed' is |
| 4595 not set), or addressable and defined (if 'is_zeroed' is set). This |
| 4596 controls how accesses to the block by the program are handled. |
| 3789 | 4597 |
| 3790 If you're using Memcheck: If you're allocating memory via superblocks, | 4598 'addr' is the start of the usable block (ie. after any |
| 3791 and then handing out small chunks of each superblock, if you don't have | 4599 redzone), 'sizeB' is its size. 'rzB' is the redzone size if the allocator |
| 3792 redzones on your small blocks, it's worth marking the superblock with | 4600 can apply redzones -- these are blocks of padding at the start and end of |
| 3793 VALGRIND_MAKE_MEM_NOACCESS when it's created, so that block overruns are | 4601 each block. Adding redzones is recommended as it makes it much more likely |
| 3794 detected. But if you can put redzones on, it's probably better to not do | 4602 Valgrind will spot block overruns. `is_zeroed' indicates if the memory is |
| 3795 this, so that messages for small overruns are described in terms of the | 4603 zeroed (or filled with another predictable value), as is the case for |
| 3796 small block rather than the superblock (but if you have a big overrun | 4604 calloc(). |
| 3797 that skips over a redzone, you could miss an error this way). See | 4605 |
| 3798 memcheck/tests/custom_alloc.c for an example. | 4606 VALGRIND_MALLOCLIKE_BLOCK should be put immediately after the point where a |
| 4607 heap block -- that will be used by the client program -- is allocated. |
| 4608 It's best to put it at the outermost level of the allocator if possible; |
| 4609 for example, if you have a function my_alloc() which calls |
| 4610 internal_alloc(), and the client request is put inside internal_alloc(), |
| 4611 stack traces relating to the heap block will contain entries for both |
| 4612 my_alloc() and internal_alloc(), which is probably not what you want. |
| 3799 | 4613 |
| 3800 WARNING: if your allocator uses malloc() or 'new' to allocate | 4614 For Memcheck users: if you use VALGRIND_MALLOCLIKE_BLOCK to carve out |
| 3801 superblocks, rather than mmap() or brk(), this will not work properly -- | 4615 custom blocks from within a heap block, B, that has been allocated with |
| 3802 you'll likely get assertion failures during leak detection. This is | 4616 malloc/calloc/new/etc, then block B will be *ignored* during leak-checking |
| 3803 because Valgrind doesn't like seeing overlapping heap blocks. Sorry. | 4617 -- the custom blocks will take precedence. |
| 3804 | 4618 |
| 3805 Nb: block must be freed via a free()-like function specified | 4619 VALGRIND_FREELIKE_BLOCK is the partner to VALGRIND_MALLOCLIKE_BLOCK. For |
| 3806 with VALGRIND_FREELIKE_BLOCK or mismatch errors will occur. */ | 4620 Memcheck, it does two things: |
| 4621 |
| 4622 - It records that the block has been deallocated. This assumes that the |
| 4623 block was annotated as having been allocated via |
| 4624 VALGRIND_MALLOCLIKE_BLOCK. Otherwise, an error will be issued. |
| 4625 |
| 4626 - It marks the block as being unaddressable. |
| 4627 |
| 4628 VALGRIND_FREELIKE_BLOCK should be put immediately after the point where a |
| 4629 heap block is deallocated. |
| 4630 |
| 4631 In many cases, these two client requests will not be enough to get your |
| 4632 allocator working well with Memcheck. More specifically, if your allocator |
| 4633 writes to freed blocks in any way then a VALGRIND_MAKE_MEM_UNDEFINED call |
| 4634 will be necessary to mark the memory as addressable just before the zeroing |
| 4635 occurs, otherwise you'll get a lot of invalid write errors. For example, |
| 4636 you'll need to do this if your allocator recycles freed blocks, but it |
| 4637 zeroes them before handing them back out (via VALGRIND_MALLOCLIKE_BLOCK). |
| 4638 Alternatively, if your allocator reuses freed blocks for allocator-internal |
| 4639 data structures, VALGRIND_MAKE_MEM_UNDEFINED calls will also be necessary. |
| 4640 |
| 4641 Really, what's happening is a blurring of the lines between the client |
| 4642 program and the allocator... after VALGRIND_FREELIKE_BLOCK is called, the |
| 4643 memory should be considered unaddressable to the client program, but the |
| 4644 allocator knows more than the rest of the client program and so may be able |
| 4645 to safely access it. Extra client requests are necessary for Valgrind to |
| 4646 understand the distinction between the allocator and the rest of the |
| 4647 program. |
| 4648 |
| 4649 Note: there is currently no VALGRIND_REALLOCLIKE_BLOCK client request; it |
| 4650 has to be emulated with MALLOCLIKE/FREELIKE and memory copying. |
| 4651 |
| 4652 Ignored if addr == 0. |
| 4653 */ |
| 3807 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ | 4654 #define VALGRIND_MALLOCLIKE_BLOCK(addr, sizeB, rzB, is_zeroed) \ |
| 3808 {unsigned int _qzz_res; \ | 4655 {unsigned int _qzz_res; \ |
| 3809 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4656 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3810 VG_USERREQ__MALLOCLIKE_BLOCK, \ | 4657 VG_USERREQ__MALLOCLIKE_BLOCK, \ |
| 3811 addr, sizeB, rzB, is_zeroed, 0); \ | 4658 addr, sizeB, rzB, is_zeroed, 0); \ |
| 3812 } | 4659 } |
| 3813 | 4660 |
| 3814 /* Mark a block of memory as having been freed by a free()-like function. | 4661 /* See the comment for VALGRIND_MALLOCLIKE_BLOCK for details. |
| 3815 `rzB' is redzone size; it must match that given to | 4662 Ignored if addr == 0. |
| 3816 VALGRIND_MALLOCLIKE_BLOCK. Memory not freed will be detected by the leak | 4663 */ |
| 3817 checker. Put it immediately after the point where the block is freed. */ | |
| 3818 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ | 4664 #define VALGRIND_FREELIKE_BLOCK(addr, rzB) \ |
| 3819 {unsigned int _qzz_res; \ | 4665 {unsigned int _qzz_res; \ |
| 3820 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4666 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3821 VG_USERREQ__FREELIKE_BLOCK, \ | 4667 VG_USERREQ__FREELIKE_BLOCK, \ |
| 3822 addr, rzB, 0, 0, 0); \ | 4668 addr, rzB, 0, 0, 0); \ |
| 3823 } | 4669 } |
| 3824 | 4670 |
| 3825 /* Create a memory pool. */ | 4671 /* Create a memory pool. */ |
| 3826 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ | 4672 #define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) \ |
| 3827 {unsigned int _qzz_res; \ | 4673 {unsigned int _qzz_res; \ |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3873 /* Resize and/or move a piece associated with a memory pool. */ | 4719 /* Resize and/or move a piece associated with a memory pool. */ |
| 3874 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ | 4720 #define VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size) \ |
| 3875 {unsigned int _qzz_res; \ | 4721 {unsigned int _qzz_res; \ |
| 3876 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4722 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3877 VG_USERREQ__MEMPOOL_CHANGE, \ | 4723 VG_USERREQ__MEMPOOL_CHANGE, \ |
| 3878 pool, addrA, addrB, size, 0); \ | 4724 pool, addrA, addrB, size, 0); \ |
| 3879 } | 4725 } |
| 3880 | 4726 |
| 3881 /* Return 1 if a mempool exists, else 0. */ | 4727 /* Return 1 if a mempool exists, else 0. */ |
| 3882 #define VALGRIND_MEMPOOL_EXISTS(pool) \ | 4728 #define VALGRIND_MEMPOOL_EXISTS(pool) \ |
| 4729 __extension__ \ |
| 3883 ({unsigned int _qzz_res; \ | 4730 ({unsigned int _qzz_res; \ |
| 3884 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4731 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3885 VG_USERREQ__MEMPOOL_EXISTS, \ | 4732 VG_USERREQ__MEMPOOL_EXISTS, \ |
| 3886 pool, 0, 0, 0, 0); \ | 4733 pool, 0, 0, 0, 0); \ |
| 3887 _qzz_res; \ | 4734 _qzz_res; \ |
| 3888 }) | 4735 }) |
| 3889 | 4736 |
| 3890 /* Mark a piece of memory as being a stack. Returns a stack id. */ | 4737 /* Mark a piece of memory as being a stack. Returns a stack id. */ |
| 3891 #define VALGRIND_STACK_REGISTER(start, end) \ | 4738 #define VALGRIND_STACK_REGISTER(start, end) \ |
| 4739 __extension__ \ |
| 3892 ({unsigned int _qzz_res; \ | 4740 ({unsigned int _qzz_res; \ |
| 3893 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4741 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3894 VG_USERREQ__STACK_REGISTER, \ | 4742 VG_USERREQ__STACK_REGISTER, \ |
| 3895 start, end, 0, 0, 0); \ | 4743 start, end, 0, 0, 0); \ |
| 3896 _qzz_res; \ | 4744 _qzz_res; \ |
| 3897 }) | 4745 }) |
| 3898 | 4746 |
| 3899 /* Unmark the piece of memory associated with a stack id as being a | 4747 /* Unmark the piece of memory associated with a stack id as being a |
| 3900 stack. */ | 4748 stack. */ |
| 3901 #define VALGRIND_STACK_DEREGISTER(id) \ | 4749 #define VALGRIND_STACK_DEREGISTER(id) \ |
| 3902 {unsigned int _qzz_res; \ | 4750 {unsigned int _qzz_res; \ |
| 3903 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4751 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3904 VG_USERREQ__STACK_DEREGISTER, \ | 4752 VG_USERREQ__STACK_DEREGISTER, \ |
| 3905 id, 0, 0, 0, 0); \ | 4753 id, 0, 0, 0, 0); \ |
| 3906 } | 4754 } |
| 3907 | 4755 |
| 3908 /* Change the start and end address of the stack id. */ | 4756 /* Change the start and end address of the stack id. */ |
| 3909 #define VALGRIND_STACK_CHANGE(id, start, end) \ | 4757 #define VALGRIND_STACK_CHANGE(id, start, end) \ |
| 3910 {unsigned int _qzz_res; \ | 4758 {unsigned int _qzz_res; \ |
| 3911 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ | 4759 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 3912 VG_USERREQ__STACK_CHANGE, \ | 4760 VG_USERREQ__STACK_CHANGE, \ |
| 3913 id, start, end, 0, 0); \ | 4761 id, start, end, 0, 0); \ |
| 3914 } | 4762 } |
| 3915 | 4763 |
| 4764 /* Load PDB debug info for Wine PE image_map. */ |
| 4765 #define VALGRIND_LOAD_PDB_DEBUGINFO(fd, ptr, total_size, delta) \ |
| 4766 {unsigned int _qzz_res; \ |
| 4767 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 4768 VG_USERREQ__LOAD_PDB_DEBUGINFO, \ |
| 4769 fd, ptr, total_size, delta, 0); \ |
| 4770 } |
| 4771 |
| 4772 /* Map a code address to a source file name and line number. buf64 |
| 4773 must point to a 64-byte buffer in the caller's address space. The |
| 4774 result will be dumped in there and is guaranteed to be zero |
| 4775 terminated. If no info is found, the first byte is set to zero. */ |
| 4776 #define VALGRIND_MAP_IP_TO_SRCLOC(addr, buf64) \ |
| 4777 {unsigned int _qzz_res; \ |
| 4778 VALGRIND_DO_CLIENT_REQUEST(_qzz_res, 0, \ |
| 4779 VG_USERREQ__MAP_IP_TO_SRCLOC, \ |
| 4780 addr, buf64, 0, 0, 0); \ |
| 4781 } |
| 4782 |
| 3916 | 4783 |
| 3917 #undef PLAT_x86_linux | 4784 #undef PLAT_x86_linux |
| 3918 #undef PLAT_amd64_linux | 4785 #undef PLAT_amd64_linux |
| 3919 #undef PLAT_ppc32_linux | 4786 #undef PLAT_ppc32_linux |
| 3920 #undef PLAT_ppc64_linux | 4787 #undef PLAT_ppc64_linux |
| 4788 #undef PLAT_arm_linux |
| 3921 #undef PLAT_ppc32_aix5 | 4789 #undef PLAT_ppc32_aix5 |
| 3922 #undef PLAT_ppc64_aix5 | 4790 #undef PLAT_ppc64_aix5 |
| 3923 | 4791 |
| 3924 #endif /* __VALGRIND_H */ | 4792 #endif /* __VALGRIND_H */ |
| OLD | NEW |