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