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 |