diff options
Diffstat (limited to 'chromium/tools/memory_watcher/preamble_patcher.h')
-rw-r--r-- | chromium/tools/memory_watcher/preamble_patcher.h | 293 |
1 files changed, 0 insertions, 293 deletions
diff --git a/chromium/tools/memory_watcher/preamble_patcher.h b/chromium/tools/memory_watcher/preamble_patcher.h deleted file mode 100644 index fae2551bd7b..00000000000 --- a/chromium/tools/memory_watcher/preamble_patcher.h +++ /dev/null @@ -1,293 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* - * Definition of PreamblePatcher - */ - -#ifndef MEMORY_WATCHER_PREAMBLE_PATCHER_H__ -#define MEMORY_WATCHER_PREAMBLE_PATCHER_H__ - -#include <windows.h> - -// compatibility shim -#include "base/logging.h" -#define ASSERT(cond, msg) DCHECK(cond) -#define ASSERT1(cond) DCHECK(cond) - -// Maximum size of the preamble stub. We overwrite at least the first 5 -// 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 :) -#define MAX_PREAMBLE_STUB_SIZE (32) - -namespace sidestep { - -// Possible results of patching/unpatching -enum SideStepError { - SIDESTEP_SUCCESS = 0, - SIDESTEP_INVALID_PARAMETER, - SIDESTEP_INSUFFICIENT_BUFFER, - SIDESTEP_JUMP_INSTRUCTION, - SIDESTEP_FUNCTION_TOO_SMALL, - SIDESTEP_UNSUPPORTED_INSTRUCTION, - SIDESTEP_NO_SUCH_MODULE, - SIDESTEP_NO_SUCH_FUNCTION, - SIDESTEP_ACCESS_DENIED, - SIDESTEP_UNEXPECTED, -}; - -#define SIDESTEP_TO_HRESULT(error) \ - MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error) - -// 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 -// that imitates the action of the original preamble. -// -// NOTE: This patching mechanism should currently only be used for -// non-production code, e.g. unit tests, because it is not threadsafe. -// See the TODO in preamble_patcher_with_stub.cc for instructions on what -// we need to do before using it in production code; it's fairly simple -// but unnecessary for now since we only intend to use it in unit tests. -// -// To patch a function, use either of the typesafe Patch() methods. You -// can unpatch a function using Unpatch(). -// -// Typical usage goes something like this: -// @code -// typedef int (*MyTypesafeFuncPtr)(int x); -// MyTypesafeFuncPtr original_func_stub; -// int MyTypesafeFunc(int x) { return x + 1; } -// int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); } -// -// void MyPatchInitializingFunction() { -// original_func_stub = PreamblePatcher::Patch( -// MyTypesafeFunc, HookMyTypesafeFunc); -// if (!original_func_stub) { -// // ... error handling ... -// } -// -// // ... continue - you have patched the function successfully ... -// } -// @endcode -// -// Note that there are a number of ways that this method of patching can -// fail. The most common are: -// - If there is a jump (jxx) instruction in the first 5 bytes of -// the function being patched, we cannot patch it because in the -// current implementation we do not know how to rewrite relative -// jumps after relocating them to the preamble-stub. Note that -// if you really really need to patch a function like this, it -// would be possible to add this functionality (but at some cost). -// - If there is a return (ret) instruction in the first 5 bytes -// we cannot patch the function because it may not be long enough -// for the jmp instruction we use to inject our patch. -// - If there is another thread currently executing within the bytes -// that are copied to the preamble stub, it will crash in an undefined -// way. -// -// If you get any other error than the above, you're either pointing the -// patcher at an invalid instruction (e.g. into the middle of a multi- -// byte instruction, or not at memory containing executable instructions) -// or, there may be a bug in the disassembler we use to find -// instruction boundaries. -// -// NOTE: In optimized builds, when you have very trivial functions that -// the compiler can reason do not have side effects, the compiler may -// 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 PreamblePatcher { - public: - - // This is a typesafe version of RawPatch(), identical in all other - // ways than it takes a template parameter indicating the type of the - // function being patched. - // - // @param T The type of the function you are patching. Usually - // you will establish this type using a typedef, as in the following - // example: - // @code - // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT); - // MessageBoxPtr original = NULL; - // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original); - // @endcode - template <class T> - static SideStepError Patch(T target_function, - T replacement_function, - T* original_function_stub) { - // NOTE: casting from a function to a pointer is contra the C++ - // spec. It's not safe on IA64, but is on i386. We use - // a C-style cast here to emphasize this is not legal C++. - return RawPatch((void*)(target_function), - (void*)(replacement_function), - (void**)(original_function_stub)); - } - - // Patches a named function imported from the named module using - // preamble patching. Uses RawPatch() to do the actual patching - // work. - // - // @param T The type of the function you are patching. Must - // exactly match the function you specify using module_name and - // function_name. - // - // @param module_name The name of the module from which the function - // is being imported. Note that the patch will fail if this module - // has not already been loaded into the current process. - // - // @param function_name The name of the function you wish to patch. - // - // @param replacement_function Your replacement function which - // will be called whenever code tries to call the original function. - // - // @param original_function_stub Pointer to memory that should receive a - // pointer that can be used (e.g. in the replacement function) to call the - // original function, or NULL to indicate failure. - // - // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS - // indicates success. - template <class T> - static SideStepError Patch(LPCTSTR module_name, - LPCSTR function_name, - T replacement_function, - T* original_function_stub) { - ASSERT1(module_name && function_name); - if (!module_name || !function_name) { - ASSERT(false, - "You must specify a module name and function name."); - return SIDESTEP_INVALID_PARAMETER; - } - HMODULE module = ::GetModuleHandle(module_name); - ASSERT1(module != NULL); - if (!module) { - ASSERT(false, "Invalid module name."); - return SIDESTEP_NO_SUCH_MODULE; - } - FARPROC existing_function = ::GetProcAddress(module, function_name); - if (!existing_function) { - return SIDESTEP_NO_SUCH_FUNCTION; - } - // NOTE: casting from a function to a pointer is contra the C++ - // spec. It's not safe on IA64, but is on i386. We use - // a C-style cast here to emphasize this is not legal C++. - return RawPatch((void*)existing_function, (void*)replacement_function, - (void**)(original_function_stub)); - } - - // Patches a function by overwriting its first few bytes with - // a jump to a different function. This is the "worker" function - // for each of the typesafe Patch() functions. In most cases, - // it is preferable to use the Patch() functions rather than - // this one as they do more checking at compile time. - // - // @param target_function A pointer to the function that should be - // patched. - // - // @param replacement_function A pointer to the function that should - // replace the target function. The replacement function must have - // exactly the same calling convention and parameters as the original - // function. - // - // @param original_function_stub Pointer to memory that should receive a - // pointer that can be used (e.g. in the replacement function) to call the - // original function, or NULL to indicate failure. - // - // @param original_function_stub Pointer to memory that should receive a - // pointer that can be used (e.g. in the replacement function) to call the - // original function, or NULL to indicate failure. - // - // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS - // indicates success. - // - // @note The preamble-stub (the memory pointed to by - // *original_function_stub) is allocated on the heap, and (in - // production binaries) never destroyed, resulting in a memory leak. This - // will be the case until we implement safe unpatching of a method. - // However, it is quite difficult to unpatch a method (because other - // threads in the process may be using it) so we are leaving it for now. - // See however UnsafeUnpatch, which can be used for binaries where you - // know only one thread is running, e.g. unit tests. - static SideStepError RawPatch(void* target_function, - void* replacement_function, - void** original_function_stub); - - // Unpatches target_function and deletes the stub that previously could be - // used to call the original version of the function. - // - // DELETES the stub that is passed to the function. - // - // @param target_function Pointer to the target function which was - // previously patched, i.e. a pointer which value should match the value - // of the symbol prior to patching it. - // - // @param replacement_function Pointer to the function target_function - // was patched to. - // - // @param original_function_stub Pointer to the stub returned when - // patching, that could be used to call the original version of the - // patched function. This function will also delete the stub, which after - // unpatching is useless. - // - // If your original call was - // origptr = Patch(VirtualAlloc, MyVirtualAlloc) - // then to undo it you would call - // Unpatch(VirtualAlloc, MyVirtualAlloc, origptr); - // - // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS - // indicates success. - static SideStepError Unpatch(void* target_function, - void* replacement_function, - void* original_function_stub); - - private: - - // 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 - // instead of allocating it. - // - // We call VirtualProtect to make the - // target function writable at least for the duration of the call. - // - // @param target_function A pointer to the function that should be - // patched. - // - // @param replacement_function A pointer to the function that should - // replace the target function. The replacement function must have - // exactly the same calling convention and parameters as the original - // function. - // - // @param preamble_stub A pointer to a buffer where the preamble stub - // should be copied. The size of the buffer should be sufficient to - // hold the preamble bytes. - // - // @param stub_size Size in bytes of the buffer allocated for the - // preamble_stub - // - // @param bytes_needed Pointer to a variable that receives the minimum - // number of bytes required for the stub. Can be set to NULL if you're - // not interested. - // - // @return An error code indicating the result of patching. - static SideStepError RawPatchWithStubAndProtections(void* target_function, - void *replacement_function, - unsigned char* preamble_stub, - unsigned long stub_size, - unsigned long* bytes_needed); - - // A helper function used by RawPatchWithStubAndProtections -- it does - // everything but the VirtualProtect wsork. Defined in - // preamble_patcher_with_stub.cc. - static SideStepError RawPatchWithStub(void* target_function, - void *replacement_function, - unsigned char* preamble_stub, - unsigned long stub_size, - unsigned long* bytes_needed); -}; - -}; // namespace sidestep - -#endif // MEMORY_WATCHER_PREAMBLE_PATCHER_H__ |