1 : // Copyright 2012 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 : // Declares TypedBlock and ConstTypedBlock. These are thin wrappers to
16 : // BlockGraph::Block objects which allow the data within a block to be
17 : // interpreted as an object of a given type.
18 : //
19 : // Example use is as follows:
20 : //
21 : // BlockGraph::Block* dos_header_block = ...;
22 : // TypedBlock<IMAGE_DOS_HEADER> dos_header;
23 : // DCHECK(dos_header.Init(0, dos_header_block));
24 : //
25 : // // Reference the fields of the object as if we had a pointer to the object.
26 : // if (dos_header->e_magic == ...) ...
27 : //
28 : // // Dereference pointers in the object using 'Dereference'. This takes care
29 : // // of finding, validating and following references within the block graph.
30 : // TypedBlock<IMAGE_NT_HEADERS> nt_headers;
31 : // DCHECK(dos_header.Dereference(dos_header->e_lfanew, &nt_headers));
32 : //
33 : // For full details of the API, refer to internal::TypedBlockImpl, defined in
34 : // syzygy/block_graph/typed_block_internal.h
35 :
36 : #ifndef SYZYGY_BLOCK_GRAPH_TYPED_BLOCK_H_
37 : #define SYZYGY_BLOCK_GRAPH_TYPED_BLOCK_H_
38 :
39 : #include "syzygy/block_graph/block_graph.h"
40 :
41 : namespace block_graph {
42 :
43 : namespace internal {
44 :
45 : typedef BlockGraph::Block* BlockPtr;
46 : typedef const BlockGraph::Block* ConstBlockPtr;
47 :
48 : // Forward declare.
49 : template <typename T, typename BlockPtr, typename ChildType>
50 : class TypedBlockImpl;
51 :
52 : } // namespace internal
53 :
54 : // Used for interpreting a non-const BlockGraph::Block's data as a mutable
55 : // object of type T. Augments TypedBlockImpl with routine's for modifying
56 : // references.
57 : template <typename T> class TypedBlock
58 : : public internal::TypedBlockImpl<T,
59 : internal::BlockPtr,
60 : TypedBlock<T>> {
61 : public:
62 : typedef BlockGraph::Block Block;
63 : typedef BlockGraph::Offset Offset;
64 : typedef BlockGraph::Reference Reference;
65 : typedef BlockGraph::ReferenceType ReferenceType;
66 : typedef BlockGraph::Size Size;
67 : typedef T ObjectType;
68 :
69 : template <typename T2> struct Rebind {
70 : typedef TypedBlock<typename T2> Type;
71 : };
72 :
73 E : TypedBlock() : TypedBlockImpl() { }
74 :
75 : // Accesses the block encapsulated by this typed block.
76 : //
77 : // @returns a non-const pointer to the encapsulated block.
78 E : internal::BlockPtr block() { return block_; }
79 :
80 : // Accesses the block encapsulated by this typed block.
81 : //
82 : // @returns a const pointer to the encapsulated block.
83 E : internal::ConstBlockPtr block() const { return block_; }
84 :
85 : // Removes the reference at the given offset. Will clear a reference of any
86 : // size and type.
87 : //
88 : // @param offset the offset of the reference to clear.
89 E : void RemoveReferenceAt(Offset offset) {
90 E : RemoveReferenceImpl(offset, 0);
91 E : }
92 :
93 : // Removes the reference at the given offset, but only if it has the given
94 : // size. Returns false if there exists a reference at the offset but with a
95 : // different size, true otherwise.
96 : //
97 : // @param offset the offset of the reference to clear.
98 : // @param size the size of the reference to clear.
99 : // @returns true on success, false otherwise.
100 E : bool RemoveReferenceAt(Offset offset, size_t size) {
101 E : return RemoveReferenceImpl(offset, size);
102 E : }
103 :
104 : // Removes the reference corresponding to the given value. Succeeds if there
105 : // is no reference at the offset, or if the existing reference has the same
106 : // size as the value.
107 : //
108 : // @tparam TIn the type of @p value.
109 : // @param value the value in this block encapsulating the reference to erase.
110 : template <typename TIn>
111 E : bool RemoveReference(const TIn& value) {
112 E : return RemoveReferenceImpl(OffsetOf(value), sizeof(TIn));
113 E : }
114 :
115 : // Builds a reference with the given type, offset and size to the given
116 : // block and offset.
117 : //
118 : // @param reference_type the type of reference to create.
119 : // @param reference_offset the offset of the reference to construct.
120 : // @param reference_size the size of the reference to construct.
121 : // @param referenced_block the block to be referenced.
122 : // @param referenced_offset the offset into the block to be directly
123 : // referenced.
124 : // @param referenced_base the offset into the block of the item that is
125 : // actually being referenced.
126 : // @returns true iff this inserts a new reference.
127 : bool SetReference(ReferenceType reference_type,
128 : Offset reference_offset,
129 : size_t reference_size,
130 : Block* referenced_block,
131 : Offset referenced_offset,
132 : Offset referenced_base);
133 :
134 : // Sets a reference from one value to a given block/offset. The size of the
135 : // reference will be sizeof(TFrom).
136 : //
137 : // @tparam TFrom the type of @p value_from.
138 : // @param reference_type the type of reference to create.
139 : // @param value_from the value which will hold the created reference.
140 : // @param block_to the block to be referenced.
141 : // @param offset_to the offset of @p block_to to be referenced directly.
142 : // @param base_to the offset of @p block_to to be actually referenced.
143 : template <typename TFrom>
144 E : bool SetReference(ReferenceType reference_type,
145 : const TFrom& value_from,
146 : Block* block_to,
147 : Offset offset_to,
148 : Offset base_to) {
149 E : DCHECK(block_to != NULL);
150 : return SetReference(reference_type, OffsetOf(value_from), sizeof(TFrom),
151 E : block_to, offset_to, base_to);
152 E : }
153 :
154 : // Sets a direct reference (where base = offset) from one value to another
155 : // typed block. The size of the reference will be sizeof(TFrom).
156 : //
157 : // @tparam TFrom the type of @p value_from.
158 : // @tparam T2 the type encapsulated by @p typed_block_to.
159 : // @param reference_type the type of reference to create.
160 : // @param value_from the value which will hold the created reference.
161 : // @param typed_block_to the typed block that will be referenced. The
162 : // reference will be constructed to the beginning of the object
163 : // encapsulated by the typed block.
164 : // @returns true iff this inserts a new reference.
165 : template <typename TFrom, typename T2>
166 E : bool SetReference(ReferenceType reference_type,
167 : const TFrom& value_from,
168 : const TypedBlock<T2>& typed_block_to) {
169 : return SetReference(reference_type, OffsetOf(value_from), sizeof(TFrom),
170 : const_cast<Block*>(typed_block_to.block()), typed_block_to.offset(),
171 E : typed_block_to.offset());
172 E : }
173 :
174 : // Sets a direct reference (where base = offset) from one value to another.
175 : // The size of the reference will be sizeof(TFrom). The offset and base are
176 : // inferred from the position of @p value_to in @p typed_block_to.
177 : //
178 : // @tparam TFrom the type of @p value_from.
179 : // @tparam T2 the type encapsulated by @p typed_block_to.
180 : // @tparam TTo the type of value_to.
181 : // @param reference_type the type of reference to create.
182 : // @param value_from the value which will hold the created reference.
183 : // @param typed_block_to the typed block that will be referenced.
184 : // @param value_to the value within @p typed_block_to that will be referenced.
185 : // @returns true iff this inserts a new reference.
186 : template <typename TFrom, typename T2, typename TTo>
187 E : bool SetReference(ReferenceType reference_type,
188 : const TFrom& value_from,
189 : const TypedBlock<T2>& typed_block_to,
190 : const TTo& value_to) {
191 E : Offset offset_to = typed_block_to.OffsetOf(value_to);
192 : return SetReference(reference_type, OffsetOf(value_from), sizeof(TFrom),
193 E : const_cast<Block*>(typed_block_to.block()), offset_to, offset_to);
194 E : }
195 :
196 : private:
197 : // Clears the reference at the given @p offset, but only if it has the given
198 : // @p size. If @p size = 0, then a reference of any size will be cleared.
199 : // Returns true on success, false otherwise.
200 : //
201 : // @param offset the offset of the reference to erase.
202 : // @param size the size of the reference to erase, 0 if it doesn't matter.
203 : bool RemoveReferenceImpl(Offset offset, size_t size);
204 :
205 : DISALLOW_COPY_AND_ASSIGN(TypedBlock);
206 : };
207 :
208 : // Used for interpreting a const BlockGraph::Block's data as a constant object
209 : // of type T.
210 : template <typename T> class ConstTypedBlock
211 : : public internal::TypedBlockImpl<const T,
212 : internal::ConstBlockPtr,
213 : ConstTypedBlock<T>> {
214 : public:
215 : typedef T ObjectType;
216 :
217 : template <typename T2> struct Rebind {
218 : typedef ConstTypedBlock<T2> Type;
219 : };
220 :
221 E : ConstTypedBlock() : TypedBlockImpl() { }
222 :
223 : // Accesses the block encapsulated by this typed block.
224 : //
225 : // @returns a const pointer to the encapsulated block.
226 E : internal::ConstBlockPtr block() const { return block_; }
227 :
228 : private:
229 : DISALLOW_COPY_AND_ASSIGN(ConstTypedBlock);
230 : };
231 :
232 : template <typename T>
233 : bool TypedBlock<T>::SetReference(ReferenceType reference_type,
234 : Offset reference_offset,
235 : Size reference_size,
236 : Block* referenced_block,
237 : Offset referenced_offset,
238 E : Offset referenced_base) {
239 E : DCHECK(referenced_block != NULL);
240 : BlockGraph::Reference reference(reference_type, reference_size,
241 : referenced_block, referenced_offset,
242 E : referenced_base);
243 E : return block_->SetReference(reference_offset, reference);
244 E : }
245 :
246 : template <typename T>
247 E : bool TypedBlock<T>::RemoveReferenceImpl(Offset offset, size_t size) {
248 E : if (size != 0) {
249 E : Reference reference;
250 E : if (block_->GetReference(offset, &reference)) {
251 E : if (reference.size() != size)
252 E : return false;
253 : }
254 : }
255 E : block_->RemoveReference(offset);
256 E : return true;
257 E : }
258 :
259 : } // namespace block_graph
260 :
261 : // This brings in the implementation.
262 : #include "syzygy/block_graph/typed_block_internal.h"
263 :
264 : #endif // SYZYGY_BLOCK_GRAPH_TYPED_BLOCK_H_
|