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