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