1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/zucchini/rel32_utils.h"
6
7 #include <stdint.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/optional.h"
14 #include "base/test/gtest_util.h"
15 #include "components/zucchini/address_translator.h"
16 #include "components/zucchini/arm_utils.h"
17 #include "components/zucchini/image_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace zucchini {
21
22 namespace {
23
24 // A trivial AddressTranslator that applies constant shift.
25 class TestAddressTranslator : public AddressTranslator {
26 public:
TestAddressTranslator(offset_t image_size,rva_t rva_begin)27 TestAddressTranslator(offset_t image_size, rva_t rva_begin) {
28 DCHECK_GE(rva_begin, 0U);
29 CHECK_EQ(AddressTranslator::kSuccess,
30 Initialize({{0, image_size, rva_begin, image_size}}));
31 }
32 };
33
34 // Checks that |reader| emits and only emits |expected_refs|, in order.
CheckReader(const std::vector<Reference> & expected_refs,std::unique_ptr<ReferenceReader> reader)35 void CheckReader(const std::vector<Reference>& expected_refs,
36 std::unique_ptr<ReferenceReader> reader) {
37 for (Reference expected_ref : expected_refs) {
38 auto ref = reader->GetNext();
39 EXPECT_TRUE(ref.has_value());
40 EXPECT_EQ(expected_ref, ref.value());
41 }
42 EXPECT_EQ(base::nullopt, reader->GetNext()); // Nothing should be left.
43 }
44
45 // Copies displacements from |bytes1| to |bytes2| and checks results against
46 // |bytes_exp_1_to_2|. Then repeats for |*bytes2| , |*byte1|, and
47 // |bytes_exp_2_to_1|. Empty expected bytes mean failure is expected. The copy
48 // function is specified by |copier|.
CheckCopy(const std::vector<uint8_t> & bytes_exp_1_to_2,const std::vector<uint8_t> & bytes_exp_2_to_1,const std::vector<uint8_t> & bytes1,const std::vector<uint8_t> & bytes2,ArmCopyDispFun copier)49 void CheckCopy(const std::vector<uint8_t>& bytes_exp_1_to_2,
50 const std::vector<uint8_t>& bytes_exp_2_to_1,
51 const std::vector<uint8_t>& bytes1,
52 const std::vector<uint8_t>& bytes2,
53 ArmCopyDispFun copier) {
54 auto run_test = [&copier](const std::vector<uint8_t>& bytes_exp,
55 const std::vector<uint8_t>& bytes_in,
56 std::vector<uint8_t> bytes_out) {
57 ConstBufferView buffer_in(&bytes_in[0], bytes_in.size());
58 MutableBufferView buffer_out(&bytes_out[0], bytes_out.size());
59 if (bytes_exp.empty()) {
60 EXPECT_FALSE(copier(buffer_in, 0U, buffer_out, 0U));
61 } else {
62 EXPECT_TRUE(copier(buffer_in, 0U, buffer_out, 0U));
63 EXPECT_EQ(bytes_exp, bytes_out);
64 }
65 };
66 run_test(bytes_exp_1_to_2, bytes1, bytes2);
67 run_test(bytes_exp_2_to_1, bytes2, bytes1);
68 }
69
70 } // namespace
71
TEST(Rel32UtilsTest,Rel32ReaderX86)72 TEST(Rel32UtilsTest, Rel32ReaderX86) {
73 constexpr offset_t kTestImageSize = 0x00100000U;
74 constexpr rva_t kRvaBegin = 0x00030000U;
75 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
76
77 // For simplicity, test data is not real X86 machine code. We are only
78 // including rel32 targets, without the full instructions.
79 std::vector<uint8_t> bytes = {
80 0xFF, 0xFF, 0xFF, 0xFF, // 00030000: (Filler)
81 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
82 0x04, 0x00, 0x00, 0x00, // 00030008: 00030010
83 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
84 0x00, 0x00, 0x00, 0x00, // 00030010: 00030014
85 0xFF, 0xFF, 0xFF, 0xFF, // 00030014: (Filler)
86 0xF4, 0xFF, 0xFF, 0xFF, // 00030018: 00030010
87 0xE4, 0xFF, 0xFF, 0xFF, // 0003001C: 00030004
88 };
89 ConstBufferView buffer(bytes.data(), bytes.size());
90 // Specify rel32 locations directly, instead of parsing.
91 std::vector<offset_t> rel32_locations = {0x0008U, 0x0010U, 0x0018U, 0x001CU};
92
93 // Generate everything.
94 auto reader1 = std::make_unique<Rel32ReaderX86>(buffer, 0x0000U, 0x0020U,
95 &rel32_locations, translator);
96 CheckReader({{0x0008U, 0x0010U},
97 {0x0010U, 0x0014U},
98 {0x0018U, 0x0010U},
99 {0x001CU, 0x0004U}},
100 std::move(reader1));
101
102 // Exclude last.
103 auto reader2 = std::make_unique<Rel32ReaderX86>(buffer, 0x0000U, 0x001CU,
104 &rel32_locations, translator);
105 CheckReader({{0x0008U, 0x0010U}, {0x0010U, 0x0014U}, {0x0018U, 0x0010U}},
106 std::move(reader2));
107
108 // Only find one.
109 auto reader3 = std::make_unique<Rel32ReaderX86>(buffer, 0x000CU, 0x0018U,
110 &rel32_locations, translator);
111 CheckReader({{0x0010U, 0x0014U}}, std::move(reader3));
112 }
113
TEST(Rel32UtilsTest,Rel32WriterX86)114 TEST(Rel32UtilsTest, Rel32WriterX86) {
115 constexpr offset_t kTestImageSize = 0x00100000U;
116 constexpr rva_t kRvaBegin = 0x00030000U;
117 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
118
119 std::vector<uint8_t> bytes(32, 0xFF);
120 MutableBufferView buffer(bytes.data(), bytes.size());
121
122 Rel32WriterX86 writer(buffer, translator);
123 writer.PutNext({0x0008U, 0x0010U});
124 EXPECT_EQ(0x00000004U, buffer.read<uint32_t>(0x08)); // 00030008: 00030010
125
126 writer.PutNext({0x0010U, 0x0014U});
127 EXPECT_EQ(0x00000000U, buffer.read<uint32_t>(0x10)); // 00030010: 00030014
128
129 writer.PutNext({0x0018U, 0x0010U});
130 EXPECT_EQ(0xFFFFFFF4U, buffer.read<uint32_t>(0x18)); // 00030018: 00030010
131
132 writer.PutNext({0x001CU, 0x0004U});
133 EXPECT_EQ(0xFFFFFFE4U, buffer.read<uint32_t>(0x1C)); // 0003001C: 00030004
134
135 EXPECT_EQ(std::vector<uint8_t>({
136 0xFF, 0xFF, 0xFF, 0xFF, // 00030000: (Filler)
137 0xFF, 0xFF, 0xFF, 0xFF, // 00030004: (Filler)
138 0x04, 0x00, 0x00, 0x00, // 00030008: 00030010
139 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
140 0x00, 0x00, 0x00, 0x00, // 00030010: 00030014
141 0xFF, 0xFF, 0xFF, 0xFF, // 00030014: (Filler)
142 0xF4, 0xFF, 0xFF, 0xFF, // 00030018: 00030010
143 0xE4, 0xFF, 0xFF, 0xFF, // 0003001C: 00030004
144 }),
145 bytes);
146 }
147
TEST(Rel32UtilsTest,Rel32ReaderArm_Arm32)148 TEST(Rel32UtilsTest, Rel32ReaderArm_Arm32) {
149 constexpr offset_t kTestImageSize = 0x00100000U;
150 constexpr rva_t kRvaBegin = 0x00030000U;
151 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
152
153 // A24.
154 std::vector<uint8_t> bytes = {
155 0xFF, 0xFF, 0xFF, 0xFF, // 00030000: (Filler)
156 0xFF, 0xFF, 0xFF, 0xFF, // 00030004: (Filler)
157 0x00, 0x00, 0x00, 0xEA, // 00030008: B 00030010 ; A24
158 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
159 0xFF, 0xFF, 0xFF, 0xEB, // 00030010: BL 00030014 ; A24
160 0xFF, 0xFF, 0xFF, 0xFF, // 00030014: (Filler)
161 0xFC, 0xFF, 0xFF, 0xEB, // 00030018: BL 00030010 ; A24
162 0xF8, 0xFF, 0xFF, 0xEA, // 0003001C: B 00030004 ; A24
163 };
164 ConstBufferView region(&bytes[0], bytes.size());
165 // Specify rel32 locations directly, instead of parsing.
166 std::vector<offset_t> rel32_locations_A24 = {0x0008U, 0x0010U, 0x0018U,
167 0x001CU};
168
169 // Generate everything.
170 auto reader1 =
171 std::make_unique<Rel32ReaderArm<Arm32Rel32Translator::AddrTraits_A24>>(
172 translator, region, rel32_locations_A24, 0x0000U, 0x0020U);
173 CheckReader({{0x0008U, 0x0010U},
174 {0x0010U, 0x0014U},
175 {0x0018U, 0x0010U},
176 {0x001CU, 0x0004U}},
177 std::move(reader1));
178
179 // Exclude last.
180 auto reader2 =
181 std::make_unique<Rel32ReaderArm<Arm32Rel32Translator::AddrTraits_A24>>(
182 translator, region, rel32_locations_A24, 0x0000U, 0x001CU);
183 CheckReader({{0x0008U, 0x0010U}, {0x0010U, 0x0014U}, {0x0018U, 0x0010U}},
184 std::move(reader2));
185
186 // Only find one.
187 auto reader3 =
188 std::make_unique<Rel32ReaderArm<Arm32Rel32Translator::AddrTraits_A24>>(
189 translator, region, rel32_locations_A24, 0x000CU, 0x0018U);
190 CheckReader({{0x0010U, 0x0014U}}, std::move(reader3));
191 }
192
TEST(Rel32UtilsTest,Rel32WriterArm_Arm32_Easy)193 TEST(Rel32UtilsTest, Rel32WriterArm_Arm32_Easy) {
194 constexpr offset_t kTestImageSize = 0x00100000U;
195 constexpr rva_t kRvaBegin = 0x00030000U;
196 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
197
198 std::vector<uint8_t> bytes = {
199 0xFF, 0xFF, // 00030000: (Filler)
200 0x01, 0xDE, // 00030002: B 00030008 ; T8
201 0xFF, 0xFF, 0xFF, 0xFF, // 00030004: (Filler)
202 0x01, 0xE0, // 00030008: B 0003000E ; T11
203 0xFF, 0xFF, // 0003000A: (Filler)
204 0x80, 0xF3, 0x00, 0x80, // 0003000C: B 00030010 ; T20
205 };
206 MutableBufferView region(&bytes[0], bytes.size());
207
208 auto writer1 =
209 std::make_unique<Rel32WriterArm<Arm32Rel32Translator::AddrTraits_T8>>(
210 translator, region);
211 writer1->PutNext({0x0002U, 0x0004U});
212 EXPECT_EQ(0xFF, bytes[0x02]); // 00030002: B 00030004 ; T8
213 EXPECT_EQ(0xDE, bytes[0x03]);
214
215 writer1->PutNext({0x0002U, 0x000AU});
216 EXPECT_EQ(0x02, bytes[0x02]); // 00030002: B 0003000A ; T8
217 EXPECT_EQ(0xDE, bytes[0x03]);
218
219 auto writer2 =
220 std::make_unique<Rel32WriterArm<Arm32Rel32Translator::AddrTraits_T11>>(
221 translator, region);
222 writer2->PutNext({0x0008U, 0x0008U});
223 EXPECT_EQ(0xFE, bytes[0x08]); // 00030008: B 00030008 ; T11
224 EXPECT_EQ(0xE7, bytes[0x09]);
225 writer2->PutNext({0x0008U, 0x0010U});
226 EXPECT_EQ(0x02, bytes[0x08]); // 00030008: B 00030010 ; T11
227 EXPECT_EQ(0xE0, bytes[0x09]);
228
229 auto writer3 =
230 std::make_unique<Rel32WriterArm<Arm32Rel32Translator::AddrTraits_T20>>(
231 translator, region);
232 writer3->PutNext({0x000CU, 0x000AU});
233 EXPECT_EQ(0xBF, bytes[0x0C]); // 0003000C: B 0003000A ; T20
234 EXPECT_EQ(0xF7, bytes[0x0D]);
235 EXPECT_EQ(0xFD, bytes[0x0E]);
236 EXPECT_EQ(0xAF, bytes[0x0F]);
237 writer3->PutNext({0x000CU, 0x0010U});
238 EXPECT_EQ(0x80, bytes[0x0C]); // 0003000C: B 00030010 ; T20
239 EXPECT_EQ(0xF3, bytes[0x0D]);
240 EXPECT_EQ(0x00, bytes[0x0E]);
241 EXPECT_EQ(0x80, bytes[0x0F]);
242 }
243
TEST(Rel32UtilsTest,Rel32WriterArm_Arm32_Hard)244 TEST(Rel32UtilsTest, Rel32WriterArm_Arm32_Hard) {
245 constexpr offset_t kTestImageSize = 0x10000000U;
246 constexpr rva_t kRvaBegin = 0x0C030000U;
247 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
248
249 std::vector<uint8_t> bytes = {
250 0xFF, 0xFF, // 0C030000: (Filler)
251 0x00, 0xF0, 0x00, 0xB8, // 0C030002: B 0C030006 ; T24
252 0xFF, 0xFF, 0xFF, 0xFF, // 0C030006: (Filler)
253 0x00, 0xF0, 0x7A, 0xE8, // 0C03000A: BLX 0C030100 ; T24
254 0xFF, 0xFF, // 0C03000E: (Filler)
255 0x00, 0xF0, 0x7A, 0xE8, // 0C030010: BLX 0C030108 ; T24
256 };
257 MutableBufferView region(&bytes[0], bytes.size());
258
259 auto writer =
260 std::make_unique<Rel32WriterArm<Arm32Rel32Translator::AddrTraits_T24>>(
261 translator, region);
262 writer->PutNext({0x0002U, 0x0000U});
263 EXPECT_EQ(0xFF, bytes[0x02]); // 0C030002: B 0C030000 ; T24
264 EXPECT_EQ(0xF7, bytes[0x03]);
265 EXPECT_EQ(0xFD, bytes[0x04]);
266 EXPECT_EQ(0xBF, bytes[0x05]);
267 writer->PutNext({0x0002U, 0x0008U});
268 EXPECT_EQ(0x00, bytes[0x02]); // 0C030002: B 0C030008 ; T24
269 EXPECT_EQ(0xF0, bytes[0x03]);
270 EXPECT_EQ(0x01, bytes[0x04]);
271 EXPECT_EQ(0xB8, bytes[0x05]);
272
273 // BLX complication, with location that's not 4-byte aligned.
274 writer->PutNext({0x000AU, 0x0010U});
275 EXPECT_EQ(0x00, bytes[0x0A]); // 0C03000A: BLX 0C030010 ; T24
276 EXPECT_EQ(0xF0, bytes[0x0B]);
277 EXPECT_EQ(0x02, bytes[0x0C]);
278 EXPECT_EQ(0xE8, bytes[0x0D]);
279 writer->PutNext({0x000AU, 0x0100U});
280 EXPECT_EQ(0x00, bytes[0x0A]); // 0C03000A: BLX 0C030100 ; T24
281 EXPECT_EQ(0xF0, bytes[0x0B]);
282 EXPECT_EQ(0x7A, bytes[0x0C]);
283 EXPECT_EQ(0xE8, bytes[0x0D]);
284 writer->PutNext({0x000AU, 0x0000U});
285 EXPECT_EQ(0xFF, bytes[0x0A]); // 0C03000A: BLX 0C030000 ; T24
286 EXPECT_EQ(0xF7, bytes[0x0B]);
287 EXPECT_EQ(0xFA, bytes[0x0C]);
288 EXPECT_EQ(0xEF, bytes[0x0D]);
289
290 // BLX complication, with location that's 4-byte aligned.
291 writer->PutNext({0x0010U, 0x0010U});
292 EXPECT_EQ(0xFF, bytes[0x10]); // 0C030010: BLX 0C030010 ; T24
293 EXPECT_EQ(0xF7, bytes[0x11]);
294 EXPECT_EQ(0xFE, bytes[0x12]);
295 EXPECT_EQ(0xEF, bytes[0x13]);
296 writer->PutNext({0x0010U, 0x0108U});
297 EXPECT_EQ(0x00, bytes[0x10]); // 0C030010: BLX 0C030108 ; T24
298 EXPECT_EQ(0xF0, bytes[0x11]);
299 EXPECT_EQ(0x7A, bytes[0x12]);
300 EXPECT_EQ(0xE8, bytes[0x13]);
301 }
302
303 // Test BLX encoding A2, which is an ARM instruction that switches to THUMB2,
304 // and therefore should have 2-byte alignment.
TEST(Rel32UtilsTest,Arm32SwitchToThumb2)305 TEST(Rel32UtilsTest, Arm32SwitchToThumb2) {
306 constexpr offset_t kTestImageSize = 0x10000000U;
307 constexpr rva_t kRvaBegin = 0x08030000U;
308 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
309
310 std::vector<uint8_t> bytes = {
311 0xFF, 0xFF, 0x00, 0x00, // 08030000: (Filler)
312 0x00, 0x00, 0x00, 0xFA, // 08030004: BLX 0803000C ; A24
313 };
314 MutableBufferView region(&bytes[0], bytes.size());
315
316 auto writer =
317 std::make_unique<Rel32WriterArm<Arm32Rel32Translator::AddrTraits_A24>>(
318 translator, region);
319
320 // To location that's 4-byte aligned.
321 writer->PutNext({0x0004U, 0x0100U});
322 EXPECT_EQ(0x3D, bytes[0x04]); // 08030004: BLX 08030100 ; A24
323 EXPECT_EQ(0x00, bytes[0x05]);
324 EXPECT_EQ(0x00, bytes[0x06]);
325 EXPECT_EQ(0xFA, bytes[0x07]);
326
327 // To location that's 2-byte aligned but not 4-byte aligned.
328 writer->PutNext({0x0004U, 0x0052U});
329 EXPECT_EQ(0x11, bytes[0x04]); // 08030004: BLX 08030052 ; A24
330 EXPECT_EQ(0x00, bytes[0x05]);
331 EXPECT_EQ(0x00, bytes[0x06]);
332 EXPECT_EQ(0xFB, bytes[0x07]);
333
334 // Clean slate code.
335 writer->PutNext({0x0004U, 0x000CU});
336 EXPECT_EQ(0x00, bytes[0x04]); // 08030004: BLX 0803000C ; A24
337 EXPECT_EQ(0x00, bytes[0x05]);
338 EXPECT_EQ(0x00, bytes[0x06]);
339 EXPECT_EQ(0xFA, bytes[0x07]);
340 }
341
TEST(Rel32UtilsTest,ArmCopyDisp_Arm32)342 TEST(Rel32UtilsTest, ArmCopyDisp_Arm32) {
343 std::vector<uint8_t> expect_fail;
344
345 // Successful A24.
346 ArmCopyDispFun copier_A24 = ArmCopyDisp<Arm32Rel32Translator::AddrTraits_A24>;
347 CheckCopy({0x12, 0x34, 0x56, 0xEB}, // 00000100: BL 0158D150
348 {0xA0, 0xC0, 0x0E, 0x2A}, // 00000100: BCS 003B0388
349 {0x12, 0x34, 0x56, 0x2A}, // 00000100: BCS 0158D150
350 {0xA0, 0xC0, 0x0E, 0xEB}, // 00000100: BL 003B0388
351 copier_A24);
352
353 // Successful T8.
354 ArmCopyDispFun copier_T8 = ArmCopyDisp<Arm32Rel32Translator::AddrTraits_T8>;
355 CheckCopy({0x12, 0xD5}, // 00000100: BPL 00000128
356 {0xAB, 0xD8}, // 00000100: BHI 0000005A
357 {0x12, 0xD8}, // 00000100: BHI 00000128
358 {0xAB, 0xD5}, // 00000100: BPL 0000005A
359 copier_T8);
360
361 // Successful T11.
362 ArmCopyDispFun copier_T11 = ArmCopyDisp<Arm32Rel32Translator::AddrTraits_T11>;
363 CheckCopy({0xF5, 0xE0}, // 00000100: B 000002EE
364 {0x12, 0xE7}, // 00000100: B FFFFFF28
365 {0xF5, 0xE0}, // 00000100: B 000002EE
366 {0x12, 0xE7}, // 00000100: B FFFFFF28
367 copier_T11);
368
369 // Failure if wrong copier is used.
370 CheckCopy(expect_fail, expect_fail, {0xF5, 0xE0}, {0x12, 0xE7}, copier_T8);
371
372 // Successful T20.
373 ArmCopyDispFun copier_T20 = ArmCopyDisp<Arm32Rel32Translator::AddrTraits_T20>;
374 CheckCopy({0x41, 0xF2, 0xA5, 0x88}, // 00000100: BLS.W 0008124E
375 {0x04, 0xF3, 0x3C, 0xA2}, // 00000100: BGT.W 0004457C
376 {0x01, 0xF3, 0xA5, 0x88}, // 00000100: BGT.W 0008124E
377 {0x44, 0xF2, 0x3C, 0xA2}, // 00000100: BLS.W 0004457C
378 copier_T20);
379 CheckCopy({0x7F, 0xF6, 0xFF, 0xAF}, // 00000100: BLS.W 00000102
380 {0x00, 0xF3, 0x00, 0x80}, // 00000100: BGT.W 00000104
381 {0x3F, 0xF7, 0xFF, 0xAF}, // 00000100: BGT.W 00000102
382 {0x40, 0xF2, 0x00, 0x80}, // 00000100: BLS.W 00000104
383 copier_T20);
384
385 // Failure if wrong copier is used.
386 CheckCopy(expect_fail, expect_fail, {0x41, 0xF2, 0xA5, 0x88},
387 {0x84, 0xF3, 0x3C, 0xA2}, copier_A24);
388
389 // T24: Mix B encoding T4 and BL encoding T1.
390 ArmCopyDispFun copier_T24 = ArmCopyDisp<Arm32Rel32Translator::AddrTraits_T24>;
391 CheckCopy({0xFF, 0xF7, 0xFF, 0xFF}, // 00000100: BL 00000102
392 {0x00, 0xF0, 0x00, 0x90}, // 00000100: B.W 00C00104
393 {0xFF, 0xF7, 0xFF, 0xBF}, // 00000100: B.W 00000102
394 {0x00, 0xF0, 0x00, 0xD0}, // 00000100: BL 00C00104
395 copier_T24);
396
397 // Mix B encoding T4 and BLX encoding T2. Note that the forward direction
398 // fails because B's target is invalid for BLX! It's possible to do "best
399 // effort" copying to reduce diff -- but right now we're not doing this.
400 CheckCopy(expect_fail, {0x00, 0xF0, 0x00, 0x90}, // 00000100: B.W 00C00104
401 {0xFF, 0xF7, 0xFF, 0xBF}, // 00000100: B.W 00000102
402 {0x00, 0xF0, 0x00, 0xC0}, // 00000100: BLX 00C00104
403 copier_T24);
404 // Success if ow B's target is valid for BLX.
405 CheckCopy({0xFF, 0xF7, 0xFE, 0xEF}, // 00000100: BLX 00000100
406 {0x00, 0xF0, 0x00, 0x90}, // 00000100: B.W 00C00104
407 {0xFF, 0xF7, 0xFE, 0xBF}, // 00000100: B.W 00000100
408 {0x00, 0xF0, 0x00, 0xC0}, // 00000100: BLX 00C00104
409 copier_T24);
410 }
411
TEST(Rel32UtilsTest,Rel32ReaderArm_AArch64)412 TEST(Rel32UtilsTest, Rel32ReaderArm_AArch64) {
413 constexpr offset_t kTestImageSize = 0x00100000U;
414 constexpr rva_t kRvaBegin = 0x00030000U;
415 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
416
417 std::vector<uint8_t> bytes = {
418 0xFF, 0xFF, 0xFF, 0xFF, // 00030000: (Filler)
419 0xFF, 0xFF, 0xFF, 0xFF, // 00030004: (Filler)
420 0x02, 0x00, 0x00, 0x14, // 00030008: B 00030010 ; Immd26
421 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
422 0x25, 0x00, 0x00, 0x35, // 00030010: CBNZ R5,00030014 ; Immd19
423 0xFF, 0xFF, 0xFF, 0xFF, // 00030014: (Filler)
424 0xCA, 0xFF, 0xFF, 0x54, // 00030018: BGE 00030010 ; Immd19
425 0x4C, 0xFF, 0x8F, 0x36, // 0003001C: TBZ X12,#17,00030004 ; Immd14
426 };
427 MutableBufferView region(&bytes[0], bytes.size());
428
429 // Generate Immd26. We specify rel32 locations directly.
430 std::vector<offset_t> rel32_locations_Immd26 = {0x0008U};
431 auto reader1 = std::make_unique<
432 Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd26>>(
433 translator, region, rel32_locations_Immd26, 0x0000U, 0x0020U);
434 CheckReader({{0x0008U, 0x0010U}}, std::move(reader1));
435
436 // Generate Immd19.
437 std::vector<offset_t> rel32_locations_Immd19 = {0x0010U, 0x0018U};
438 auto reader2 = std::make_unique<
439 Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd19>>(
440 translator, region, rel32_locations_Immd19, 0x0000U, 0x0020U);
441 CheckReader({{0x0010U, 0x0014U}, {0x0018U, 0x0010U}}, std::move(reader2));
442
443 // Generate Immd14.
444 std::vector<offset_t> rel32_locations_Immd14 = {0x001CU};
445 auto reader3 = std::make_unique<
446 Rel32ReaderArm<AArch64Rel32Translator::AddrTraits_Immd14>>(
447 translator, region, rel32_locations_Immd14, 0x0000U, 0x0020U);
448 CheckReader({{0x001CU, 0x0004U}}, std::move(reader3));
449 }
450
TEST(Rel32UtilsTest,Rel32WriterArm_AArch64)451 TEST(Rel32UtilsTest, Rel32WriterArm_AArch64) {
452 constexpr offset_t kTestImageSize = 0x00100000U;
453 constexpr rva_t kRvaBegin = 0x00030000U;
454 TestAddressTranslator translator(kTestImageSize, kRvaBegin);
455
456 std::vector<uint8_t> bytes = {
457 0xFF, 0xFF, 0xFF, 0xFF, // 00030000: (Filler)
458 0xFF, 0xFF, 0xFF, 0xFF, // 00030004: (Filler)
459 0x02, 0x00, 0x00, 0x14, // 00030008: B 00030010 ; Immd26
460 0xFF, 0xFF, 0xFF, 0xFF, // 0003000C: (Filler)
461 0x25, 0x00, 0x00, 0x35, // 00030010: CBNZ R5,00030014 ; Immd19
462 0xFF, 0xFF, 0xFF, 0xFF, // 00030014: (Filler)
463 0xCA, 0xFF, 0xFF, 0x54, // 00030018: BGE 00030010 ; Immd19
464 0x4C, 0xFF, 0x8F, 0x36, // 0003001C: TBZ X12,#17,00030004 ; Immd14
465 };
466 MutableBufferView region(&bytes[0], bytes.size());
467
468 auto writer1 = std::make_unique<
469 Rel32WriterArm<AArch64Rel32Translator::AddrTraits_Immd26>>(translator,
470 region);
471 writer1->PutNext({0x0008U, 0x0000U});
472 EXPECT_EQ(0xFE, bytes[0x08]); // 00030008: B 00030000 ; Immd26
473 EXPECT_EQ(0xFF, bytes[0x09]);
474 EXPECT_EQ(0xFF, bytes[0x0A]);
475 EXPECT_EQ(0x17, bytes[0x0B]);
476
477 auto writer2 = std::make_unique<
478 Rel32WriterArm<AArch64Rel32Translator::AddrTraits_Immd19>>(translator,
479 region);
480 writer2->PutNext({0x0010U, 0x0000U});
481 EXPECT_EQ(0x85, bytes[0x10]); // 00030010: CBNZ R5,00030000 ; Immd19
482 EXPECT_EQ(0xFF, bytes[0x11]);
483 EXPECT_EQ(0xFF, bytes[0x12]);
484 EXPECT_EQ(0x35, bytes[0x13]);
485 writer2->PutNext({0x0018U, 0x001CU});
486 EXPECT_EQ(0x2A, bytes[0x18]); // 00030018: BGE 0003001C ; Immd19
487 EXPECT_EQ(0x00, bytes[0x19]);
488 EXPECT_EQ(0x00, bytes[0x1A]);
489 EXPECT_EQ(0x54, bytes[0x1B]);
490
491 auto writer3 = std::make_unique<
492 Rel32WriterArm<AArch64Rel32Translator::AddrTraits_Immd14>>(translator,
493 region);
494 writer3->PutNext({0x001CU, 0x0010U});
495 EXPECT_EQ(0xAC, bytes[0x1C]); // 0003001C: TBZ X12,#17,00030010 ; Immd14
496 EXPECT_EQ(0xFF, bytes[0x1D]);
497 EXPECT_EQ(0x8F, bytes[0x1E]);
498 EXPECT_EQ(0x36, bytes[0x1F]);
499 }
500
TEST(Rel32UtilsTest,ArmCopyDisp_AArch64)501 TEST(Rel32UtilsTest, ArmCopyDisp_AArch64) {
502 std::vector<uint8_t> expect_fail;
503
504 // Successful Imm26.
505 ArmCopyDispFun copier_Immd26 =
506 ArmCopyDisp<AArch64Rel32Translator::AddrTraits_Immd26>;
507 CheckCopy({0x12, 0x34, 0x56, 0x94}, // 00000100: BL 0158D148
508 {0xA1, 0xC0, 0x0E, 0x17}, // 00000100: B FC3B0384
509 {0x12, 0x34, 0x56, 0x14}, // 00000100: B 0158D148
510 {0xA1, 0xC0, 0x0E, 0x97}, // 00000100: BL FC3B0384
511 copier_Immd26);
512
513 // Successful Imm19.
514 ArmCopyDispFun copier_Immd19 =
515 ArmCopyDisp<AArch64Rel32Translator::AddrTraits_Immd19>;
516 CheckCopy({0x24, 0x12, 0x34, 0x54}, // 00000100: BMI 00068344
517 {0xD7, 0xA5, 0xFC, 0xB4}, // 00000100: CBZ X23,FFFF95B8
518 {0x37, 0x12, 0x34, 0xB4}, // 00000100: CBZ X23,00068344
519 {0xC4, 0xA5, 0xFC, 0x54}, // 00000100: BMI FFFF95B8
520 copier_Immd19);
521
522 // Successful Imm14.
523 ArmCopyDispFun copier_Immd14 =
524 ArmCopyDisp<AArch64Rel32Translator::AddrTraits_Immd14>;
525 CheckCopy({0x00, 0x00, 0x00, 0x36}, // 00000100: TBZ X0,#0,00000100
526 {0xFF, 0xFF, 0xFF, 0xB7}, // 00000100: TBNZ ZR,#63,000000FC
527 {0x1F, 0x00, 0xF8, 0xB7}, // 00000100: TBNZ ZR,#63,00000100
528 {0xE0, 0xFF, 0x07, 0x36}, // 00000100: TBZ X0,#0,000000FC
529 copier_Immd14);
530
531 // Failure if wrong copier is used.
532 CheckCopy(expect_fail, expect_fail, {0x1F, 0x00, 0xF8, 0xB7},
533 {0xE0, 0xFF, 0x07, 0x36}, copier_Immd26);
534 }
535
536 } // namespace zucchini
537