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

Unified Diff: chrome_frame/vtable_patch_manager.cc

Issue 126143005: Remove Chrome Frame code and resources. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync to r244038 Created 6 years, 11 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 | « chrome_frame/vtable_patch_manager.h ('k') | chrome_frame/vtable_patch_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome_frame/vtable_patch_manager.cc
diff --git a/chrome_frame/vtable_patch_manager.cc b/chrome_frame/vtable_patch_manager.cc
deleted file mode 100644
index da1bbabbff6ad7fa8748a35e38fc79e7084cb0c6..0000000000000000000000000000000000000000
--- a/chrome_frame/vtable_patch_manager.cc
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2011 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 "chrome_frame/vtable_patch_manager.h"
-
-#include <atlcomcli.h>
-
-#include <algorithm>
-
-#include "base/atomicops.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/lock.h"
-#include "chrome_frame/function_stub.h"
-#include "chrome_frame/pin_module.h"
-
-namespace vtable_patch {
-
-// The number of times we retry a patch/unpatch operation in case of
-// VM races with other 3rd party software trying to patch the same thing.
-const int kMaxRetries = 3;
-
-// We hold a lock over all patching operations to make sure that we don't
-// e.g. race on VM operations to the same patches, or to physical pages
-// shared across different VTABLEs.
-base::Lock patch_lock_;
-
-namespace internal {
-// Because other parties in our process might be attempting to patch the same
-// virtual tables at the same time, we have a race to modify the VM protections
-// on the pages. We also need to do a compare/swap type operation when we
-// modify the function, so as to be sure that we grab the most recent value.
-// Hence the SEH blocks and the nasty-looking compare/swap operation.
-bool ReplaceFunctionPointer(void** entry, void* new_proc, void* curr_proc) {
- __try {
- base::subtle::Atomic32 prev_value;
-
- prev_value = base::subtle::NoBarrier_CompareAndSwap(
- reinterpret_cast<base::subtle::Atomic32 volatile*>(entry),
- reinterpret_cast<base::subtle::Atomic32>(curr_proc),
- reinterpret_cast<base::subtle::Atomic32>(new_proc));
-
- return curr_proc == reinterpret_cast<void*>(prev_value);
- } __except(EXCEPTION_EXECUTE_HANDLER) {
- // Oops, we took exception on access.
- }
-
- return false;
-}
-
-} // namespace
-
-// Convenient definition of a VTABLE
-typedef PROC* Vtable;
-
-// Returns a pointer to the VTable of a COM interface.
-// @param unknown [in] The pointer of the COM interface.
-inline Vtable GetIFVTable(void* unknown) {
- return reinterpret_cast<Vtable>(*reinterpret_cast<void**>(unknown));
-}
-
-HRESULT PatchInterfaceMethods(void* unknown, MethodPatchInfo* patches) {
- // Do some sanity checking of the input arguments.
- if (NULL == unknown || NULL == patches) {
- NOTREACHED();
- return E_INVALIDARG;
- }
-
- Vtable vtable = GetIFVTable(unknown);
- DCHECK(vtable);
-
- // All VM operations, patching and manipulation of MethodPatchInfo
- // is done under a global lock, to ensure multiple threads don't
- // race, whether on an individual patch, or on VM operations to
- // the same physical pages.
- base::AutoLock lock(patch_lock_);
-
- for (MethodPatchInfo* it = patches; it->index_ != -1; ++it) {
- if (it->stub_ != NULL) {
- // If this DCHECK fires it means that we are using the same VTable
- // information to patch two different interfaces, or we've lost a
- // race with another thread who's patching the same interface.
- DLOG(WARNING) << "Attempting to patch two different VTables with the "
- "same VTable information, or patching the same interface on "
- "multiple threads";
- continue;
- }
-
- PROC original_fn = vtable[it->index_];
- FunctionStub* stub = NULL;
-
-#ifndef NDEBUG
- stub = FunctionStub::FromCode(original_fn);
- if (stub != NULL) {
- DLOG(ERROR) << "attempt to patch a function that's already patched";
- DCHECK(stub->destination_function() ==
- reinterpret_cast<uintptr_t>(it->method_)) <<
- "patching the same method multiple times with different hooks?";
- continue;
- }
-#endif
-
- stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(original_fn),
- it->method_);
- if (!stub) {
- NOTREACHED();
- return E_OUTOFMEMORY;
- }
-
- // Do the VM operations and the patching in a loop, to try and ensure
- // we succeed even if there's a VM operation or a patch race against
- // other 3rd parties patching.
- bool succeeded = false;
- for (int i = 0; !succeeded && i < kMaxRetries; ++i) {
- DWORD protect = 0;
- if (!::VirtualProtect(&vtable[it->index_], sizeof(PROC),
- PAGE_EXECUTE_READWRITE, &protect)) {
- HRESULT hr = AtlHresultFromLastError();
- DLOG(ERROR) << "VirtualProtect failed 0x" << std::hex << hr;
-
- // Go around again in the feeble hope that this is
- // a temporary problem.
- continue;
- }
- original_fn = vtable[it->index_];
- stub->set_argument(reinterpret_cast<uintptr_t>(original_fn));
- succeeded = internal::ReplaceFunctionPointer(
- reinterpret_cast<void**>(&vtable[it->index_]), stub->code(),
- original_fn);
-
- if (!::VirtualProtect(&vtable[it->index_], sizeof(PROC), protect,
- &protect)) {
- DLOG(ERROR) << "VirtualProtect failed to restore protection";
- }
- }
-
- if (!succeeded) {
- FunctionStub::Destroy(stub);
- stub = NULL;
-
- DLOG(ERROR) << "Failed to patch VTable.";
- return E_FAIL;
- } else {
- // Success, save the stub we created.
- it->stub_ = stub;
- chrome_frame::PinModule();
- }
- }
-
- return S_OK;
-}
-
-HRESULT UnpatchInterfaceMethods(MethodPatchInfo* patches) {
- base::AutoLock lock(patch_lock_);
-
- for (MethodPatchInfo* it = patches; it->index_ != -1; ++it) {
- if (it->stub_) {
- DCHECK(it->stub_->destination_function() ==
- reinterpret_cast<uintptr_t>(it->method_));
- // Modify the stub to just jump directly to the original function.
- it->stub_->BypassStub(reinterpret_cast<void*>(it->stub_->argument()));
- it->stub_ = NULL;
- // Leave the stub in memory so that we won't break any possible chains.
-
- // TODO(siggi): why not restore the original VTBL pointer here, provided
- // we haven't been chained?
- } else {
- DLOG(WARNING) << "attempt to unpatch a function that wasn't patched";
- }
- }
-
- return S_OK;
-}
-
-// Disabled for now as we're not using it atm.
-#if 0
-
-DynamicPatchManager::DynamicPatchManager(const MethodPatchInfo* patch_prototype)
- : patch_prototype_(patch_prototype) {
- DCHECK(patch_prototype_);
- DCHECK(patch_prototype_->stub_ == NULL);
-}
-
-DynamicPatchManager::~DynamicPatchManager() {
- UnpatchAll();
-}
-
-HRESULT DynamicPatchManager::PatchObject(void* unknown) {
- int patched_methods = 0;
- for (; patch_prototype_[patched_methods].index_ != -1; patched_methods++) {
- // If you hit this, then you are likely using the prototype instance for
- // patching in _addition_ to this class. This is not a good idea :)
- DCHECK(patch_prototype_[patched_methods].stub_ == NULL);
- }
-
- // Prepare a new patch object using the patch info from the prototype.
- int mem_size = sizeof(PatchedObject) +
- sizeof(MethodPatchInfo) * patched_methods;
- PatchedObject* entry = reinterpret_cast<PatchedObject*>(new char[mem_size]);
- entry->vtable_ = GetIFVTable(unknown);
- memcpy(entry->patch_info_, patch_prototype_,
- sizeof(MethodPatchInfo) * (patched_methods + 1));
-
- patch_list_lock_.Acquire();
-
- // See if we've already patched this vtable before.
- // The search is done via the == operator of the PatchedObject class.
- PatchList::const_iterator it = std::find(patch_list_.begin(),
- patch_list_.end(), entry);
- HRESULT hr;
- if (it == patch_list_.end()) {
- hr = PatchInterfaceMethods(unknown, entry->patch_info_);
- if (SUCCEEDED(hr)) {
- patch_list_.push_back(entry);
- entry = NULL; // Ownership transferred to the array.
- }
- } else {
- hr = S_FALSE;
- }
-
- patch_list_lock_.Release();
-
- delete entry;
-
- return hr;
-}
-
-bool DynamicPatchManager::UnpatchAll() {
- patch_list_lock_.Acquire();
- PatchList::iterator it;
- for (it = patch_list_.begin(); it != patch_list_.end(); it++) {
- UnpatchInterfaceMethods((*it)->patch_info_);
- delete (*it);
- }
- patch_list_.clear();
- patch_list_lock_.Release();
-
- return true;
-}
-
-#endif // disabled DynamicPatchManager
-
-} // namespace vtable_patch
« no previous file with comments | « chrome_frame/vtable_patch_manager.h ('k') | chrome_frame/vtable_patch_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698