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
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 @@
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)[X86_REG_ESP] = user->esp;
(*regs)[X86_REG_EIP] = user->eip;
- regs->SetFromRaw();
return regs;
}
@@ -99,7 +109,6 @@
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 @@
// 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 @@
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 @@
// 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.