1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include <cstdint>
16 :
17 m : namespace testing {
18 :
19 : // Note: we declare different functions (return different integers) to avoid
20 : // the possibility of vtables overlapping.
21 :
22 m : struct NoVirtualMethodUDT {
23 m : int a;
24 m : int f();
25 m : };
26 :
27 m : struct VirtualMethodUDT {
28 m : int a;
29 m : virtual int f() { return 1; }
30 m : };
31 :
32 m : struct ComposedUDT {
33 m : int a;
34 m : VirtualMethodUDT udt;
35 m : virtual int f() { return 2; }
36 m : };
37 :
38 : // A class that only overrides virtual methods provided by its virtual base is
39 : // expected to have its vftable pointer at offset 0 of its virtual base.
40 m : struct VirtualChildUDT : virtual VirtualMethodUDT {
41 m : int b;
42 m : int f() override { return 3; }
43 m : };
44 :
45 m : struct VirtualChildWithVirtualMethodUDT : virtual VirtualMethodUDT {
46 m : int b;
47 m : int f() override { return 4; }
48 m : virtual int g() { return 5; }
49 m : };
50 :
51 : // Another case where we expect no vftable at offset 0 (interfaces).
52 m : struct IA { virtual int one() = 0; };
53 m : struct IB { virtual int two() = 0; };
54 m : struct SimpleBase { int member; };
55 m : struct InterfaceImplUDT : public SimpleBase, public IA, public IB {
56 m : int one() override { return 6; }
57 m : int two() override { return 7; }
58 m : };
59 :
60 : // Gets the expected vftable virtual addresses.
61 : // @param buffer_size size of @p vftable_vas
62 : // @param vftable_vas on success, contains the expected vftable virtual
63 : // addresses.
64 : // @param count on success, the count of returned vftable virtual addresses.
65 : // @returns true on success, false otherwise.
66 m : extern "C" bool GetExpectedVftableVAs(unsigned buffer_size,
67 m : uint64_t* vftable_vas,
68 m : unsigned* count) {
69 m : if (!vftable_vas || !count)
70 m : return false;
71 : // Validate pointer size.
72 m : if (sizeof(unsigned) != sizeof(unsigned*))
73 m : return false;
74 m : if (buffer_size < 3U)
75 m : return false;
76 :
77 m : unsigned cnt = 0U;
78 :
79 m : {
80 m : VirtualMethodUDT udt;
81 m : vftable_vas[cnt] =
82 m : static_cast<uint64_t>(*reinterpret_cast<uintptr_t*>(&udt));
83 m : cnt++;
84 m : }
85 :
86 m : {
87 m : ComposedUDT udt;
88 m : vftable_vas[cnt] =
89 m : static_cast<uint64_t>(*reinterpret_cast<uintptr_t*>(&udt));
90 m : cnt++;
91 m : }
92 :
93 m : {
94 m : VirtualChildWithVirtualMethodUDT udt;
95 m : vftable_vas[cnt] =
96 m : static_cast<uint64_t>(*reinterpret_cast<uintptr_t*>(&udt));
97 m : cnt++;
98 m : }
99 :
100 : // TODO(manzagop): handle the other cases.
101 :
102 m : *count = cnt;
103 m : return true;
104 m : }
105 :
106 m : } // namespace testing
|