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 |