| OLD | NEW |
| 1 /* Copyright (c) 2007, Google Inc. | 1 /* Copyright (c) 2007, Google Inc. |
| 2 * All rights reserved. | 2 * All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 * | 29 * |
| 30 * --- | 30 * --- |
| 31 * Author: Joi Sigurdsson | 31 * Author: Joi Sigurdsson |
| 32 * Author: Scott Francis |
| 32 * | 33 * |
| 33 * Definition of PreamblePatcher | 34 * Definition of PreamblePatcher |
| 34 */ | 35 */ |
| 35 | 36 |
| 36 #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 37 #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
| 37 #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 38 #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
| 38 | 39 |
| 40 #include "config.h" |
| 39 #include <windows.h> | 41 #include <windows.h> |
| 40 | 42 |
| 41 // compatibility shim | 43 // compatibility shim |
| 42 #include "base/logging.h" | 44 #include "base/logging.h" |
| 43 #define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) | 45 #define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) |
| 44 #define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) | 46 #define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) |
| 45 | 47 |
| 46 // Maximum size of the preamble stub. We overwrite at least the first 5 | 48 // Maximum size of the preamble stub. We overwrite at least the first 5 |
| 47 // bytes of the function. Considering the worst case scenario, we need 4 | 49 // bytes of the function. Considering the worst case scenario, we need 4 |
| 48 // bytes + the max instruction size + 5 more bytes for our jump back to | 50 // bytes + the max instruction size + 5 more bytes for our jump back to |
| 49 // the original code. With that in mind, 32 is a good number :) | 51 // the original code. With that in mind, 32 is a good number :) |
| 52 #ifdef _M_X64 |
| 53 // In 64-bit mode we may need more room. In 64-bit mode all jumps must be |
| 54 // within +/-2GB of RIP. Because of this limitation we may need to use a |
| 55 // trampoline to jump to the replacement function if it is further than 2GB |
| 56 // away from the target. The trampoline is 14 bytes. |
| 57 // |
| 58 // So 4 bytes + max instruction size (17 bytes) + 5 bytes to jump back to the |
| 59 // original code + trampoline size. 64 bytes is a nice number :-) |
| 60 #define MAX_PREAMBLE_STUB_SIZE (64) |
| 61 #else |
| 50 #define MAX_PREAMBLE_STUB_SIZE (32) | 62 #define MAX_PREAMBLE_STUB_SIZE (32) |
| 63 #endif |
| 64 |
| 65 // Determines if this is a 64-bit binary. |
| 66 #ifdef _M_X64 |
| 67 static const bool kIs64BitBinary = true; |
| 68 #else |
| 69 static const bool kIs64BitBinary = false; |
| 70 #endif |
| 51 | 71 |
| 52 namespace sidestep { | 72 namespace sidestep { |
| 53 | 73 |
| 54 // Possible results of patching/unpatching | 74 // Possible results of patching/unpatching |
| 55 enum SideStepError { | 75 enum SideStepError { |
| 56 SIDESTEP_SUCCESS = 0, | 76 SIDESTEP_SUCCESS = 0, |
| 57 SIDESTEP_INVALID_PARAMETER, | 77 SIDESTEP_INVALID_PARAMETER, |
| 58 SIDESTEP_INSUFFICIENT_BUFFER, | 78 SIDESTEP_INSUFFICIENT_BUFFER, |
| 59 SIDESTEP_JUMP_INSTRUCTION, | 79 SIDESTEP_JUMP_INSTRUCTION, |
| 60 SIDESTEP_FUNCTION_TOO_SMALL, | 80 SIDESTEP_FUNCTION_TOO_SMALL, |
| 61 SIDESTEP_UNSUPPORTED_INSTRUCTION, | 81 SIDESTEP_UNSUPPORTED_INSTRUCTION, |
| 62 SIDESTEP_NO_SUCH_MODULE, | 82 SIDESTEP_NO_SUCH_MODULE, |
| 63 SIDESTEP_NO_SUCH_FUNCTION, | 83 SIDESTEP_NO_SUCH_FUNCTION, |
| 64 SIDESTEP_ACCESS_DENIED, | 84 SIDESTEP_ACCESS_DENIED, |
| 65 SIDESTEP_UNEXPECTED, | 85 SIDESTEP_UNEXPECTED, |
| 66 }; | 86 }; |
| 67 | 87 |
| 68 #define SIDESTEP_TO_HRESULT(error) \ | 88 #define SIDESTEP_TO_HRESULT(error) \ |
| 69 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) | 89 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) |
| 70 | 90 |
| 91 class DeleteUnsignedCharArray; |
| 92 |
| 71 // Implements a patching mechanism that overwrites the first few bytes of | 93 // Implements a patching mechanism that overwrites the first few bytes of |
| 72 // a function preamble with a jump to our hook function, which is then | 94 // a function preamble with a jump to our hook function, which is then |
| 73 // able to call the original function via a specially-made preamble-stub | 95 // able to call the original function via a specially-made preamble-stub |
| 74 // that imitates the action of the original preamble. | 96 // that imitates the action of the original preamble. |
| 75 // | 97 // |
| 76 // NOTE: This patching mechanism should currently only be used for | 98 // NOTE: This patching mechanism should currently only be used for |
| 77 // non-production code, e.g. unit tests, because it is not threadsafe. | 99 // non-production code, e.g. unit tests, because it is not threadsafe. |
| 78 // See the TODO in preamble_patcher_with_stub.cc for instructions on what | 100 // See the TODO in preamble_patcher_with_stub.cc for instructions on what |
| 79 // we need to do before using it in production code; it's fairly simple | 101 // we need to do before using it in production code; it's fairly simple |
| 80 // but unnecessary for now since we only intend to use it in unit tests. | 102 // but unnecessary for now since we only intend to use it in unit tests. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // patcher at an invalid instruction (e.g. into the middle of a multi- | 141 // patcher at an invalid instruction (e.g. into the middle of a multi- |
| 120 // byte instruction, or not at memory containing executable instructions) | 142 // byte instruction, or not at memory containing executable instructions) |
| 121 // or, there may be a bug in the disassembler we use to find | 143 // or, there may be a bug in the disassembler we use to find |
| 122 // instruction boundaries. | 144 // instruction boundaries. |
| 123 // | 145 // |
| 124 // NOTE: In optimized builds, when you have very trivial functions that | 146 // NOTE: In optimized builds, when you have very trivial functions that |
| 125 // the compiler can reason do not have side effects, the compiler may | 147 // the compiler can reason do not have side effects, the compiler may |
| 126 // reuse the result of calling the function with a given parameter, which | 148 // reuse the result of calling the function with a given parameter, which |
| 127 // may mean if you patch the function in between your patch will never get | 149 // may mean if you patch the function in between your patch will never get |
| 128 // invoked. See preamble_patcher_test.cc for an example. | 150 // invoked. See preamble_patcher_test.cc for an example. |
| 129 class PreamblePatcher { | 151 class PERFTOOLS_DLL_DECL PreamblePatcher { |
| 130 public: | 152 public: |
| 131 | 153 |
| 132 // This is a typesafe version of RawPatch(), identical in all other | 154 // This is a typesafe version of RawPatch(), identical in all other |
| 133 // ways than it takes a template parameter indicating the type of the | 155 // ways than it takes a template parameter indicating the type of the |
| 134 // function being patched. | 156 // function being patched. |
| 135 // | 157 // |
| 136 // @param T The type of the function you are patching. Usually | 158 // @param T The type of the function you are patching. Usually |
| 137 // you will establish this type using a typedef, as in the following | 159 // you will establish this type using a typedef, as in the following |
| 138 // example: | 160 // example: |
| 139 // @code | 161 // @code |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 // | 302 // |
| 281 // @return Either target_function (the input parameter), or if | 303 // @return Either target_function (the input parameter), or if |
| 282 // target_function's body consists entirely of a JMP instruction, | 304 // target_function's body consists entirely of a JMP instruction, |
| 283 // the address it JMPs to (or more precisely, the address at the end | 305 // the address it JMPs to (or more precisely, the address at the end |
| 284 // of a chain of JMPs). | 306 // of a chain of JMPs). |
| 285 template <class T> | 307 template <class T> |
| 286 static T ResolveTarget(T target_function) { | 308 static T ResolveTarget(T target_function) { |
| 287 return (T)ResolveTargetImpl((unsigned char*)target_function, NULL); | 309 return (T)ResolveTargetImpl((unsigned char*)target_function, NULL); |
| 288 } | 310 } |
| 289 | 311 |
| 312 // Allocates a block of memory of size MAX_PREAMBLE_STUB_SIZE that is as |
| 313 // close (within 2GB) as possible to target. This is done to ensure that |
| 314 // we can perform a relative jump from target to a trampoline if the |
| 315 // replacement function is > +-2GB from target. This means that we only need |
| 316 // to patch 5 bytes in the target function. |
| 317 // |
| 318 // @param target Pointer to target function. |
| 319 // |
| 320 // @return Returns a block of memory of size MAX_PREAMBLE_STUB_SIZE that can |
| 321 // be used to store a function preamble block. |
| 322 static unsigned char* AllocPreambleBlockNear(void* target); |
| 323 |
| 324 // Frees a block allocated by AllocPreambleBlockNear. |
| 325 // |
| 326 // @param block Block that was returned by AllocPreambleBlockNear. |
| 327 static void FreePreambleBlock(unsigned char* block); |
| 328 |
| 290 private: | 329 private: |
| 330 friend class DeleteUnsignedCharArray; |
| 331 |
| 332 // Used to store data allocated for preamble stubs |
| 333 struct PreamblePage { |
| 334 unsigned int magic_; |
| 335 PreamblePage* next_; |
| 336 // This member points to a linked list of free blocks within the page |
| 337 // or NULL if at the end |
| 338 void* free_; |
| 339 }; |
| 340 |
| 341 // In 64-bit mode, the replacement function must be within 2GB of the original |
| 342 // target in order to only require 5 bytes for the function patch. To meet |
| 343 // this requirement we're creating an allocator within this class to |
| 344 // allocate blocks that are within 2GB of a given target. This member is the |
| 345 // head of a linked list of pages used to allocate blocks that are within |
| 346 // 2GB of the target. |
| 347 static PreamblePage* preamble_pages_; |
| 348 |
| 349 // Page granularity |
| 350 static long granularity_; |
| 351 |
| 352 // Page size |
| 353 static long pagesize_; |
| 354 |
| 355 // Determines if the patcher has been initialized. |
| 356 static bool initialized_; |
| 357 |
| 358 // Used to initialize static members. |
| 359 static void Initialize(); |
| 360 |
| 291 // Patches a function by overwriting its first few bytes with | 361 // Patches a function by overwriting its first few bytes with |
| 292 // a jump to a different function. This is similar to the RawPatch | 362 // a jump to a different function. This is similar to the RawPatch |
| 293 // function except that it uses the stub allocated by the caller | 363 // function except that it uses the stub allocated by the caller |
| 294 // instead of allocating it. | 364 // instead of allocating it. |
| 295 // | 365 // |
| 296 // We call VirtualProtect to make the | 366 // We call VirtualProtect to make the |
| 297 // target function writable at least for the duration of the call. | 367 // target function writable at least for the duration of the call. |
| 298 // | 368 // |
| 299 // @param target_function A pointer to the function that should be | 369 // @param target_function A pointer to the function that should be |
| 300 // patched. | 370 // patched. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 311 // @param stub_size Size in bytes of the buffer allocated for the | 381 // @param stub_size Size in bytes of the buffer allocated for the |
| 312 // preamble_stub | 382 // preamble_stub |
| 313 // | 383 // |
| 314 // @param bytes_needed Pointer to a variable that receives the minimum | 384 // @param bytes_needed Pointer to a variable that receives the minimum |
| 315 // number of bytes required for the stub. Can be set to NULL if you're | 385 // number of bytes required for the stub. Can be set to NULL if you're |
| 316 // not interested. | 386 // not interested. |
| 317 // | 387 // |
| 318 // @return An error code indicating the result of patching. | 388 // @return An error code indicating the result of patching. |
| 319 static SideStepError RawPatchWithStubAndProtections( | 389 static SideStepError RawPatchWithStubAndProtections( |
| 320 void* target_function, | 390 void* target_function, |
| 321 void *replacement_function, | 391 void* replacement_function, |
| 322 unsigned char* preamble_stub, | 392 unsigned char* preamble_stub, |
| 323 unsigned long stub_size, | 393 unsigned long stub_size, |
| 324 unsigned long* bytes_needed); | 394 unsigned long* bytes_needed); |
| 325 | 395 |
| 326 // A helper function used by RawPatchWithStubAndProtections -- it | 396 // A helper function used by RawPatchWithStubAndProtections -- it |
| 327 // does everything but the VirtualProtect work. Defined in | 397 // does everything but the VirtualProtect work. Defined in |
| 328 // preamble_patcher_with_stub.cc. | 398 // preamble_patcher_with_stub.cc. |
| 329 // | 399 // |
| 330 // @param target_function A pointer to the function that should be | 400 // @param target_function A pointer to the function that should be |
| 331 // patched. | 401 // patched. |
| 332 // | 402 // |
| 333 // @param replacement_function A pointer to the function that should | 403 // @param replacement_function A pointer to the function that should |
| 334 // replace the target function. The replacement function must have | 404 // replace the target function. The replacement function must have |
| 335 // exactly the same calling convention and parameters as the original | 405 // exactly the same calling convention and parameters as the original |
| 336 // function. | 406 // function. |
| 337 // | 407 // |
| 338 // @param preamble_stub A pointer to a buffer where the preamble stub | 408 // @param preamble_stub A pointer to a buffer where the preamble stub |
| 339 // should be copied. The size of the buffer should be sufficient to | 409 // should be copied. The size of the buffer should be sufficient to |
| 340 // hold the preamble bytes. | 410 // hold the preamble bytes. |
| 341 // | 411 // |
| 342 // @param stub_size Size in bytes of the buffer allocated for the | 412 // @param stub_size Size in bytes of the buffer allocated for the |
| 343 // preamble_stub | 413 // preamble_stub |
| 344 // | 414 // |
| 345 // @param bytes_needed Pointer to a variable that receives the minimum | 415 // @param bytes_needed Pointer to a variable that receives the minimum |
| 346 // number of bytes required for the stub. Can be set to NULL if you're | 416 // number of bytes required for the stub. Can be set to NULL if you're |
| 347 // not interested. | 417 // not interested. |
| 348 // | 418 // |
| 349 // @return An error code indicating the result of patching. | 419 // @return An error code indicating the result of patching. |
| 350 static SideStepError RawPatchWithStub(void* target_function, | 420 static SideStepError RawPatchWithStub(void* target_function, |
| 351 void *replacement_function, | 421 void* replacement_function, |
| 352 unsigned char* preamble_stub, | 422 unsigned char* preamble_stub, |
| 353 unsigned long stub_size, | 423 unsigned long stub_size, |
| 354 unsigned long* bytes_needed); | 424 unsigned long* bytes_needed); |
| 355 | 425 |
| 356 | 426 |
| 357 // A helper routine when patching, which follows jmp instructions at | 427 // A helper routine when patching, which follows jmp instructions at |
| 358 // function addresses, to get to the "actual" function contents. | 428 // function addresses, to get to the "actual" function contents. |
| 359 // This allows us to identify two functions that are at different | 429 // This allows us to identify two functions that are at different |
| 360 // addresses but actually resolve to the same code. | 430 // addresses but actually resolve to the same code. |
| 361 // | 431 // |
| 362 // @param target_function Pointer to a function. | 432 // @param target_function Pointer to a function. |
| 363 // | 433 // |
| 364 // @param stop_before If, when following JMP instructions from | 434 // @param stop_before If, when following JMP instructions from |
| 365 // target_function, we get to the address stop, we return | 435 // target_function, we get to the address stop, we return |
| 366 // immediately, the address that jumps to stop_before. | 436 // immediately, the address that jumps to stop_before. |
| 367 // | 437 // |
| 438 // @param stop_before_trampoline When following JMP instructions from |
| 439 // target_function, stop before a trampoline is detected. See comment in |
| 440 // PreamblePatcher::RawPatchWithStub for more information. This parameter |
| 441 // has no effect in 32-bit mode. |
| 442 // |
| 368 // @return Either target_function (the input parameter), or if | 443 // @return Either target_function (the input parameter), or if |
| 369 // target_function's body consists entirely of a JMP instruction, | 444 // target_function's body consists entirely of a JMP instruction, |
| 370 // the address it JMPs to (or more precisely, the address at the end | 445 // the address it JMPs to (or more precisely, the address at the end |
| 371 // of a chain of JMPs). | 446 // of a chain of JMPs). |
| 372 static void* ResolveTargetImpl(unsigned char* target_function, | 447 static void* ResolveTargetImpl(unsigned char* target_function, |
| 373 unsigned char* stop_before); | 448 unsigned char* stop_before, |
| 449 bool stop_before_trampoline = false); |
| 450 |
| 451 // Helper routine that attempts to allocate a page as close (within 2GB) |
| 452 // as possible to target. |
| 453 // |
| 454 // @param target Pointer to target function. |
| 455 // |
| 456 // @return Returns an address that is within 2GB of target. |
| 457 static void* AllocPageNear(void* target); |
| 458 |
| 459 // Helper routine that determines if a target instruction is a short |
| 460 // conditional jump. |
| 461 // |
| 462 // @param target Pointer to instruction. |
| 463 // |
| 464 // @param instruction_size Size of the instruction in bytes. |
| 465 // |
| 466 // @return Returns true if the instruction is a short conditional jump. |
| 467 static bool IsShortConditionalJump(unsigned char* target, |
| 468 unsigned int instruction_size); |
| 469 |
| 470 // Helper routine that determines if a target instruction is a near |
| 471 // conditional jump. |
| 472 // |
| 473 // @param target Pointer to instruction. |
| 474 // |
| 475 // @param instruction_size Size of the instruction in bytes. |
| 476 // |
| 477 // @return Returns true if the instruction is a near conditional jump. |
| 478 static bool IsNearConditionalJump(unsigned char* target, |
| 479 unsigned int instruction_size); |
| 480 |
| 481 // Helper routine that determines if a target instruction is a near |
| 482 // relative jump. |
| 483 // |
| 484 // @param target Pointer to instruction. |
| 485 // |
| 486 // @param instruction_size Size of the instruction in bytes. |
| 487 // |
| 488 // @return Returns true if the instruction is a near absolute jump. |
| 489 static bool IsNearRelativeJump(unsigned char* target, |
| 490 unsigned int instruction_size); |
| 491 |
| 492 // Helper routine that determines if a target instruction is a near |
| 493 // absolute call. |
| 494 // |
| 495 // @param target Pointer to instruction. |
| 496 // |
| 497 // @param instruction_size Size of the instruction in bytes. |
| 498 // |
| 499 // @return Returns true if the instruction is a near absolute call. |
| 500 static bool IsNearAbsoluteCall(unsigned char* target, |
| 501 unsigned int instruction_size); |
| 502 |
| 503 // Helper routine that determines if a target instruction is a near |
| 504 // absolute call. |
| 505 // |
| 506 // @param target Pointer to instruction. |
| 507 // |
| 508 // @param instruction_size Size of the instruction in bytes. |
| 509 // |
| 510 // @return Returns true if the instruction is a near absolute call. |
| 511 static bool IsNearRelativeCall(unsigned char* target, |
| 512 unsigned int instruction_size); |
| 513 |
| 514 // Helper routine that determines if a target instruction is a 64-bit MOV |
| 515 // that uses a RIP-relative displacement. |
| 516 // |
| 517 // @param target Pointer to instruction. |
| 518 // |
| 519 // @param instruction_size Size of the instruction in bytes. |
| 520 // |
| 521 // @return Returns true if the instruction is a MOV with displacement. |
| 522 static bool IsMovWithDisplacement(unsigned char* target, |
| 523 unsigned int instruction_size); |
| 524 |
| 525 // Helper routine that converts a short conditional jump instruction |
| 526 // to a near conditional jump in a target buffer. Note that the target |
| 527 // buffer must be within 2GB of the source for the near jump to work. |
| 528 // |
| 529 // A short conditional jump instruction is in the format: |
| 530 // 7x xx = Jcc rel8off |
| 531 // |
| 532 // @param source Pointer to instruction. |
| 533 // |
| 534 // @param instruction_size Size of the instruction. |
| 535 // |
| 536 // @param target Target buffer to write the new instruction. |
| 537 // |
| 538 // @param target_bytes Pointer to a buffer that contains the size |
| 539 // of the target instruction, in bytes. |
| 540 // |
| 541 // @param target_size Size of the target buffer. |
| 542 // |
| 543 // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. |
| 544 static SideStepError PatchShortConditionalJump(unsigned char* source, |
| 545 unsigned int instruction_size, |
| 546 unsigned char* target, |
| 547 unsigned int* target_bytes, |
| 548 unsigned int target_size); |
| 549 |
| 550 // Helper routine that converts an instruction that will convert various |
| 551 // jump-like instructions to corresponding instructions in the target buffer. |
| 552 // What this routine does is fix up the relative offsets contained in jump |
| 553 // instructions to point back to the original target routine. Like with |
| 554 // PatchShortConditionalJump, the target buffer must be within 2GB of the |
| 555 // source. |
| 556 // |
| 557 // We currently handle the following instructions: |
| 558 // |
| 559 // E9 xx xx xx xx = JMP rel32off |
| 560 // 0F 8x xx xx xx xx = Jcc rel32off |
| 561 // FF /2 xx xx xx xx = CALL reg/mem32/mem64 |
| 562 // E8 xx xx xx xx = CALL rel32off |
| 563 // |
| 564 // It should not be hard to update this function to support other |
| 565 // instructions that jump to relative targets. |
| 566 // |
| 567 // @param source Pointer to instruction. |
| 568 // |
| 569 // @param instruction_size Size of the instruction. |
| 570 // |
| 571 // @param target Target buffer to write the new instruction. |
| 572 // |
| 573 // @param target_bytes Pointer to a buffer that contains the size |
| 574 // of the target instruction, in bytes. |
| 575 // |
| 576 // @param target_size Size of the target buffer. |
| 577 // |
| 578 // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. |
| 579 static SideStepError PatchNearJumpOrCall(unsigned char* source, |
| 580 unsigned int instruction_size, |
| 581 unsigned char* target, |
| 582 unsigned int* target_bytes, |
| 583 unsigned int target_size); |
| 584 |
| 585 // Helper routine that patches a 64-bit MOV instruction with a RIP-relative |
| 586 // displacement. The target buffer must be within 2GB of the source. |
| 587 // |
| 588 // 48 8B 0D XX XX XX XX = MOV rel32off |
| 589 // |
| 590 // @param source Pointer to instruction. |
| 591 // |
| 592 // @param instruction_size Size of the instruction. |
| 593 // |
| 594 // @param target Target buffer to write the new instruction. |
| 595 // |
| 596 // @param target_bytes Pointer to a buffer that contains the size |
| 597 // of the target instruction, in bytes. |
| 598 // |
| 599 // @param target_size Size of the target buffer. |
| 600 // |
| 601 // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error. |
| 602 static SideStepError PatchMovWithDisplacement(unsigned char* source, |
| 603 unsigned int instruction_size, |
| 604 unsigned char* target, |
| 605 unsigned int* target_bytes, |
| 606 unsigned int target_size); |
| 374 }; | 607 }; |
| 375 | 608 |
| 376 }; // namespace sidestep | 609 }; // namespace sidestep |
| 377 | 610 |
| 378 #endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 611 #endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
| OLD | NEW |