RegsX86_64.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 <string.h>
  18. #include <functional>
  19. #include <unwindstack/Elf.h>
  20. #include <unwindstack/MachineX86_64.h>
  21. #include <unwindstack/MapInfo.h>
  22. #include <unwindstack/Memory.h>
  23. #include <unwindstack/RegsX86_64.h>
  24. #include <unwindstack/UcontextX86_64.h>
  25. #include <unwindstack/UserX86_64.h>
  26. namespace unwindstack {
  27. RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {}
  28. ArchEnum RegsX86_64::Arch() {
  29. return ARCH_X86_64;
  30. }
  31. uint64_t RegsX86_64::pc() {
  32. return regs_[X86_64_REG_PC];
  33. }
  34. uint64_t RegsX86_64::sp() {
  35. return regs_[X86_64_REG_SP];
  36. }
  37. void RegsX86_64::set_pc(uint64_t pc) {
  38. regs_[X86_64_REG_PC] = pc;
  39. }
  40. void RegsX86_64::set_sp(uint64_t sp) {
  41. regs_[X86_64_REG_SP] = sp;
  42. }
  43. uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf*) {
  44. if (rel_pc == 0) {
  45. return 0;
  46. }
  47. return 1;
  48. }
  49. bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
  50. // Attempt to get the return address from the top of the stack.
  51. uint64_t new_pc;
  52. if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
  53. new_pc == regs_[X86_64_REG_PC]) {
  54. return false;
  55. }
  56. regs_[X86_64_REG_PC] = new_pc;
  57. return true;
  58. }
  59. void RegsX86_64::IterateRegisters(std::function<void(const char*, uint64_t)> fn) {
  60. fn("rax", regs_[X86_64_REG_RAX]);
  61. fn("rbx", regs_[X86_64_REG_RBX]);
  62. fn("rcx", regs_[X86_64_REG_RCX]);
  63. fn("rdx", regs_[X86_64_REG_RDX]);
  64. fn("r8", regs_[X86_64_REG_R8]);
  65. fn("r9", regs_[X86_64_REG_R9]);
  66. fn("r10", regs_[X86_64_REG_R10]);
  67. fn("r11", regs_[X86_64_REG_R11]);
  68. fn("r12", regs_[X86_64_REG_R12]);
  69. fn("r13", regs_[X86_64_REG_R13]);
  70. fn("r14", regs_[X86_64_REG_R14]);
  71. fn("r15", regs_[X86_64_REG_R15]);
  72. fn("rdi", regs_[X86_64_REG_RDI]);
  73. fn("rsi", regs_[X86_64_REG_RSI]);
  74. fn("rbp", regs_[X86_64_REG_RBP]);
  75. fn("rsp", regs_[X86_64_REG_RSP]);
  76. fn("rip", regs_[X86_64_REG_RIP]);
  77. }
  78. Regs* RegsX86_64::Read(void* remote_data) {
  79. x86_64_user_regs* user = reinterpret_cast<x86_64_user_regs*>(remote_data);
  80. RegsX86_64* regs = new RegsX86_64();
  81. (*regs)[X86_64_REG_RAX] = user->rax;
  82. (*regs)[X86_64_REG_RBX] = user->rbx;
  83. (*regs)[X86_64_REG_RCX] = user->rcx;
  84. (*regs)[X86_64_REG_RDX] = user->rdx;
  85. (*regs)[X86_64_REG_R8] = user->r8;
  86. (*regs)[X86_64_REG_R9] = user->r9;
  87. (*regs)[X86_64_REG_R10] = user->r10;
  88. (*regs)[X86_64_REG_R11] = user->r11;
  89. (*regs)[X86_64_REG_R12] = user->r12;
  90. (*regs)[X86_64_REG_R13] = user->r13;
  91. (*regs)[X86_64_REG_R14] = user->r14;
  92. (*regs)[X86_64_REG_R15] = user->r15;
  93. (*regs)[X86_64_REG_RDI] = user->rdi;
  94. (*regs)[X86_64_REG_RSI] = user->rsi;
  95. (*regs)[X86_64_REG_RBP] = user->rbp;
  96. (*regs)[X86_64_REG_RSP] = user->rsp;
  97. (*regs)[X86_64_REG_RIP] = user->rip;
  98. return regs;
  99. }
  100. void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
  101. // R8-R15
  102. memcpy(&regs_[X86_64_REG_R8], &ucontext->uc_mcontext.r8, 8 * sizeof(uint64_t));
  103. // Rest of the registers.
  104. regs_[X86_64_REG_RDI] = ucontext->uc_mcontext.rdi;
  105. regs_[X86_64_REG_RSI] = ucontext->uc_mcontext.rsi;
  106. regs_[X86_64_REG_RBP] = ucontext->uc_mcontext.rbp;
  107. regs_[X86_64_REG_RBX] = ucontext->uc_mcontext.rbx;
  108. regs_[X86_64_REG_RDX] = ucontext->uc_mcontext.rdx;
  109. regs_[X86_64_REG_RAX] = ucontext->uc_mcontext.rax;
  110. regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
  111. regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
  112. regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
  113. }
  114. Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
  115. x86_64_ucontext_t* x86_64_ucontext = reinterpret_cast<x86_64_ucontext_t*>(ucontext);
  116. RegsX86_64* regs = new RegsX86_64();
  117. regs->SetFromUcontext(x86_64_ucontext);
  118. return regs;
  119. }
  120. bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) {
  121. uint64_t data;
  122. Memory* elf_memory = elf->memory();
  123. // Read from elf memory since it is usually more expensive to read from
  124. // process memory.
  125. if (!elf_memory->ReadFully(rel_pc, &data, sizeof(data)) || data != 0x0f0000000fc0c748) {
  126. return false;
  127. }
  128. uint16_t data2;
  129. if (!elf_memory->ReadFully(rel_pc + 8, &data2, sizeof(data2)) || data2 != 0x0f05) {
  130. return false;
  131. }
  132. // __restore_rt:
  133. // 0x48 0xc7 0xc0 0x0f 0x00 0x00 0x00 mov $0xf,%rax
  134. // 0x0f 0x05 syscall
  135. // 0x0f nopl 0x0($rax)
  136. // Read the mcontext data from the stack.
  137. // sp points to the ucontext data structure, read only the mcontext part.
  138. x86_64_ucontext_t x86_64_ucontext;
  139. if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
  140. sizeof(x86_64_mcontext_t))) {
  141. return false;
  142. }
  143. SetFromUcontext(&x86_64_ucontext);
  144. return true;
  145. }
  146. Regs* RegsX86_64::Clone() {
  147. return new RegsX86_64(*this);
  148. }
  149. } // namespace unwindstack