| Index: third_party/tcmalloc/chromium/src/windows/preamble_patcher.h
|
| ===================================================================
|
| --- third_party/tcmalloc/chromium/src/windows/preamble_patcher.h (revision 126022)
|
| +++ third_party/tcmalloc/chromium/src/windows/preamble_patcher.h (working copy)
|
| @@ -29,7 +29,6 @@
|
| *
|
| * ---
|
| * Author: Joi Sigurdsson
|
| - * Author: Scott Francis
|
| *
|
| * Definition of PreamblePatcher
|
| */
|
| @@ -37,7 +36,6 @@
|
| #ifndef GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
|
| #define GOOGLE_PERFTOOLS_PREAMBLE_PATCHER_H_
|
|
|
| -#include "config.h"
|
| #include <windows.h>
|
|
|
| // compatibility shim
|
| @@ -49,26 +47,8 @@
|
| // bytes of the function. Considering the worst case scenario, we need 4
|
| // bytes + the max instruction size + 5 more bytes for our jump back to
|
| // the original code. With that in mind, 32 is a good number :)
|
| -#ifdef _M_X64
|
| -// In 64-bit mode we may need more room. In 64-bit mode all jumps must be
|
| -// within +/-2GB of RIP. Because of this limitation we may need to use a
|
| -// trampoline to jump to the replacement function if it is further than 2GB
|
| -// away from the target. The trampoline is 14 bytes.
|
| -//
|
| -// So 4 bytes + max instruction size (17 bytes) + 5 bytes to jump back to the
|
| -// original code + trampoline size. 64 bytes is a nice number :-)
|
| -#define MAX_PREAMBLE_STUB_SIZE (64)
|
| -#else
|
| #define MAX_PREAMBLE_STUB_SIZE (32)
|
| -#endif
|
|
|
| -// Determines if this is a 64-bit binary.
|
| -#ifdef _M_X64
|
| -static const bool kIs64BitBinary = true;
|
| -#else
|
| -static const bool kIs64BitBinary = false;
|
| -#endif
|
| -
|
| namespace sidestep {
|
|
|
| // Possible results of patching/unpatching
|
| @@ -88,8 +68,6 @@
|
| #define SIDESTEP_TO_HRESULT(error) \
|
| MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error)
|
|
|
| -class DeleteUnsignedCharArray;
|
| -
|
| // Implements a patching mechanism that overwrites the first few bytes of
|
| // a function preamble with a jump to our hook function, which is then
|
| // able to call the original function via a specially-made preamble-stub
|
| @@ -148,7 +126,7 @@
|
| // reuse the result of calling the function with a given parameter, which
|
| // may mean if you patch the function in between your patch will never get
|
| // invoked. See preamble_patcher_test.cc for an example.
|
| -class PERFTOOLS_DLL_DECL PreamblePatcher {
|
| +class PreamblePatcher {
|
| public:
|
|
|
| // This is a typesafe version of RawPatch(), identical in all other
|
| @@ -309,55 +287,7 @@
|
| return (T)ResolveTargetImpl((unsigned char*)target_function, NULL);
|
| }
|
|
|
| - // Allocates a block of memory of size MAX_PREAMBLE_STUB_SIZE that is as
|
| - // close (within 2GB) as possible to target. This is done to ensure that
|
| - // we can perform a relative jump from target to a trampoline if the
|
| - // replacement function is > +-2GB from target. This means that we only need
|
| - // to patch 5 bytes in the target function.
|
| - //
|
| - // @param target Pointer to target function.
|
| - //
|
| - // @return Returns a block of memory of size MAX_PREAMBLE_STUB_SIZE that can
|
| - // be used to store a function preamble block.
|
| - static unsigned char* AllocPreambleBlockNear(void* target);
|
| -
|
| - // Frees a block allocated by AllocPreambleBlockNear.
|
| - //
|
| - // @param block Block that was returned by AllocPreambleBlockNear.
|
| - static void FreePreambleBlock(unsigned char* block);
|
| -
|
| private:
|
| - friend class DeleteUnsignedCharArray;
|
| -
|
| - // Used to store data allocated for preamble stubs
|
| - struct PreamblePage {
|
| - unsigned int magic_;
|
| - PreamblePage* next_;
|
| - // This member points to a linked list of free blocks within the page
|
| - // or NULL if at the end
|
| - void* free_;
|
| - };
|
| -
|
| - // In 64-bit mode, the replacement function must be within 2GB of the original
|
| - // target in order to only require 5 bytes for the function patch. To meet
|
| - // this requirement we're creating an allocator within this class to
|
| - // allocate blocks that are within 2GB of a given target. This member is the
|
| - // head of a linked list of pages used to allocate blocks that are within
|
| - // 2GB of the target.
|
| - static PreamblePage* preamble_pages_;
|
| -
|
| - // Page granularity
|
| - static long granularity_;
|
| -
|
| - // Page size
|
| - static long pagesize_;
|
| -
|
| - // Determines if the patcher has been initialized.
|
| - static bool initialized_;
|
| -
|
| - // Used to initialize static members.
|
| - static void Initialize();
|
| -
|
| // Patches a function by overwriting its first few bytes with
|
| // a jump to a different function. This is similar to the RawPatch
|
| // function except that it uses the stub allocated by the caller
|
| @@ -388,7 +318,7 @@
|
| // @return An error code indicating the result of patching.
|
| static SideStepError RawPatchWithStubAndProtections(
|
| void* target_function,
|
| - void* replacement_function,
|
| + void *replacement_function,
|
| unsigned char* preamble_stub,
|
| unsigned long stub_size,
|
| unsigned long* bytes_needed);
|
| @@ -418,7 +348,7 @@
|
| //
|
| // @return An error code indicating the result of patching.
|
| static SideStepError RawPatchWithStub(void* target_function,
|
| - void* replacement_function,
|
| + void *replacement_function,
|
| unsigned char* preamble_stub,
|
| unsigned long stub_size,
|
| unsigned long* bytes_needed);
|
| @@ -435,175 +365,12 @@
|
| // target_function, we get to the address stop, we return
|
| // immediately, the address that jumps to stop_before.
|
| //
|
| - // @param stop_before_trampoline When following JMP instructions from
|
| - // target_function, stop before a trampoline is detected. See comment in
|
| - // PreamblePatcher::RawPatchWithStub for more information. This parameter
|
| - // has no effect in 32-bit mode.
|
| - //
|
| // @return Either target_function (the input parameter), or if
|
| // target_function's body consists entirely of a JMP instruction,
|
| // the address it JMPs to (or more precisely, the address at the end
|
| // of a chain of JMPs).
|
| static void* ResolveTargetImpl(unsigned char* target_function,
|
| - unsigned char* stop_before,
|
| - bool stop_before_trampoline = false);
|
| -
|
| - // Helper routine that attempts to allocate a page as close (within 2GB)
|
| - // as possible to target.
|
| - //
|
| - // @param target Pointer to target function.
|
| - //
|
| - // @return Returns an address that is within 2GB of target.
|
| - static void* AllocPageNear(void* target);
|
| -
|
| - // Helper routine that determines if a target instruction is a short
|
| - // conditional jump.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a short conditional jump.
|
| - static bool IsShortConditionalJump(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that determines if a target instruction is a near
|
| - // conditional jump.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a near conditional jump.
|
| - static bool IsNearConditionalJump(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that determines if a target instruction is a near
|
| - // relative jump.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a near absolute jump.
|
| - static bool IsNearRelativeJump(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that determines if a target instruction is a near
|
| - // absolute call.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a near absolute call.
|
| - static bool IsNearAbsoluteCall(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that determines if a target instruction is a near
|
| - // absolute call.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a near absolute call.
|
| - static bool IsNearRelativeCall(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that determines if a target instruction is a 64-bit MOV
|
| - // that uses a RIP-relative displacement.
|
| - //
|
| - // @param target Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction in bytes.
|
| - //
|
| - // @return Returns true if the instruction is a MOV with displacement.
|
| - static bool IsMovWithDisplacement(unsigned char* target,
|
| - unsigned int instruction_size);
|
| -
|
| - // Helper routine that converts a short conditional jump instruction
|
| - // to a near conditional jump in a target buffer. Note that the target
|
| - // buffer must be within 2GB of the source for the near jump to work.
|
| - //
|
| - // A short conditional jump instruction is in the format:
|
| - // 7x xx = Jcc rel8off
|
| - //
|
| - // @param source Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction.
|
| - //
|
| - // @param target Target buffer to write the new instruction.
|
| - //
|
| - // @param target_bytes Pointer to a buffer that contains the size
|
| - // of the target instruction, in bytes.
|
| - //
|
| - // @param target_size Size of the target buffer.
|
| - //
|
| - // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
|
| - static SideStepError PatchShortConditionalJump(unsigned char* source,
|
| - unsigned int instruction_size,
|
| - unsigned char* target,
|
| - unsigned int* target_bytes,
|
| - unsigned int target_size);
|
| -
|
| - // Helper routine that converts an instruction that will convert various
|
| - // jump-like instructions to corresponding instructions in the target buffer.
|
| - // What this routine does is fix up the relative offsets contained in jump
|
| - // instructions to point back to the original target routine. Like with
|
| - // PatchShortConditionalJump, the target buffer must be within 2GB of the
|
| - // source.
|
| - //
|
| - // We currently handle the following instructions:
|
| - //
|
| - // E9 xx xx xx xx = JMP rel32off
|
| - // 0F 8x xx xx xx xx = Jcc rel32off
|
| - // FF /2 xx xx xx xx = CALL reg/mem32/mem64
|
| - // E8 xx xx xx xx = CALL rel32off
|
| - //
|
| - // It should not be hard to update this function to support other
|
| - // instructions that jump to relative targets.
|
| - //
|
| - // @param source Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction.
|
| - //
|
| - // @param target Target buffer to write the new instruction.
|
| - //
|
| - // @param target_bytes Pointer to a buffer that contains the size
|
| - // of the target instruction, in bytes.
|
| - //
|
| - // @param target_size Size of the target buffer.
|
| - //
|
| - // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
|
| - static SideStepError PatchNearJumpOrCall(unsigned char* source,
|
| - unsigned int instruction_size,
|
| - unsigned char* target,
|
| - unsigned int* target_bytes,
|
| - unsigned int target_size);
|
| -
|
| - // Helper routine that patches a 64-bit MOV instruction with a RIP-relative
|
| - // displacement. The target buffer must be within 2GB of the source.
|
| - //
|
| - // 48 8B 0D XX XX XX XX = MOV rel32off
|
| - //
|
| - // @param source Pointer to instruction.
|
| - //
|
| - // @param instruction_size Size of the instruction.
|
| - //
|
| - // @param target Target buffer to write the new instruction.
|
| - //
|
| - // @param target_bytes Pointer to a buffer that contains the size
|
| - // of the target instruction, in bytes.
|
| - //
|
| - // @param target_size Size of the target buffer.
|
| - //
|
| - // @return Returns SIDESTEP_SUCCESS if successful, otherwise an error.
|
| - static SideStepError PatchMovWithDisplacement(unsigned char* source,
|
| - unsigned int instruction_size,
|
| - unsigned char* target,
|
| - unsigned int* target_bytes,
|
| - unsigned int target_size);
|
| + unsigned char* stop_before);
|
| };
|
|
|
| }; // namespace sidestep
|
|
|