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

Unified Diff: tools/memory_watcher/preamble_patcher.cc

Issue 314253003: Remove memory_watcher tool as well as --memory-profile command line flag. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix compile issue on non-ChromeOS platforms Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/memory_watcher/preamble_patcher.h ('k') | tools/memory_watcher/preamble_patcher_with_stub.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/memory_watcher/preamble_patcher.cc
diff --git a/tools/memory_watcher/preamble_patcher.cc b/tools/memory_watcher/preamble_patcher.cc
deleted file mode 100644
index 846d88141be32b8a3602f120b9d8199f67dc4e93..0000000000000000000000000000000000000000
--- a/tools/memory_watcher/preamble_patcher.cc
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (c) 2010 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.
-
-#include "preamble_patcher.h"
-#include "memory_hook.h"
-#include "mini_disassembler.h"
-
-// compatibility shims
-#include "base/logging.h"
-
-// Definitions of assembly statements we need
-#define ASM_JMP32REL 0xE9
-#define ASM_INT3 0xCC
-
-namespace sidestep {
-
-SideStepError PreamblePatcher::RawPatchWithStubAndProtections(
- void* target_function, void *replacement_function,
- unsigned char* preamble_stub, unsigned long stub_size,
- unsigned long* bytes_needed) {
- // We need to be able to write to a process-local copy of the first
- // MAX_PREAMBLE_STUB_SIZE bytes of target_function. We may be giving execute
- // privilege to something that doesn't have it, but that's the price to pay
- // for tools.
- DWORD old_target_function_protect = 0;
- BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
- MAX_PREAMBLE_STUB_SIZE,
- PAGE_EXECUTE_READWRITE,
- &old_target_function_protect);
- if (!succeeded) {
- ASSERT(false, "Failed to make page containing target function "
- "copy-on-write.");
- return SIDESTEP_ACCESS_DENIED;
- }
-
- SideStepError error_code = RawPatchWithStub(target_function,
- replacement_function,
- preamble_stub,
- stub_size,
- bytes_needed);
- if (SIDESTEP_SUCCESS != error_code) {
- ASSERT1(false);
- return error_code;
- }
-
- // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
- // pTargetFunction to what they were before we started goofing around.
- succeeded = ::VirtualProtect(reinterpret_cast<void*>(target_function),
- MAX_PREAMBLE_STUB_SIZE,
- old_target_function_protect,
- &old_target_function_protect);
- if (!succeeded) {
- ASSERT(false, "Failed to restore protection to target function.");
- // We must not return an error here because the function has actually
- // been patched, and returning an error would likely cause our client
- // code not to unpatch it. So we just keep going.
- }
-
- // Flush the instruction cache to make sure the processor doesn't execute the
- // old version of the instructions (before our patch).
- //
- // FlushInstructionCache is actually a no-op at least on single-processor
- // XP machines. I'm not sure why this is so, but it is, yet I want to keep
- // the call to the API here for correctness in case there is a difference in
- // some variants of Windows/hardware.
- succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
- target_function,
- MAX_PREAMBLE_STUB_SIZE);
- if (!succeeded) {
- ASSERT(false, "Failed to flush instruction cache.");
- // We must not return an error here because the function has actually
- // been patched, and returning an error would likely cause our client
- // code not to unpatch it. So we just keep going.
- }
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::RawPatch(void* target_function,
- void* replacement_function,
- void** original_function_stub) {
- if (!target_function || !replacement_function || !original_function_stub ||
- (*original_function_stub) || target_function == replacement_function) {
- ASSERT(false, "Preconditions not met");
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- // @see MAX_PREAMBLE_STUB_SIZE for an explanation of how we arrives at
- // this size
- unsigned char* preamble_stub =
- reinterpret_cast<unsigned char*>(
- MemoryHook::Alloc(sizeof(unsigned char) * MAX_PREAMBLE_STUB_SIZE));
- if (!preamble_stub) {
- ASSERT(false, "Unable to allocate preamble-stub.");
- return SIDESTEP_INSUFFICIENT_BUFFER;
- }
-
- // Change the protection of the newly allocated preamble stub to
- // PAGE_EXECUTE_READWRITE. This is required to work with DEP (Data
- // Execution Prevention) which will cause an exception if code is executed
- // from a page on which you do not have read access.
- DWORD old_stub_protect = 0;
- BOOL succeeded = VirtualProtect(preamble_stub, MAX_PREAMBLE_STUB_SIZE,
- PAGE_EXECUTE_READWRITE, &old_stub_protect);
- if (!succeeded) {
- ASSERT(false, "Failed to make page preamble stub read-write-execute.");
- delete[] preamble_stub;
- return SIDESTEP_ACCESS_DENIED;
- }
-
- SideStepError error_code = RawPatchWithStubAndProtections(target_function,
- replacement_function,
- preamble_stub,
- MAX_PREAMBLE_STUB_SIZE,
- NULL);
- if (SIDESTEP_SUCCESS != error_code) {
- ASSERT1(false);
- delete[] preamble_stub;
- return error_code;
- }
-
- *original_function_stub = reinterpret_cast<void*>(preamble_stub);
-
- // NOTE: For hooking malloc/free, we don't want to use streams which
- // allocate. Basically, we've hooked malloc, but not necessarily
- // hooked free yet. To do anything which uses the heap could crash
- // with a mismatched malloc/free!
- //VLOG(1) << "PreamblePatcher::RawPatch successfully patched 0x"
- // << target_function;
-
- return SIDESTEP_SUCCESS;
-}
-
-SideStepError PreamblePatcher::Unpatch(void* target_function,
- void* replacement_function,
- void* original_function_stub) {
- ASSERT1(target_function && original_function_stub);
- if (!target_function || !original_function_stub) {
- return SIDESTEP_INVALID_PARAMETER;
- }
-
- // We disassemble the preamble of the _stub_ to see how many bytes we
- // originally copied to the stub.
- MiniDisassembler disassembler;
- unsigned int preamble_bytes = 0;
- while (preamble_bytes < 5) {
- InstructionType instruction_type = disassembler.Disassemble(
- reinterpret_cast<unsigned char*>(original_function_stub) +
- preamble_bytes, preamble_bytes);
- if (IT_GENERIC != instruction_type) {
- ASSERT(false, "Should only have generic instructions in stub!!");
- return SIDESTEP_UNSUPPORTED_INSTRUCTION;
- }
- }
-
- // Before unpatching, target_function should be a JMP to
- // replacement_function. If it's not, then either it's an error, or
- // we're falling into the case where the original instruction was a
- // JMP, and we patched the jumped_to address rather than the JMP
- // itself. (For instance, if malloc() is just a JMP to __malloc(),
- // we patched __malloc() and not malloc().)
- unsigned char* target = reinterpret_cast<unsigned char*>(target_function);
- while (1) { // we stop when target is a JMP to replacement_function
- if (target[0] != ASM_JMP32REL) {
- ASSERT(false, "target_function does not look like it was patched.");
- return SIDESTEP_INVALID_PARAMETER;
- }
- int relative_offset; // Windows guarantees int is 4 bytes
- ASSERT1(sizeof(relative_offset) == 4);
- memcpy(reinterpret_cast<void*>(&relative_offset),
- reinterpret_cast<void*>(target + 1), 4);
- unsigned char* jump_to = target + 5 + relative_offset;
- if (jump_to == replacement_function)
- break;
- target = jump_to; // follow the jmp
- }
-
- // We need to be able to write to a process-local copy of the first
- // MAX_PREAMBLE_STUB_SIZE bytes of target_function. We may be giving execute
- // privilege to something that doesn't have it, but that's the price to pay
- // for tools.
- DWORD old_target_function_protect = 0;
- BOOL succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
- MAX_PREAMBLE_STUB_SIZE,
- PAGE_EXECUTE_READWRITE,
- &old_target_function_protect);
- if (!succeeded) {
- ASSERT(false, "Failed to make page containing target function "
- "copy-on-write.");
- return SIDESTEP_ACCESS_DENIED;
- }
-
- // Replace the first few bytes of the original function with the bytes we
- // previously moved to the preamble stub.
- memcpy(reinterpret_cast<void*>(target),
- original_function_stub, preamble_bytes);
-
- // Stub is now useless so delete it.
- // [csilvers: Commented out for perftools because it causes big problems
- // when we're unpatching malloc. We just let this live on as a leak.]
- //delete original_function_stub;
-
- // Restore the protection of the first MAX_PREAMBLE_STUB_SIZE bytes of
- // target to what they were before we started goofing around.
- succeeded = ::VirtualProtect(reinterpret_cast<void*>(target),
- MAX_PREAMBLE_STUB_SIZE,
- old_target_function_protect,
- &old_target_function_protect);
-
- // Flush the instruction cache to make sure the processor doesn't execute the
- // old version of the instructions (before our patch).
- //
- // See comment on FlushInstructionCache elsewhere in this file.
- succeeded = ::FlushInstructionCache(::GetCurrentProcess(),
- target,
- MAX_PREAMBLE_STUB_SIZE);
- if (!succeeded) {
- ASSERT(false, "Failed to flush instruction cache.");
- return SIDESTEP_UNEXPECTED;
- }
-
- VLOG(1) << "PreamblePatcher::Unpatch successfully unpatched 0x"
- << target_function;
- return SIDESTEP_SUCCESS;
-}
-
-}; // namespace sidestep
« no previous file with comments | « tools/memory_watcher/preamble_patcher.h ('k') | tools/memory_watcher/preamble_patcher_with_stub.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698