ArmExidx.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * Copyright (C) 2016 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stdint.h>
  17. #include <deque>
  18. #include <string>
  19. #include <android-base/stringprintf.h>
  20. #include <unwindstack/Log.h>
  21. #include <unwindstack/MachineArm.h>
  22. #include <unwindstack/Memory.h>
  23. #include <unwindstack/RegsArm.h>
  24. #include "ArmExidx.h"
  25. #include "Check.h"
  26. namespace unwindstack {
  27. static constexpr uint8_t LOG_CFA_REG = 64;
  28. void ArmExidx::LogRawData() {
  29. std::string log_str("Raw Data:");
  30. for (const uint8_t data : data_) {
  31. log_str += android::base::StringPrintf(" 0x%02x", data);
  32. }
  33. log(log_indent_, log_str.c_str());
  34. }
  35. bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
  36. data_.clear();
  37. status_ = ARM_STATUS_NONE;
  38. if (entry_offset & 1) {
  39. // The offset needs to be at least two byte aligned.
  40. status_ = ARM_STATUS_INVALID_ALIGNMENT;
  41. return false;
  42. }
  43. // Each entry is a 32 bit prel31 offset followed by 32 bits
  44. // of unwind information. If bit 31 of the unwind data is zero,
  45. // then this is a prel31 offset to the start of the unwind data.
  46. // If the unwind data is 1, then this is a cant unwind entry.
  47. // Otherwise, this data is the compact form of the unwind information.
  48. uint32_t data;
  49. if (!elf_memory_->Read32(entry_offset + 4, &data)) {
  50. status_ = ARM_STATUS_READ_FAILED;
  51. status_address_ = entry_offset + 4;
  52. return false;
  53. }
  54. if (data == 1) {
  55. // This is a CANT UNWIND entry.
  56. status_ = ARM_STATUS_NO_UNWIND;
  57. if (log_type_ != ARM_LOG_NONE) {
  58. if (log_type_ == ARM_LOG_FULL) {
  59. log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
  60. }
  61. log(log_indent_, "[cantunwind]");
  62. }
  63. return false;
  64. }
  65. if (data & (1UL << 31)) {
  66. // This is a compact table entry.
  67. if ((data >> 24) & 0xf) {
  68. // This is a non-zero index, this code doesn't support
  69. // other formats.
  70. status_ = ARM_STATUS_INVALID_PERSONALITY;
  71. return false;
  72. }
  73. data_.push_back((data >> 16) & 0xff);
  74. data_.push_back((data >> 8) & 0xff);
  75. uint8_t last_op = data & 0xff;
  76. data_.push_back(last_op);
  77. if (last_op != ARM_OP_FINISH) {
  78. // If this didn't end with a finish op, add one.
  79. data_.push_back(ARM_OP_FINISH);
  80. }
  81. if (log_type_ == ARM_LOG_FULL) {
  82. LogRawData();
  83. }
  84. return true;
  85. }
  86. // Get the address of the ops.
  87. // Sign extend the data value if necessary.
  88. int32_t signed_data = static_cast<int32_t>(data << 1) >> 1;
  89. uint32_t addr = (entry_offset + 4) + signed_data;
  90. if (!elf_memory_->Read32(addr, &data)) {
  91. status_ = ARM_STATUS_READ_FAILED;
  92. status_address_ = addr;
  93. return false;
  94. }
  95. size_t num_table_words;
  96. if (data & (1UL << 31)) {
  97. // Compact model.
  98. switch ((data >> 24) & 0xf) {
  99. case 0:
  100. num_table_words = 0;
  101. data_.push_back((data >> 16) & 0xff);
  102. break;
  103. case 1:
  104. case 2:
  105. num_table_words = (data >> 16) & 0xff;
  106. addr += 4;
  107. break;
  108. default:
  109. // Only a personality of 0, 1, 2 is valid.
  110. status_ = ARM_STATUS_INVALID_PERSONALITY;
  111. return false;
  112. }
  113. data_.push_back((data >> 8) & 0xff);
  114. data_.push_back(data & 0xff);
  115. } else {
  116. // Generic model.
  117. // Skip the personality routine data, it doesn't contain any data
  118. // needed to decode the unwind information.
  119. addr += 4;
  120. if (!elf_memory_->Read32(addr, &data)) {
  121. status_ = ARM_STATUS_READ_FAILED;
  122. status_address_ = addr;
  123. return false;
  124. }
  125. num_table_words = (data >> 24) & 0xff;
  126. data_.push_back((data >> 16) & 0xff);
  127. data_.push_back((data >> 8) & 0xff);
  128. data_.push_back(data & 0xff);
  129. addr += 4;
  130. }
  131. if (num_table_words > 5) {
  132. status_ = ARM_STATUS_MALFORMED;
  133. return false;
  134. }
  135. for (size_t i = 0; i < num_table_words; i++) {
  136. if (!elf_memory_->Read32(addr, &data)) {
  137. status_ = ARM_STATUS_READ_FAILED;
  138. status_address_ = addr;
  139. return false;
  140. }
  141. data_.push_back((data >> 24) & 0xff);
  142. data_.push_back((data >> 16) & 0xff);
  143. data_.push_back((data >> 8) & 0xff);
  144. data_.push_back(data & 0xff);
  145. addr += 4;
  146. }
  147. if (data_.back() != ARM_OP_FINISH) {
  148. // If this didn't end with a finish op, add one.
  149. data_.push_back(ARM_OP_FINISH);
  150. }
  151. if (log_type_ == ARM_LOG_FULL) {
  152. LogRawData();
  153. }
  154. return true;
  155. }
  156. inline bool ArmExidx::GetByte(uint8_t* byte) {
  157. if (data_.empty()) {
  158. status_ = ARM_STATUS_TRUNCATED;
  159. return false;
  160. }
  161. *byte = data_.front();
  162. data_.pop_front();
  163. return true;
  164. }
  165. inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
  166. CHECK((byte >> 4) == 0x8);
  167. uint16_t registers = (byte & 0xf) << 8;
  168. if (!GetByte(&byte)) {
  169. return false;
  170. }
  171. registers |= byte;
  172. if (registers == 0) {
  173. // 10000000 00000000: Refuse to unwind
  174. if (log_type_ != ARM_LOG_NONE) {
  175. log(log_indent_, "Refuse to unwind");
  176. }
  177. status_ = ARM_STATUS_NO_UNWIND;
  178. return false;
  179. }
  180. // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
  181. registers <<= 4;
  182. if (log_type_ != ARM_LOG_NONE) {
  183. if (log_type_ == ARM_LOG_FULL) {
  184. bool add_comma = false;
  185. std::string msg = "pop {";
  186. for (size_t reg = 4; reg < 16; reg++) {
  187. if (registers & (1 << reg)) {
  188. if (add_comma) {
  189. msg += ", ";
  190. }
  191. msg += android::base::StringPrintf("r%zu", reg);
  192. add_comma = true;
  193. }
  194. }
  195. log(log_indent_, "%s}", msg.c_str());
  196. } else {
  197. uint32_t cfa_offset = __builtin_popcount(registers) * 4;
  198. log_cfa_offset_ += cfa_offset;
  199. for (size_t reg = 4; reg < 16; reg++) {
  200. if (registers & (1 << reg)) {
  201. log_regs_[reg] = cfa_offset;
  202. cfa_offset -= 4;
  203. }
  204. }
  205. }
  206. if (log_skip_execution_) {
  207. return true;
  208. }
  209. }
  210. for (size_t reg = 4; reg < 16; reg++) {
  211. if (registers & (1 << reg)) {
  212. if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
  213. status_ = ARM_STATUS_READ_FAILED;
  214. status_address_ = cfa_;
  215. return false;
  216. }
  217. cfa_ += 4;
  218. }
  219. }
  220. // If the sp register is modified, change the cfa value.
  221. if (registers & (1 << ARM_REG_SP)) {
  222. cfa_ = (*regs_)[ARM_REG_SP];
  223. }
  224. // Indicate if the pc register was set.
  225. if (registers & (1 << ARM_REG_PC)) {
  226. pc_set_ = true;
  227. }
  228. return true;
  229. }
  230. inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
  231. CHECK((byte >> 4) == 0x9);
  232. uint8_t bits = byte & 0xf;
  233. if (bits == 13 || bits == 15) {
  234. // 10011101: Reserved as prefix for ARM register to register moves
  235. // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
  236. if (log_type_ != ARM_LOG_NONE) {
  237. log(log_indent_, "[Reserved]");
  238. }
  239. status_ = ARM_STATUS_RESERVED;
  240. return false;
  241. }
  242. // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
  243. if (log_type_ != ARM_LOG_NONE) {
  244. if (log_type_ == ARM_LOG_FULL) {
  245. log(log_indent_, "vsp = r%d", bits);
  246. } else {
  247. log_regs_[LOG_CFA_REG] = bits;
  248. }
  249. if (log_skip_execution_) {
  250. return true;
  251. }
  252. }
  253. // It is impossible for bits to be larger than the total number of
  254. // arm registers, so don't bother checking if bits is a valid register.
  255. cfa_ = (*regs_)[bits];
  256. return true;
  257. }
  258. inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
  259. CHECK((byte >> 4) == 0xa);
  260. // 10100nnn: Pop r4-r[4+nnn]
  261. // 10101nnn: Pop r4-r[4+nnn], r14
  262. if (log_type_ != ARM_LOG_NONE) {
  263. uint8_t end_reg = byte & 0x7;
  264. if (log_type_ == ARM_LOG_FULL) {
  265. std::string msg = "pop {r4";
  266. if (end_reg) {
  267. msg += android::base::StringPrintf("-r%d", 4 + end_reg);
  268. }
  269. if (byte & 0x8) {
  270. log(log_indent_, "%s, r14}", msg.c_str());
  271. } else {
  272. log(log_indent_, "%s}", msg.c_str());
  273. }
  274. } else {
  275. end_reg += 4;
  276. uint32_t cfa_offset = (end_reg - 3) * 4;
  277. if (byte & 0x8) {
  278. cfa_offset += 4;
  279. }
  280. log_cfa_offset_ += cfa_offset;
  281. for (uint8_t reg = 4; reg <= end_reg; reg++) {
  282. log_regs_[reg] = cfa_offset;
  283. cfa_offset -= 4;
  284. }
  285. if (byte & 0x8) {
  286. log_regs_[14] = cfa_offset;
  287. }
  288. }
  289. if (log_skip_execution_) {
  290. return true;
  291. }
  292. }
  293. for (size_t i = 4; i <= 4 + (byte & 0x7); i++) {
  294. if (!process_memory_->Read32(cfa_, &(*regs_)[i])) {
  295. status_ = ARM_STATUS_READ_FAILED;
  296. status_address_ = cfa_;
  297. return false;
  298. }
  299. cfa_ += 4;
  300. }
  301. if (byte & 0x8) {
  302. if (!process_memory_->Read32(cfa_, &(*regs_)[ARM_REG_R14])) {
  303. status_ = ARM_STATUS_READ_FAILED;
  304. status_address_ = cfa_;
  305. return false;
  306. }
  307. cfa_ += 4;
  308. }
  309. return true;
  310. }
  311. inline bool ArmExidx::DecodePrefix_10_11_0000() {
  312. // 10110000: Finish
  313. if (log_type_ != ARM_LOG_NONE) {
  314. if (log_type_ == ARM_LOG_FULL) {
  315. log(log_indent_, "finish");
  316. }
  317. if (log_skip_execution_) {
  318. status_ = ARM_STATUS_FINISH;
  319. return false;
  320. }
  321. }
  322. status_ = ARM_STATUS_FINISH;
  323. return false;
  324. }
  325. inline bool ArmExidx::DecodePrefix_10_11_0001() {
  326. uint8_t byte;
  327. if (!GetByte(&byte)) {
  328. return false;
  329. }
  330. if (byte == 0) {
  331. // 10110001 00000000: Spare
  332. if (log_type_ != ARM_LOG_NONE) {
  333. log(log_indent_, "Spare");
  334. }
  335. status_ = ARM_STATUS_SPARE;
  336. return false;
  337. }
  338. if (byte >> 4) {
  339. // 10110001 xxxxyyyy: Spare (xxxx != 0000)
  340. if (log_type_ != ARM_LOG_NONE) {
  341. log(log_indent_, "Spare");
  342. }
  343. status_ = ARM_STATUS_SPARE;
  344. return false;
  345. }
  346. // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
  347. if (log_type_ != ARM_LOG_NONE) {
  348. if (log_type_ == ARM_LOG_FULL) {
  349. bool add_comma = false;
  350. std::string msg = "pop {";
  351. for (size_t i = 0; i < 4; i++) {
  352. if (byte & (1 << i)) {
  353. if (add_comma) {
  354. msg += ", ";
  355. }
  356. msg += android::base::StringPrintf("r%zu", i);
  357. add_comma = true;
  358. }
  359. }
  360. log(log_indent_, "%s}", msg.c_str());
  361. } else {
  362. byte &= 0xf;
  363. uint32_t cfa_offset = __builtin_popcount(byte) * 4;
  364. log_cfa_offset_ += cfa_offset;
  365. for (size_t reg = 0; reg < 4; reg++) {
  366. if (byte & (1 << reg)) {
  367. log_regs_[reg] = cfa_offset;
  368. cfa_offset -= 4;
  369. }
  370. }
  371. }
  372. if (log_skip_execution_) {
  373. return true;
  374. }
  375. }
  376. for (size_t reg = 0; reg < 4; reg++) {
  377. if (byte & (1 << reg)) {
  378. if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
  379. status_ = ARM_STATUS_READ_FAILED;
  380. status_address_ = cfa_;
  381. return false;
  382. }
  383. cfa_ += 4;
  384. }
  385. }
  386. return true;
  387. }
  388. inline void ArmExidx::AdjustRegisters(int32_t offset) {
  389. for (auto& entry : log_regs_) {
  390. if (entry.first >= LOG_CFA_REG) {
  391. break;
  392. }
  393. entry.second += offset;
  394. }
  395. }
  396. inline bool ArmExidx::DecodePrefix_10_11_0010() {
  397. // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
  398. uint32_t result = 0;
  399. uint32_t shift = 0;
  400. uint8_t byte;
  401. do {
  402. if (!GetByte(&byte)) {
  403. return false;
  404. }
  405. result |= (byte & 0x7f) << shift;
  406. shift += 7;
  407. } while (byte & 0x80);
  408. result <<= 2;
  409. if (log_type_ != ARM_LOG_NONE) {
  410. int32_t cfa_offset = 0x204 + result;
  411. if (log_type_ == ARM_LOG_FULL) {
  412. log(log_indent_, "vsp = vsp + %d", cfa_offset);
  413. } else {
  414. log_cfa_offset_ += cfa_offset;
  415. }
  416. AdjustRegisters(cfa_offset);
  417. if (log_skip_execution_) {
  418. return true;
  419. }
  420. }
  421. cfa_ += 0x204 + result;
  422. return true;
  423. }
  424. inline bool ArmExidx::DecodePrefix_10_11_0011() {
  425. // 10110011 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by FSTMFDX
  426. uint8_t byte;
  427. if (!GetByte(&byte)) {
  428. return false;
  429. }
  430. if (log_type_ != ARM_LOG_NONE) {
  431. uint8_t start_reg = byte >> 4;
  432. uint8_t end_reg = start_reg + (byte & 0xf);
  433. if (log_type_ == ARM_LOG_FULL) {
  434. std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
  435. if (end_reg) {
  436. msg += android::base::StringPrintf("-d%d", end_reg);
  437. }
  438. log(log_indent_, "%s}", msg.c_str());
  439. } else {
  440. log(log_indent_, "Unsupported DX register display");
  441. }
  442. if (log_skip_execution_) {
  443. return true;
  444. }
  445. }
  446. cfa_ += (byte & 0xf) * 8 + 12;
  447. return true;
  448. }
  449. inline bool ArmExidx::DecodePrefix_10_11_01nn() {
  450. // 101101nn: Spare
  451. if (log_type_ != ARM_LOG_NONE) {
  452. log(log_indent_, "Spare");
  453. }
  454. status_ = ARM_STATUS_SPARE;
  455. return false;
  456. }
  457. inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
  458. CHECK((byte & ~0x07) == 0xb8);
  459. // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
  460. if (log_type_ != ARM_LOG_NONE) {
  461. if (log_type_ == ARM_LOG_FULL) {
  462. uint8_t last_reg = (byte & 0x7);
  463. std::string msg = "pop {d8";
  464. if (last_reg) {
  465. msg += android::base::StringPrintf("-d%d", last_reg + 8);
  466. }
  467. log(log_indent_, "%s}", msg.c_str());
  468. } else {
  469. log(log_indent_, "Unsupported DX register display");
  470. }
  471. if (log_skip_execution_) {
  472. return true;
  473. }
  474. }
  475. // Only update the cfa.
  476. cfa_ += (byte & 0x7) * 8 + 12;
  477. return true;
  478. }
  479. inline bool ArmExidx::DecodePrefix_10(uint8_t byte) {
  480. CHECK((byte >> 6) == 0x2);
  481. switch ((byte >> 4) & 0x3) {
  482. case 0:
  483. return DecodePrefix_10_00(byte);
  484. case 1:
  485. return DecodePrefix_10_01(byte);
  486. case 2:
  487. return DecodePrefix_10_10(byte);
  488. default:
  489. switch (byte & 0xf) {
  490. case 0:
  491. return DecodePrefix_10_11_0000();
  492. case 1:
  493. return DecodePrefix_10_11_0001();
  494. case 2:
  495. return DecodePrefix_10_11_0010();
  496. case 3:
  497. return DecodePrefix_10_11_0011();
  498. default:
  499. if (byte & 0x8) {
  500. return DecodePrefix_10_11_1nnn(byte);
  501. } else {
  502. return DecodePrefix_10_11_01nn();
  503. }
  504. }
  505. }
  506. }
  507. inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
  508. CHECK((byte & ~0x07) == 0xc0);
  509. uint8_t bits = byte & 0x7;
  510. if (bits == 6) {
  511. if (!GetByte(&byte)) {
  512. return false;
  513. }
  514. // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
  515. if (log_type_ != ARM_LOG_NONE) {
  516. if (log_type_ == ARM_LOG_FULL) {
  517. uint8_t start_reg = byte >> 4;
  518. std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
  519. uint8_t end_reg = byte & 0xf;
  520. if (end_reg) {
  521. msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
  522. }
  523. log(log_indent_, "%s}", msg.c_str());
  524. } else {
  525. log(log_indent_, "Unsupported wRX register display");
  526. }
  527. if (log_skip_execution_) {
  528. return true;
  529. }
  530. }
  531. // Only update the cfa.
  532. cfa_ += (byte & 0xf) * 8 + 8;
  533. } else if (bits == 7) {
  534. if (!GetByte(&byte)) {
  535. return false;
  536. }
  537. if (byte == 0) {
  538. // 11000111 00000000: Spare
  539. if (log_type_ != ARM_LOG_NONE) {
  540. log(log_indent_, "Spare");
  541. }
  542. status_ = ARM_STATUS_SPARE;
  543. return false;
  544. } else if ((byte >> 4) == 0) {
  545. // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
  546. if (log_type_ != ARM_LOG_NONE) {
  547. if (log_type_ == ARM_LOG_FULL) {
  548. bool add_comma = false;
  549. std::string msg = "pop {";
  550. for (size_t i = 0; i < 4; i++) {
  551. if (byte & (1 << i)) {
  552. if (add_comma) {
  553. msg += ", ";
  554. }
  555. msg += android::base::StringPrintf("wCGR%zu", i);
  556. add_comma = true;
  557. }
  558. }
  559. log(log_indent_, "%s}", msg.c_str());
  560. } else {
  561. log(log_indent_, "Unsupported wCGR register display");
  562. }
  563. if (log_skip_execution_) {
  564. return true;
  565. }
  566. }
  567. // Only update the cfa.
  568. cfa_ += __builtin_popcount(byte) * 4;
  569. } else {
  570. // 11000111 xxxxyyyy: Spare (xxxx != 0000)
  571. if (log_type_ != ARM_LOG_NONE) {
  572. log(log_indent_, "Spare");
  573. }
  574. status_ = ARM_STATUS_SPARE;
  575. return false;
  576. }
  577. } else {
  578. // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
  579. if (log_type_ != ARM_LOG_NONE) {
  580. if (log_type_ == ARM_LOG_FULL) {
  581. std::string msg = "pop {wR10";
  582. uint8_t nnn = byte & 0x7;
  583. if (nnn) {
  584. msg += android::base::StringPrintf("-wR%d", 10 + nnn);
  585. }
  586. log(log_indent_, "%s}", msg.c_str());
  587. } else {
  588. log(log_indent_, "Unsupported wRX register display");
  589. }
  590. if (log_skip_execution_) {
  591. return true;
  592. }
  593. }
  594. // Only update the cfa.
  595. cfa_ += (byte & 0x7) * 8 + 8;
  596. }
  597. return true;
  598. }
  599. inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
  600. CHECK((byte & ~0x07) == 0xc8);
  601. uint8_t bits = byte & 0x7;
  602. if (bits == 0) {
  603. // 11001000 sssscccc: Pop VFP double precision registers D[16+ssss]-D[16+ssss+cccc] by VPUSH
  604. if (!GetByte(&byte)) {
  605. return false;
  606. }
  607. if (log_type_ != ARM_LOG_NONE) {
  608. if (log_type_ == ARM_LOG_FULL) {
  609. uint8_t start_reg = byte >> 4;
  610. std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
  611. uint8_t end_reg = byte & 0xf;
  612. if (end_reg) {
  613. msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
  614. }
  615. log(log_indent_, "%s}", msg.c_str());
  616. } else {
  617. log(log_indent_, "Unsupported DX register display");
  618. }
  619. if (log_skip_execution_) {
  620. return true;
  621. }
  622. }
  623. // Only update the cfa.
  624. cfa_ += (byte & 0xf) * 8 + 8;
  625. } else if (bits == 1) {
  626. // 11001001 sssscccc: Pop VFP double precision registers D[ssss]-D[ssss+cccc] by VPUSH
  627. if (!GetByte(&byte)) {
  628. return false;
  629. }
  630. if (log_type_ != ARM_LOG_NONE) {
  631. if (log_type_ == ARM_LOG_FULL) {
  632. uint8_t start_reg = byte >> 4;
  633. std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
  634. uint8_t end_reg = byte & 0xf;
  635. if (end_reg) {
  636. msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
  637. }
  638. log(log_indent_, "%s}", msg.c_str());
  639. } else {
  640. log(log_indent_, "Unsupported DX register display");
  641. }
  642. if (log_skip_execution_) {
  643. return true;
  644. }
  645. }
  646. // Only update the cfa.
  647. cfa_ += (byte & 0xf) * 8 + 8;
  648. } else {
  649. // 11001yyy: Spare (yyy != 000, 001)
  650. if (log_type_ != ARM_LOG_NONE) {
  651. log(log_indent_, "Spare");
  652. }
  653. status_ = ARM_STATUS_SPARE;
  654. return false;
  655. }
  656. return true;
  657. }
  658. inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
  659. CHECK((byte & ~0x07) == 0xd0);
  660. // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
  661. if (log_type_ != ARM_LOG_NONE) {
  662. if (log_type_ == ARM_LOG_FULL) {
  663. std::string msg = "pop {d8";
  664. uint8_t end_reg = byte & 0x7;
  665. if (end_reg) {
  666. msg += android::base::StringPrintf("-d%d", 8 + end_reg);
  667. }
  668. log(log_indent_, "%s}", msg.c_str());
  669. } else {
  670. log(log_indent_, "Unsupported DX register display");
  671. }
  672. if (log_skip_execution_) {
  673. return true;
  674. }
  675. }
  676. cfa_ += (byte & 0x7) * 8 + 8;
  677. return true;
  678. }
  679. inline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
  680. CHECK((byte >> 6) == 0x3);
  681. switch ((byte >> 3) & 0x7) {
  682. case 0:
  683. return DecodePrefix_11_000(byte);
  684. case 1:
  685. return DecodePrefix_11_001(byte);
  686. case 2:
  687. return DecodePrefix_11_010(byte);
  688. default:
  689. // 11xxxyyy: Spare (xxx != 000, 001, 010)
  690. if (log_type_ != ARM_LOG_NONE) {
  691. log(log_indent_, "Spare");
  692. }
  693. status_ = ARM_STATUS_SPARE;
  694. return false;
  695. }
  696. }
  697. bool ArmExidx::Decode() {
  698. status_ = ARM_STATUS_NONE;
  699. uint8_t byte;
  700. if (!GetByte(&byte)) {
  701. return false;
  702. }
  703. switch (byte >> 6) {
  704. case 0:
  705. // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
  706. if (log_type_ != ARM_LOG_NONE) {
  707. int32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
  708. if (log_type_ == ARM_LOG_FULL) {
  709. log(log_indent_, "vsp = vsp + %d", cfa_offset);
  710. } else {
  711. log_cfa_offset_ += cfa_offset;
  712. }
  713. AdjustRegisters(cfa_offset);
  714. if (log_skip_execution_) {
  715. break;
  716. }
  717. }
  718. cfa_ += ((byte & 0x3f) << 2) + 4;
  719. break;
  720. case 1:
  721. // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
  722. if (log_type_ != ARM_LOG_NONE) {
  723. uint32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
  724. if (log_type_ == ARM_LOG_FULL) {
  725. log(log_indent_, "vsp = vsp - %d", cfa_offset);
  726. } else {
  727. log_cfa_offset_ -= cfa_offset;
  728. }
  729. AdjustRegisters(-cfa_offset);
  730. if (log_skip_execution_) {
  731. break;
  732. }
  733. }
  734. cfa_ -= ((byte & 0x3f) << 2) + 4;
  735. break;
  736. case 2:
  737. return DecodePrefix_10(byte);
  738. default:
  739. return DecodePrefix_11(byte);
  740. }
  741. return true;
  742. }
  743. bool ArmExidx::Eval() {
  744. pc_set_ = false;
  745. while (Decode());
  746. return status_ == ARM_STATUS_FINISH;
  747. }
  748. void ArmExidx::LogByReg() {
  749. if (log_type_ != ARM_LOG_BY_REG) {
  750. return;
  751. }
  752. uint8_t cfa_reg;
  753. if (log_regs_.count(LOG_CFA_REG) == 0) {
  754. cfa_reg = 13;
  755. } else {
  756. cfa_reg = log_regs_[LOG_CFA_REG];
  757. }
  758. if (log_cfa_offset_ != 0) {
  759. char sign = (log_cfa_offset_ > 0) ? '+' : '-';
  760. log(log_indent_, "cfa = r%zu %c %d", cfa_reg, sign, abs(log_cfa_offset_));
  761. } else {
  762. log(log_indent_, "cfa = r%zu", cfa_reg);
  763. }
  764. for (const auto& entry : log_regs_) {
  765. if (entry.first >= LOG_CFA_REG) {
  766. break;
  767. }
  768. if (entry.second == 0) {
  769. log(log_indent_, "r%zu = [cfa]", entry.first);
  770. } else {
  771. char sign = (entry.second > 0) ? '-' : '+';
  772. log(log_indent_, "r%zu = [cfa %c %d]", entry.first, sign, abs(entry.second));
  773. }
  774. }
  775. }
  776. } // namespace unwindstack