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