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