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 : // Implements the ExplodeBasicBlockSubGraphTransform and
16 : // ExplodeBasicBlocksTransform classes.
17 :
18 : #include "syzygy/pe/transforms/explode_basic_blocks_transform.h"
19 :
20 : #include "syzygy/block_graph/basic_block_subgraph.h"
21 : #include "syzygy/block_graph/block_builder.h"
22 :
23 : namespace pe {
24 : namespace transforms {
25 : namespace {
26 :
27 : using block_graph::BasicBlock;
28 : using block_graph::BlockBuilder;
29 : using block_graph::BlockGraph;
30 : using block_graph::BasicBlockSubGraph;
31 :
32 : typedef BlockGraph::Block Block;
33 :
34 : void GetTypeAndAttributes(const Block* original_block,
35 : const BasicBlock& basic_block,
36 : BlockGraph::BlockType* type,
37 E : BlockGraph::BlockAttributes* attributes) {
38 E : DCHECK(original_block != NULL);
39 E : DCHECK(type != NULL);
40 E : DCHECK(attributes != NULL);
41 :
42 E : if (basic_block.type() == BasicBlock::BASIC_DATA_BLOCK) {
43 E : *type = BlockGraph::DATA_BLOCK;
44 E : } else {
45 E : DCHECK_EQ(BasicBlock::BASIC_CODE_BLOCK, basic_block.type());
46 E : *type = BlockGraph::CODE_BLOCK;
47 : }
48 :
49 E : *attributes = original_block->attributes();
50 E : if (basic_block.is_padding())
51 E : *attributes |= BlockGraph::PADDING_BLOCK;
52 E : }
53 :
54 : } // namespace
55 :
56 : const char ExplodeBasicBlockSubGraphTransform::kTransformName[] =
57 : "ExplodeBasicBlockSubGraphTransform";
58 :
59 : ExplodeBasicBlockSubGraphTransform::ExplodeBasicBlockSubGraphTransform(
60 : bool exclude_padding)
61 : : exclude_padding_(exclude_padding),
62 : output_code_blocks_(0),
63 E : output_data_blocks_(0) {
64 E : }
65 :
66 : bool ExplodeBasicBlockSubGraphTransform::TransformBasicBlockSubGraph(
67 : const TransformPolicyInterface* policy,
68 : BlockGraph* block_graph,
69 E : BasicBlockSubGraph* subgraph) {
70 E : DCHECK(policy != NULL);
71 E : DCHECK(block_graph != NULL);
72 E : DCHECK(subgraph != NULL);
73 :
74 : // Remove any extant block descriptions.
75 E : subgraph->block_descriptions().clear();
76 :
77 : // Generate a new block description for each basic-block in the subgraph,
78 : // skipping basic-end blocks.
79 : BasicBlockSubGraph::BBCollection::iterator it =
80 E : subgraph->basic_blocks().begin();
81 E : for (; it != subgraph->basic_blocks().end(); ++it) {
82 E : BasicBlock* bb = *it;
83 :
84 : // Skip end blocks. They don't have any actual content, so we can safely
85 : // ignore them.
86 E : if (bb->type() == BasicBlock::BASIC_END_BLOCK)
87 E : continue;
88 :
89 E : BlockGraph::BlockType type = BlockGraph::CODE_BLOCK;
90 E : BlockGraph::BlockAttributes attributes = 0;
91 E : GetTypeAndAttributes(subgraph->original_block(), *bb, &type, &attributes);
92 :
93 E : if (exclude_padding_ && (attributes & BlockGraph::PADDING_BLOCK) != 0)
94 E : continue;
95 :
96 E : if (type == BlockGraph::CODE_BLOCK) {
97 E : ++output_code_blocks_;
98 E : } else {
99 E : ++output_data_blocks_;
100 : }
101 :
102 : BasicBlockSubGraph::BlockDescription* desc = subgraph->AddBlockDescription(
103 : bb->name(),
104 : subgraph->original_block()->compiland_name(),
105 : type,
106 : subgraph->original_block()->section(),
107 : 4,
108 E : attributes);
109 E : desc->basic_block_order.push_back(bb);
110 E : }
111 E : return true;
112 E : }
113 :
114 : const char ExplodeBasicBlocksTransform::kTransformName[] =
115 : "ExplodeBasicBlocksTransform";
116 :
117 : ExplodeBasicBlocksTransform::ExplodeBasicBlocksTransform()
118 : : exclude_padding_(false),
119 : non_decomposable_code_blocks_(0),
120 : skipped_code_blocks_(0),
121 : input_code_blocks_(0),
122 : output_code_blocks_(0),
123 E : output_data_blocks_(0) {
124 E : }
125 :
126 : bool ExplodeBasicBlocksTransform::OnBlock(
127 : const TransformPolicyInterface* policy,
128 : BlockGraph* block_graph,
129 E : BlockGraph::Block* block) {
130 E : DCHECK(policy != NULL);
131 E : DCHECK(block_graph != NULL);
132 E : DCHECK(block != NULL);
133 :
134 : // Skip non-code blocks.
135 E : if (block->type() != BlockGraph::CODE_BLOCK)
136 E : return true;
137 :
138 : // Skip gap blocks.
139 E : if (block->attributes() & BlockGraph::GAP_BLOCK)
140 i : return true;
141 :
142 E : if (!policy->BlockIsSafeToBasicBlockDecompose(block)) {
143 E : VLOG(1) << "Skipping block '" << block->name() << "', attributes: "
144 : << BlockGraph::BlockAttributesToString(block->attributes());
145 :
146 E : ++non_decomposable_code_blocks_;
147 E : return true;
148 : }
149 :
150 E : if (SkipThisBlock(block)) {
151 E : ++skipped_code_blocks_;
152 E : return true;
153 : }
154 :
155 E : ExplodeBasicBlockSubGraphTransform transform(exclude_padding_);
156 :
157 : if (!ApplyBasicBlockSubGraphTransform(
158 E : &transform, policy, block_graph, block, NULL)) {
159 i : return false;
160 : }
161 :
162 E : ++input_code_blocks_;
163 E : output_code_blocks_ += transform.output_code_blocks();
164 E : output_data_blocks_ += transform.output_data_blocks();
165 :
166 E : return true;
167 E : }
168 :
169 : bool ExplodeBasicBlocksTransform::PostBlockGraphIteration(
170 : const TransformPolicyInterface* unused_policy,
171 : BlockGraph* unused_block_graph,
172 E : BlockGraph::Block* unused_header_block) {
173 E : LOG(INFO) << "Exploded " << input_code_blocks_ << " input code blocks to";
174 E : LOG(INFO) << " Code blocks: " << output_code_blocks_;
175 E : LOG(INFO) << " Data blocks: " << output_data_blocks_;
176 E : LOG(INFO) << "Non-decomposable blocks: " << non_decomposable_code_blocks_;
177 E : LOG(INFO) << "Skipped blocks: " << skipped_code_blocks_;
178 :
179 E : return true;
180 E : }
181 :
182 E : bool ExplodeBasicBlocksTransform::SkipThisBlock(const Block* candidate) {
183 E : return false;
184 E : }
185 :
186 : } // namespace transforms
187 : } // namespace pe
|