OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "courgette/encoded_program.h" | 5 #include "courgette/encoded_program.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "courgette/image_utils.h" | 14 #include "courgette/image_utils.h" |
15 #include "courgette/label_manager.h" | 15 #include "courgette/label_manager.h" |
16 #include "courgette/streams.h" | 16 #include "courgette/streams.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
18 | 18 |
19 namespace courgette { | 19 namespace courgette { |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 // Helper class to instantiate RVAToLabel while managing allocation. | 23 // Helper class to instantiate RVAToLabel while managing allocation. |
24 class RVAToLabelMaker { | 24 class TestLabelManager : public LabelManager { |
25 public: | 25 public: |
26 RVAToLabelMaker() {} | 26 void RawAddLabel(int index, RVA rva) { |
27 ~RVAToLabelMaker() {} | |
28 | |
29 // Adds a Label for storage. Must be called before Make(), since |labels_map_| | |
30 // has pointers into |labels_|, and |labels_.push_back()| can invalidate them. | |
31 void Add(int index, RVA rva) { | |
32 DCHECK(label_map_.empty()); | |
33 labels_.push_back(Label(rva, index)); // Don't care about |count_|. | 27 labels_.push_back(Label(rva, index)); // Don't care about |count_|. |
34 } | 28 } |
35 | |
36 // Initializes |label_map_| and returns a pointer to it. | |
37 RVAToLabel* Make() { | |
38 for (size_t i = 0; i < labels_.size(); ++i) { | |
39 DCHECK_EQ(0U, label_map_.count(labels_[i].rva_)); | |
40 label_map_[labels_[i].rva_] = &labels_[i]; | |
41 } | |
42 return &label_map_; | |
43 } | |
44 | |
45 const std::vector<Label>& GetLabels() const { return labels_; } | |
46 | |
47 private: | |
48 std::vector<Label> labels_; // Stores all Labels. | |
49 RVAToLabel label_map_; // Has pointers to |labels_| elements. | |
50 }; | 29 }; |
51 | 30 |
52 // Creates a simple new program with given addresses. The orders of elements | 31 // Creates a simple new program with given addresses. The orders of elements |
53 // in |abs32_specs| and |rel32_specs| are important. | 32 // in |abs32_specs| and |rel32_specs| are important. |
54 std::unique_ptr<EncodedProgram> CreateTestProgram( | 33 std::unique_ptr<EncodedProgram> CreateTestProgram( |
55 RVAToLabelMaker* abs32_maker, | 34 const TestLabelManager& abs32_label_manager, |
56 RVAToLabelMaker* rel32_maker) { | 35 const TestLabelManager& rel32_label_manager) { |
57 RVAToLabel* abs32_labels = abs32_maker->Make(); | |
58 RVAToLabel* rel32_labels = rel32_maker->Make(); | |
59 | |
60 std::unique_ptr<EncodedProgram> program(new EncodedProgram()); | 36 std::unique_ptr<EncodedProgram> program(new EncodedProgram()); |
61 | 37 |
62 uint32_t base = 0x00900000; | 38 uint32_t base = 0x00900000; |
63 program->set_image_base(base); | 39 program->set_image_base(base); |
64 | 40 |
65 EXPECT_TRUE(program->DefineLabels(*abs32_labels, *rel32_labels)); | 41 EXPECT_TRUE(program->ImportLabels(abs32_label_manager, rel32_label_manager)); |
66 | 42 |
67 EXPECT_TRUE(program->AddOrigin(0)); // Start at base. | 43 EXPECT_TRUE(program->AddOrigin(0)); // Start at base. |
68 | 44 |
69 // Arbitrary: Add instructions in the order they're defined in |*_maker|. | 45 // Add instructions. Since we're using TestLabelManager, Labels are sorted in |
70 for (const Label& label : abs32_maker->GetLabels()) | 46 // the order they're added via Add(). |
| 47 for (const Label& label : abs32_label_manager.Labels()) |
71 EXPECT_TRUE(program->AddAbs32(label.index_)); | 48 EXPECT_TRUE(program->AddAbs32(label.index_)); |
72 for (const Label& label : rel32_maker->GetLabels()) | 49 for (const Label& label : rel32_label_manager.Labels()) |
73 EXPECT_TRUE(program->AddRel32(label.index_)); | 50 EXPECT_TRUE(program->AddRel32(label.index_)); |
74 | 51 |
75 return program; | 52 return program; |
76 } | 53 } |
77 | 54 |
78 bool CompareSink(const uint8_t expected[], | 55 bool CompareSink(const uint8_t expected[], |
79 size_t num_expected, | 56 size_t num_expected, |
80 SinkStream* ss) { | 57 SinkStream* ss) { |
81 size_t n = ss->Length(); | 58 size_t n = ss->Length(); |
82 if (num_expected != n) | 59 if (num_expected != n) |
83 return false; | 60 return false; |
84 const uint8_t* buffer = ss->Buffer(); | 61 const uint8_t* buffer = ss->Buffer(); |
85 return memcmp(&expected[0], buffer, n) == 0; | 62 return memcmp(&expected[0], buffer, n) == 0; |
86 } | 63 } |
87 | 64 |
88 } // namespace | 65 } // namespace |
89 | 66 |
90 // Create a simple program with a few addresses and references and | 67 // Create a simple program with a few addresses and references and |
91 // check that the bits produced are as expected. | 68 // check that the bits produced are as expected. |
92 TEST(EncodedProgramTest, Test) { | 69 TEST(EncodedProgramTest, Test) { |
93 // ABS32 index 7 <-- base + 4. | 70 // ABS32 index 7 <-- base + 4. |
94 RVAToLabelMaker abs32_label_maker; | 71 TestLabelManager abs32_label_manager; |
95 abs32_label_maker.Add(7, 4); | 72 abs32_label_manager.RawAddLabel(7, 4); |
96 // REL32 index 5 <-- base + 0. | 73 // REL32 index 5 <-- base + 0. |
97 RVAToLabelMaker rel32_label_maker; | 74 TestLabelManager rel32_label_manager; |
98 rel32_label_maker.Add(5, 0); | 75 rel32_label_manager.RawAddLabel(5, 0); |
99 | 76 |
100 std::unique_ptr<EncodedProgram> program( | 77 std::unique_ptr<EncodedProgram> program( |
101 CreateTestProgram(&abs32_label_maker, &rel32_label_maker)); | 78 CreateTestProgram(abs32_label_manager, rel32_label_manager)); |
102 | 79 |
103 // Serialize and deserialize. | 80 // Serialize and deserialize. |
104 SinkStreamSet sinks; | 81 SinkStreamSet sinks; |
105 EXPECT_TRUE(program->WriteTo(&sinks)); | 82 EXPECT_TRUE(program->WriteTo(&sinks)); |
106 program.reset(); | 83 program.reset(); |
107 | 84 |
108 SinkStream sink; | 85 SinkStream sink; |
109 bool can_collect = sinks.CopyTo(&sink); | 86 bool can_collect = sinks.CopyTo(&sink); |
110 EXPECT_TRUE(can_collect); | 87 EXPECT_TRUE(can_collect); |
111 | 88 |
(...skipping 20 matching lines...) Expand all Loading... |
132 0xF8, 0xFF, 0xFF, | 109 0xF8, 0xFF, 0xFF, |
133 0xFF // REL32 from next line to base + 2 | 110 0xFF // REL32 from next line to base + 2 |
134 }; | 111 }; |
135 EXPECT_TRUE(CompareSink(golden, arraysize(golden), &assembled)); | 112 EXPECT_TRUE(CompareSink(golden, arraysize(golden), &assembled)); |
136 } | 113 } |
137 | 114 |
138 // A larger test with multiple addresses. We encode the program and check the | 115 // A larger test with multiple addresses. We encode the program and check the |
139 // contents of the address streams. | 116 // contents of the address streams. |
140 TEST(EncodedProgramTest, TestWriteAddress) { | 117 TEST(EncodedProgramTest, TestWriteAddress) { |
141 // Absolute addresses by index: [_, _, _, 2, _, 23, _, 11]. | 118 // Absolute addresses by index: [_, _, _, 2, _, 23, _, 11]. |
142 RVAToLabelMaker abs32_label_maker; | 119 TestLabelManager abs32_label_manager; |
143 abs32_label_maker.Add(7, 11); | 120 abs32_label_manager.RawAddLabel(7, 11); |
144 abs32_label_maker.Add(3, 2); | 121 abs32_label_manager.RawAddLabel(3, 2); |
145 abs32_label_maker.Add(5, 23); | 122 abs32_label_manager.RawAddLabel(5, 23); |
146 // Relative addresses by index: [16, 7, _, 32]. | 123 // Relative addresses by index: [16, 7, _, 32]. |
147 RVAToLabelMaker rel32_label_maker; | 124 TestLabelManager rel32_label_manager; |
148 rel32_label_maker.Add(0, 16); | 125 rel32_label_manager.RawAddLabel(0, 16); |
149 rel32_label_maker.Add(3, 32); | 126 rel32_label_manager.RawAddLabel(3, 32); |
150 rel32_label_maker.Add(1, 7); | 127 rel32_label_manager.RawAddLabel(1, 7); |
151 | 128 |
152 std::unique_ptr<EncodedProgram> program( | 129 std::unique_ptr<EncodedProgram> program( |
153 CreateTestProgram(&abs32_label_maker, &rel32_label_maker)); | 130 CreateTestProgram(abs32_label_manager, rel32_label_manager)); |
154 | 131 |
155 SinkStreamSet sinks; | 132 SinkStreamSet sinks; |
156 EXPECT_TRUE(program->WriteTo(&sinks)); | 133 EXPECT_TRUE(program->WriteTo(&sinks)); |
157 program.reset(); | 134 program.reset(); |
158 | 135 |
159 // Check indexes and addresses in sinks. | 136 // Check indexes and addresses in sinks. |
160 const uint8_t golden_abs32_indexes[] = { | 137 const uint8_t golden_abs32_indexes[] = { |
161 0x03, 0x07, 0x03, 0x05 // 3 indexes: [7, 3, 5]. | 138 0x03, 0x07, 0x03, 0x05 // 3 indexes: [7, 3, 5]. |
162 }; | 139 }; |
163 EXPECT_TRUE(CompareSink(golden_abs32_indexes, | 140 EXPECT_TRUE(CompareSink(golden_abs32_indexes, |
(...skipping 30 matching lines...) Expand all Loading... |
194 const uint8_t golden_rel32_addresses[] = { | 171 const uint8_t golden_rel32_addresses[] = { |
195 0x04, // 4 address deltas. | 172 0x04, // 4 address deltas. |
196 0x20, 0x11, 0x00, 0x32, | 173 0x20, 0x11, 0x00, 0x32, |
197 }; | 174 }; |
198 EXPECT_TRUE(CompareSink(golden_rel32_addresses, | 175 EXPECT_TRUE(CompareSink(golden_rel32_addresses, |
199 arraysize(golden_rel32_addresses), | 176 arraysize(golden_rel32_addresses), |
200 sinks.stream(kStreamRel32Addresses))); | 177 sinks.stream(kStreamRel32Addresses))); |
201 } | 178 } |
202 | 179 |
203 } // namespace courgette | 180 } // namespace courgette |
OLD | NEW |