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 : BasicBlockSubGraph::BBCollection::iterator it =
79 E : subgraph->basic_blocks().begin();
80 E : for (; it != subgraph->basic_blocks().end(); ++it) {
81 E : BasicBlock* bb = *it;
82 E : BlockGraph::BlockType type = BlockGraph::CODE_BLOCK;
83 E : BlockGraph::BlockAttributes attributes = 0;
84 E : GetTypeAndAttributes(subgraph->original_block(), *bb, &type, &attributes);
85 :
86 E : if (exclude_padding_ && (attributes & BlockGraph::PADDING_BLOCK) != 0)
87 E : continue;
88 :
89 E : if (type == BlockGraph::CODE_BLOCK)
90 E : ++output_code_blocks_;
91 E : else
92 E : ++output_data_blocks_;
93 :
94 : BasicBlockSubGraph::BlockDescription* desc = subgraph->AddBlockDescription(
95 : bb->name(),
96 : subgraph->original_block()->compiland_name(),
97 : type,
98 : subgraph->original_block()->section(),
99 : 4,
100 E : attributes);
101 E : desc->basic_block_order.push_back(bb);
102 E : }
103 E : return true;
104 E : }
105 :
106 : const char ExplodeBasicBlocksTransform::kTransformName[] =
107 : "ExplodeBasicBlocksTransform";
108 :
109 : ExplodeBasicBlocksTransform::ExplodeBasicBlocksTransform()
110 : : exclude_padding_(false),
111 : non_decomposable_code_blocks_(0),
112 : skipped_code_blocks_(0),
113 : input_code_blocks_(0),
114 : output_code_blocks_(0),
115 E : output_data_blocks_(0) {
116 E : }
117 :
118 : bool ExplodeBasicBlocksTransform::OnBlock(
119 : const TransformPolicyInterface* policy,
120 : BlockGraph* block_graph,
121 E : BlockGraph::Block* block) {
122 E : DCHECK(policy != NULL);
123 E : DCHECK(block_graph != NULL);
124 E : DCHECK(block != NULL);
125 :
126 : // Skip non-code blocks.
127 E : if (block->type() != BlockGraph::CODE_BLOCK)
128 E : return true;
129 :
130 : // Skip gap blocks.
131 E : if (block->attributes() & BlockGraph::GAP_BLOCK)
132 i : return true;
133 :
134 E : if (!policy->BlockIsSafeToBasicBlockDecompose(block)) {
135 E : VLOG(1) << "Skipping block '" << block->name() << "', attributes: "
136 : << BlockGraph::BlockAttributesToString(block->attributes());
137 :
138 E : ++non_decomposable_code_blocks_;
139 E : return true;
140 : }
141 :
142 E : if (SkipThisBlock(block)) {
143 E : ++skipped_code_blocks_;
144 E : return true;
145 : }
146 :
147 E : ExplodeBasicBlockSubGraphTransform transform(exclude_padding_);
148 :
149 : if (!ApplyBasicBlockSubGraphTransform(
150 E : &transform, policy, block_graph, block, NULL)) {
151 i : return false;
152 : }
153 :
154 E : ++input_code_blocks_;
155 E : output_code_blocks_ += transform.output_code_blocks();
156 E : output_data_blocks_ += transform.output_data_blocks();
157 :
158 E : return true;
159 E : }
160 :
161 : bool ExplodeBasicBlocksTransform::PostBlockGraphIteration(
162 : const TransformPolicyInterface* unused_policy,
163 : BlockGraph* unused_block_graph,
164 E : BlockGraph::Block* unused_header_block) {
165 E : LOG(INFO) << "Exploded " << input_code_blocks_ << " input code blocks to";
166 E : LOG(INFO) << " Code blocks: " << output_code_blocks_;
167 E : LOG(INFO) << " Data blocks: " << output_data_blocks_;
168 E : LOG(INFO) << "Non-decomposable blocks: " << non_decomposable_code_blocks_;
169 E : LOG(INFO) << "Skipped blocks: " << skipped_code_blocks_;
170 :
171 E : return true;
172 E : }
173 :
174 E : bool ExplodeBasicBlocksTransform::SkipThisBlock(const Block* candidate) {
175 E : return false;
176 E : }
177 :
178 : } // namespace transforms
179 : } // namespace pe
|