Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: third_party/tcmalloc/chromium/src/windows/preamble_patcher.h

Issue 9666033: Experiment for updating the tcmalloc chromium branch to r144 (gperftools 2.0). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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_
OLDNEW
« no previous file with comments | « third_party/tcmalloc/chromium/src/windows/port.cc ('k') | third_party/tcmalloc/chromium/src/windows/preamble_patcher.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698