Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: syzygy/instrument/transforms/filler_transform.cc

Issue 1169603003: [Syzygy Instrumenter] Add FillerTransform. (Closed) Base URL: https://code.google.com/p/syzygy.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/instrument/transforms/filler_transform.h"
16
17 #include "base/logging.h"
18 #include "syzygy/assm/assembler_base.h"
19 #include "syzygy/block_graph/basic_block_assembler.h"
20 #include "syzygy/block_graph/basic_block_subgraph.h"
21 #include "syzygy/block_graph/block_util.h"
22 #include "syzygy/block_graph/transform_policy.h"
23
24 namespace instrument {
25 namespace transforms {
26
27 const char FillerBasicBlockTransform::kTransformName[] =
28 "FillerBasicBlockTransform";
29
30 const char FillerTransform::kTransformName[] = "FillerTransform";
31
32 size_t NopInjector::Inject(BasicBlock::Instructions* instructions) const {
33 size_t num_injected = 0LL;
34 // Since the locations in |nop_spec_| are sorted, we can perform a parallel
35 // visit of |nop_spec_| and |instructions| to inject NOPs.
36 NopSpec::const_iterator nop_it = nop_spec_.begin();
37 BasicBlock::Instructions::iterator inst_it = instructions->begin();
38 size_t offset = 0LL;
39 while (nop_it != nop_spec_.end() && inst_it != instructions->end()) {
40 // Always increase offset. For each offset, either add NOP or proceed to
41 // the next instruction.
42 if (nop_it->first == offset) {
43 block_graph::BasicBlockAssembler assm(inst_it, instructions);
44 assm.nop(nop_it->second);
45 ++nop_it;
46 ++num_injected;
47 } else {
48 ++inst_it;
49 }
50 ++offset;
51 }
52 return num_injected;
53 }
54
55 bool FillerBasicBlockTransform::TransformBasicBlockSubGraph(
56 const TransformPolicyInterface* policy,
57 BlockGraph* block_graph,
58 BasicBlockSubGraph* basic_block_subgraph) {
59 DCHECK(nullptr != policy);
60 DCHECK(nullptr != block_graph);
61 DCHECK(nullptr != basic_block_subgraph);
62
63 // Locations for code injection.
64 NopInjector nop_injector({{1, NopInjector::NOP1}});
65
66 // Visit each basic code block and inject NOPs.
67 BasicBlockSubGraph::BBCollection& basic_blocks =
68 basic_block_subgraph->basic_blocks();
69 for (auto bb = basic_blocks.begin(); bb != basic_blocks.end(); ++bb) {
70 BasicCodeBlock* bc_block = BasicCodeBlock::Cast(*bb);
71 if (bc_block != nullptr)
72 nop_injector.Inject(&bc_block->instructions());
73 }
74 return true;
75 }
76
77 FillerTransform::FillerTransform(const std::vector<std::string>& target_list)
78 : basic_block_transform_(new FillerBasicBlockTransform()),
79 num_block_(0),
80 num_code_block_(0),
81 num_target_updated_(0) {
82 // Targets are not found yet, so initialize value to false.
83 for (const std::string& target : target_list)
84 target_names_[target] = false;
85 }
86
87 bool FillerTransform::ShouldProcessBlock(Block* block) const {
88 return target_names_.find(block->name()) != target_names_.end();
89 }
90
91 void FillerTransform::CheckAllTargetFound() const {
92 bool has_missing = false;
93 for (auto it = target_names_.begin(); it != target_names_.end(); ++it) {
94 if (it->second)
95 continue;
96 if (!has_missing) {
97 LOG(ERROR) << "There are missing target(s):";
98 has_missing = true;
99 }
100 LOG(ERROR) << " " << it->first;
101 }
102 }
103
104 bool FillerTransform::PreBlockGraphIteration(
105 const TransformPolicyInterface* policy,
106 BlockGraph* block_graph,
107 Block* header_block) {
108 return true;
109 }
110
111 bool FillerTransform::OnBlock(const TransformPolicyInterface* policy,
112 BlockGraph* block_graph,
113 Block* block) {
114 DCHECK(nullptr != policy);
115 DCHECK(nullptr != block_graph);
116 DCHECK(nullptr != block);
117
118 ++num_block_;
119 if (block->type() != BlockGraph::CODE_BLOCK)
120 return true;
121
122 ++num_code_block_;
123 if (!ShouldProcessBlock(block))
124 return true;
125
126 // Mark target as found.
127 std::string name(block->name());
128 auto target_it = target_names_.find(block->name());
129 if (target_it != target_names_.end())
130 target_it->second = true;
131
132 // Skip blocks that aren't eligible for basic-block decomposition.
133 if (!policy->BlockIsSafeToBasicBlockDecompose(block))
134 return true;
135
136 ++num_target_updated_;
137 // Apply the basic block transform.
138 return ApplyBasicBlockSubGraphTransform(
139 basic_block_transform_.get(), policy, block_graph, block, NULL);
140 }
141
142 bool FillerTransform::PostBlockGraphIteration(
143 const TransformPolicyInterface* policy,
144 BlockGraph* block_graph,
145 Block* header_block) {
146 LOG(INFO) << "Found " << num_block_ << " block(s).";
147 LOG(INFO) << "Found " << num_code_block_ << " code block(s).";
148 LOG(INFO) << "Updated " << num_target_updated_ << " blocks(s).";
149 CheckAllTargetFound();
150 return true;
151 }
152
153 } // namespace transforms
154 } // namespace instrument
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698