| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome_frame/function_stub.h" | |
| 6 #include "testing/gtest/include/gtest/gtest.h" | |
| 7 | |
| 8 #define NO_INLINE __declspec(noinline) | |
| 9 | |
| 10 namespace { | |
| 11 | |
| 12 typedef int (__stdcall* FooPrototype)(); | |
| 13 | |
| 14 NO_INLINE int __stdcall Foo() { | |
| 15 return 1; | |
| 16 } | |
| 17 | |
| 18 NO_INLINE int __stdcall PatchedFoo(FooPrototype original) { | |
| 19 return original() + 1; | |
| 20 } | |
| 21 | |
| 22 } // end namespace | |
| 23 | |
| 24 TEST(PatchTests, FunctionStub) { | |
| 25 EXPECT_EQ(Foo(), 1); | |
| 26 // Create a function stub that calls PatchedFoo and supplies it with | |
| 27 // a pointer to Foo. | |
| 28 FunctionStub* stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(&Foo), | |
| 29 &PatchedFoo); | |
| 30 EXPECT_TRUE(stub != NULL); | |
| 31 // Call the stub as it were Foo(). The call should get forwarded to Foo(). | |
| 32 FooPrototype patch = reinterpret_cast<FooPrototype>(stub->code()); | |
| 33 EXPECT_EQ(patch(), 2); | |
| 34 // Now neutralize the stub so that it calls Foo() directly without touching | |
| 35 // PatchedFoo(). | |
| 36 // stub->BypassStub(&Foo); | |
| 37 stub->BypassStub(reinterpret_cast<void*>(stub->argument())); | |
| 38 EXPECT_EQ(patch(), 1); | |
| 39 // We're done with the stub. | |
| 40 FunctionStub::Destroy(stub); | |
| 41 } | |
| 42 | |
| 43 // Basic tests to check the validity of a stub. | |
| 44 TEST(PatchTests, FunctionStubCompare) { | |
| 45 EXPECT_EQ(Foo(), 1); | |
| 46 | |
| 47 // Detect the absence of a stub | |
| 48 FunctionStub* stub = reinterpret_cast<FunctionStub*>(&Foo); | |
| 49 EXPECT_FALSE(stub->is_valid()); | |
| 50 | |
| 51 stub = FunctionStub::Create(reinterpret_cast<uintptr_t>(&Foo), &PatchedFoo); | |
| 52 EXPECT_TRUE(stub != NULL); | |
| 53 EXPECT_TRUE(stub->is_valid()); | |
| 54 | |
| 55 FooPrototype patch = reinterpret_cast<FooPrototype>(stub->code()); | |
| 56 EXPECT_EQ(patch(), 2); | |
| 57 | |
| 58 // See if we can get the correct absolute pointer to the hook function | |
| 59 // back from the stub. | |
| 60 EXPECT_EQ(stub->absolute_target(), reinterpret_cast<uintptr_t>(&PatchedFoo)); | |
| 61 | |
| 62 // Also verify that the argument being passed to the hook function is indeed | |
| 63 // the pointer to the original function (again, absolute not relative). | |
| 64 EXPECT_EQ(stub->argument(), reinterpret_cast<uintptr_t>(&Foo)); | |
| 65 } | |
| OLD | NEW |