rel32_utils_unittest.cc 22 KB

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