| 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 |