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 a helper class for serializing a block-graph.
16 :
17 : #ifndef SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_SERIALIZER_H_
18 : #define SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_SERIALIZER_H_
19 :
20 : #include "base/callback.h"
21 : #include "syzygy/block_graph/block_graph.h"
22 : #include "syzygy/core/address.h"
23 :
24 : namespace block_graph {
25 :
26 : // A class for serializing a block-graph.
27 : class BlockGraphSerializer {
28 : public:
29 : typedef uint32_t Attributes;
30 : typedef core::InArchive InArchive;
31 : typedef core::OutArchive OutArchive;
32 : typedef core::RelativeAddress RelativeAddress;
33 :
34 : // An enumeration that governs the mode of data serialization.
35 : enum DataMode {
36 : // In this mode no block data is serialized. The data will be recovered from
37 : // an external data source via the LoadBlockDataCallback. While serializing
38 : // an optional SaveBlockDataCallback may save any metadata necessary to
39 : // recover the original block data.
40 : OUTPUT_NO_DATA,
41 : DEFAULT_DATA_MODE = OUTPUT_NO_DATA,
42 :
43 : // In this mode of serialization, only blocks that own their own data will
44 : // have the data serialized explicitly. The other block data will be
45 : // recovered via LoadBlockDataCallback, and saved via the optional
46 : // SaveBlockDataCallback.
47 : OUTPUT_OWNED_DATA,
48 :
49 : // In this mode all block data is serialized directly. The generated
50 : // serialization is completely independent of any external data sources.
51 : // Even if either of the callbacks are set, they will never be invoked.
52 : OUTPUT_ALL_DATA,
53 :
54 : // This needs to be last.
55 : DATA_MODE_MAX,
56 : };
57 :
58 : // Attributes that govern the serializer behaviour.
59 : enum AttributesEnum {
60 : // The serializer uses default behaviour.
61 : DEFAULT_ATTRIBUTES = 0,
62 :
63 : // If specified then no strings will be written as part of the
64 : // serialization (block names, label names). They are useful as debugging
65 : // information, but not required by any transforms.
66 : OMIT_STRINGS = (1 << 0),
67 :
68 : // If specified then all labels will be omitted from the serialization.
69 : // They are not needed for block level motion, but this will make basic
70 : // block disassembly impossible.
71 : OMIT_LABELS = (1 << 1),
72 :
73 : // This needs to be last, and the next unused attributes enum bit.
74 : ATTRIBUTES_MAX = (1 << 2),
75 : };
76 :
77 : // Defines the callback used to save data for a block. The callback is given
78 : // the following parameters:
79 : //
80 : // 1. bool data_already_saved
81 : // If this is true the block's contents have been saved explicitly in the
82 : // stream.
83 : // 2. const BlockGraph::Block& block
84 : // The block whose data is to be saved.
85 : // 3. OutArchive* out_archive
86 : // The output archive. Can be used to write data that will then be used
87 : // by LoadBlockDataCallback.
88 : //
89 : // If this callback writes any data the matching LoadBlockDataCallback must
90 : // read the same data. Otherwise, serialization will lose its synchronization
91 : // and derail. This callback is optional, but if present is called for every
92 : // single block. It can be used to serialize additional data alongside a
93 : // block.
94 : typedef base::Callback<bool(bool,
95 : const BlockGraph::Block&,
96 : core::OutArchive*)> SaveBlockDataCallback;
97 :
98 : // Defines the callback used to load data for a block. The callback is given
99 : // the following parameters:
100 : //
101 : // 1. bool need_to_set_data
102 : // If this is true then the callback is responsible for filling in the
103 : // block's data. Otherwise, it will already have been set by the time of
104 : // this call.
105 : // 2. size_t data_size
106 : // The size of the data that was in the block at serialization time.
107 : // Can be ignored if need_to_set_data is false.
108 : // 3. BlockGraph::Block* block
109 : // The block whose data is to be retrieved. The block will have all of
110 : // its attributes set. If need_to_set_data is true then data-size will be
111 : // zero and the data pointer will be null.
112 : // 4. InArchive* in_archive
113 : // The input archive. Can be used to read data that was written by the
114 : // corresponding SaveBlockDataCallback.
115 : //
116 : // The callback should read any data set by SaveBlockData. Additionally, if
117 : // data_size is non-zero, block->data_size is 0 and the block's data is
118 : // currently NULL it should also set the block's data. If the call has failed
119 : // it should return false. Upon return it is expected that
120 : // block->data_size() == data_size and that block->data() != NULL. It is up to
121 : // the callback to ensure that the contents match those that were there at
122 : // serialization time.
123 : //
124 : // If this function is provided it will be called for every single block in
125 : // the block-graph. It must be provided if there are any blocks whose data
126 : // needs to be set.
127 : typedef base::Callback<bool(bool,
128 : size_t,
129 : BlockGraph::Block*,
130 : core::InArchive*)> LoadBlockDataCallback;
131 :
132 : // Default constructor.
133 E : BlockGraphSerializer()
134 E : : data_mode_(DEFAULT_DATA_MODE), attributes_(DEFAULT_ATTRIBUTES) { }
135 :
136 : // @name For setting and accessing the data mode.
137 : // @{
138 E : DataMode data_mode() const { return data_mode_; }
139 E : void set_data_mode(DataMode data_mode) { data_mode_ = data_mode; }
140 : // @}
141 :
142 : // @name For setting and accessing attributes.
143 : // @{
144 : // Adds new attributes, combining them with the existing attributes.
145 : // @param attr the attributes to add.
146 E : void add_attributes(Attributes attr) { attributes_ |= attr; }
147 : // Clears the given attributes, removing them from the existing attributes.
148 : // @param attr the attributes to clear.
149 E : void clear_attributes(Attributes attr) { attributes_ &= ~attr; }
150 : // Sets the attributes wholesale.
151 : // @param attr the new attributes to use.
152 E : void set_attributes(Attributes attr) { attributes_ = attr; }
153 : // @returns the current attributes.
154 E : Attributes attributes() const { return attributes_; }
155 : // Determines if all the given attributes are set.
156 : // @param attr the attributes to check for.
157 : // @returns true if all attributes in @p attr are set.
158 E : bool has_attributes(Attributes attr) const {
159 E : return (attributes_ & attr) == attr;
160 E : }
161 : // Determines if any of the given attributes are set.
162 : // @param attr the attributes to check for.
163 : // @returns true if any of the attributes in @p attr are set.
164 E : bool has_any_attributes(Attributes attr) const {
165 E : return (attributes_ & attr) != 0;
166 E : }
167 : // @}
168 :
169 : // Sets a callback to be used by the save function for writing block
170 : // data. This is optional, and will only be used by the OUTPUT_NO_DATA or
171 : // OUTPUT_OWNED_DATA data modes.
172 : // @param save_block_data_callback the callback to be used.
173 : void set_save_block_data_callback(
174 E : const SaveBlockDataCallback& save_block_data_callback) {
175 E : save_block_data_callback_ = std::unique_ptr<SaveBlockDataCallback>(
176 : new SaveBlockDataCallback(save_block_data_callback));
177 E : }
178 :
179 : // Saves the given block-graph to the provided output archive.
180 : // @param block_graph the block-graph to be serialized.
181 : // @param out_archive the archive to be written to.
182 : // @returns true on success, false otherwise.
183 : bool Save(const BlockGraph& block_graph, core::OutArchive* out_archive) const;
184 :
185 : // Sets a callback to be used by the load function for retrieving block
186 : // data. This is optional, but is required to be set prior to calling Load
187 : // for any block-graph that was serialized using OUTPUT_NO_DATA or
188 : // OUTPUT_OWNED_DATA.
189 : // @param load_block_data_callback the callback to be used.
190 : void set_load_block_data_callback(
191 E : const LoadBlockDataCallback& load_block_data_callback) {
192 E : load_block_data_callback_ = std::unique_ptr<LoadBlockDataCallback>(
193 : new LoadBlockDataCallback(load_block_data_callback));
194 E : }
195 :
196 : // Loads a block-graph from the provided input archive. The data-mode and
197 : // attributes used in the serialization will also be updated. If an external
198 : // data source is required SetBlockDataCallback must be called prior to Load.
199 : // @param block_graph the block-graph to be written to.
200 : // @param in_archive the archive to be read from.
201 : // @returns true on success, false otherwise.
202 : bool Load(BlockGraph* block_graph, core::InArchive* in_archive);
203 :
204 : protected:
205 : // @{
206 : // The block-graph is serialized by breaking it down into its constituent
207 : // pieces, and saving each of these using the following functions.
208 : bool SaveBlockGraphProperties(const BlockGraph& block_graph,
209 : OutArchive* out_archive) const;
210 : bool LoadBlockGraphProperties(uint32_t version,
211 : BlockGraph* block_graph,
212 : InArchive* in_archive) const;
213 :
214 : bool SaveBlocks(const BlockGraph& block_graph, OutArchive* out_archive) const;
215 : bool LoadBlocks(uint32_t version,
216 : BlockGraph* block_graph,
217 : InArchive* in_archive) const;
218 :
219 : bool SaveBlockGraphReferences(const BlockGraph& block_graph,
220 : OutArchive* out_archive) const;
221 : bool LoadBlockGraphReferences(BlockGraph* block_graph,
222 : InArchive* in_archive) const;
223 :
224 : bool SaveBlockProperties(const BlockGraph::Block& block,
225 : OutArchive* out_archive) const;
226 : bool LoadBlockProperties(uint32_t version,
227 : BlockGraph::Block* block,
228 : InArchive* in_archive) const;
229 :
230 : bool SaveBlockLabels(const BlockGraph::Block& block,
231 : OutArchive* out_archive) const;
232 : bool LoadBlockLabels(BlockGraph::Block* block, InArchive* in_archive) const;
233 :
234 : bool SaveBlockData(const BlockGraph::Block& block,
235 : OutArchive* out_archive) const;
236 : bool LoadBlockData(BlockGraph::Block* block, InArchive* in_archive) const;
237 :
238 : bool SaveBlockReferences(const BlockGraph::Block& block,
239 : OutArchive* out_archive) const;
240 : bool LoadBlockReferences(BlockGraph* block_graph,
241 : BlockGraph::Block* block,
242 : InArchive* in_archive) const;
243 :
244 : bool SaveReference(const BlockGraph::Reference& ref,
245 : OutArchive* out_archive) const;
246 : bool LoadReference(BlockGraph* block_graph,
247 : BlockGraph::Reference* ref,
248 : InArchive* in_archive) const;
249 : // @}
250 :
251 : // @{
252 : // Utility functions for loading and saving integer values with a simple
253 : // variable-length encoding.
254 : bool SaveUint32(uint32_t value, OutArchive* out_archive) const;
255 : bool LoadUint32(uint32_t* value, InArchive* in_archive) const;
256 : bool SaveInt32(int32_t value, OutArchive* out_archive) const;
257 : bool LoadInt32(int32_t* value, InArchive* in_archive) const;
258 : // @}
259 :
260 : // The mode in which the serializer is operating for block data.
261 : DataMode data_mode_;
262 : // Controls the specifics of how the serialization is performed.
263 : Attributes attributes_;
264 :
265 : // Optional callbacks.
266 : std::unique_ptr<SaveBlockDataCallback> save_block_data_callback_;
267 : std::unique_ptr<LoadBlockDataCallback> load_block_data_callback_;
268 :
269 : private:
270 : // A helper function that implements loading of block properties. The
271 : // separation to two functions avoids duplication of logging on each
272 : // return false branch.
273 : bool LoadBlockPropertiesImpl(uint32_t version,
274 : BlockGraph::Block* block,
275 : InArchive* in_archive) const;
276 : };
277 :
278 : } // namespace block_graph
279 :
280 : #endif // SYZYGY_BLOCK_GRAPH_BLOCK_GRAPH_SERIALIZER_H_
|