rel32_finder_unittest.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  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_finder.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <deque>
  9. #include <iterator>
  10. #include <string>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/check_op.h"
  14. #include "base/format_macros.h"
  15. #include "base/numerics/safe_conversions.h"
  16. #include "base/strings/stringprintf.h"
  17. #include "components/zucchini/arm_utils.h"
  18. #include "components/zucchini/buffer_view.h"
  19. #include "components/zucchini/disassembler_elf.h"
  20. #include "components/zucchini/image_utils.h"
  21. #include "testing/gtest/include/gtest/gtest.h"
  22. namespace zucchini {
  23. TEST(Abs32GapFinderTest, All) {
  24. const size_t kRegionTotal = 99;
  25. std::vector<uint8_t> buffer(kRegionTotal);
  26. ConstBufferView image(buffer.data(), buffer.size());
  27. // Common test code that returns the resulting segments as a string.
  28. auto run_test = [&](size_t rlo, size_t rhi,
  29. std::deque<offset_t> abs32_locations,
  30. std::ptrdiff_t abs32_width) -> std::string {
  31. CHECK_LE(rlo, kRegionTotal);
  32. CHECK_LE(rhi, kRegionTotal);
  33. CHECK(std::is_sorted(abs32_locations.begin(), abs32_locations.end()));
  34. CHECK_GT(abs32_width, 0);
  35. ConstBufferView region =
  36. ConstBufferView::FromRange(image.begin() + rlo, image.begin() + rhi);
  37. Abs32GapFinder gap_finder(image, region, abs32_locations, abs32_width);
  38. std::string out_str;
  39. while (gap_finder.FindNext()) {
  40. ConstBufferView gap = gap_finder.GetGap();
  41. size_t lo = base::checked_cast<size_t>(gap.begin() - image.begin());
  42. size_t hi = base::checked_cast<size_t>(gap.end() - image.begin());
  43. out_str.append(base::StringPrintf("[%" PRIuS ",%" PRIuS ")", lo, hi));
  44. }
  45. return out_str;
  46. };
  47. // Empty regions yield empty segments.
  48. EXPECT_EQ("", run_test(0, 0, {}, 4));
  49. EXPECT_EQ("", run_test(9, 9, {}, 4));
  50. EXPECT_EQ("", run_test(8, 8, {8}, 4));
  51. EXPECT_EQ("", run_test(8, 8, {0, 12}, 4));
  52. // If no abs32 locations exist then the segment is the main range.
  53. EXPECT_EQ("[0,99)", run_test(0, 99, {}, 4));
  54. EXPECT_EQ("[20,21)", run_test(20, 21, {}, 4));
  55. EXPECT_EQ("[51,55)", run_test(51, 55, {}, 4));
  56. // abs32 locations found near start of main range.
  57. EXPECT_EQ("[10,20)", run_test(10, 20, {5}, 4));
  58. EXPECT_EQ("[10,20)", run_test(10, 20, {6}, 4));
  59. EXPECT_EQ("[11,20)", run_test(10, 20, {7}, 4));
  60. EXPECT_EQ("[12,20)", run_test(10, 20, {8}, 4));
  61. EXPECT_EQ("[13,20)", run_test(10, 20, {9}, 4));
  62. EXPECT_EQ("[14,20)", run_test(10, 20, {10}, 4));
  63. EXPECT_EQ("[10,11)[15,20)", run_test(10, 20, {11}, 4));
  64. // abs32 locations found near end of main range.
  65. EXPECT_EQ("[10,15)[19,20)", run_test(10, 20, {15}, 4));
  66. EXPECT_EQ("[10,16)", run_test(10, 20, {16}, 4));
  67. EXPECT_EQ("[10,17)", run_test(10, 20, {17}, 4));
  68. EXPECT_EQ("[10,18)", run_test(10, 20, {18}, 4));
  69. EXPECT_EQ("[10,19)", run_test(10, 20, {19}, 4));
  70. EXPECT_EQ("[10,20)", run_test(10, 20, {20}, 4));
  71. EXPECT_EQ("[10,20)", run_test(10, 20, {21}, 4));
  72. // Main range completely eclipsed by abs32 location.
  73. EXPECT_EQ("", run_test(10, 11, {7}, 4));
  74. EXPECT_EQ("", run_test(10, 11, {8}, 4));
  75. EXPECT_EQ("", run_test(10, 11, {9}, 4));
  76. EXPECT_EQ("", run_test(10, 11, {10}, 4));
  77. EXPECT_EQ("", run_test(10, 12, {8}, 4));
  78. EXPECT_EQ("", run_test(10, 12, {9}, 4));
  79. EXPECT_EQ("", run_test(10, 12, {10}, 4));
  80. EXPECT_EQ("", run_test(10, 13, {9}, 4));
  81. EXPECT_EQ("", run_test(10, 13, {10}, 4));
  82. EXPECT_EQ("", run_test(10, 14, {10}, 4));
  83. EXPECT_EQ("", run_test(10, 14, {8, 12}, 4));
  84. // Partial eclipses.
  85. EXPECT_EQ("[24,25)", run_test(20, 25, {20}, 4));
  86. EXPECT_EQ("[20,21)", run_test(20, 25, {21}, 4));
  87. EXPECT_EQ("[20,21)[25,26)", run_test(20, 26, {21}, 4));
  88. // abs32 location outside main range.
  89. EXPECT_EQ("[40,60)", run_test(40, 60, {36, 60}, 4));
  90. EXPECT_EQ("[41,61)", run_test(41, 61, {0, 10, 20, 30, 34, 62, 68, 80}, 4));
  91. // Change abs32 width.
  92. EXPECT_EQ("[10,11)[12,14)[16,19)", run_test(10, 20, {9, 11, 14, 15, 19}, 1));
  93. EXPECT_EQ("", run_test(10, 11, {10}, 1));
  94. EXPECT_EQ("[18,23)[29,31)", run_test(17, 31, {15, 23, 26, 31}, 3));
  95. EXPECT_EQ("[17,22)[25,26)[29,30)", run_test(17, 31, {14, 22, 26, 30}, 3));
  96. EXPECT_EQ("[10,11)[19,20)", run_test(10, 20, {11}, 8));
  97. // Mixed cases with abs32 width = 4.
  98. EXPECT_EQ("[10,15)[19,20)[24,25)", run_test(8, 25, {2, 6, 15, 20, 27}, 4));
  99. EXPECT_EQ("[0,25)[29,45)[49,50)", run_test(0, 50, {25, 45}, 4));
  100. EXPECT_EQ("[10,20)[28,50)", run_test(10, 50, {20, 24}, 4));
  101. EXPECT_EQ("[49,50)[54,60)[64,70)[74,80)[84,87)",
  102. run_test(49, 87, {10, 20, 30, 40, 50, 60, 70, 80, 90}, 4));
  103. EXPECT_EQ("[0,10)[14,20)[24,25)[29,50)", run_test(0, 50, {10, 20, 25}, 4));
  104. }
  105. namespace {
  106. // A mock Rel32Finder to inject next search result on Scan().
  107. class TestRel32Finder : public Rel32Finder {
  108. public:
  109. using Rel32Finder::Rel32Finder;
  110. // Rel32Finder:
  111. NextIterators Scan(ConstBufferView region) override { return next_result; }
  112. NextIterators next_result;
  113. };
  114. AddressTranslator GetTrivialTranslator(size_t size) {
  115. AddressTranslator translator;
  116. EXPECT_EQ(AddressTranslator::kSuccess,
  117. translator.Initialize({{0, base::checked_cast<offset_t>(size), 0U,
  118. base::checked_cast<rva_t>(size)}}));
  119. return translator;
  120. }
  121. } // namespace
  122. TEST(Rel32FinderTest, Scan) {
  123. const size_t kRegionTotal = 99;
  124. std::vector<uint8_t> buffer(kRegionTotal);
  125. ConstBufferView image(buffer.data(), buffer.size());
  126. AddressTranslator translator(GetTrivialTranslator(image.size()));
  127. TestRel32Finder finder(image, translator);
  128. finder.SetRegion(image);
  129. auto check_finder_state = [&](const TestRel32Finder& finder,
  130. size_t expected_cursor,
  131. size_t expected_accept_it) {
  132. CHECK_LE(expected_cursor, kRegionTotal);
  133. CHECK_LE(expected_accept_it, kRegionTotal);
  134. EXPECT_EQ(image.begin() + expected_cursor, finder.region().begin());
  135. EXPECT_EQ(image.begin() + expected_accept_it, finder.accept_it());
  136. };
  137. check_finder_state(finder, 0, 0);
  138. finder.next_result = {image.begin() + 1, image.begin() + 1};
  139. EXPECT_TRUE(finder.FindNext());
  140. check_finder_state(finder, 1, 1);
  141. finder.next_result = {image.begin() + 2, image.begin() + 2};
  142. EXPECT_TRUE(finder.FindNext());
  143. check_finder_state(finder, 2, 2);
  144. finder.next_result = {image.begin() + 5, image.begin() + 6};
  145. EXPECT_TRUE(finder.FindNext());
  146. check_finder_state(finder, 5, 6);
  147. finder.Accept();
  148. check_finder_state(finder, 6, 6);
  149. finder.next_result = {image.begin() + 7, image.begin() + 7};
  150. EXPECT_TRUE(finder.FindNext());
  151. check_finder_state(finder, 7, 7);
  152. finder.next_result = {image.begin() + 8, image.begin() + 8};
  153. EXPECT_TRUE(finder.FindNext());
  154. check_finder_state(finder, 8, 8);
  155. finder.next_result = {image.begin() + 99, image.begin() + 99};
  156. EXPECT_TRUE(finder.FindNext());
  157. check_finder_state(finder, 99, 99);
  158. finder.next_result = {nullptr, nullptr};
  159. EXPECT_FALSE(finder.FindNext());
  160. check_finder_state(finder, 99, 99);
  161. }
  162. namespace {
  163. // X86 test data. (x) and +x entries are covered by abs32 references, which have
  164. // width = 4.
  165. constexpr uint8_t kDataX86[] = {
  166. 0x55, // 00: push ebp
  167. 0x8B, 0xEC, // 01: mov ebp,esp
  168. 0xE8, 0, 0, 0, 0, // 03: call 08
  169. (0xE9), +0, +0, +0, 0, // 08: jmp 0D
  170. 0x0F, 0x80, 0, 0, 0, 0, // 0D: jo 13
  171. 0x0F, 0x81, 0, 0, (0), +0, // 13: jno 19
  172. +0x0F, +0x82, 0, 0, 0, 0, // 19: jb 1F
  173. 0x0F, 0x83, 0, 0, 0, 0, // 1F: jae 25
  174. 0x0F, (0x84), +0, +0, +0, (0), // 25: je 2B
  175. +0x0F, +0x85, +0, 0, 0, 0, // 2B: jne 31
  176. 0x0F, 0x86, 0, 0, 0, 0, // 31: jbe 37
  177. 0x0F, 0x87, 0, 0, 0, 0, // 37: ja 3D
  178. 0x0F, 0x88, 0, (0), +0, +0, // 3D: js 43
  179. +0x0F, 0x89, 0, 0, 0, 0, // 43: jns 49
  180. 0x0F, 0x8A, 0, 0, 0, 0, // 49: jp 4F
  181. 0x0F, 0x8B, (0), +0, +0, +0, // 4F: jnp 55
  182. 0x0F, 0x8C, 0, 0, 0, 0, // 55: jl 5B
  183. 0x0F, 0x8D, 0, 0, (0), +0, // 5B: jge 61
  184. +0x0F, +0x8E, (0), +0, +0, +0, // 61: jle 67
  185. 0x0F, 0x8F, 0, 0, 0, 0, // 67: jg 6D
  186. 0x5D, // 6D: pop ebp
  187. 0xC3, // C3: ret
  188. };
  189. // Abs32 locations corresponding to |kDataX86|, with width = 4.
  190. constexpr offset_t kAbs32X86[] = {0x08, 0x17, 0x26, 0x2A,
  191. 0x40, 0x51, 0x5F, 0x63};
  192. } // namespace
  193. TEST(Rel32FinderX86Test, FindNext) {
  194. ConstBufferView image =
  195. ConstBufferView::FromRange(std::begin(kDataX86), std::end(kDataX86));
  196. AddressTranslator translator(GetTrivialTranslator(image.size()));
  197. Rel32FinderX86 rel_finder(image, translator);
  198. rel_finder.SetRegion(image);
  199. // List of expected locations as pairs of {cursor offset, rel32 offset},
  200. // ignoring |kAbs32X86|.
  201. std::vector<std::pair<size_t, size_t>> expected_locations = {
  202. {0x04, 0x04}, {0x09, 0x09}, {0x0E, 0x0F}, {0x14, 0x15}, {0x1A, 0x1B},
  203. {0x20, 0x21}, {0x26, 0x27}, {0x2C, 0x2D}, {0x32, 0x33}, {0x38, 0x39},
  204. {0x3E, 0x3F}, {0x44, 0x45}, {0x4A, 0x4B}, {0x50, 0x51}, {0x56, 0x57},
  205. {0x5C, 0x5D}, {0x62, 0x63}, {0x68, 0x69},
  206. };
  207. for (auto location : expected_locations) {
  208. EXPECT_TRUE(rel_finder.FindNext());
  209. auto rel32 = rel_finder.GetRel32();
  210. EXPECT_EQ(location.first,
  211. size_t(rel_finder.region().begin() - image.begin()));
  212. EXPECT_EQ(location.second, rel32.location);
  213. EXPECT_EQ(image.begin() + (rel32.location + 4), rel_finder.accept_it());
  214. EXPECT_FALSE(rel32.can_point_outside_section);
  215. rel_finder.Accept();
  216. }
  217. EXPECT_FALSE(rel_finder.FindNext());
  218. }
  219. TEST(Rel32FinderX86Test, Integrated) {
  220. // Truncated form of Rel32FinderIntel::Result.
  221. using TruncatedResults = std::pair<offset_t, rva_t>;
  222. ConstBufferView image =
  223. ConstBufferView::FromRange(std::begin(kDataX86), std::end(kDataX86));
  224. std::deque<offset_t> abs32_locations(std::begin(kAbs32X86),
  225. std::end(kAbs32X86));
  226. std::vector<TruncatedResults> results;
  227. Abs32GapFinder gap_finder(image, image, abs32_locations,
  228. DisassemblerElfX86::Traits::kVAWidth);
  229. AddressTranslator translator(GetTrivialTranslator(image.size()));
  230. Rel32FinderX86 rel_finder(image, translator);
  231. while (gap_finder.FindNext()) {
  232. rel_finder.SetRegion(gap_finder.GetGap());
  233. while (rel_finder.FindNext()) {
  234. auto rel32 = rel_finder.GetRel32();
  235. rel_finder.Accept();
  236. results.emplace_back(TruncatedResults{rel32.location, rel32.target_rva});
  237. }
  238. }
  239. std::vector<TruncatedResults> expected_results = {
  240. {0x04, 0x08},
  241. /* {0x09, 0x0D}, */ {0x0F, 0x13},
  242. /* {0x15, 0x19}, */ /*{0x1B, 0x1F}, */
  243. {0x21, 0x25},
  244. /* {0x27, 0x2B}, */ /* {0x2D, 0x31}, */ {0x33, 0x37},
  245. {0x39, 0x3D},
  246. /* {0x3F, 0x43}, */ /* {0x45, 0x49}, */ {0x4B, 0x4F},
  247. /* {0x51, 0x55}, */ {0x57, 0x5B},
  248. /* {0x5D, 0x61}, */ /* {0x63, 0x67}, */ {0x69, 0x6D},
  249. };
  250. EXPECT_EQ(expected_results, results);
  251. }
  252. TEST(Rel32FinderX86Test, Accept) {
  253. constexpr uint8_t data[] = {
  254. 0xB9, 0x00, 0x00, 0x00, 0xE9, // 00: mov E9000000
  255. 0xE8, 0x00, 0x00, 0x00, 0xE9, // 05: call E900000A
  256. 0xE8, 0x00, 0x00, 0x00, 0xE9, // 0A: call E900000F
  257. };
  258. ConstBufferView image =
  259. ConstBufferView::FromRange(std::begin(data), std::end(data));
  260. auto next_location = [](Rel32FinderX86& rel_finder) -> offset_t {
  261. EXPECT_TRUE(rel_finder.FindNext());
  262. auto rel32 = rel_finder.GetRel32();
  263. return rel32.location;
  264. };
  265. AddressTranslator translator(GetTrivialTranslator(image.size()));
  266. Rel32FinderX86 rel_finder(image, translator);
  267. rel_finder.SetRegion(image);
  268. EXPECT_EQ(0x05U, next_location(rel_finder)); // False positive.
  269. rel_finder.Accept();
  270. // False negative: shadowed by 0x05
  271. // EXPECT_EQ(0x06, next_location(rel_finder));
  272. EXPECT_EQ(0x0AU, next_location(rel_finder)); // False positive.
  273. EXPECT_EQ(0x0BU, next_location(rel_finder)); // Found if 0x0A is discarded.
  274. }
  275. namespace {
  276. // X64 test data. (x) and +x entries are covered by abs32 references, which have
  277. // width = 8.
  278. constexpr uint8_t kDataX64[] = {
  279. 0x55, // 00: push ebp
  280. 0x8B, 0xEC, // 01: mov ebp,esp
  281. 0xE8, 0, 0, 0, 0, // 03: call 08
  282. 0xE9, 0, 0, 0, (0), // 08: jmp 0D
  283. +0x0F, +0x80, +0, +0, +0, +0, // 0D: jo 13
  284. +0x0F, 0x81, 0, 0, 0, 0, // 13: jno 19
  285. 0x0F, 0x82, 0, 0, 0, 0, // 19: jb 1F
  286. (0x0F), +0x83, +0, +0, +0, +0, // 1F: jae 25
  287. +0x0F, +0x84, 0, 0, 0, 0, // 25: je 2B
  288. 0x0F, 0x85, 0, 0, 0, 0, // 2B: jne 31
  289. 0x0F, 0x86, (0), +0, +0, +0, // 31: jbe 37
  290. +0x0F, +0x87, +0, +0, (0), +0, // 37: ja 3D
  291. +0x0F, +0x88, +0, +0, +0, +0, // 3D: js 43
  292. 0x0F, 0x89, 0, 0, 0, 0, // 43: jns 49
  293. (0x0F), +0x8A, +0, +0, +0, +0, // 49: jp 4F
  294. +0x0F, +0x8B, 0, 0, 0, 0, // 4F: jnp 55
  295. 0x0F, 0x8C, 0, 0, 0, 0, // 55: jl 5B
  296. 0x0F, 0x8D, 0, 0, 0, 0, // 5B: jge 61
  297. 0x0F, 0x8E, 0, 0, 0, 0, // 61: jle 67
  298. 0x0F, 0x8F, 0, (0), +0, +0, // 67: jg 6F
  299. +0xFF, +0x15, +0, +0, +0, 0, // 6D: call [rip+00] # 73
  300. 0xFF, 0x25, 0, 0, 0, 0, // 73: jmp [rip+00] # 79
  301. 0x8B, 0x05, 0, 0, 0, 0, // 79: mov eax,[rip+00] # 7F
  302. 0x8B, 0x3D, 0, 0, 0, 0, // 7F: mov edi,[rip+00] # 85
  303. 0x8D, 0x05, 0, 0, 0, 0, // 85: lea eax,[rip+00] # 8B
  304. 0x8D, 0x3D, 0, 0, 0, 0, // 8B: lea edi,[rip+00] # 91
  305. 0x48, 0x8B, 0x05, 0, 0, 0, 0, // 91: mov rax,[rip+00] # 98
  306. 0x48, (0x8B), +0x3D, +0, +0, +0, +0, // 98: mov rdi,[rip+00] # 9F
  307. +0x48, +0x8D, 0x05, 0, 0, 0, 0, // 9F: lea rax,[rip+00] # A6
  308. 0x48, 0x8D, 0x3D, 0, 0, 0, 0, // A6: lea rdi,[rip+00] # AD
  309. 0x4C, 0x8B, 0x05, 0, 0, 0, (0), // AD: mov r8,[rip+00] # B4
  310. +0x4C, +0x8B, +0x3D, +0, +0, +0, +0, // B4: mov r15,[rip+00] # BB
  311. 0x4C, 0x8D, 0x05, 0, 0, 0, 0, // BB: lea r8,[rip+00] # C2
  312. 0x4C, 0x8D, 0x3D, 0, 0, 0, 0, // C2: lea r15,[rip+00] # C9
  313. 0x66, 0x8B, 0x05, (0), +0, +0, +0, // C9: mov ax,[rip+00] # D0
  314. +0x66, +0x8B, +0x3D, +0, 0, 0, 0, // D0: mov di,[rip+00] # D7
  315. 0x66, 0x8D, 0x05, 0, 0, 0, 0, // D7: lea ax,[rip+00] # DE
  316. 0x66, 0x8D, 0x3D, 0, 0, 0, 0, // DE: lea di,[rip+00] # E5
  317. 0x5D, // E5: pop ebp
  318. 0xC3, // E6: ret
  319. };
  320. // Abs32 locations corresponding to |kDataX64|, with width = 8.
  321. constexpr offset_t kAbs32X64[] = {0x0C, 0x1F, 0x33, 0x3B, 0x49,
  322. 0x6A, 0x99, 0xB3, 0xCC};
  323. } // namespace
  324. TEST(Rel32FinderX64Test, FindNext) {
  325. ConstBufferView image =
  326. ConstBufferView::FromRange(std::begin(kDataX64), std::end(kDataX64));
  327. AddressTranslator translator(GetTrivialTranslator(image.size()));
  328. Rel32FinderX64 rel_finder(image, translator);
  329. rel_finder.SetRegion(image);
  330. // Lists of expected locations as pairs of {cursor offset, rel32 offset},
  331. // ignoring |kAbs32X64|.
  332. std::vector<std::pair<size_t, size_t>> expected_locations = {
  333. {0x04, 0x04}, {0x09, 0x09}, {0x0E, 0x0F}, {0x14, 0x15}, {0x1A, 0x1B},
  334. {0x20, 0x21}, {0x26, 0x27}, {0x2C, 0x2D}, {0x32, 0x33}, {0x38, 0x39},
  335. {0x3E, 0x3F}, {0x44, 0x45}, {0x4A, 0x4B}, {0x50, 0x51}, {0x56, 0x57},
  336. {0x5C, 0x5D}, {0x62, 0x63}, {0x68, 0x69},
  337. };
  338. std::vector<std::pair<size_t, size_t>> expected_locations_rip = {
  339. {0x6E, 0x6F}, {0x74, 0x75}, {0x7A, 0x7B}, {0x80, 0x81}, {0x86, 0x87},
  340. {0x8C, 0x8D}, {0x93, 0x94}, {0x9A, 0x9B}, {0xA1, 0xA2}, {0xA8, 0xA9},
  341. {0xAF, 0xB0}, {0xB6, 0xB7}, {0xBD, 0xBE}, {0xC4, 0xC5}, {0xCB, 0xCC},
  342. {0xD2, 0xD3}, {0xD9, 0xDA}, {0xE0, 0xE1},
  343. };
  344. // Jump instructions, which cannot point outside section.
  345. for (auto location : expected_locations) {
  346. EXPECT_TRUE(rel_finder.FindNext());
  347. auto rel32 = rel_finder.GetRel32();
  348. EXPECT_EQ(location.first,
  349. size_t(rel_finder.region().begin() - image.begin()));
  350. EXPECT_EQ(location.second, rel32.location);
  351. EXPECT_EQ(image.begin() + (rel32.location + 4), rel_finder.accept_it());
  352. EXPECT_FALSE(rel32.can_point_outside_section);
  353. rel_finder.Accept();
  354. }
  355. // PC-relative data access instructions, which can point outside section.
  356. for (auto location : expected_locations_rip) {
  357. EXPECT_TRUE(rel_finder.FindNext());
  358. auto rel32 = rel_finder.GetRel32();
  359. EXPECT_EQ(location.first,
  360. size_t(rel_finder.region().begin() - image.begin()));
  361. EXPECT_EQ(location.second, rel32.location);
  362. EXPECT_EQ(image.begin() + (rel32.location + 4), rel_finder.accept_it());
  363. EXPECT_TRUE(rel32.can_point_outside_section); // Different from before.
  364. rel_finder.Accept();
  365. }
  366. EXPECT_FALSE(rel_finder.FindNext());
  367. }
  368. TEST(Rel32FinderX64Test, Integrated) {
  369. // Truncated form of Rel32FinderIntel::Result.
  370. using TruncatedResults = std::pair<offset_t, rva_t>;
  371. ConstBufferView image =
  372. ConstBufferView::FromRange(std::begin(kDataX64), std::end(kDataX64));
  373. std::deque<offset_t> abs32_locations(std::begin(kAbs32X64),
  374. std::end(kAbs32X64));
  375. std::vector<TruncatedResults> results;
  376. Abs32GapFinder gap_finder(image, image, abs32_locations,
  377. DisassemblerElfX64::Traits::kVAWidth);
  378. AddressTranslator translator(GetTrivialTranslator(image.size()));
  379. Rel32FinderX64 rel_finder(image, translator);
  380. while (gap_finder.FindNext()) {
  381. rel_finder.SetRegion(gap_finder.GetGap());
  382. while (rel_finder.FindNext()) {
  383. auto rel32 = rel_finder.GetRel32();
  384. rel_finder.Accept();
  385. results.emplace_back(TruncatedResults{rel32.location, rel32.target_rva});
  386. }
  387. }
  388. std::vector<TruncatedResults> expected_results = {
  389. {0x04, 0x08},
  390. /* {0x09, 0x0D}, */
  391. /* {0x0F, 0x13}, */ /* {0x15, 0x19}, */ {0x1B, 0x1F},
  392. /* {0x21, 0x25}, */ /* {0x27, 0x2B}, */ {0x2D, 0x31},
  393. /* {0x33, 0x37}, */ /* {0x39, 0x3D}, */
  394. /* {0x3F, 0x43}, */ {0x45, 0x49},
  395. /* {0x4B, 0x4F}, */ /* {0x51, 0x55}, */
  396. {0x57, 0x5B},
  397. {0x5D, 0x61},
  398. {0x63, 0x67}, /* {0x69, 0x6F}, */
  399. /* {0x6F, 0x73}, */ {0x75, 0x79},
  400. {0x7B, 0x7F},
  401. {0x81, 0x85},
  402. {0x87, 0x8B},
  403. {0x8D, 0x91},
  404. {0x94, 0x98},
  405. /* {0x9B, 0x9F}, */ /* {0xA2, 0xA6}, */ {0xA9, 0xAD},
  406. /* {0xB0, 0xB4}, */ /* {0xB7, 0xBB}, */ {0xBE, 0xC2},
  407. {0xC5, 0xC9},
  408. /* {0xCC, 0xD0}, */ /* {0xD3, 0xD7}, */ {0xDA, 0xDE},
  409. {0xE1, 0xE5},
  410. };
  411. EXPECT_EQ(expected_results, results);
  412. }
  413. namespace {
  414. // Runs the ARM rel32 extraction (nested) loop on |image| using |rel32_finder|,
  415. // given |abs32_locations| for abs32 references each having |abs32_width|.
  416. // Returns the list of extracted references.
  417. template <class REL32_FINDER>
  418. std::vector<typename REL32_FINDER::Result> ArmExtractRel32(
  419. ConstBufferView image,
  420. const std::deque<offset_t>& abs32_locations,
  421. int abs32_width,
  422. REL32_FINDER&& rel32_finder) {
  423. std::vector<typename REL32_FINDER::Result> results;
  424. Abs32GapFinder gap_finder(image, image, abs32_locations, abs32_width);
  425. while (gap_finder.FindNext()) {
  426. rel32_finder.SetRegion(gap_finder.GetGap());
  427. while (rel32_finder.FindNext()) {
  428. typename REL32_FINDER::Result rel32 = rel32_finder.GetRel32();
  429. rel32_finder.Accept();
  430. results.emplace_back(rel32);
  431. }
  432. }
  433. return results;
  434. }
  435. } // namespace
  436. namespace {
  437. // AArch32 ARM mode test data. (x) and +x entries are covered by abs32
  438. // references (if used), which have width = 4.
  439. constexpr uint8_t kDataAarch32ArmMode[] = {
  440. 0x00, 0x01, 0x02, 0xEA, // 00: B 00080408 ; B encoding A1
  441. 0x00, 0x01, (0x02), +0xEA, // 04: B 0008040C ; B encoding A1
  442. +0x00, +0x01, 0x02, 0xEA, // 08: B 00080410 ; B encoding A1
  443. 0x00, 0x01, 0x02, 0xEA, // 0C: B 00080414 ; B encoding A1
  444. 0x00, 0x01, 0x02, (0xEA), // 10: B 00080418 ; B encoding A1
  445. +0x00, +0x01, +0x02, 0xEA, // 14: B 0008041C ; B encoding A1
  446. 0x00, 0x01, 0x02, 0xEA, // 18: B 00080420 ; B encoding A1
  447. };
  448. // Abs32 locations corresponding to |kDataAarch32ArmMode|, with width = 4.
  449. constexpr offset_t kAbs32Aarch32ArmMode[] = {0x6, 0x13};
  450. } // namespace
  451. TEST(Rel32FinderAArch32Test, IntegratedArmModeWithoutAbs32) {
  452. using AddrType = AArch32Rel32Translator::AddrType;
  453. using Result = Rel32FinderAArch32::Result;
  454. std::vector<Result> expected_results = {
  455. {0x00, 0x80408, AddrType::ADDR_A24}, {0x04, 0x8040C, AddrType::ADDR_A24},
  456. {0x08, 0x80410, AddrType::ADDR_A24}, {0x0C, 0x80414, AddrType::ADDR_A24},
  457. {0x10, 0x80418, AddrType::ADDR_A24}, {0x14, 0x8041C, AddrType::ADDR_A24},
  458. {0x18, 0x80420, AddrType::ADDR_A24},
  459. };
  460. ConstBufferView image = ConstBufferView::FromRange(
  461. std::begin(kDataAarch32ArmMode), std::end(kDataAarch32ArmMode));
  462. AddressTranslator translator(GetTrivialTranslator(image.size()));
  463. Rel32FinderAArch32 rel32_finder(image, translator, /* is_thumb2 */ false);
  464. std::vector<Result> results = ArmExtractRel32(
  465. image, /* abs32_locations */ {}, DisassemblerElfAArch32::Traits::kVAWidth,
  466. std::move(rel32_finder));
  467. EXPECT_EQ(expected_results, results);
  468. }
  469. TEST(Rel32FinderAArch32Test, IntegratedArmModeWithAbs32) {
  470. using AddrType = AArch32Rel32Translator::AddrType;
  471. using Result = Rel32FinderAArch32::Result;
  472. std::vector<Result> expected_results = {
  473. {0x00, 0x80408, AddrType::ADDR_A24},
  474. /* {0x04, 0x8040C, AddrType::ADDR_A24}, */
  475. /* {0x08, 0x80410, AddrType::ADDR_A24}, */
  476. {0x0C, 0x80414, AddrType::ADDR_A24},
  477. /* {0x10, 0x80418, AddrType::ADDR_A24}, */
  478. /* {0x14, 0x8041C, AddrType::ADDR_A24}, */
  479. {0x18, 0x80420, AddrType::ADDR_A24},
  480. };
  481. ConstBufferView image = ConstBufferView::FromRange(
  482. std::begin(kDataAarch32ArmMode), std::end(kDataAarch32ArmMode));
  483. std::deque<offset_t> abs32_locations(std::begin(kAbs32Aarch32ArmMode),
  484. std::end(kAbs32Aarch32ArmMode));
  485. AddressTranslator translator(GetTrivialTranslator(image.size()));
  486. Rel32FinderAArch32 rel32_finder(image, translator, /* is_thumb2 */ false);
  487. std::vector<Result> results = ArmExtractRel32(
  488. image, abs32_locations, DisassemblerElfAArch32::Traits::kVAWidth,
  489. std::move(rel32_finder));
  490. EXPECT_EQ(expected_results, results);
  491. }
  492. namespace {
  493. // AArch32 THUMB2 mode test data. (x) and +x entries are covered by abs32
  494. // references (if used), which have width = 4.
  495. constexpr uint8_t kDataAarch32Thumb2Mode[] = {
  496. 0x00, 0xDE, // 00: B.AL 00000004 ; B encoding T1
  497. 0x00, 0xDE, // 02: B.AL 00000006 ; B encoding T1
  498. 0x00, (0xDE), // 04: B.AL 00000008 ; B encoding T1
  499. +0x00, +0xDE, // 06: B.AL 0000000A ; B encoding T1
  500. +0x00, 0xE0, // 08: B 0000000C ; B encoding T2
  501. 0x00, 0xE0, // 0A: B 0000000E ; B encoding T2
  502. 0x00, 0xE0, // 0C: B 00000010 ; B encoding T2
  503. (0x00), +0xE0, // 0E: B 00000012 ; B encoding T2
  504. +0x00, +0xF0, 0x00, 0x80, // 10: B 00000014 ; B encoding T3
  505. 0x00, 0xF0, 0x00, 0x80, // 14: B 00000018 ; B encoding T3
  506. (0x00), +0xF0, +0x00, +0x80, // 18: B 0000001C ; B encoding T3
  507. 0x00, 0xF0, 0x00, 0x80, // 1C: B 00000020 ; B encoding T3
  508. 0x00, 0xF0, 0x00, 0xB8, // 20: B 00000024 ; B encoding T4
  509. 0x00, 0xF0, 0x00, (0xB8), // 24: B 00000028 ; B encoding T4
  510. +0xFE, +0xDE, // 28: B.AL 00000028 ; B encoding T1
  511. +0x00, 0xF0, 0x00, 0xF8, // 2A: BL 0000002E ; BL encoding T1
  512. 0x00, 0xF0, 0x00, 0xE8, // 2E: BLX 00000030 ; BLX encoding T2
  513. 0x00, 0x0B, // 32: NOP
  514. 0x00, 0xF0, 0x00, 0xE8, // 34: BLX 00000038 ; BLX encoding T2
  515. 0x00, 0xF0, 0x00, 0xB8, // 38: B 0000003C ; B encoding T4
  516. };
  517. // Abs32 locations corresponding to |kDataAarch32Thumb2Mode|, with width = 4.
  518. constexpr offset_t kAbs32Aarch32Thumb2Mode[] = {0x05, 0x0E, 0x18, 0x27};
  519. } // namespace
  520. TEST(Rel32FinderAArch32Test, IntegratedThumb2ModeWithoutAbs32) {
  521. using AddrType = AArch32Rel32Translator::AddrType;
  522. using Result = Rel32FinderAArch32::Result;
  523. std::vector<Result> expected_results = {
  524. {0x00, 0x04, AddrType::ADDR_T8}, {0x02, 0x06, AddrType::ADDR_T8},
  525. {0x04, 0x08, AddrType::ADDR_T8}, {0x06, 0x0A, AddrType::ADDR_T8},
  526. {0x08, 0x0C, AddrType::ADDR_T11}, {0x0A, 0x0E, AddrType::ADDR_T11},
  527. {0x0C, 0x10, AddrType::ADDR_T11}, {0x0E, 0x12, AddrType::ADDR_T11},
  528. {0x10, 0x14, AddrType::ADDR_T20}, {0x14, 0x18, AddrType::ADDR_T20},
  529. {0x18, 0x1C, AddrType::ADDR_T20}, {0x1C, 0x20, AddrType::ADDR_T20},
  530. {0x20, 0x24, AddrType::ADDR_T24}, {0x24, 0x28, AddrType::ADDR_T24},
  531. {0x28, 0x28, AddrType::ADDR_T8}, {0x2A, 0x2E, AddrType::ADDR_T24},
  532. {0x2E, 0x30, AddrType::ADDR_T24}, {0x34, 0x38, AddrType::ADDR_T24},
  533. {0x38, 0x3C, AddrType::ADDR_T24},
  534. };
  535. ConstBufferView image = ConstBufferView::FromRange(
  536. std::begin(kDataAarch32Thumb2Mode), std::end(kDataAarch32Thumb2Mode));
  537. AddressTranslator translator(GetTrivialTranslator(image.size()));
  538. Rel32FinderAArch32 rel32_finder(image, translator, /* is_thumb2 */ true);
  539. std::vector<Result> results = ArmExtractRel32(
  540. image, /* abs32_locations */ {}, DisassemblerElfAArch32::Traits::kVAWidth,
  541. std::move(rel32_finder));
  542. EXPECT_EQ(expected_results, results);
  543. }
  544. TEST(Rel32FinderAArch32Test, IntegratedThumb2ModeWithAbs32) {
  545. using AddrType = AArch32Rel32Translator::AddrType;
  546. using Result = Rel32FinderAArch32::Result;
  547. std::vector<Result> expected_results = {
  548. {0x00, 0x04, AddrType::ADDR_T8},
  549. {0x02, 0x06, AddrType::ADDR_T8},
  550. /* {0x04, 0x08, AddrType::ADDR_T8}, */
  551. /* {0x06, 0x0A, AddrType::ADDR_T8}, */
  552. /* {0x08, 0x0C, AddrType::ADDR_T11}, */
  553. {0x0A, 0x0E, AddrType::ADDR_T11},
  554. {0x0C, 0x10, AddrType::ADDR_T11},
  555. /* {0x0E, 0x12, AddrType::ADDR_T11}, */
  556. /* {0x10, 0x14, AddrType::ADDR_T20}, */
  557. {0x14, 0x18, AddrType::ADDR_T20},
  558. /* {0x18, 0x1C, AddrType::ADDR_T20}, */
  559. {0x1C, 0x20, AddrType::ADDR_T20},
  560. {0x20, 0x24, AddrType::ADDR_T24},
  561. /* {0x24, 0x28, AddrType::ADDR_T24}, */
  562. /* {0x28, 0x28, AddrType::ADDR_T8}, */
  563. /* {0x2A, 0x2E, AddrType::ADDR_T24}, */
  564. // Abs32 reference 0x27 disrupts alignment, and THUMB2 disassembly starts
  565. // at 0x2C, causing the following to be excluded!
  566. /* {0x2E, 0x30, AddrType::ADDR_T24}, */
  567. {0x34, 0x38, AddrType::ADDR_T24},
  568. {0x38, 0x3C, AddrType::ADDR_T24},
  569. };
  570. ConstBufferView image = ConstBufferView::FromRange(
  571. std::begin(kDataAarch32Thumb2Mode), std::end(kDataAarch32Thumb2Mode));
  572. std::deque<offset_t> abs32_locations(std::begin(kAbs32Aarch32Thumb2Mode),
  573. std::end(kAbs32Aarch32Thumb2Mode));
  574. AddressTranslator translator(GetTrivialTranslator(image.size()));
  575. Rel32FinderAArch32 rel32_finder(image, translator, /* is_thumb2 */ true);
  576. std::vector<Result> results = ArmExtractRel32(
  577. image, abs32_locations, DisassemblerElfAArch32::Traits::kVAWidth,
  578. std::move(rel32_finder));
  579. EXPECT_EQ(expected_results, results);
  580. }
  581. namespace {
  582. // AArch32 THUMB2 mode test data. (x) and +x entries are covered by abs32
  583. // references (if used), which have width = 8.
  584. constexpr uint8_t kDataAarch64[] = {
  585. 0x0E, 0x00, 0x00, 0x36, // 00: TBZ X0,#0,00000000 ; Immd14
  586. 0x0E, 0x00, 0x00, (0x36), // 04: TBZ X0,#0,00000004 ; Immd14
  587. +0x0E, +0x00, +0x00, +0x36, // 08: TBZ X0,#0,00000008 ; Immd14
  588. +0x0E, +0x00, +0x00, 0x54, // 0C: B.AL 0000000C ; Immd19
  589. 0x0E, 0x00, 0x00, 0x54, // 10: B.AL 00000010 ; Immd19
  590. (0x0E), +0x00, +0x00, +0x54, // 14: B.AL 00000014 ; Immd19
  591. +0x00, +0x00, +0x00, +0x94, // 18: BL 00000018 ; Immd26
  592. 0x00, 0x00, 0x00, 0x14, // 1C: B 0000001C ; Immd26
  593. 0x00, 0x00, 0x00, 0x94, // 20: BL 00000020 ; Immd26
  594. 0x00, 0x00, 0x00, 0x14, // 24: B 00000024 ; Immd26
  595. };
  596. // Abs32 locations corresponding to |kDataAarch64|, with width = 8.
  597. constexpr offset_t kAbs32Aarch64[] = {0x07, 0x14};
  598. } // namespace
  599. TEST(Rel32FinderAArch64Test, IntegratedWithoutAbs32) {
  600. using AddrType = AArch64Rel32Translator::AddrType;
  601. using Result = Rel32FinderAArch64::Result;
  602. std::vector<Result> expected_results = {
  603. {0x00, 0x00, AddrType::ADDR_IMMD14}, {0x04, 0x04, AddrType::ADDR_IMMD14},
  604. {0x08, 0x08, AddrType::ADDR_IMMD14}, {0x0C, 0x0C, AddrType::ADDR_IMMD19},
  605. {0x10, 0x10, AddrType::ADDR_IMMD19}, {0x14, 0x14, AddrType::ADDR_IMMD19},
  606. {0x18, 0x18, AddrType::ADDR_IMMD26}, {0x1C, 0x1C, AddrType::ADDR_IMMD26},
  607. {0x20, 0x20, AddrType::ADDR_IMMD26}, {0x24, 0x24, AddrType::ADDR_IMMD26},
  608. };
  609. ConstBufferView image = ConstBufferView::FromRange(std::begin(kDataAarch64),
  610. std::end(kDataAarch64));
  611. AddressTranslator translator(GetTrivialTranslator(image.size()));
  612. Rel32FinderAArch64 rel32_finder(image, translator);
  613. std::vector<Result> results = ArmExtractRel32(
  614. image, /* abs32_locations */ {}, DisassemblerElfAArch64::Traits::kVAWidth,
  615. std::move(rel32_finder));
  616. EXPECT_EQ(expected_results, results);
  617. }
  618. TEST(Rel32FinderAArch64Test, IntegratedWithAbs32) {
  619. using AddrType = AArch64Rel32Translator::AddrType;
  620. using Result = Rel32FinderAArch64::Result;
  621. std::vector<Result> expected_results = {
  622. {0x00, 0x00, AddrType::ADDR_IMMD14},
  623. /* {0x04, 0x04, AddrType::ADDR_IMMD14}, */
  624. /* {0x08, 0x08, AddrType::ADDR_IMMD14}, */
  625. /* {0x0C, 0x0C, AddrType::ADDR_IMMD19}, */
  626. {0x10, 0x10, AddrType::ADDR_IMMD19},
  627. /* {0x14, 0x14, AddrType::ADDR_IMMD19}, */
  628. /* {0x18, 0x18, AddrType::ADDR_IMMD26}, */
  629. {0x1C, 0x1C, AddrType::ADDR_IMMD26},
  630. {0x20, 0x20, AddrType::ADDR_IMMD26},
  631. {0x24, 0x24, AddrType::ADDR_IMMD26},
  632. };
  633. ConstBufferView image = ConstBufferView::FromRange(std::begin(kDataAarch64),
  634. std::end(kDataAarch64));
  635. std::deque<offset_t> abs32_locations(std::begin(kAbs32Aarch64),
  636. std::end(kAbs32Aarch64));
  637. AddressTranslator translator(GetTrivialTranslator(image.size()));
  638. Rel32FinderAArch64 rel32_finder(image, translator);
  639. std::vector<Result> results = ArmExtractRel32(
  640. image, abs32_locations, DisassemblerElfAArch64::Traits::kVAWidth,
  641. std::move(rel32_finder));
  642. EXPECT_EQ(expected_results, results);
  643. }
  644. } // namespace zucchini