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 | |
33 * | 32 * |
34 * Definition of PreamblePatcher | 33 * Definition of PreamblePatcher |
35 */ | 34 */ |
36 | 35 |
37 #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 36 #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
38 #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 37 #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
39 | 38 |
40 #include "config.h" | |
41 #include <windows.h> | 39 #include <windows.h> |
42 | 40 |
43 // compatibility shim | 41 // compatibility shim |
44 #include "base/logging.h" | 42 #include "base/logging.h" |
45 #define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) | 43 #define SIDESTEP_ASSERT(cond) RAW_DCHECK(cond, #cond) |
46 #define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) | 44 #define SIDESTEP_LOG(msg) RAW_VLOG(1, msg) |
47 | 45 |
48 // Maximum size of the preamble stub. We overwrite at least the first 5 | 46 // Maximum size of the preamble stub. We overwrite at least the first 5 |
49 // bytes of the function. Considering the worst case scenario, we need 4 | 47 // bytes of the function. Considering the worst case scenario, we need 4 |
50 // bytes + the max instruction size + 5 more bytes for our jump back to | 48 // bytes + the max instruction size + 5 more bytes for our jump back to |
51 // the original code. With that in mind, 32 is a good number :) | 49 // 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 | |
62 #define MAX_PREAMBLE_STUB_SIZE (32) | 50 #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 | |
71 | 51 |
72 namespace sidestep { | 52 namespace sidestep { |
73 | 53 |
74 // Possible results of patching/unpatching | 54 // Possible results of patching/unpatching |
75 enum SideStepError { | 55 enum SideStepError { |
76 SIDESTEP_SUCCESS = 0, | 56 SIDESTEP_SUCCESS = 0, |
77 SIDESTEP_INVALID_PARAMETER, | 57 SIDESTEP_INVALID_PARAMETER, |
78 SIDESTEP_INSUFFICIENT_BUFFER, | 58 SIDESTEP_INSUFFICIENT_BUFFER, |
79 SIDESTEP_JUMP_INSTRUCTION, | 59 SIDESTEP_JUMP_INSTRUCTION, |
80 SIDESTEP_FUNCTION_TOO_SMALL, | 60 SIDESTEP_FUNCTION_TOO_SMALL, |
81 SIDESTEP_UNSUPPORTED_INSTRUCTION, | 61 SIDESTEP_UNSUPPORTED_INSTRUCTION, |
82 SIDESTEP_NO_SUCH_MODULE, | 62 SIDESTEP_NO_SUCH_MODULE, |
83 SIDESTEP_NO_SUCH_FUNCTION, | 63 SIDESTEP_NO_SUCH_FUNCTION, |
84 SIDESTEP_ACCESS_DENIED, | 64 SIDESTEP_ACCESS_DENIED, |
85 SIDESTEP_UNEXPECTED, | 65 SIDESTEP_UNEXPECTED, |
86 }; | 66 }; |
87 | 67 |
88 #define SIDESTEP_TO_HRESULT(error) \ | 68 #define SIDESTEP_TO_HRESULT(error) \ |
89 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) | 69 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) |
90 | 70 |
91 class DeleteUnsignedCharArray; | |
92 | |
93 // Implements a patching mechanism that overwrites the first few bytes of | 71 // Implements a patching mechanism that overwrites the first few bytes of |
94 // a function preamble with a jump to our hook function, which is then | 72 // a function preamble with a jump to our hook function, which is then |
95 // able to call the original function via a specially-made preamble-stub | 73 // able to call the original function via a specially-made preamble-stub |
96 // that imitates the action of the original preamble. | 74 // that imitates the action of the original preamble. |
97 // | 75 // |
98 // NOTE: This patching mechanism should currently only be used for | 76 // NOTE: This patching mechanism should currently only be used for |
99 // non-production code, e.g. unit tests, because it is not threadsafe. | 77 // non-production code, e.g. unit tests, because it is not threadsafe. |
100 // See the TODO in preamble_patcher_with_stub.cc for instructions on what | 78 // See the TODO in preamble_patcher_with_stub.cc for instructions on what |
101 // we need to do before using it in production code; it's fairly simple | 79 // we need to do before using it in production code; it's fairly simple |
102 // but unnecessary for now since we only intend to use it in unit tests. | 80 // 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... |
141 // patcher at an invalid instruction (e.g. into the middle of a multi- | 119 // patcher at an invalid instruction (e.g. into the middle of a multi- |
142 // byte instruction, or not at memory containing executable instructions) | 120 // byte instruction, or not at memory containing executable instructions) |
143 // or, there may be a bug in the disassembler we use to find | 121 // or, there may be a bug in the disassembler we use to find |
144 // instruction boundaries. | 122 // instruction boundaries. |
145 // | 123 // |
146 // NOTE: In optimized builds, when you have very trivial functions that | 124 // NOTE: In optimized builds, when you have very trivial functions that |
147 // the compiler can reason do not have side effects, the compiler may | 125 // the compiler can reason do not have side effects, the compiler may |
148 // reuse the result of calling the function with a given parameter, which | 126 // reuse the result of calling the function with a given parameter, which |
149 // may mean if you patch the function in between your patch will never get | 127 // may mean if you patch the function in between your patch will never get |
150 // invoked. See preamble_patcher_test.cc for an example. | 128 // invoked. See preamble_patcher_test.cc for an example. |
151 class PERFTOOLS_DLL_DECL PreamblePatcher { | 129 class PreamblePatcher { |
152 public: | 130 public: |
153 | 131 |
154 // This is a typesafe version of RawPatch(), identical in all other | 132 // This is a typesafe version of RawPatch(), identical in all other |
155 // ways than it takes a template parameter indicating the type of the | 133 // ways than it takes a template parameter indicating the type of the |
156 // function being patched. | 134 // function being patched. |
157 // | 135 // |
158 // @param T The type of the function you are patching. Usually | 136 // @param T The type of the function you are patching. Usually |
159 // you will establish this type using a typedef, as in the following | 137 // you will establish this type using a typedef, as in the following |
160 // example: | 138 // example: |
161 // @code | 139 // @code |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
302 // | 280 // |
303 // @return Either target_function (the input parameter), or if | 281 // @return Either target_function (the input parameter), or if |
304 // target_function's body consists entirely of a JMP instruction, | 282 // target_function's body consists entirely of a JMP instruction, |
305 // the address it JMPs to (or more precisely, the address at the end | 283 // the address it JMPs to (or more precisely, the address at the end |
306 // of a chain of JMPs). | 284 // of a chain of JMPs). |
307 template <class T> | 285 template <class T> |
308 static T ResolveTarget(T target_function) { | 286 static T ResolveTarget(T target_function) { |
309 return (T)ResolveTargetImpl((unsigned char*)target_function, NULL); | 287 return (T)ResolveTargetImpl((unsigned char*)target_function, NULL); |
310 } | 288 } |
311 | 289 |
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 | |
329 private: | 290 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 | |
361 // Patches a function by overwriting its first few bytes with | 291 // Patches a function by overwriting its first few bytes with |
362 // a jump to a different function. This is similar to the RawPatch | 292 // a jump to a different function. This is similar to the RawPatch |
363 // function except that it uses the stub allocated by the caller | 293 // function except that it uses the stub allocated by the caller |
364 // instead of allocating it. | 294 // instead of allocating it. |
365 // | 295 // |
366 // We call VirtualProtect to make the | 296 // We call VirtualProtect to make the |
367 // target function writable at least for the duration of the call. | 297 // target function writable at least for the duration of the call. |
368 // | 298 // |
369 // @param target_function A pointer to the function that should be | 299 // @param target_function A pointer to the function that should be |
370 // patched. | 300 // patched. |
(...skipping 10 matching lines...) Expand all Loading... |
381 // @param stub_size Size in bytes of the buffer allocated for the | 311 // @param stub_size Size in bytes of the buffer allocated for the |
382 // preamble_stub | 312 // preamble_stub |
383 // | 313 // |
384 // @param bytes_needed Pointer to a variable that receives the minimum | 314 // @param bytes_needed Pointer to a variable that receives the minimum |
385 // number of bytes required for the stub. Can be set to NULL if you're | 315 // number of bytes required for the stub. Can be set to NULL if you're |
386 // not interested. | 316 // not interested. |
387 // | 317 // |
388 // @return An error code indicating the result of patching. | 318 // @return An error code indicating the result of patching. |
389 static SideStepError RawPatchWithStubAndProtections( | 319 static SideStepError RawPatchWithStubAndProtections( |
390 void* target_function, | 320 void* target_function, |
391 void* replacement_function, | 321 void *replacement_function, |
392 unsigned char* preamble_stub, | 322 unsigned char* preamble_stub, |
393 unsigned long stub_size, | 323 unsigned long stub_size, |
394 unsigned long* bytes_needed); | 324 unsigned long* bytes_needed); |
395 | 325 |
396 // A helper function used by RawPatchWithStubAndProtections -- it | 326 // A helper function used by RawPatchWithStubAndProtections -- it |
397 // does everything but the VirtualProtect work. Defined in | 327 // does everything but the VirtualProtect work. Defined in |
398 // preamble_patcher_with_stub.cc. | 328 // preamble_patcher_with_stub.cc. |
399 // | 329 // |
400 // @param target_function A pointer to the function that should be | 330 // @param target_function A pointer to the function that should be |
401 // patched. | 331 // patched. |
402 // | 332 // |
403 // @param replacement_function A pointer to the function that should | 333 // @param replacement_function A pointer to the function that should |
404 // replace the target function. The replacement function must have | 334 // replace the target function. The replacement function must have |
405 // exactly the same calling convention and parameters as the original | 335 // exactly the same calling convention and parameters as the original |
406 // function. | 336 // function. |
407 // | 337 // |
408 // @param preamble_stub A pointer to a buffer where the preamble stub | 338 // @param preamble_stub A pointer to a buffer where the preamble stub |
409 // should be copied. The size of the buffer should be sufficient to | 339 // should be copied. The size of the buffer should be sufficient to |
410 // hold the preamble bytes. | 340 // hold the preamble bytes. |
411 // | 341 // |
412 // @param stub_size Size in bytes of the buffer allocated for the | 342 // @param stub_size Size in bytes of the buffer allocated for the |
413 // preamble_stub | 343 // preamble_stub |
414 // | 344 // |
415 // @param bytes_needed Pointer to a variable that receives the minimum | 345 // @param bytes_needed Pointer to a variable that receives the minimum |
416 // number of bytes required for the stub. Can be set to NULL if you're | 346 // number of bytes required for the stub. Can be set to NULL if you're |
417 // not interested. | 347 // not interested. |
418 // | 348 // |
419 // @return An error code indicating the result of patching. | 349 // @return An error code indicating the result of patching. |
420 static SideStepError RawPatchWithStub(void* target_function, | 350 static SideStepError RawPatchWithStub(void* target_function, |
421 void* replacement_function, | 351 void *replacement_function, |
422 unsigned char* preamble_stub, | 352 unsigned char* preamble_stub, |
423 unsigned long stub_size, | 353 unsigned long stub_size, |
424 unsigned long* bytes_needed); | 354 unsigned long* bytes_needed); |
425 | 355 |
426 | 356 |
427 // A helper routine when patching, which follows jmp instructions at | 357 // A helper routine when patching, which follows jmp instructions at |
428 // function addresses, to get to the "actual" function contents. | 358 // function addresses, to get to the "actual" function contents. |
429 // This allows us to identify two functions that are at different | 359 // This allows us to identify two functions that are at different |
430 // addresses but actually resolve to the same code. | 360 // addresses but actually resolve to the same code. |
431 // | 361 // |
432 // @param target_function Pointer to a function. | 362 // @param target_function Pointer to a function. |
433 // | 363 // |
434 // @param stop_before If, when following JMP instructions from | 364 // @param stop_before If, when following JMP instructions from |
435 // target_function, we get to the address stop, we return | 365 // target_function, we get to the address stop, we return |
436 // immediately, the address that jumps to stop_before. | 366 // immediately, the address that jumps to stop_before. |
437 // | 367 // |
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 // | |
443 // @return Either target_function (the input parameter), or if | 368 // @return Either target_function (the input parameter), or if |
444 // target_function's body consists entirely of a JMP instruction, | 369 // target_function's body consists entirely of a JMP instruction, |
445 // the address it JMPs to (or more precisely, the address at the end | 370 // the address it JMPs to (or more precisely, the address at the end |
446 // of a chain of JMPs). | 371 // of a chain of JMPs). |
447 static void* ResolveTargetImpl(unsigned char* target_function, | 372 static void* ResolveTargetImpl(unsigned char* target_function, |
448 unsigned char* stop_before, | 373 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); | |
607 }; | 374 }; |
608 | 375 |
609 }; // namespace sidestep | 376 }; // namespace sidestep |
610 | 377 |
611 #endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ | 378 #endif // GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_ |
OLD | NEW |