| Index: chrome_frame/function_stub.cc
|
| ===================================================================
|
| --- chrome_frame/function_stub.cc (revision 0)
|
| +++ chrome_frame/function_stub.cc (revision 0)
|
| @@ -0,0 +1,141 @@
|
| +// Copyright (c) 2009 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/function_stub.h"
|
| +
|
| +#include <new>
|
| +#include "base/lock.h"
|
| +#include "base/logging.h"
|
| +
|
| +#ifndef _M_IX86
|
| +#error Only x86 supported right now.
|
| +#endif
|
| +
|
| +namespace {
|
| +typedef enum AsmConstants {
|
| + POP_EAX = 0x58,
|
| + PUSH_IND = 0x35ff,
|
| + PUSH_EAX = 0x50,
|
| + JUMP_IND = 0x25ff,
|
| +};
|
| +
|
| +// A quick and dirty wrapper class that allows us to defer allocating
|
| +// the executable heap until first use, and to release it teardown.
|
| +class ExecutableHeap {
|
| + public:
|
| + ExecutableHeap() : heap_(NULL) {
|
| + }
|
| +
|
| + ~ExecutableHeap() {
|
| + if (heap_ != NULL) {
|
| + BOOL ret = ::HeapDestroy(heap_);
|
| + heap_ = NULL;
|
| + }
|
| + }
|
| +
|
| + void* Allocate(size_t size) {
|
| + if (!heap_)
|
| + CreateHeap();
|
| +
|
| + DCHECK(heap_);
|
| +
|
| + return ::HeapAlloc(heap_, 0, size);
|
| + }
|
| +
|
| + void Free(void* ptr) {
|
| + DCHECK(heap_ != NULL);
|
| + ::HeapFree(heap_, 0, ptr);
|
| + }
|
| +
|
| + void CreateHeap() {
|
| + AutoLock lock(init_lock_);
|
| +
|
| + if (heap_ == NULL)
|
| + heap_ = ::HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
|
| + }
|
| +
|
| + private:
|
| + Lock init_lock_;
|
| + HANDLE heap_;
|
| +};
|
| +
|
| +// Our executable heap instance, all stubs are allocated from here.
|
| +ExecutableHeap heap_;
|
| +
|
| +} // namespace
|
| +
|
| +extern "C" IMAGE_DOS_HEADER __ImageBase;
|
| +
|
| +bool FunctionStub::is_valid() const {
|
| + return signature_ == reinterpret_cast<HMODULE>(&__ImageBase) &&
|
| + !is_bypassed();
|
| +}
|
| +
|
| +FunctionStub::FunctionStub(uintptr_t extra_argument, void* dest)
|
| + : signature_(reinterpret_cast<HMODULE>(&__ImageBase)),
|
| + argument_(extra_argument),
|
| + destination_function_(reinterpret_cast<uintptr_t>(dest)) {
|
| + bypass_address_ = reinterpret_cast<uintptr_t>(&stub_.pop_return_addr_);
|
| + Init(&stub_);
|
| +}
|
| +
|
| +FunctionStub::~FunctionStub() {
|
| +}
|
| +
|
| +void FunctionStub::Init(FunctionStubAsm* stub) {
|
| + DCHECK(stub != NULL);
|
| +
|
| + stub->jump_to_bypass_ = JUMP_IND;
|
| + stub->bypass_target_addr_ = reinterpret_cast<uintptr_t>(&bypass_address_);
|
| + stub->pop_return_addr_ = POP_EAX;
|
| + stub->push_ = PUSH_IND;
|
| + stub->arg_addr_ = reinterpret_cast<uintptr_t>(&argument_);
|
| + stub->push_return_addr_ = PUSH_EAX;
|
| + stub->jump_to_target = JUMP_IND;
|
| + stub->target_addr_ = reinterpret_cast<uintptr_t>(&destination_function_);
|
| +
|
| + // Flush the instruction cache for the newly written code.
|
| + BOOL ret = ::FlushInstructionCache(::GetCurrentProcess(),
|
| + stub,
|
| + sizeof(*stub));
|
| +}
|
| +
|
| +void FunctionStub::BypassStub(void* new_target) {
|
| + set_bypass_address(reinterpret_cast<uintptr_t>(new_target));
|
| +}
|
| +
|
| +FunctionStub* FunctionStub::Create(uintptr_t extra_argument, void* dest) {
|
| + DCHECK(dest);
|
| + FunctionStub* stub =
|
| + reinterpret_cast<FunctionStub*>(heap_.Allocate(sizeof(FunctionStub)));
|
| +
|
| + if (stub != NULL)
|
| + new (stub) FunctionStub(extra_argument, dest);
|
| +
|
| + return stub;
|
| +}
|
| +
|
| +FunctionStub* FunctionStub::FromCode(void* address) {
|
| + // Address points to arbitrary code here, which may e.g.
|
| + // lie at the end of an executable segment, which in turn
|
| + // may terminate earlier than the last address we probe.
|
| + // We therefore execute under an SEH, so as not to crash
|
| + // on failed probes.
|
| + __try {
|
| + // Retrieve the candidata function stub.
|
| + FunctionStub* candidate = CONTAINING_RECORD(address, FunctionStub, stub_);
|
| + if (candidate->stub_.jump_to_bypass_ == JUMP_IND &&
|
| + candidate->signature_ == reinterpret_cast<HMODULE>(&__ImageBase)) {
|
| + return candidate;
|
| + }
|
| + } __except(EXCEPTION_EXECUTE_HANDLER) {
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +bool FunctionStub::Destroy(FunctionStub* stub) {
|
| + heap_.Free(stub);
|
| +
|
| + return true;
|
| +}
|
|
|
| Property changes on: chrome_frame\function_stub.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|