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 |