1 | // Licensed to the .NET Foundation under one or more agreements. |
---|---|
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // ZapInnerPtr.h |
6 | // |
7 | |
8 | // |
9 | // ZapNode that points into middle of other ZapNode. It is used to create |
10 | // pointers into datastructures that are not convenient to split into smaller zap nodes. |
11 | // |
12 | // ====================================================================================== |
13 | |
14 | #ifndef __ZAPINNERPTR_H__ |
15 | #define __ZAPINNERPTR_H__ |
16 | |
17 | class ZapInnerPtr : public ZapNode |
18 | { |
19 | ZapNode * m_pBase; |
20 | |
21 | public: |
22 | ZapInnerPtr(ZapNode * pBase) |
23 | : m_pBase(pBase) |
24 | { |
25 | } |
26 | |
27 | ZapNode * GetBase() |
28 | { |
29 | return m_pBase; |
30 | } |
31 | |
32 | virtual int GetOffset() = 0; |
33 | |
34 | void Resolve() |
35 | { |
36 | if (m_pBase->IsPlaced()) |
37 | { |
38 | SetRVA(m_pBase->GetRVA() + GetOffset()); |
39 | } |
40 | } |
41 | |
42 | virtual ZapNodeType GetType() |
43 | { |
44 | return ZapNodeType_InnerPtr; |
45 | } |
46 | }; |
47 | |
48 | class ZapInnerPtrTable |
49 | { |
50 | // Create more space efficient nodes for a few common constant offsets |
51 | template <DWORD offset> |
52 | class InnerPtrConst : public ZapInnerPtr |
53 | { |
54 | public: |
55 | InnerPtrConst(ZapNode * pBase) |
56 | : ZapInnerPtr(pBase) |
57 | { |
58 | } |
59 | |
60 | virtual int GetOffset() |
61 | { |
62 | return offset; |
63 | } |
64 | }; |
65 | |
66 | // The generic node for arbitrary offsets |
67 | class InnerPtrVar : public ZapInnerPtr |
68 | { |
69 | int m_offset; |
70 | |
71 | public: |
72 | InnerPtrVar(ZapNode * pBase, SSIZE_T offset) |
73 | : ZapInnerPtr(pBase), m_offset((int)offset) |
74 | { |
75 | if (offset != (int)offset) |
76 | ThrowHR(COR_E_OVERFLOW); |
77 | } |
78 | |
79 | virtual int GetOffset() |
80 | { |
81 | return m_offset; |
82 | } |
83 | }; |
84 | |
85 | struct InnerPtrKey |
86 | { |
87 | InnerPtrKey(ZapNode * pBase, SSIZE_T offset) |
88 | : m_pBase(pBase), m_offset(offset) |
89 | { |
90 | } |
91 | |
92 | ZapNode * m_pBase; |
93 | SSIZE_T m_offset; |
94 | }; |
95 | |
96 | class InnerPtrTraits : public NoRemoveSHashTraits< DefaultSHashTraits<ZapInnerPtr *> > |
97 | { |
98 | public: |
99 | typedef const InnerPtrKey key_t; |
100 | |
101 | static key_t GetKey(element_t e) |
102 | { |
103 | LIMITED_METHOD_CONTRACT; |
104 | return InnerPtrKey(e->GetBase(), e->GetOffset()); |
105 | } |
106 | static BOOL Equals(key_t k1, key_t k2) |
107 | { |
108 | LIMITED_METHOD_CONTRACT; |
109 | return (k1.m_pBase == k2.m_pBase) && (k1.m_offset == k2.m_offset); |
110 | } |
111 | static count_t Hash(key_t k) |
112 | { |
113 | LIMITED_METHOD_CONTRACT; |
114 | return (count_t)(size_t)k.m_pBase ^ (count_t)k.m_offset; |
115 | } |
116 | |
117 | static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } |
118 | static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } |
119 | }; |
120 | |
121 | typedef SHash< InnerPtrTraits > InnerPtrTable; |
122 | |
123 | InnerPtrTable m_entries; |
124 | ZapWriter * m_pWriter; |
125 | |
126 | public: |
127 | ZapInnerPtrTable(ZapWriter * pWriter) |
128 | : m_pWriter(pWriter) |
129 | { |
130 | } |
131 | |
132 | void Preallocate(COUNT_T cbILImage) |
133 | { |
134 | PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapInnerPtrTable::m_entries, cbILImage); |
135 | } |
136 | |
137 | // Returns ZapNode that points at given offset in base ZapNode |
138 | ZapNode * Get(ZapNode * pBase, SSIZE_T offset); |
139 | |
140 | // Assign offsets to the inner-ptr ZapNodes |
141 | void Resolve(); |
142 | }; |
143 | |
144 | #endif // __ZAPINNERPTR_H__ |
145 |