arm_utils_unittest.cc 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. // Copyright 2019 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/arm_utils.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <cctype>
  9. #include <initializer_list>
  10. #include <map>
  11. #include <sstream>
  12. #include <string>
  13. #include <vector>
  14. #include "base/check_op.h"
  15. #include "components/zucchini/address_translator.h"
  16. #include "testing/gtest/include/gtest/gtest.h"
  17. namespace zucchini {
  18. namespace {
  19. // "Clean slate" |code|s for branch instruction encodings with |disp| = 0, and
  20. // if applicable, |cond| = 0.
  21. uint32_t kCleanSlateB_A1 = 0x0A000000; // A24.
  22. uint32_t kCleanSlateBL_A1 = 0x0B000000; // A24.
  23. uint32_t kCleanSlateBLX_A2 = 0xFA000000; // A24.
  24. uint16_t kCleanSlateB_T1 = 0xD000; // T8.
  25. uint16_t kCleanSlateB_T2 = 0xE000; // T11.
  26. uint32_t kCleanSlateB_T3 = 0xF0008000; // T20.
  27. // For T24 encodings, |disp| = 0 means J1 = J2 = 1, so include 0x00002800.
  28. uint32_t kCleanSlateB_T4 = 0xF0009000 | 0x00002800; // T24.
  29. uint32_t kCleanSlateBL_T1 = 0xF000D000 | 0x00002800; // T24.
  30. uint32_t kCleanSlateBLX_T2 = 0xF000C000 | 0x00002800; // T24.
  31. // For AArch64.
  32. uint32_t kCleanSlate64TBZw = 0x36000000; // Immd14.
  33. uint32_t kCleanSlate64TBZz = 0xB6000000; // Immd14.
  34. uint32_t kCleanSlate64TBNZw = 0x37000000; // Immd14.
  35. uint32_t kCleanSlate64TBNZz = 0xB7000000; // Immd14.
  36. uint32_t kCleanSlate64Bcond = 0x54000000; // Immd19.
  37. uint32_t kCleanSlate64CBZw = 0x34000000; // Immd19.
  38. uint32_t kCleanSlate64CBZz = 0xB4000000; // Immd19.
  39. uint32_t kCleanSlate64CBNZw = 0x35000000; // Immd19.
  40. uint32_t kCleanSlate64CBNZz = 0xB5000000; // Immd19.
  41. uint32_t kCleanSlate64B = 0x14000000; // Immd26.
  42. uint32_t kCleanSlate64BL = 0x94000000; // Immd26.
  43. // Special case: Cond = 0xE => AL.
  44. uint32_t kCleanSlateBAL_A1 = kCleanSlateB_A1 | (0xE << 28); //
  45. // Test helper: Extracts |components| from |value| (may be |code| or |disp|)
  46. // based on |pattern|. Also performs consistency checks. On success, writes to
  47. // |*components| and returns true. Otherwise returns false.
  48. // Example (all numbers are in binary):
  49. // |pattern| = "11110Scc cciiiiii 10(J1)0(J2)jjj jjjj...."
  50. // |value| = 11110111 00111000 10 1 0 0 111 11000101
  51. // Result: Noting that all 0's and 1's are consistent, returns true with:
  52. // |*components| = {S: 1, c: 1100, i: 111000, J1: 1, J2: 0, j: 1111100}
  53. // Rules for |pattern|:
  54. // * Spaces are ignored.
  55. // * '.' means "don't care".
  56. // * '0' and '1' are expected literals; mismatch leads to failure.
  57. // * A variable name is specified as:
  58. // * A single letter.
  59. // * "(var)", where "var" is a name that begins with a letter.
  60. // * If a variable's first letter is uppercase, then it's a singleton bit.
  61. // * If repeated, consistency check is applied (must be identical).
  62. // * If a variable's first letter is lowercase, then it spans multiple bits.
  63. // * These need not be contiguous, but order is preserved (big-endian).
  64. static bool SplitBits(const std::string& pattern,
  65. uint32_t value,
  66. std::map<std::string, uint32_t>* components) {
  67. CHECK(components);
  68. // Split |pattern| into |token_list|.
  69. std::vector<std::string> token_list;
  70. size_t bracket_start = std::string::npos;
  71. for (size_t i = 0; i < pattern.size(); ++i) {
  72. char ch = pattern[i];
  73. if (bracket_start == std::string::npos) {
  74. if (ch == '(')
  75. bracket_start = i + 1;
  76. else if (ch != ' ') // Ignore space.
  77. token_list.push_back(std::string(1, ch));
  78. } else if (ch == ')') {
  79. token_list.push_back(pattern.substr(bracket_start, i - bracket_start));
  80. bracket_start = std::string::npos;
  81. }
  82. }
  83. CHECK_EQ(std::string::npos, bracket_start); // No dangling "(".
  84. // Process each token.
  85. size_t num_tokens = token_list.size();
  86. std::map<std::string, uint32_t> temp_components;
  87. CHECK(num_tokens == 32 || (num_tokens == 16 && value <= 0xFFFF));
  88. for (size_t i = 0; i < num_tokens; ++i) {
  89. const std::string& token = token_list[i];
  90. CHECK(!token.empty());
  91. uint32_t bit = (value >> (num_tokens - 1 - i)) & 1;
  92. if (token == "0" || token == "1") {
  93. if (token[0] != static_cast<char>('0' + bit))
  94. return false; // Fail: Mismatch.
  95. } else if (isupper(token[0])) {
  96. if (temp_components.count(token)) {
  97. if (temp_components[token] != bit)
  98. return false; // Fail: Singleton bit not uniform.
  99. } else {
  100. temp_components[token] = bit;
  101. }
  102. } else if (islower(token[0])) {
  103. temp_components[token] = (temp_components[token] << 1) | bit;
  104. } else if (token != ".") {
  105. return false; // Fail: Unrecognized token.
  106. }
  107. }
  108. components->swap(temp_components);
  109. return true;
  110. }
  111. // AArch32 or AArch64 instruction specification for tests. May be 16-bit or
  112. // 32-bit (determined by INT_T).
  113. template <typename INT_T>
  114. struct ArmRelInstruction {
  115. ArmRelInstruction(const std::string& code_pattern_in, INT_T code)
  116. : code_pattern(code_pattern_in), clean_slate_code(code) {}
  117. // Code pattern for SplitBits().
  118. std::string code_pattern;
  119. // "Clean slate" |code| encodes |disp| = 0.
  120. INT_T clean_slate_code;
  121. };
  122. // Tester for ARM Encode / Decode functions for |disp| <-> |code|.
  123. template <typename TRAITS>
  124. class ArmTranslatorEncodeDecodeTest {
  125. public:
  126. using CODE_T = typename TRAITS::code_t;
  127. ArmTranslatorEncodeDecodeTest() {}
  128. // For each instruction (with |clean_slate_code| in |instr_list|) and for each
  129. // |disp| in |good_disp_list|, forms |code| with |encode_fun()| and checks for
  130. // success. Extracts |disp_out| with |decode_fun()| and checks that it's the
  131. // original |disp|. For each (|disp|, |code|) pair, extracts components using
  132. // SplitBits(), and checks that components from |toks_list| are identical. For
  133. // each |disp| in |bad_disp_list|, checks that |decode_fun_()| fails.
  134. void Run(const std::string& disp_pattern,
  135. const std::vector<std::string>& toks_list,
  136. const std::vector<ArmRelInstruction<CODE_T>>& instr_list,
  137. const std::vector<arm_disp_t>& good_disp_list,
  138. const std::vector<arm_disp_t>& bad_disp_list) {
  139. ArmAlign (*decode_fun)(CODE_T, arm_disp_t*) = TRAITS::Decode;
  140. bool (*encode_fun)(arm_disp_t, CODE_T*) = TRAITS::Encode;
  141. for (const ArmRelInstruction<CODE_T> instr : instr_list) {
  142. // Parse clean slate code bytes, and ensure it's well-formed.
  143. std::map<std::string, uint32_t> clean_slate_code_components;
  144. EXPECT_TRUE(SplitBits(instr.code_pattern, instr.clean_slate_code,
  145. &clean_slate_code_components));
  146. for (arm_disp_t disp : good_disp_list) {
  147. CODE_T code = instr.clean_slate_code;
  148. // Encode |disp| to |code|.
  149. EXPECT_TRUE((*encode_fun)(disp, &code)) << disp;
  150. arm_disp_t disp_out = 0;
  151. // Extract components (performs consistency checks) and compare.
  152. std::map<std::string, uint32_t> disp_components;
  153. EXPECT_TRUE(SplitBits(disp_pattern, static_cast<uint32_t>(disp),
  154. &disp_components));
  155. std::map<std::string, uint32_t> code_components;
  156. EXPECT_TRUE(SplitBits(instr.code_pattern, code, &code_components));
  157. for (const std::string& tok : toks_list) {
  158. EXPECT_EQ(1U, disp_components.count(tok)) << tok;
  159. EXPECT_EQ(1U, code_components.count(tok)) << tok;
  160. EXPECT_EQ(disp_components[tok], code_components[tok]) << tok;
  161. }
  162. // Decode |code| to |disp_out|, check fidelity.
  163. EXPECT_NE(kArmAlignFail, (*decode_fun)(code, &disp_out));
  164. EXPECT_EQ(disp, disp_out);
  165. // Sanity check: Re-encode |disp| into |code|, ensure no change.
  166. CODE_T code_copy = code;
  167. EXPECT_TRUE((*encode_fun)(disp, &code));
  168. EXPECT_EQ(code_copy, code);
  169. // Encode 0, ensure we get clean slate |code| back.
  170. EXPECT_TRUE((*encode_fun)(0, &code));
  171. EXPECT_EQ(instr.clean_slate_code, code);
  172. }
  173. for (arm_disp_t disp : bad_disp_list) {
  174. CODE_T code = instr.clean_slate_code;
  175. EXPECT_FALSE((*encode_fun)(disp, &code)) << disp;
  176. // Value does not get modified after failure.
  177. EXPECT_EQ(instr.clean_slate_code, code);
  178. }
  179. }
  180. }
  181. };
  182. // Tester for ARM Write / Read functions for |target_rva| <-> |code|.
  183. template <typename TRAITS>
  184. class ArmTranslatorWriteReadTest {
  185. public:
  186. using CODE_T = typename TRAITS::code_t;
  187. ArmTranslatorWriteReadTest() {}
  188. // Expects successful Write() to |clean_slate_code| for each |target_rva_list|
  189. // RVA, using each |instr_rva_list| RVA, and that the resulting |code| leads
  190. // to successful Read(), which recovers |instr_rva|.
  191. void Accept(CODE_T clean_slate_code,
  192. const std::vector<rva_t>& instr_rva_list,
  193. const std::vector<rva_t>& target_rva_list) {
  194. bool (*read_fun)(rva_t, CODE_T, rva_t*) = TRAITS::Read;
  195. bool (*write_fun)(rva_t, rva_t, CODE_T*) = TRAITS::Write;
  196. for (rva_t instr_rva : instr_rva_list) {
  197. for (rva_t target_rva : target_rva_list) {
  198. CODE_T code = clean_slate_code;
  199. // Write |target_rva| to |code|.
  200. EXPECT_TRUE((*write_fun)(instr_rva, target_rva, &code)) << target_rva;
  201. rva_t target_rva_out = kInvalidRva;
  202. // Read |code| to |target_rva_out|, check fidelity.
  203. EXPECT_TRUE((*read_fun)(instr_rva, code, &target_rva_out));
  204. EXPECT_EQ(target_rva, target_rva_out);
  205. // Sanity check: Rewrite |target_rva| into |code|, ensure no change.
  206. CODE_T code_copy = code;
  207. EXPECT_TRUE((*write_fun)(instr_rva, target_rva, &code));
  208. EXPECT_EQ(code_copy, code);
  209. }
  210. }
  211. }
  212. // Expects failed Write() to |clean_slate_code| for each |target_rva_list|
  213. // RVA, using each |instr_rva_list| RVA.
  214. void Reject(CODE_T clean_slate_code,
  215. const std::vector<rva_t>& instr_rva_list,
  216. const std::vector<rva_t>& target_rva_list) {
  217. bool (*write_fun)(rva_t, rva_t, CODE_T*) = TRAITS::Write;
  218. for (rva_t instr_rva : instr_rva_list) {
  219. for (rva_t target_rva : target_rva_list) {
  220. CODE_T code = clean_slate_code;
  221. EXPECT_FALSE((*write_fun)(instr_rva, target_rva, &code)) << target_rva;
  222. // Output variable is unmodified after failure.
  223. EXPECT_EQ(clean_slate_code, code);
  224. }
  225. }
  226. }
  227. };
  228. } // namespace
  229. // Test for test helper.
  230. TEST(ArmUtilsTest, SplitBits) {
  231. // If |expected| == "BAD" then we expect failure.
  232. auto run_test = [](const std::string& expected, const std::string& pattern,
  233. uint32_t value) {
  234. std::map<std::string, uint32_t> components;
  235. if (expected == "BAD") {
  236. EXPECT_FALSE(SplitBits(pattern, value, &components));
  237. EXPECT_TRUE(components.empty());
  238. } else {
  239. EXPECT_TRUE(SplitBits(pattern, value, &components));
  240. std::ostringstream oss;
  241. // Not using AsHex<>, since number of digits is not fixed.
  242. oss << std::uppercase << std::hex;
  243. std::string sep = "";
  244. for (auto it : components) {
  245. oss << sep << it.first << "=" << it.second;
  246. sep = ",";
  247. }
  248. EXPECT_EQ(expected, oss.str());
  249. }
  250. };
  251. run_test("a=ABCD0123", "aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa", 0xABCD0123);
  252. run_test("a=ABCD,b=123", "aaaaaaaa aaaaaaaa bbbbbbbb bbbbbbbb", 0xABCD0123);
  253. run_test("a=23,b=1,c=CD,d=AB", "dddddddd cccccccc bbbbbbbb aaaaaaaa",
  254. 0xABCD0123);
  255. run_test("", "........ ........ ........ ........", 0xABCD0123);
  256. run_test("t=AC02", " tttt.... tt tt.... tttt....tttt.... ", 0xABCD0123);
  257. run_test("a=8,b=C,c=E,d1=F", "aaaabbbb cccc(d1)(d1)(d1)(d1)", 0x8CEF);
  258. run_test("a=F,b=7,c=3,d1=1", "abc(d1)abc(d1) abc(d1)abc(d1)", 0x8CEF);
  259. run_test("A1=0,X=1", "(A1)XX(A1) X(A1)(A1)(A1) (X)(A1)(X)X(X)(X)X(A1)",
  260. 0x68BE);
  261. run_test("BAD", "(A1)XX(A1) X(A1)(A1)(A1) (X)(A1)(X)X(X)(X)X(A1)", 0x68BF);
  262. run_test("BAD", "(A1)XX(A1) X(A1)(A1)(A1) (X)(A1)(X)X(X)(X)X(A1)", 0x683E);
  263. run_test("A=1,B=0,a=C", "AAAAaaaa BBBB01..", 0xFC06);
  264. run_test("A=1,B=0,a=4", "AAAAaaaa BBBB01..", 0xF406);
  265. run_test("A=0,B=1,a=C", "AAAAaaaa BBBB01..", 0x0CF5);
  266. run_test("BAD", "AAAAaaaa BBBB01..", 0xEC06); // Non-uniform A.
  267. run_test("BAD", "AAAAaaaa BBBB01..", 0xFC16); // Non-uniform B.
  268. run_test("BAD", "AAAAaaaa BBBB01..", 0xFC02); // Constant mismatch.
  269. }
  270. TEST(AArch32Rel32Translator, Fetch) {
  271. std::vector<uint8_t> bytes = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE};
  272. ConstBufferView region(&bytes[0], bytes.size());
  273. AArch32Rel32Translator translator;
  274. EXPECT_EQ(0x76543210U, translator.FetchArmCode32(region, 0U));
  275. EXPECT_EQ(0xFEDCBA98U, translator.FetchArmCode32(region, 4U));
  276. EXPECT_EQ(0x3210U, translator.FetchThumb2Code16(region, 0U));
  277. EXPECT_EQ(0xFEDCU, translator.FetchThumb2Code16(region, 6U));
  278. EXPECT_EQ(0x32107654U, translator.FetchThumb2Code32(region, 0U));
  279. EXPECT_EQ(0xBA98FEDCU, translator.FetchThumb2Code32(region, 4U));
  280. }
  281. TEST(AArch32Rel32Translator, Store) {
  282. std::vector<uint8_t> expected = {
  283. 0xFF, 0xFF, 0xFF, 0xFF, // Padding.
  284. 0x10, 0x32, 0x54, 0x76, // ARM 32-bit.
  285. 0xFF, 0xFF, // Padding.
  286. 0x42, 0x86, // THUMB2 16-bit.
  287. 0xFF, 0xFF, // Padding.
  288. 0xDC, 0xFE, 0x98, 0xBA, // THUMB2 32-bit.
  289. 0xFF, 0xFF, 0xFF, 0xFF // Padding.
  290. };
  291. std::vector<uint8_t> bytes(4 * 2 + 2 * 3 + 4 * 2, 0xFF);
  292. MutableBufferView region(&bytes[0], bytes.size());
  293. CHECK_EQ(expected.size(), bytes.size());
  294. AArch32Rel32Translator translator;
  295. translator.StoreArmCode32(region, 4U, 0x76543210U);
  296. translator.StoreThumb2Code16(region, 10U, 0x8642U);
  297. translator.StoreThumb2Code32(region, 14U, 0xFEDCBA98U);
  298. EXPECT_EQ(expected, bytes);
  299. }
  300. // Detailed test of Encode/Decode: Check valid and invalid |disp| for various
  301. // clean slate |code| cases. Also check |disp| and |code| binary components,
  302. // which in AArch32Rel32Translator comments.
  303. TEST(AArch32Rel32Translator, EncodeDecode) {
  304. // A24 tests.
  305. ArmTranslatorEncodeDecodeTest<AArch32Rel32Translator::AddrTraits_A24>
  306. test_A24;
  307. for (int cond = 0; cond <= 0x0E; ++cond) {
  308. ArmRelInstruction<uint32_t> B_A1_cond("cccc1010 Siiiiiii iiiiiiii iiiiiiii",
  309. kCleanSlateB_A1 | (cond << 28));
  310. ArmRelInstruction<uint32_t> BL_A1_cond(
  311. "cccc1011 Siiiiiii iiiiiiii iiiiiiii", kCleanSlateBL_A1 | (cond << 28));
  312. test_A24.Run("SSSSSSSi iiiiiiii iiiiiiii iiiiii00", {"S", "i"},
  313. {B_A1_cond, BL_A1_cond},
  314. {0x01FFFFFC, -0x02000000, 0, 4, -4, 0x40, 0x44},
  315. {2, -2, 0x41, 0x42, 0x43, 0x02000000, -0x02000004});
  316. }
  317. // BLX encoding A2, which has 2-byte alignment.
  318. ArmRelInstruction<uint32_t> BLX_A2("1111101H Siiiiiii iiiiiiii iiiiiiii",
  319. kCleanSlateBLX_A2);
  320. test_A24.Run("SSSSSSSi iiiiiiii iiiiiiii iiiiiiH0", {"S", "i", "H"}, {BLX_A2},
  321. {0x01FFFFFC, 0x01FFFFFE, -0x02000000, 0, 2, -2, 4, 0x40, 0x42},
  322. {1, -1, 0x41, 0x43, 0x02000000, -0x02000002});
  323. // T8 tests.
  324. ArmTranslatorEncodeDecodeTest<AArch32Rel32Translator::AddrTraits_T8> test_T8;
  325. for (int cond = 0; cond <= 0x0E; ++cond) {
  326. ArmRelInstruction<uint16_t> B_T1_cond("1101cccc Siiiiiii",
  327. kCleanSlateB_T1 | (cond << 8));
  328. test_T8.Run("SSSSSSSS SSSSSSSS SSSSSSSS iiiiiii0", {"S", "i"}, {B_T1_cond},
  329. {0x00FE, -0x0100, 0, 2, -2, 4, 0x40, 0x42},
  330. {1, -1, 0x41, 0x43, 0x0100, -0x0102});
  331. }
  332. ArmRelInstruction<uint16_t> B_T1_invalid("11011111 ........",
  333. kCleanSlateB_T1 | (0x0F << 8));
  334. test_T8.Run("........ ........ ........ ........", std::vector<std::string>(),
  335. {B_T1_invalid}, std::vector<arm_disp_t>(),
  336. {0x00FE, -0x0100, 0, 2, 4, 0x40, 0x41, 0x0100, -0x0102});
  337. // T11 tests.
  338. ArmTranslatorEncodeDecodeTest<AArch32Rel32Translator::AddrTraits_T11>
  339. test_T11;
  340. ArmRelInstruction<uint16_t> B_T2("11100Sii iiiiiiii", kCleanSlateB_T2);
  341. test_T11.Run("SSSSSSSS SSSSSSSS SSSSSiii iiiiiii0", {"S", "i"}, {B_T2},
  342. {0x07FE, -0x0800, 0, 2, -2, 4, 0x40, 0x42},
  343. {1, -1, 0x41, 0x43, 0x0800, -0x0802});
  344. // T20 tests.
  345. ArmTranslatorEncodeDecodeTest<AArch32Rel32Translator::AddrTraits_T20>
  346. test_T20;
  347. for (int cond = 0; cond <= 0x0E; ++cond) {
  348. ArmRelInstruction<uint32_t> B_T3_cond(
  349. "11110Scc cciiiiii 10(J1)0(J2)jjj jjjjjjjj",
  350. kCleanSlateB_T3 | (cond << 22));
  351. test_T20.Run("SSSSSSSS SSSS(J2)(J1)ii iiiijjjj jjjjjjj0",
  352. {"S", "J2", "J1", "i", "j"}, {B_T3_cond},
  353. {0x000FFFFE, -0x00100000, 0, 2, -2, 4, 0x40, 0x42},
  354. {1, -1, 0x41, 0x43, 0x00100000, -0x00100002});
  355. }
  356. ArmRelInstruction<uint32_t> B_T3_invalid(
  357. "11110.11 11...... 10.0.... ........", kCleanSlateB_T3 | (0x0F << 22));
  358. test_T20.Run("........ ........ ........ ........",
  359. std::vector<std::string>(), {B_T3_invalid},
  360. std::vector<arm_disp_t>(),
  361. {0x000FFFFE, -0x00100000, 0, 2, 4, 0x40, 0x42, 1, 0x41, 0x43,
  362. 0x00100000, -0x00100002});
  363. // T24 tests.
  364. ArmTranslatorEncodeDecodeTest<AArch32Rel32Translator::AddrTraits_T24>
  365. test_T24;
  366. // "Clean slate" means J1 = J2 = 1, so we include 0x00002800.
  367. ArmRelInstruction<uint32_t> B_T4("11110Sii iiiiiiii 10(J1)1(J2)jjj jjjjjjjj",
  368. kCleanSlateB_T4);
  369. ArmRelInstruction<uint32_t> BL_T1("11110Sii iiiiiiii 11(J1)1(J2)jjj jjjjjjjj",
  370. kCleanSlateBL_T1);
  371. test_T24.Run("SSSSSSSS (I1)(I2)iiiiii iiiijjjj jjjjjjj0",
  372. {"S", "i", "j"}, // Skip "J1", "J2", "I1", "I2" checks.
  373. {B_T4, BL_T1},
  374. {0x00FFFFFE, -0x01000000, 0, 2, -2, 4, -4, 0x40, 0x42},
  375. {1, -1, 0x41, 0x43, 0x01000000, -0x01000002});
  376. // For BLX encoding T2, |disp| must be multiple of 4.
  377. ArmRelInstruction<uint32_t> BLX_T2(
  378. "11110Sii iiiiiiii 11(J1)0(J2)jjj jjjjjjj0", kCleanSlateBLX_T2);
  379. test_T24.Run(
  380. "SSSSSSSS (I1)(I2)iiiiii iiiijjjj jjjjjj00",
  381. {"S", "i", "j"}, // Skip "J1", "J2", "I1", "I2" checks.
  382. {BLX_T2}, {0x00FFFFFC, -0x01000000, 0, 4, -4, 0x40},
  383. {1, -1, 2, -2, 0x41, 0x42, 0x43, 0x00FFFFFE, 0x01000000, -0x01000002});
  384. }
  385. TEST(AArch32Rel32Translator, WriteRead) {
  386. std::vector<rva_t> aligned4;
  387. std::vector<rva_t> misaligned4;
  388. std::vector<rva_t> aligned2;
  389. std::vector<rva_t> misaligned2;
  390. for (rva_t rva = 0x1FFC; rva <= 0x2010; ++rva) {
  391. ((rva % 4 == 0) ? aligned4 : misaligned4).push_back(rva);
  392. ((rva % 2 == 0) ? aligned2 : misaligned2).push_back(rva);
  393. }
  394. CHECK_EQ(6U, aligned4.size());
  395. CHECK_EQ(15U, misaligned4.size());
  396. CHECK_EQ(11U, aligned2.size());
  397. CHECK_EQ(10U, misaligned2.size());
  398. // Helpers to convert an instruction's RVA to PC.
  399. auto pcArm = [](rva_t instr_rva) -> rva_t { return instr_rva + 8; };
  400. auto pcThumb2 = [](rva_t instr_rva) -> rva_t { return instr_rva + 4; };
  401. // A24 tests.
  402. ArmTranslatorWriteReadTest<AArch32Rel32Translator::AddrTraits_A24> test_A24;
  403. for (uint32_t clean_slate_code : {kCleanSlateB_A1, kCleanSlateBL_A1}) {
  404. test_A24.Accept(clean_slate_code, aligned4, aligned4);
  405. test_A24.Reject(clean_slate_code, aligned4, misaligned4);
  406. test_A24.Reject(clean_slate_code, misaligned4, aligned4);
  407. test_A24.Reject(clean_slate_code, misaligned4, misaligned4);
  408. // Signed (24 + 2)-bit range, 4-byte aligned: [-0x02000000, 0x01FFFFFC].
  409. test_A24.Accept(clean_slate_code, {0x15000000},
  410. {pcArm(0x13000000), pcArm(0x16FFFFFC)});
  411. test_A24.Reject(clean_slate_code, {0x15000000},
  412. {pcArm(0x13000000 - 4), pcArm(0x16FFFFFC + 4)});
  413. }
  414. // BLX complication: ARM -> THUMB2.
  415. test_A24.Accept(kCleanSlateBLX_A2, aligned4, aligned2);
  416. test_A24.Reject(kCleanSlateBLX_A2, aligned4, misaligned2);
  417. test_A24.Reject(kCleanSlateBLX_A2, misaligned4, aligned2);
  418. test_A24.Reject(kCleanSlateBLX_A2, misaligned4, misaligned2);
  419. test_A24.Accept(kCleanSlateBLX_A2, {0x15000000},
  420. {pcArm(0x13000000), pcArm(0x16FFFFFE)});
  421. test_A24.Reject(kCleanSlateBLX_A2, {0x15000000},
  422. {pcArm(0x13000000 - 4), pcArm(0x13000000 - 2),
  423. pcArm(0x16FFFFFE + 2), pcArm(0x16FFFFFE + 4)});
  424. // T8 tests.
  425. ArmTranslatorWriteReadTest<AArch32Rel32Translator::AddrTraits_T8> test_T8;
  426. test_T8.Accept(kCleanSlateB_T1, aligned2, aligned2);
  427. test_T8.Reject(kCleanSlateB_T1, aligned2, misaligned2);
  428. test_T8.Reject(kCleanSlateB_T1, misaligned2, aligned2);
  429. test_T8.Reject(kCleanSlateB_T1, misaligned2, misaligned2);
  430. // Signed (8 + 1)-bit range, 2-byte aligned: [-0x0100, 0x00FE].
  431. test_T8.Accept(kCleanSlateB_T1, {0x10000500},
  432. {pcThumb2(0x10000400), pcThumb2(0x100005FE)});
  433. test_T8.Reject(kCleanSlateB_T1, {0x10000500},
  434. {pcThumb2(0x10000400 - 2), pcThumb2(0x100005FE + 2)});
  435. // T11 tests.
  436. ArmTranslatorWriteReadTest<AArch32Rel32Translator::AddrTraits_T11> test_T11;
  437. test_T11.Accept(kCleanSlateB_T2, aligned2, aligned2);
  438. test_T11.Reject(kCleanSlateB_T2, aligned2, misaligned2);
  439. test_T11.Reject(kCleanSlateB_T2, misaligned2, aligned2);
  440. test_T11.Reject(kCleanSlateB_T2, misaligned2, misaligned2);
  441. // Signed (11 + 1)-bit range, 2-byte aligned: [-0x0800, 0x07FE].
  442. test_T11.Accept(kCleanSlateB_T2, {0x10003000},
  443. {pcThumb2(0x10002800), pcThumb2(0x100037FE)});
  444. test_T11.Reject(kCleanSlateB_T2, {0x10003000},
  445. {pcThumb2(0x10002800 - 2), pcThumb2(0x100037FE + 2)});
  446. // T20 tests.
  447. ArmTranslatorWriteReadTest<AArch32Rel32Translator::AddrTraits_T20> test_T20;
  448. test_T20.Accept(kCleanSlateB_T3, aligned2, aligned2);
  449. test_T20.Reject(kCleanSlateB_T3, aligned2, misaligned2);
  450. test_T20.Reject(kCleanSlateB_T3, misaligned2, aligned2);
  451. test_T20.Reject(kCleanSlateB_T3, misaligned2, misaligned2);
  452. // Signed (20 + 1)-bit range, 2-byte aligned: [-0x00100000, 0x000FFFFE].
  453. test_T20.Accept(kCleanSlateB_T3, {0x10300000},
  454. {pcThumb2(0x10200000), pcThumb2(0x103FFFFE)});
  455. test_T20.Reject(kCleanSlateB_T3, {0x10300000},
  456. {pcThumb2(0x10200000 - 2), pcThumb2(0x103FFFFE + 2)});
  457. // T24 tests.
  458. ArmTranslatorWriteReadTest<AArch32Rel32Translator::AddrTraits_T24> test_T24;
  459. for (uint32_t clean_slate_code : {kCleanSlateB_T4, kCleanSlateBL_T1}) {
  460. test_T24.Accept(clean_slate_code, aligned2, aligned2);
  461. test_T24.Reject(clean_slate_code, aligned2, misaligned2);
  462. test_T24.Reject(clean_slate_code, misaligned2, aligned2);
  463. test_T24.Reject(clean_slate_code, misaligned2, misaligned2);
  464. // Signed (24 + 1)-bit range, 2-byte aligned: [-0x01000000, 0x00FFFFFE].
  465. test_T24.Accept(clean_slate_code, {0x16000000},
  466. {pcThumb2(0x15000000), pcThumb2(0x16FFFFFE)});
  467. test_T24.Reject(clean_slate_code, {0x16000000},
  468. {pcThumb2(0x15000000 - 2), pcThumb2(0x16FFFFFE + 2)});
  469. }
  470. // BLX complication: THUMB2 -> ARM.
  471. test_T24.Accept(kCleanSlateBLX_T2, aligned2, aligned4);
  472. test_T24.Reject(kCleanSlateBLX_T2, aligned2, misaligned4);
  473. test_T24.Reject(kCleanSlateBLX_T2, misaligned2, aligned4);
  474. test_T24.Reject(kCleanSlateBLX_T2, misaligned2, misaligned4);
  475. test_T24.Accept(kCleanSlateBLX_T2, {0x16000000},
  476. {pcThumb2(0x15000000), pcThumb2(0x16FFFFFC)});
  477. test_T24.Reject(kCleanSlateBLX_T2, {0x16000000},
  478. {pcThumb2(0x15000000 - 4), pcThumb2(0x15000000 - 2),
  479. pcThumb2(0x16FFFFFC + 2), pcThumb2(0x16FFFFFC + 4)});
  480. }
  481. // Typical usage in |target_rva| extraction.
  482. TEST(AArch32Rel32Translator, Main) {
  483. // ARM mode (32-bit).
  484. // 00103050: 00 01 02 EA B 00183458 ; B encoding A1 (cond = AL).
  485. {
  486. rva_t instr_rva = 0x00103050U;
  487. AArch32Rel32Translator translator;
  488. std::vector<uint8_t> bytes = {0x00, 0x01, 0x02, 0xEA};
  489. MutableBufferView region(&bytes[0], bytes.size());
  490. uint32_t code = translator.FetchArmCode32(region, 0U);
  491. EXPECT_EQ(0xEA020100U, code);
  492. // |code| <-> |disp|.
  493. arm_disp_t disp = 0;
  494. EXPECT_EQ(kArmAlign4, translator.DecodeA24(code, &disp));
  495. EXPECT_EQ(+0x00080400, disp);
  496. uint32_t code_from_disp = kCleanSlateBAL_A1;
  497. EXPECT_TRUE(translator.EncodeA24(disp, &code_from_disp));
  498. EXPECT_EQ(code, code_from_disp);
  499. // |code| <-> |target_rva|.
  500. rva_t target_rva = kInvalidRva;
  501. EXPECT_TRUE(translator.ReadA24(instr_rva, code, &target_rva));
  502. // 0x00103050 + 8 + 0x00080400.
  503. EXPECT_EQ(0x00183458U, target_rva);
  504. uint32_t code_from_rva = kCleanSlateBAL_A1;
  505. EXPECT_TRUE(translator.WriteA24(instr_rva, target_rva, &code_from_rva));
  506. EXPECT_EQ(code, code_from_rva);
  507. }
  508. // THUMB2 mode (16-bit).
  509. // 001030A2: F3 E7 B 0010308C ; B encoding T2.
  510. {
  511. rva_t instr_rva = 0x001030A2U;
  512. AArch32Rel32Translator translator;
  513. std::vector<uint8_t> bytes = {0xF3, 0xE7};
  514. MutableBufferView region(&bytes[0], bytes.size());
  515. uint16_t code = translator.FetchThumb2Code16(region, 0U);
  516. // Sii iiiiiiii = 111 11110011 = -1101 = -0x0D.
  517. EXPECT_EQ(0xE7F3U, code);
  518. // |code| <-> |disp|.
  519. arm_disp_t disp = 0;
  520. EXPECT_EQ(kArmAlign2, translator.DecodeT11(code, &disp));
  521. EXPECT_EQ(-0x0000001A, disp); // -0x0D * 2 = -0x1A.
  522. uint16_t code_from_disp = kCleanSlateB_T2;
  523. EXPECT_TRUE(translator.EncodeT11(disp, &code_from_disp));
  524. EXPECT_EQ(code, code_from_disp);
  525. // |code| <-> |target_rva|.
  526. rva_t target_rva = kInvalidRva;
  527. EXPECT_TRUE(translator.ReadT11(instr_rva, code, &target_rva));
  528. // 0x001030A2 + 4 - 0x0000001A.
  529. EXPECT_EQ(0x0010308CU, target_rva);
  530. uint16_t code_from_rva = kCleanSlateB_T2;
  531. EXPECT_TRUE(translator.WriteT11(instr_rva, target_rva, &code_from_rva));
  532. EXPECT_EQ(code, code_from_rva);
  533. }
  534. // THUMB2 mode (32-bit).
  535. // 001030A2: 00 F0 01 FA BL 001034A8 ; BL encoding T1.
  536. {
  537. rva_t instr_rva = 0x001030A2U;
  538. AArch32Rel32Translator translator;
  539. std::vector<uint8_t> bytes = {0x00, 0xF0, 0x01, 0xFA};
  540. MutableBufferView region(&bytes[0], bytes.size());
  541. uint32_t code = translator.FetchThumb2Code32(region, 0U);
  542. EXPECT_EQ(0xF000FA01U, code);
  543. // |code| <-> |disp|.
  544. arm_disp_t disp = 0;
  545. EXPECT_EQ(kArmAlign2, translator.DecodeT24(code, &disp));
  546. EXPECT_EQ(+0x00000402, disp);
  547. uint32_t code_from_disp = kCleanSlateBL_T1;
  548. EXPECT_TRUE(translator.EncodeT24(disp, &code_from_disp));
  549. EXPECT_EQ(code, code_from_disp);
  550. // |code| <-> |target_rva|.
  551. rva_t target_rva = kInvalidRva;
  552. EXPECT_TRUE(translator.ReadT24(instr_rva, code, &target_rva));
  553. // 0x001030A2 + 4 + 0x00000002.
  554. EXPECT_EQ(0x001034A8U, target_rva);
  555. uint32_t code_from_rva = kCleanSlateBL_T1;
  556. EXPECT_TRUE(translator.WriteT24(instr_rva, target_rva, &code_from_rva));
  557. EXPECT_EQ(code, code_from_rva);
  558. }
  559. }
  560. TEST(AArch32Rel32Translator, BLXComplication) {
  561. auto run_test = [](rva_t instr_rva,
  562. std::vector<uint8_t> bytes, // Pass by value.
  563. uint32_t expected_code, arm_disp_t expected_disp,
  564. uint32_t clean_slate_code, rva_t expected_target_rva) {
  565. AArch32Rel32Translator translator;
  566. MutableBufferView region(&bytes[0], bytes.size());
  567. uint32_t code = translator.FetchThumb2Code32(region, 0U);
  568. EXPECT_EQ(expected_code, code);
  569. // |code| <-> |disp|.
  570. arm_disp_t disp = 0;
  571. EXPECT_TRUE(translator.DecodeT24(code, &disp));
  572. EXPECT_EQ(expected_disp, disp);
  573. uint32_t code_from_disp = clean_slate_code;
  574. EXPECT_TRUE(translator.EncodeT24(disp, &code_from_disp));
  575. EXPECT_EQ(code, code_from_disp);
  576. // |code| <-> |target_rva|.
  577. rva_t target_rva = kInvalidRva;
  578. EXPECT_TRUE(translator.ReadT24(instr_rva, code, &target_rva));
  579. EXPECT_EQ(expected_target_rva, target_rva);
  580. uint32_t code_from_rva = clean_slate_code;
  581. EXPECT_TRUE(translator.WriteT24(instr_rva, target_rva, &code_from_rva));
  582. EXPECT_EQ(code, code_from_rva);
  583. };
  584. // No complication, 4-byte aligned.
  585. // 001030A0: 01 F0 06 B0 B 005040B0 ; B encoding T4.
  586. run_test(0x001030A0U, // Multiple of 4.
  587. {0x01, 0xF0, 0x06, 0xB0}, 0xF001B006U, 0x0040100C, kCleanSlateB_T4,
  588. // "Canonical" |target_rva|: 0x001030A0 + 4 + 0x0040100C.
  589. 0x005040B0U);
  590. // No complication, not 4-byte aligned.
  591. // 001030A2: 01 F0 06 B0 B 005040B2 ; B encoding T4.
  592. run_test(0x001030A2U, // Shift by 2: Not multiple of 4.
  593. {0x01, 0xF0, 0x06, 0xB0}, 0xF001B006U, 0x0040100C, kCleanSlateB_T4,
  594. // Shifted by 2: 0x001030A2 + 4 + 0x0040100C.
  595. 0x005040B2U);
  596. // Repeat the above, but use BLX instead of B.
  597. // BLX complication, 4-byte aligned.
  598. // 001030A0: 01 F0 06 E0 BLX 005040B0 ; BLX encoding T2.
  599. run_test(0x001030A0U, // Multiple of 4.
  600. {0x01, 0xF0, 0x06, 0xE0}, 0xF001E006U, 0x0040100C, kCleanSlateBLX_T2,
  601. // Canonical again: align_down_4(0x001030A0 + 4 + 0x0040100C).
  602. 0x005040B0U);
  603. // BLX complication, not 4-byte aligned.
  604. // 001030A2: 01 F0 06 E0 BLX 005040B0 ; BLX encoding T2.
  605. run_test(0x001030A2U, // Shift by 2: Not multiple of 4.
  606. {0x01, 0xF0, 0x06, 0xE0}, 0xF001E006U, 0x0040100C, kCleanSlateBLX_T2,
  607. // No shift: align_down_4(0x001030A2 + 4 + 0x0040100C).
  608. 0x005040B0U);
  609. }
  610. TEST(AArch64Rel32Translator, FetchStore) {
  611. std::vector<uint8_t> bytes = {0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE};
  612. std::vector<uint8_t> expected = {0xAB, 0x33, 0x22, 0x11,
  613. 0x69, 0x5A, 0xFF, 0x00};
  614. MutableBufferView region(&bytes[0], bytes.size());
  615. AArch64Rel32Translator translator;
  616. EXPECT_EQ(0x76543210U, translator.FetchCode32(region, 0U));
  617. EXPECT_EQ(0xFEDCBA98U, translator.FetchCode32(region, 4U));
  618. translator.StoreCode32(region, 0U, 0x112233ABU);
  619. translator.StoreCode32(region, 4U, 0x00FF5A69);
  620. EXPECT_EQ(expected, bytes);
  621. }
  622. TEST(AArch64Rel32Translator, EncodeDecode) {
  623. // Immd14 tests.
  624. ArmTranslatorEncodeDecodeTest<AArch64Rel32Translator::AddrTraits_Immd14>
  625. test_immd14;
  626. for (int b40 : {0, 1, 7, 31}) {
  627. uint32_t b40_mask = b40 << 19;
  628. for (int Rt : {0, 1, 15, 30}) {
  629. uint32_t mask = b40_mask | Rt;
  630. ArmRelInstruction<uint32_t> TBZw_Rt("00110110 bbbbbSii iiiiiiii iiittttt",
  631. kCleanSlate64TBZw | mask);
  632. ArmRelInstruction<uint32_t> TBZz_Rt("10110110 bbbbbSii iiiiiiii iiittttt",
  633. kCleanSlate64TBZz | mask);
  634. ArmRelInstruction<uint32_t> TBNZw_Rt(
  635. "00110111 bbbbbSii iiiiiiii iiittttt", kCleanSlate64TBNZw | mask);
  636. ArmRelInstruction<uint32_t> TBNZz_Rt(
  637. "10110111 bbbbbSii iiiiiiii iiittttt", kCleanSlate64TBNZz | mask);
  638. test_immd14.Run("SSSSSSSS SSSSSSSS Siiiiiii iiiiii00", {"S", "i"},
  639. {TBZw_Rt, TBZz_Rt, TBNZw_Rt, TBNZz_Rt},
  640. {0x00007FFC, -0x00008000, 0, 4, -4, 0x40, 0x44},
  641. {2, -2, 0x41, 0x42, 0x43, 0x00008000, -0x00008004});
  642. }
  643. }
  644. // Immd19 tests.
  645. ArmTranslatorEncodeDecodeTest<AArch64Rel32Translator::AddrTraits_Immd19>
  646. test_immd19;
  647. for (int cond = 0; cond <= 0x0E; ++cond) {
  648. ArmRelInstruction<uint32_t> B_cond("01010100 Siiiiiii iiiiiiii iii0cccc",
  649. kCleanSlate64Bcond | cond);
  650. test_immd19.Run("SSSSSSSS SSSSiiii iiiiiiii iiiiii00", {"S", "i"}, {B_cond},
  651. {0x000FFFFC, -0x00100000, 0, 4, -4, 0x40, 0x44},
  652. {2, -2, 0x41, 0x42, 0x43, 0x00100000, -0x00100004});
  653. }
  654. for (int Rt : {0, 1, 15, 30}) {
  655. ArmRelInstruction<uint32_t> CBZw_Rt("00110100 Siiiiiii iiiiiiii iiittttt",
  656. kCleanSlate64CBZw | Rt);
  657. ArmRelInstruction<uint32_t> CBZz_Rt("10110100 Siiiiiii iiiiiiii iiittttt",
  658. kCleanSlate64CBZz | Rt);
  659. ArmRelInstruction<uint32_t> CBNZw_Rt("00110101 Siiiiiii iiiiiiii iiittttt",
  660. kCleanSlate64CBNZw | Rt);
  661. ArmRelInstruction<uint32_t> CBNZz_Rt("10110101 Siiiiiii iiiiiiii iiittttt",
  662. kCleanSlate64CBNZz | Rt);
  663. test_immd19.Run("SSSSSSSS SSSSiiii iiiiiiii iiiiii00", {"S", "i"},
  664. {CBZw_Rt, CBZz_Rt, CBNZw_Rt, CBNZz_Rt},
  665. {0x000FFFFC, -0x00100000, 0, 4, -4, 0x40, 0x44},
  666. {2, -2, 0x41, 0x42, 0x43, 0x00100000, -0x00100004});
  667. }
  668. // Immd26 tests.
  669. ArmTranslatorEncodeDecodeTest<AArch64Rel32Translator::AddrTraits_Immd26>
  670. test_immd26;
  671. ArmRelInstruction<uint32_t> B("000101Si iiiiiiii iiiiiiii iiiiiiii",
  672. kCleanSlate64B);
  673. ArmRelInstruction<uint32_t> BL("100101Si iiiiiiii iiiiiiii iiiiiiii",
  674. kCleanSlate64BL);
  675. test_immd26.Run("SSSSSiii iiiiiiii iiiiiiii iiiiii00", {"S", "i"}, {B, BL},
  676. {0x07FFFFFC, -0x08000000, 0, 4, -4, 0x40, 0x44},
  677. {2, -2, 0x41, 0x42, 0x43, 0x08000000, -0x08000004});
  678. }
  679. TEST(AArch64Rel32Translator, WriteRead) {
  680. std::vector<rva_t> aligned4;
  681. std::vector<rva_t> misaligned4;
  682. for (rva_t rva = 0x1FFC; rva <= 0x2010; ++rva) {
  683. ((rva % 4 == 0) ? aligned4 : misaligned4).push_back(rva);
  684. }
  685. CHECK_EQ(6U, aligned4.size());
  686. CHECK_EQ(15U, misaligned4.size());
  687. // Helper to convert an instruction's RVA to PC.
  688. auto pcAArch64 = [](rva_t instr_rva) -> rva_t { return instr_rva; };
  689. // Immd14 tests.
  690. ArmTranslatorWriteReadTest<AArch64Rel32Translator::AddrTraits_Immd14>
  691. test_immd14;
  692. for (uint32_t clean_slate_code : {kCleanSlate64TBZw, kCleanSlate64TBZz,
  693. kCleanSlate64TBNZw, kCleanSlate64TBNZz}) {
  694. test_immd14.Accept(clean_slate_code, aligned4, aligned4);
  695. test_immd14.Reject(clean_slate_code, aligned4, misaligned4);
  696. test_immd14.Reject(clean_slate_code, misaligned4, aligned4);
  697. test_immd14.Reject(clean_slate_code, misaligned4, misaligned4);
  698. // Signed (14 + 2)-bit range, 4-byte aligned: [-0x00008000, 0x00007FFC].
  699. test_immd14.Accept(clean_slate_code, {0x10040000},
  700. {pcAArch64(0x10038000), pcAArch64(0x10047FFC)});
  701. test_immd14.Reject(clean_slate_code, {0x15000000},
  702. {pcAArch64(0x10038000 - 4), pcAArch64(0x10047FFC + 4)});
  703. }
  704. // Immd19 tests.
  705. ArmTranslatorWriteReadTest<AArch64Rel32Translator::AddrTraits_Immd19>
  706. test_immd19;
  707. for (uint32_t clean_slate_code :
  708. {kCleanSlate64Bcond, kCleanSlate64CBZw, kCleanSlate64CBZz,
  709. kCleanSlate64CBNZw, kCleanSlate64CBNZz}) {
  710. test_immd19.Accept(clean_slate_code, aligned4, aligned4);
  711. test_immd19.Reject(clean_slate_code, aligned4, misaligned4);
  712. test_immd19.Reject(clean_slate_code, misaligned4, aligned4);
  713. test_immd19.Reject(clean_slate_code, misaligned4, misaligned4);
  714. // Signed (19 + 2)-bit range, 4-byte aligned: [-0x00100000, 0x000FFFFC].
  715. test_immd19.Accept(clean_slate_code, {0x10300000},
  716. {pcAArch64(0x10200000), pcAArch64(0x103FFFFC)});
  717. test_immd19.Reject(clean_slate_code, {0x10300000},
  718. {pcAArch64(0x10200000 - 4), pcAArch64(0x103FFFFC + 4)});
  719. }
  720. // Immd26 tests.
  721. ArmTranslatorWriteReadTest<AArch64Rel32Translator::AddrTraits_Immd26>
  722. test_immd26;
  723. for (uint32_t clean_slate_code : {kCleanSlate64B, kCleanSlate64BL}) {
  724. test_immd26.Accept(clean_slate_code, aligned4, aligned4);
  725. test_immd26.Reject(clean_slate_code, aligned4, misaligned4);
  726. test_immd26.Reject(clean_slate_code, misaligned4, aligned4);
  727. test_immd26.Reject(clean_slate_code, misaligned4, misaligned4);
  728. // Signed (26 + 2)-bit range, 4-byte aligned: [-0x08000000, 0x07FFFFFC].
  729. test_immd26.Accept(clean_slate_code, {0x30000000},
  730. {pcAArch64(0x28000000), pcAArch64(0x37FFFFFC)});
  731. test_immd26.Reject(clean_slate_code, {0x30000000},
  732. {pcAArch64(0x28000000 - 4), pcAArch64(0x37FFFFFC + 4)});
  733. }
  734. }
  735. // Typical usage in |target_rva| extraction.
  736. TEST(AArch64Rel32Translator, Main) {
  737. // 00103050: 02 01 02 14 B 00183458
  738. rva_t instr_rva = 0x00103050U;
  739. AArch64Rel32Translator translator;
  740. std::vector<uint8_t> bytes = {0x02, 0x01, 0x02, 0x14};
  741. MutableBufferView region(&bytes[0], bytes.size());
  742. uint32_t code = translator.FetchCode32(region, 0U);
  743. EXPECT_EQ(0x14020102U, code);
  744. // |code| <-> |disp|.
  745. arm_disp_t disp = 0;
  746. EXPECT_TRUE(translator.DecodeImmd26(code, &disp));
  747. EXPECT_EQ(+0x00080408, disp);
  748. uint32_t code_from_disp = kCleanSlate64B;
  749. EXPECT_TRUE(translator.EncodeImmd26(disp, &code_from_disp));
  750. EXPECT_EQ(code, code_from_disp);
  751. // |code| <-> |target_rva|.
  752. rva_t target_rva = kInvalidRva;
  753. EXPECT_TRUE(translator.ReadImmd26(instr_rva, code, &target_rva));
  754. // 0x00103050 + 0 + 0x00080408.
  755. EXPECT_EQ(0x00183458U, target_rva);
  756. uint32_t code_from_rva = kCleanSlate64B;
  757. EXPECT_TRUE(translator.WriteImmd26(instr_rva, target_rva, &code_from_rva));
  758. EXPECT_EQ(code, code_from_rva);
  759. }
  760. } // namespace zucchini