| 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> |
| 8 #include <stdint.h> |
| 9 |
| 7 #include "base/macros.h" | 10 #include "base/macros.h" |
| 8 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 9 #include "courgette/disassembler.h" | 12 #include "courgette/disassembler.h" |
| 10 #include "courgette/streams.h" | 13 #include "courgette/streams.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 14 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 15 |
| 13 namespace { | 16 namespace { |
| 14 | 17 |
| 15 using courgette::EncodedProgram; | 18 using courgette::EncodedProgram; |
| 16 | 19 |
| 17 struct AddressSpec { | 20 struct AddressSpec { |
| 18 int32 index; | 21 int32_t index; |
| 19 courgette::RVA rva; | 22 courgette::RVA rva; |
| 20 }; | 23 }; |
| 21 | 24 |
| 22 // Creates a simple new program with given addresses. The orders of elements | 25 // Creates a simple new program with given addresses. The orders of elements |
| 23 // in |abs32_specs| and |rel32_specs| are important. | 26 // in |abs32_specs| and |rel32_specs| are important. |
| 24 scoped_ptr<EncodedProgram> CreateTestProgram(AddressSpec* abs32_specs, | 27 scoped_ptr<EncodedProgram> CreateTestProgram(AddressSpec* abs32_specs, |
| 25 size_t num_abs32_specs, | 28 size_t num_abs32_specs, |
| 26 AddressSpec* rel32_specs, | 29 AddressSpec* rel32_specs, |
| 27 size_t num_rel32_specs) { | 30 size_t num_rel32_specs) { |
| 28 scoped_ptr<EncodedProgram> program(new EncodedProgram()); | 31 scoped_ptr<EncodedProgram> program(new EncodedProgram()); |
| 29 | 32 |
| 30 uint32 base = 0x00900000; | 33 uint32_t base = 0x00900000; |
| 31 program->set_image_base(base); | 34 program->set_image_base(base); |
| 32 | 35 |
| 33 for (size_t i = 0; i < num_abs32_specs; ++i) { | 36 for (size_t i = 0; i < num_abs32_specs; ++i) { |
| 34 EXPECT_TRUE(program->DefineAbs32Label(abs32_specs[i].index, | 37 EXPECT_TRUE(program->DefineAbs32Label(abs32_specs[i].index, |
| 35 abs32_specs[i].rva)); | 38 abs32_specs[i].rva)); |
| 36 } | 39 } |
| 37 for (size_t i = 0; i < num_rel32_specs; ++i) { | 40 for (size_t i = 0; i < num_rel32_specs; ++i) { |
| 38 EXPECT_TRUE(program->DefineRel32Label(rel32_specs[i].index, | 41 EXPECT_TRUE(program->DefineRel32Label(rel32_specs[i].index, |
| 39 rel32_specs[i].rva)); | 42 rel32_specs[i].rva)); |
| 40 } | 43 } |
| 41 program->EndLabels(); | 44 program->EndLabels(); |
| 42 | 45 |
| 43 EXPECT_TRUE(program->AddOrigin(0)); // Start at base. | 46 EXPECT_TRUE(program->AddOrigin(0)); // Start at base. |
| 44 for (size_t i = 0; i < num_abs32_specs; ++i) | 47 for (size_t i = 0; i < num_abs32_specs; ++i) |
| 45 EXPECT_TRUE(program->AddAbs32(abs32_specs[i].index)); | 48 EXPECT_TRUE(program->AddAbs32(abs32_specs[i].index)); |
| 46 for (size_t i = 0; i < num_rel32_specs; ++i) | 49 for (size_t i = 0; i < num_rel32_specs; ++i) |
| 47 EXPECT_TRUE(program->AddRel32(rel32_specs[i].index)); | 50 EXPECT_TRUE(program->AddRel32(rel32_specs[i].index)); |
| 48 return program; | 51 return program; |
| 49 } | 52 } |
| 50 | 53 |
| 51 bool CompareSink(const uint8 expected[], | 54 bool CompareSink(const uint8_t expected[], |
| 52 size_t num_expected, | 55 size_t num_expected, |
| 53 courgette::SinkStream* ss) { | 56 courgette::SinkStream* ss) { |
| 54 size_t n = ss->Length(); | 57 size_t n = ss->Length(); |
| 55 if (num_expected != n) | 58 if (num_expected != n) |
| 56 return false; | 59 return false; |
| 57 const uint8* buffer = ss->Buffer(); | 60 const uint8_t* buffer = ss->Buffer(); |
| 58 return memcmp(&expected[0], buffer, n) == 0; | 61 return memcmp(&expected[0], buffer, n) == 0; |
| 59 } | 62 } |
| 60 | 63 |
| 61 } // namespace | 64 } // namespace |
| 62 | 65 |
| 63 // Create a simple program with a few addresses and references and | 66 // Create a simple program with a few addresses and references and |
| 64 // check that the bits produced are as expected. | 67 // check that the bits produced are as expected. |
| 65 TEST(EncodedProgramTest, Test) { | 68 TEST(EncodedProgramTest, Test) { |
| 66 // ABS32 index 7 == base + 4. | 69 // ABS32 index 7 == base + 4. |
| 67 AddressSpec abs32_specs[] = {{7, 4}}; | 70 AddressSpec abs32_specs[] = {{7, 4}}; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 91 scoped_ptr<EncodedProgram> encoded2(new EncodedProgram()); | 94 scoped_ptr<EncodedProgram> encoded2(new EncodedProgram()); |
| 92 bool can_read = encoded2->ReadFrom(&sources); | 95 bool can_read = encoded2->ReadFrom(&sources); |
| 93 EXPECT_TRUE(can_read); | 96 EXPECT_TRUE(can_read); |
| 94 | 97 |
| 95 // Finally, try to assemble. | 98 // Finally, try to assemble. |
| 96 courgette::SinkStream assembled; | 99 courgette::SinkStream assembled; |
| 97 bool can_assemble = encoded2->AssembleTo(&assembled); | 100 bool can_assemble = encoded2->AssembleTo(&assembled); |
| 98 EXPECT_TRUE(can_assemble); | 101 EXPECT_TRUE(can_assemble); |
| 99 encoded2.reset(); | 102 encoded2.reset(); |
| 100 | 103 |
| 101 const uint8 golden[] = { | 104 const uint8_t golden[] = { |
| 102 0x04, 0x00, 0x90, 0x00, // ABS32 to base + 4 | 105 0x04, 0x00, 0x90, |
| 103 0xF8, 0xFF, 0xFF, 0xFF // REL32 from next line to base + 2 | 106 0x00, // ABS32 to base + 4 |
| 107 0xF8, 0xFF, 0xFF, |
| 108 0xFF // REL32 from next line to base + 2 |
| 104 }; | 109 }; |
| 105 EXPECT_TRUE(CompareSink(golden, arraysize(golden), &assembled)); | 110 EXPECT_TRUE(CompareSink(golden, arraysize(golden), &assembled)); |
| 106 } | 111 } |
| 107 | 112 |
| 108 // A larger test with multiple addresses. We encode the program and check the | 113 // A larger test with multiple addresses. We encode the program and check the |
| 109 // contents of the address streams. | 114 // contents of the address streams. |
| 110 TEST(EncodedProgramTest, TestWriteAddress) { | 115 TEST(EncodedProgramTest, TestWriteAddress) { |
| 111 // Absolute addresses by index: [_, _, _, 2, _, 23, _, 11]. | 116 // Absolute addresses by index: [_, _, _, 2, _, 23, _, 11]. |
| 112 AddressSpec abs32_specs[] = {{7, 11}, {3, 2}, {5, 23}}; | 117 AddressSpec abs32_specs[] = {{7, 11}, {3, 2}, {5, 23}}; |
| 113 // Relative addresses by index: [16, 7, _, 32]. | 118 // Relative addresses by index: [16, 7, _, 32]. |
| 114 AddressSpec rel32_specs[] = {{0, 16}, {3, 32}, {1, 7}}; | 119 AddressSpec rel32_specs[] = {{0, 16}, {3, 32}, {1, 7}}; |
| 115 scoped_ptr<EncodedProgram> program( | 120 scoped_ptr<EncodedProgram> program( |
| 116 CreateTestProgram(abs32_specs, arraysize(abs32_specs), | 121 CreateTestProgram(abs32_specs, arraysize(abs32_specs), |
| 117 rel32_specs, arraysize(rel32_specs))); | 122 rel32_specs, arraysize(rel32_specs))); |
| 118 | 123 |
| 119 courgette::SinkStreamSet sinks; | 124 courgette::SinkStreamSet sinks; |
| 120 EXPECT_TRUE(program->WriteTo(&sinks)); | 125 EXPECT_TRUE(program->WriteTo(&sinks)); |
| 121 program.reset(); | 126 program.reset(); |
| 122 | 127 |
| 123 // Check addresses in sinks. | 128 // Check addresses in sinks. |
| 124 const uint8 golden_abs32_indexes[] = { | 129 const uint8_t golden_abs32_indexes[] = { |
| 125 0x03, 0x07, 0x03, 0x05 // 3 indexes: [7, 3, 5]. | 130 0x03, 0x07, 0x03, 0x05 // 3 indexes: [7, 3, 5]. |
| 126 }; | 131 }; |
| 127 EXPECT_TRUE(CompareSink(golden_abs32_indexes, | 132 EXPECT_TRUE(CompareSink(golden_abs32_indexes, |
| 128 arraysize(golden_abs32_indexes), | 133 arraysize(golden_abs32_indexes), |
| 129 sinks.stream(courgette::kStreamAbs32Indexes))); | 134 sinks.stream(courgette::kStreamAbs32Indexes))); |
| 130 | 135 |
| 131 const uint8 golden_rel32_indexes[] = { | 136 const uint8_t golden_rel32_indexes[] = { |
| 132 0x03, 0x00, 0x03, 0x01 // 3 indexes: [0, 3, 1]. | 137 0x03, 0x00, 0x03, 0x01 // 3 indexes: [0, 3, 1]. |
| 133 }; | 138 }; |
| 134 EXPECT_TRUE(CompareSink(golden_rel32_indexes, | 139 EXPECT_TRUE(CompareSink(golden_rel32_indexes, |
| 135 arraysize(golden_rel32_indexes), | 140 arraysize(golden_rel32_indexes), |
| 136 sinks.stream(courgette::kStreamRel32Indexes))); | 141 sinks.stream(courgette::kStreamRel32Indexes))); |
| 137 | 142 |
| 138 // Addresses: [_, _, _, 2, _, 23, _, 11]. | 143 // Addresses: [_, _, _, 2, _, 23, _, 11]. |
| 139 // Padded: [0, 0, 0, 2, 2, 23, 23, 11]. | 144 // Padded: [0, 0, 0, 2, 2, 23, 23, 11]. |
| 140 // Delta: [0, 0, 0, 2, 0, 21, 0, -12]. | 145 // Delta: [0, 0, 0, 2, 0, 21, 0, -12]. |
| 141 // Hex: [0, 0, 0, 0x02, 0, 0x15, 0, 0xFFFFFFF4]. | 146 // Hex: [0, 0, 0, 0x02, 0, 0x15, 0, 0xFFFFFFF4]. |
| 142 // Complement neg: [0, 0, 0, 0x02, 0, 0x15, 0, (0x0B)]. | 147 // Complement neg: [0, 0, 0, 0x02, 0, 0x15, 0, (0x0B)]. |
| 143 // Varint32 Signed: [0, 0, 0, 0x04, 0, 0x2A, 0, 0x17]. | 148 // Varint32 Signed: [0, 0, 0, 0x04, 0, 0x2A, 0, 0x17]. |
| 144 const uint8 golden_abs32_addresses[] = { | 149 const uint8_t golden_abs32_addresses[] = { |
| 145 0x08, // 8 address deltas. | 150 0x08, // 8 address deltas. |
| 146 0x00, 0x00, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x17, | 151 0x00, 0x00, 0x00, 0x04, 0x00, 0x2A, 0x00, 0x17, |
| 147 }; | 152 }; |
| 148 EXPECT_TRUE(CompareSink(golden_abs32_addresses, | 153 EXPECT_TRUE(CompareSink(golden_abs32_addresses, |
| 149 arraysize(golden_abs32_addresses), | 154 arraysize(golden_abs32_addresses), |
| 150 sinks.stream(courgette::kStreamAbs32Addresses))); | 155 sinks.stream(courgette::kStreamAbs32Addresses))); |
| 151 | 156 |
| 152 // Addresses: [16, 7, _, 32]. | 157 // Addresses: [16, 7, _, 32]. |
| 153 // Padded: [16, 7, 7, 32]. | 158 // Padded: [16, 7, 7, 32]. |
| 154 // Delta: [16, -9, 0, 25]. | 159 // Delta: [16, -9, 0, 25]. |
| 155 // Hex: [0x10, 0xFFFFFFF7, 0, 0x19]. | 160 // Hex: [0x10, 0xFFFFFFF7, 0, 0x19]. |
| 156 // Complement Neg: [0x10, (0x08), 0, 0x19]. | 161 // Complement Neg: [0x10, (0x08), 0, 0x19]. |
| 157 // Varint32 Signed: [0x20, 0x11, 0, 0x32]. | 162 // Varint32 Signed: [0x20, 0x11, 0, 0x32]. |
| 158 const uint8 golden_rel32_addresses[] = { | 163 const uint8_t golden_rel32_addresses[] = { |
| 159 0x04, // 4 address deltas. | 164 0x04, // 4 address deltas. |
| 160 0x20, 0x11, 0x00, 0x32, | 165 0x20, 0x11, 0x00, 0x32, |
| 161 }; | 166 }; |
| 162 EXPECT_TRUE(CompareSink(golden_rel32_addresses, | 167 EXPECT_TRUE(CompareSink(golden_rel32_addresses, |
| 163 arraysize(golden_rel32_addresses), | 168 arraysize(golden_rel32_addresses), |
| 164 sinks.stream(courgette::kStreamRel32Addresses))); | 169 sinks.stream(courgette::kStreamRel32Addresses))); |
| 165 } | 170 } |
| OLD | NEW |