ElfInterfaceArm.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 <elf.h>
  17. #include <stdint.h>
  18. #include <unwindstack/MachineArm.h>
  19. #include <unwindstack/Memory.h>
  20. #include <unwindstack/RegsArm.h>
  21. #include "ArmExidx.h"
  22. #include "ElfInterfaceArm.h"
  23. namespace unwindstack {
  24. bool ElfInterfaceArm::Init(uint64_t* load_bias) {
  25. if (!ElfInterface32::Init(load_bias)) {
  26. return false;
  27. }
  28. load_bias_ = *load_bias;
  29. return true;
  30. }
  31. bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
  32. if (start_offset_ == 0 || total_entries_ == 0) {
  33. last_error_.code = ERROR_UNWIND_INFO;
  34. return false;
  35. }
  36. size_t first = 0;
  37. size_t last = total_entries_;
  38. while (first < last) {
  39. size_t current = (first + last) / 2;
  40. uint32_t addr = addrs_[current];
  41. if (addr == 0) {
  42. if (!GetPrel31Addr(start_offset_ + current * 8, &addr)) {
  43. return false;
  44. }
  45. addrs_[current] = addr;
  46. }
  47. if (pc == addr) {
  48. *entry_offset = start_offset_ + current * 8;
  49. return true;
  50. }
  51. if (pc < addr) {
  52. last = current;
  53. } else {
  54. first = current + 1;
  55. }
  56. }
  57. if (last != 0) {
  58. *entry_offset = start_offset_ + (last - 1) * 8;
  59. return true;
  60. }
  61. last_error_.code = ERROR_UNWIND_INFO;
  62. return false;
  63. }
  64. bool ElfInterfaceArm::GetPrel31Addr(uint32_t offset, uint32_t* addr) {
  65. uint32_t data;
  66. if (!memory_->Read32(offset, &data)) {
  67. last_error_.code = ERROR_MEMORY_INVALID;
  68. last_error_.address = offset;
  69. return false;
  70. }
  71. // Sign extend the value if necessary.
  72. int32_t value = (static_cast<int32_t>(data) << 1) >> 1;
  73. *addr = offset + value;
  74. return true;
  75. }
  76. #if !defined(PT_ARM_EXIDX)
  77. #define PT_ARM_EXIDX 0x70000001
  78. #endif
  79. void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint64_t ph_filesz) {
  80. if (type != PT_ARM_EXIDX) {
  81. return;
  82. }
  83. // The offset already takes into account the load bias.
  84. start_offset_ = ph_offset;
  85. // Always use filesz instead of memsz. In most cases they are the same,
  86. // but some shared libraries wind up setting one correctly and not the other.
  87. total_entries_ = ph_filesz / 8;
  88. }
  89. bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
  90. // Dwarf unwind information is precise about whether a pc is covered or not,
  91. // but arm unwind information only has ranges of pc. In order to avoid
  92. // incorrectly doing a bad unwind using arm unwind information for a
  93. // different function, always try and unwind with the dwarf information first.
  94. return ElfInterface32::Step(pc, regs, process_memory, finished) ||
  95. StepExidx(pc, regs, process_memory, finished);
  96. }
  97. bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
  98. // Adjust the load bias to get the real relative pc.
  99. if (pc < load_bias_) {
  100. last_error_.code = ERROR_UNWIND_INFO;
  101. return false;
  102. }
  103. pc -= load_bias_;
  104. RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs);
  105. uint64_t entry_offset;
  106. if (!FindEntry(pc, &entry_offset)) {
  107. return false;
  108. }
  109. ArmExidx arm(regs_arm, memory_, process_memory);
  110. arm.set_cfa(regs_arm->sp());
  111. bool return_value = false;
  112. if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
  113. // If the pc was not set, then use the LR registers for the PC.
  114. if (!arm.pc_set()) {
  115. (*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
  116. }
  117. (*regs_arm)[ARM_REG_SP] = arm.cfa();
  118. return_value = true;
  119. // If the pc was set to zero, consider this the final frame.
  120. *finished = (regs_arm->pc() == 0) ? true : false;
  121. }
  122. if (arm.status() == ARM_STATUS_NO_UNWIND) {
  123. *finished = true;
  124. return true;
  125. }
  126. if (!return_value) {
  127. switch (arm.status()) {
  128. case ARM_STATUS_NONE:
  129. case ARM_STATUS_NO_UNWIND:
  130. case ARM_STATUS_FINISH:
  131. last_error_.code = ERROR_NONE;
  132. break;
  133. case ARM_STATUS_RESERVED:
  134. case ARM_STATUS_SPARE:
  135. case ARM_STATUS_TRUNCATED:
  136. case ARM_STATUS_MALFORMED:
  137. case ARM_STATUS_INVALID_ALIGNMENT:
  138. case ARM_STATUS_INVALID_PERSONALITY:
  139. last_error_.code = ERROR_UNWIND_INFO;
  140. break;
  141. case ARM_STATUS_READ_FAILED:
  142. last_error_.code = ERROR_MEMORY_INVALID;
  143. last_error_.address = arm.status_address();
  144. break;
  145. }
  146. }
  147. return return_value;
  148. }
  149. bool ElfInterfaceArm::GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) {
  150. // For ARM, thumb function symbols have bit 0 set, but the address passed
  151. // in here might not have this bit set and result in a failure to find
  152. // the thumb function names. Adjust the address and offset to account
  153. // for this possible case.
  154. if (ElfInterface32::GetFunctionName(addr | 1, name, offset)) {
  155. *offset &= ~1;
  156. return true;
  157. }
  158. return false;
  159. }
  160. } // namespace unwindstack