1 : // Copyright 2013 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 : // Unittests for ChainedBasicBlockTransforms.
16 :
17 : #include "syzygy/block_graph/transforms/chained_basic_block_transforms.h"
18 :
19 : #include "gtest/gtest.h"
20 : #include "syzygy/block_graph/basic_block.h"
21 : #include "syzygy/block_graph/basic_block_assembler.h"
22 : #include "syzygy/block_graph/basic_block_decomposer.h"
23 : #include "syzygy/block_graph/basic_block_subgraph.h"
24 : #include "syzygy/block_graph/block_graph.h"
25 : #include "syzygy/block_graph/transform.h"
26 : #include "syzygy/block_graph/unittest_util.h"
27 :
28 : #include "mnemonics.h" // NOLINT
29 :
30 : namespace block_graph {
31 : namespace transforms {
32 : namespace {
33 :
34 : class TestChainedBasicBlockTransforms : public ChainedBasicBlockTransforms {
35 : public:
36 : using ChainedBasicBlockTransforms::transforms_;
37 : };
38 :
39 : const uint8 kData1Data[] =
40 : { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
41 :
42 : // kNop9 + kRet
43 : const uint8 kCode1Data[] =
44 : { 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3 };
45 : // kRet
46 : const uint8 kCode2Data[] = { 0xC3 };
47 :
48 : class ChainedBasicBlockTransformsTest : public testing::Test {
49 : public:
50 E : virtual void SetUp() {
51 : BlockGraph::Block* d1 =
52 E : block_graph_.AddBlock(BlockGraph::DATA_BLOCK, sizeof(kData1Data), "d1");
53 E : ASSERT_NE(reinterpret_cast<BlockGraph::Block*>(NULL), d1);
54 E : d1->SetData(kData1Data, sizeof(kData1Data));
55 :
56 : BlockGraph::Block* c1 =
57 E : block_graph_.AddBlock(BlockGraph::CODE_BLOCK, sizeof(kCode1Data), "c1");
58 E : ASSERT_NE(reinterpret_cast<BlockGraph::Block*>(NULL), c1);
59 E : c1->SetData(kCode1Data, sizeof(kCode1Data));
60 :
61 : BlockGraph::Block* c2 =
62 E : block_graph_.AddBlock(BlockGraph::CODE_BLOCK, sizeof(kCode2Data), "c2");
63 E : ASSERT_NE(reinterpret_cast<BlockGraph::Block*>(NULL), c2);
64 E : c2->SetData(kCode2Data, sizeof(kCode2Data));
65 :
66 E : header_ = d1;
67 E : }
68 :
69 E : bool Relink(TestChainedBasicBlockTransforms* transform) {
70 E : DCHECK_NE(reinterpret_cast<TestChainedBasicBlockTransforms*>(NULL),
71 : transform);
72 : return ApplyBlockGraphTransform(transform,
73 : &policy_,
74 : &block_graph_,
75 E : header_);
76 E : }
77 :
78 : protected:
79 : testing::DummyTransformPolicy policy_;
80 : BlockGraph block_graph_;
81 : BlockGraph::Block* header_;
82 : };
83 :
84 : class InsertOrRemoveBasicBlockTransform
85 : : public block_graph::transforms::NamedBasicBlockSubGraphTransformImpl<
86 : InsertOrRemoveBasicBlockTransform> {
87 : public:
88 E : InsertOrRemoveBasicBlockTransform(std::set<std::string>* blocks,
89 : bool insert)
90 : : blocks_(blocks), insert_(insert) {
91 E : }
92 :
93 : bool TransformBasicBlockSubGraph(
94 : const TransformPolicyInterface* policy,
95 : BlockGraph* block_graph,
96 : BasicBlockSubGraph* basic_block_subgraph) override;
97 :
98 : static const char InsertOrRemoveBasicBlockTransform::kTransformName[];
99 :
100 : bool insert_;
101 : std::set<std::string>* blocks_;
102 : };
103 :
104 : bool InsertOrRemoveBasicBlockTransform::TransformBasicBlockSubGraph(
105 : const TransformPolicyInterface* policy,
106 : BlockGraph* block_graph,
107 E : BasicBlockSubGraph* subgraph) {
108 E : DCHECK_NE(reinterpret_cast<TransformPolicyInterface*>(NULL), policy);
109 E : DCHECK_NE(reinterpret_cast<BlockGraph*>(NULL), block_graph);
110 E : DCHECK_NE(reinterpret_cast<BasicBlockSubGraph*>(NULL), subgraph);
111 :
112 E : if (insert_) {
113 E : blocks_->insert(subgraph->original_block()->name());
114 E : } else {
115 E : blocks_->erase(subgraph->original_block()->name());
116 : }
117 :
118 E : return true;
119 E : }
120 :
121 : const char InsertOrRemoveBasicBlockTransform::kTransformName[] =
122 : "InsertOrRemoveBasicBlockTransform";
123 :
124 : } // namespace
125 :
126 E : TEST_F(ChainedBasicBlockTransformsTest, NoTransforms) {
127 E : TestChainedBasicBlockTransforms chains;
128 E : EXPECT_EQ(std::string("ChainedBasicBlockTransforms"), chains.name());
129 E : EXPECT_TRUE(chains.transforms_.empty());
130 E : }
131 :
132 E : TEST_F(ChainedBasicBlockTransformsTest, AppendTransforms) {
133 E : std::set<std::string> blocks;
134 E : InsertOrRemoveBasicBlockTransform insert(&blocks, true);
135 E : InsertOrRemoveBasicBlockTransform remove(&blocks, false);
136 :
137 : // Validate AppendTransform.
138 E : TestChainedBasicBlockTransforms chains;
139 E : EXPECT_TRUE(chains.transforms_.empty());
140 E : chains.AppendTransform(&insert);
141 E : EXPECT_EQ(1U, chains.transforms_.size());
142 E : chains.AppendTransform(&remove);
143 E : EXPECT_EQ(2U, chains.transforms_.size());
144 E : }
145 :
146 E : TEST_F(ChainedBasicBlockTransformsTest, SingleTransforms) {
147 E : std::set<std::string> blocks;
148 E : InsertOrRemoveBasicBlockTransform insert(&blocks, true);
149 :
150 E : TestChainedBasicBlockTransforms chains;
151 E : chains.AppendTransform(&insert);
152 E : EXPECT_TRUE(Relink(&chains));
153 :
154 : // Validate that the data block are ignored.
155 E : EXPECT_TRUE(blocks.find("d1") == blocks.end());
156 :
157 : // Validate that code block are present.
158 E : EXPECT_TRUE(blocks.find("c1") != blocks.end());
159 E : EXPECT_TRUE(blocks.find("c2") != blocks.end());
160 :
161 : // Validate that insert pass was executed.
162 E : EXPECT_EQ(2U, blocks.size());
163 E : }
164 :
165 E : TEST_F(ChainedBasicBlockTransformsTest, FullTransforms) {
166 E : std::set<std::string> blocks;
167 E : InsertOrRemoveBasicBlockTransform insert(&blocks, true);
168 E : InsertOrRemoveBasicBlockTransform remove(&blocks, false);
169 :
170 E : TestChainedBasicBlockTransforms chains;
171 E : chains.AppendTransform(&insert);
172 E : chains.AppendTransform(&remove);
173 E : EXPECT_TRUE(Relink(&chains));
174 :
175 : // Validate that both passes were executed.
176 E : EXPECT_TRUE(blocks.empty());
177 E : }
178 :
179 : } // namespace transforms
180 : } // namespace block_graph
|