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