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