diff options
author | Yabin Cui <yabinc@google.com> | 2018-03-14 18:16:22 -0700 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2018-03-16 23:38:07 -0700 |
commit | 28eeb35529bc6ac2453d6f713131883ecba1dc15 (patch) | |
tree | 3ba5533a755b8ce04574dc8d9bb30f940814aedf /libunwindstack/RegsX86.cpp | |
parent | 088fd9fa172e9b2463882981f0449ed42fd998c1 (diff) | |
download | unwinding-28eeb35529bc6ac2453d6f713131883ecba1dc15.tar.gz |
Always set the sp reg to the cfa for DWARF.
There are a few places where it is assumed that this register is
set to the cfa value when interpreting DWARF information.
Add a testcase for unwinding art_quick_osr_stub on ARM.
Bug: 73954823
Test: Ran libunwindstack/libbacktrace unit tests.
Test: Random debuggerd -b of process on a hikey.
Test: Ran the 137 art test on host.
Change-Id: Ida6ccdc38c3cfeea6b57fe861a0cc127b150b790
Diffstat (limited to 'libunwindstack/RegsX86.cpp')
-rw-r--r-- | libunwindstack/RegsX86.cpp | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/libunwindstack/RegsX86.cpp b/libunwindstack/RegsX86.cpp index 573cb23..bb95a13 100644 --- a/libunwindstack/RegsX86.cpp +++ b/libunwindstack/RegsX86.cpp @@ -28,13 +28,28 @@ namespace unwindstack { -RegsX86::RegsX86() - : RegsImpl<uint32_t>(X86_REG_LAST, X86_REG_SP, Location(LOCATION_SP_OFFSET, -4)) {} +RegsX86::RegsX86() : RegsImpl<uint32_t>(X86_REG_LAST, Location(LOCATION_SP_OFFSET, -4)) {} ArchEnum RegsX86::Arch() { return ARCH_X86; } +uint64_t RegsX86::pc() { + return regs_[X86_REG_PC]; +} + +uint64_t RegsX86::sp() { + return regs_[X86_REG_SP]; +} + +void RegsX86::set_pc(uint64_t pc) { + regs_[X86_REG_PC] = static_cast<uint32_t>(pc); +} + +void RegsX86::set_sp(uint64_t sp) { + regs_[X86_REG_SP] = static_cast<uint32_t>(sp); +} + uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { if (!elf->valid() || rel_pc == 0) { return 0; @@ -42,19 +57,15 @@ uint64_t RegsX86::GetPcAdjustment(uint64_t rel_pc, Elf* elf) { return 1; } -void RegsX86::SetFromRaw() { - set_pc(regs_[X86_REG_PC]); - set_sp(regs_[X86_REG_SP]); -} - bool RegsX86::SetPcFromReturnAddress(Memory* process_memory) { // Attempt to get the return address from the top of the stack. uint32_t new_pc; - if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) { + if (!process_memory->ReadFully(regs_[X86_REG_SP], &new_pc, sizeof(new_pc)) || + new_pc == regs_[X86_REG_PC]) { return false; } - set_pc(new_pc); + regs_[X86_REG_PC] = new_pc; return true; } @@ -84,7 +95,6 @@ Regs* RegsX86::Read(void* user_data) { (*regs)[X86_REG_ESP] = user->esp; (*regs)[X86_REG_EIP] = user->eip; - regs->SetFromRaw(); return regs; } @@ -99,7 +109,6 @@ void RegsX86::SetFromUcontext(x86_ucontext_t* ucontext) { regs_[X86_REG_ECX] = ucontext->uc_mcontext.ecx; regs_[X86_REG_EAX] = ucontext->uc_mcontext.eax; regs_[X86_REG_EIP] = ucontext->uc_mcontext.eip; - SetFromRaw(); } Regs* RegsX86::CreateFromUcontext(void* ucontext) { @@ -131,7 +140,7 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem // int signum // struct sigcontext (same format as mcontext) struct x86_mcontext_t context; - if (!process_memory->ReadFully(sp() + 4, &context, sizeof(context))) { + if (!process_memory->ReadFully(regs_[X86_REG_SP] + 4, &context, sizeof(context))) { return false; } regs_[X86_REG_EBP] = context.ebp; @@ -141,7 +150,6 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem regs_[X86_REG_ECX] = context.ecx; regs_[X86_REG_EAX] = context.eax; regs_[X86_REG_EIP] = context.eip; - SetFromRaw(); return true; } else if ((data & 0x00ffffffffffffffULL) == 0x0080cd000000adb8ULL) { // With SA_SIGINFO set, the return sequence is: @@ -157,7 +165,7 @@ bool RegsX86::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem // Get the location of the sigcontext data. uint32_t ptr; - if (!process_memory->ReadFully(sp() + 8, &ptr, sizeof(ptr))) { + if (!process_memory->ReadFully(regs_[X86_REG_SP] + 8, &ptr, sizeof(ptr))) { return false; } // Only read the portion of the data structure we care about. |