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 : #include "syzygy/block_graph/transform.h"
16 :
17 : #include "syzygy/block_graph/basic_block_decomposer.h"
18 : #include "syzygy/block_graph/block_builder.h"
19 : #include "syzygy/block_graph/block_util.h"
20 :
21 : namespace block_graph {
22 :
23 : bool ApplyImageLayoutTransform(
24 : ImageLayoutTransformInterface* transform,
25 : const TransformPolicyInterface* policy,
26 : const pe::ImageLayout* image_layout,
27 E : const OrderedBlockGraph* ordered_block_graph) {
28 E : DCHECK(transform != NULL);
29 E : DCHECK(transform->name() != NULL);
30 E : DCHECK(policy != NULL);
31 E : DCHECK_GT(strlen(transform->name()), 0u);
32 E : DCHECK(image_layout != NULL);
33 E : DCHECK(ordered_block_graph != NULL);
34 :
35 : // Only the contents of block data can be changed in-place. References are
36 : // allowed to change. However one cannot add, delete or reorder blocks and/or
37 : // sections, nor can the size of blocks or sections be changed by adding or
38 : // deteling data bytes.
39 : // Get total number and the size of each block.
40 E : size_t no_blocks = image_layout->blocks.size();
41 E : std::vector<size_t> block_size;
42 E : auto block_it = image_layout->blocks.begin();
43 E : for (; block_it != image_layout->blocks.end(); ++block_it) {
44 i : block_size.push_back(block_it->first.size());
45 i : }
46 :
47 E : if (!transform->TransformImageLayout(policy, image_layout,
48 : ordered_block_graph)) {
49 i : LOG(ERROR) << "Layout transform \"" << transform->name() << "\" failed.";
50 i : return false;
51 : }
52 :
53 : // Ensure the number of blocks and the size of each block has not changed
54 E : if (no_blocks != image_layout->blocks.size()) {
55 i : LOG(ERROR) << "Layout transform \"" << transform->name() << "\" changed "
56 : << "number of blocks.";
57 i : return false;
58 : }
59 E : block_it = image_layout->blocks.begin();
60 E : for (size_t i = 0; block_it != image_layout->blocks.end(); ++block_it, ++i) {
61 i : if (block_size[i] != block_it->first.size()) {
62 i : LOG(ERROR) << "Layout transform \"" << transform->name() << "\" changed "
63 : << "size of blocks.";
64 i : return false;
65 : }
66 i : }
67 :
68 E : return true;
69 E : }
70 :
71 : bool ApplyImageLayoutTransforms(
72 : const std::vector<ImageLayoutTransformInterface*>& transforms,
73 : const TransformPolicyInterface* policy,
74 : const pe::ImageLayout* image_layout,
75 E : const OrderedBlockGraph* ordered_block_graph) {
76 E : DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
77 E : DCHECK_NE(reinterpret_cast<pe::ImageLayout*>(NULL), image_layout);
78 E : DCHECK_NE(reinterpret_cast<OrderedBlockGraph*>(NULL), ordered_block_graph);
79 :
80 : // Apply the transforms sequentially.
81 E : for (size_t i = 0; i < transforms.size(); ++i) {
82 E : if (!ApplyImageLayoutTransform(transforms[i],
83 : policy,
84 : image_layout,
85 : ordered_block_graph)) {
86 i : return false;
87 : }
88 E : }
89 :
90 E : return true;
91 E : }
92 :
93 : bool ApplyBlockGraphTransform(BlockGraphTransformInterface* transform,
94 : const TransformPolicyInterface* policy,
95 : BlockGraph* block_graph,
96 E : BlockGraph::Block* header_block) {
97 E : DCHECK(transform != NULL);
98 E : DCHECK(transform->name() != NULL);
99 E : DCHECK(policy != NULL);
100 E : DCHECK_GT(strlen(transform->name()), 0u);
101 E : DCHECK(block_graph != NULL);
102 E : DCHECK(header_block != NULL);
103 :
104 : // Get the ID of the header block. As a sanity check we want to ensure
105 : // that it still exists after the transform.
106 E : BlockGraph::BlockId header_block_id = header_block->id();
107 :
108 E : if (!transform->TransformBlockGraph(policy, block_graph, header_block)) {
109 E : LOG(ERROR) << "Transform \"" << transform->name() << "\" failed.";
110 E : return false;
111 : }
112 :
113 : // Ensure that the header block still exists. If it was changed, it needs
114 : // to have been changed in place.
115 E : BlockGraph::Block* block = block_graph->GetBlockById(header_block_id);
116 E : if (block == NULL) {
117 E : LOG(ERROR) << "Header block not found after \"" << transform->name()
118 : << "\" transform.";
119 E : return false;
120 : }
121 E : DCHECK_EQ(header_block, block);
122 :
123 E : return true;
124 E : }
125 :
126 : bool ApplyBlockGraphTransforms(
127 : const std::vector<BlockGraphTransformInterface*>& transforms,
128 : const TransformPolicyInterface* policy,
129 : BlockGraph* block_graph,
130 E : BlockGraph::Block* header_block) {
131 E : DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
132 E : DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
133 E : DCHECK_NE(reinterpret_cast<BlockGraph::Block*>(NULL), header_block);
134 :
135 : // Apply the transforms sequentially.
136 E : for (size_t i = 0; i < transforms.size(); ++i) {
137 E : if (!ApplyBlockGraphTransform(transforms[i],
138 : policy,
139 : block_graph,
140 : header_block)) {
141 E : return false;
142 : }
143 E : }
144 :
145 E : return true;
146 E : }
147 :
148 : bool ApplyBasicBlockSubGraphTransform(
149 : BasicBlockSubGraphTransformInterface* transform,
150 : const TransformPolicyInterface* policy,
151 : BlockGraph* block_graph,
152 : BlockGraph::Block* block,
153 E : BlockVector* new_blocks) {
154 E : DCHECK(transform != NULL);
155 E : DCHECK(policy != NULL);
156 E : DCHECK(block_graph != NULL);
157 E : DCHECK(block != NULL);
158 E : DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
159 E : DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
160 :
161 : // Decompose block to basic blocks.
162 E : BasicBlockSubGraph subgraph;
163 E : BasicBlockDecomposer bb_decomposer(block, &subgraph);
164 E : if (!bb_decomposer.Decompose()) {
165 : // If the failure is due to unsupported instructions then simply mark the
166 : // block as undecomposable so it won't be processed again.
167 i : if (bb_decomposer.contains_unsupported_instructions()) {
168 i : VLOG(1) << "Block contains unsupported instruction(s): "
169 : << BlockInfo(block);
170 i : block->set_attribute(BlockGraph::UNSUPPORTED_INSTRUCTIONS);
171 i : return true;
172 : }
173 :
174 i : return false;
175 : }
176 :
177 : // Call the transform.
178 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
179 E : return false;
180 :
181 : // Update the block-graph post transform.
182 E : BlockBuilder builder(block_graph);
183 E : if (!builder.Merge(&subgraph))
184 i : return false;
185 :
186 E : if (new_blocks != NULL) {
187 E : new_blocks->assign(builder.new_blocks().begin(),
188 : builder.new_blocks().end());
189 : }
190 :
191 E : return true;
192 E : }
193 :
194 : bool ApplyBasicBlockSubGraphTransforms(
195 : const std::vector<BasicBlockSubGraphTransformInterface*>& transforms,
196 : const TransformPolicyInterface* policy,
197 : BlockGraph* block_graph,
198 : BlockGraph::Block* block,
199 E : BlockVector* new_blocks) {
200 E : DCHECK(policy != NULL);
201 E : DCHECK(block_graph != NULL);
202 E : DCHECK(block != NULL);
203 E : DCHECK_EQ(BlockGraph::CODE_BLOCK, block->type());
204 E : DCHECK(policy->BlockIsSafeToBasicBlockDecompose(block));
205 :
206 : // Decompose block to basic blocks.
207 E : BasicBlockSubGraph subgraph;
208 E : BasicBlockDecomposer bb_decomposer(block, &subgraph);
209 E : if (!bb_decomposer.Decompose())
210 i : return false;
211 :
212 : // Call the transforms.
213 : std::vector<BasicBlockSubGraphTransformInterface*>::const_iterator it =
214 E : transforms.begin();
215 E : for (; it != transforms.end(); ++it) {
216 E : BasicBlockSubGraphTransformInterface* transform = *it;
217 E : DCHECK(transform != NULL);
218 E : if (!transform->TransformBasicBlockSubGraph(policy, block_graph, &subgraph))
219 i : return false;
220 E : }
221 :
222 : // Update the block-graph post transform.
223 E : BlockBuilder builder(block_graph);
224 E : if (!builder.Merge(&subgraph))
225 i : return false;
226 :
227 E : if (new_blocks != NULL) {
228 E : new_blocks->assign(builder.new_blocks().begin(),
229 : builder.new_blocks().end());
230 : }
231 :
232 E : return true;
233 E : }
234 :
235 : } // namespace block_graph
|