Merge "Always set the sp reg to the cfa for DWARF."
This commit is contained in:
commit
b22451f178
36 changed files with 417 additions and 254 deletions
|
@ -188,6 +188,7 @@ cc_test {
|
|||
data: [
|
||||
"tests/files/elf32.xz",
|
||||
"tests/files/elf64.xz",
|
||||
"tests/files/offline/art_quick_osr_stub_arm/*",
|
||||
"tests/files/offline/bad_eh_frame_hdr_arm64/*",
|
||||
"tests/files/offline/debug_frame_first_x86/*",
|
||||
"tests/files/offline/eh_frame_hdr_begin_x86_64/*",
|
||||
|
|
|
@ -190,8 +190,6 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
|||
// Always set the dex pc to zero when evaluating.
|
||||
cur_regs->set_dex_pc(0);
|
||||
|
||||
AddressType prev_cfa = regs->sp();
|
||||
|
||||
EvalInfo<AddressType> eval_info{.loc_regs = &loc_regs,
|
||||
.cie = cie,
|
||||
.regular_memory = regular_memory,
|
||||
|
@ -204,14 +202,7 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me
|
|||
last_error_.code = DWARF_ERROR_ILLEGAL_VALUE;
|
||||
return false;
|
||||
}
|
||||
// If the stack pointer register is the CFA, and the stack
|
||||
// pointer register does not have any associated location
|
||||
// information, use the current cfa value.
|
||||
if (regs->sp_reg() == loc->values[0] && loc_regs.count(regs->sp_reg()) == 0) {
|
||||
eval_info.cfa = prev_cfa;
|
||||
} else {
|
||||
eval_info.cfa = (*cur_regs)[loc->values[0]];
|
||||
}
|
||||
eval_info.cfa = (*cur_regs)[loc->values[0]];
|
||||
eval_info.cfa += loc->values[1];
|
||||
break;
|
||||
case DWARF_LOCATION_VAL_EXPRESSION: {
|
||||
|
|
|
@ -127,13 +127,9 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
|
|||
if (arm.ExtractEntryData(entry_offset) && arm.Eval()) {
|
||||
// If the pc was not set, then use the LR registers for the PC.
|
||||
if (!arm.pc_set()) {
|
||||
regs_arm->set_pc((*regs_arm)[ARM_REG_LR]);
|
||||
(*regs_arm)[ARM_REG_PC] = regs_arm->pc();
|
||||
} else {
|
||||
regs_arm->set_pc((*regs_arm)[ARM_REG_PC]);
|
||||
(*regs_arm)[ARM_REG_PC] = (*regs_arm)[ARM_REG_LR];
|
||||
}
|
||||
regs_arm->set_sp(arm.cfa());
|
||||
(*regs_arm)[ARM_REG_SP] = regs_arm->sp();
|
||||
(*regs_arm)[ARM_REG_SP] = arm.cfa();
|
||||
return_value = true;
|
||||
|
||||
// If the pc was set to zero, consider this the final frame.
|
||||
|
|
|
@ -28,13 +28,28 @@
|
|||
|
||||
namespace unwindstack {
|
||||
|
||||
RegsArm::RegsArm()
|
||||
: RegsImpl<uint32_t>(ARM_REG_LAST, ARM_REG_SP, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
|
||||
RegsArm::RegsArm() : RegsImpl<uint32_t>(ARM_REG_LAST, Location(LOCATION_REGISTER, ARM_REG_LR)) {}
|
||||
|
||||
ArchEnum RegsArm::Arch() {
|
||||
return ARCH_ARM;
|
||||
}
|
||||
|
||||
uint64_t RegsArm::pc() {
|
||||
return regs_[ARM_REG_PC];
|
||||
}
|
||||
|
||||
uint64_t RegsArm::sp() {
|
||||
return regs_[ARM_REG_SP];
|
||||
}
|
||||
|
||||
void RegsArm::set_pc(uint64_t pc) {
|
||||
regs_[ARM_REG_PC] = pc;
|
||||
}
|
||||
|
||||
void RegsArm::set_sp(uint64_t sp) {
|
||||
regs_[ARM_REG_SP] = sp;
|
||||
}
|
||||
|
||||
uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
||||
uint64_t load_bias = elf->GetLoadBias();
|
||||
if (rel_pc < load_bias) {
|
||||
|
@ -56,17 +71,13 @@ uint64_t RegsArm::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
|||
return 4;
|
||||
}
|
||||
|
||||
void RegsArm::SetFromRaw() {
|
||||
set_pc(regs_[ARM_REG_PC]);
|
||||
set_sp(regs_[ARM_REG_SP]);
|
||||
}
|
||||
|
||||
bool RegsArm::SetPcFromReturnAddress(Memory*) {
|
||||
if (pc() == regs_[ARM_REG_LR]) {
|
||||
uint32_t lr = regs_[ARM_REG_LR];
|
||||
if (regs_[ARM_REG_PC] == lr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_pc(regs_[ARM_REG_LR]);
|
||||
regs_[ARM_REG_PC] = lr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -94,7 +105,6 @@ Regs* RegsArm::Read(void* remote_data) {
|
|||
|
||||
RegsArm* regs = new RegsArm();
|
||||
memcpy(regs->RawData(), &user->regs[0], ARM_REG_LAST * sizeof(uint32_t));
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -103,7 +113,6 @@ Regs* RegsArm::CreateFromUcontext(void* ucontext) {
|
|||
|
||||
RegsArm* regs = new RegsArm();
|
||||
memcpy(regs->RawData(), &arm_ucontext->uc_mcontext.regs[0], ARM_REG_LAST * sizeof(uint32_t));
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -118,6 +127,7 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
|
|||
|
||||
uint64_t offset = 0;
|
||||
if (data == 0xe3a07077 || data == 0xef900077 || data == 0xdf002777) {
|
||||
uint64_t sp = regs_[ARM_REG_SP];
|
||||
// non-RT sigreturn call.
|
||||
// __restore:
|
||||
//
|
||||
|
@ -131,17 +141,18 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
|
|||
// Form 3 (thumb):
|
||||
// 0x77 0x27 movs r7, #77
|
||||
// 0x00 0xdf svc 0
|
||||
if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
|
||||
if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
if (data == 0x5ac3c35a) {
|
||||
// SP + uc_mcontext offset + r0 offset.
|
||||
offset = sp() + 0x14 + 0xc;
|
||||
offset = sp + 0x14 + 0xc;
|
||||
} else {
|
||||
// SP + r0 offset
|
||||
offset = sp() + 0xc;
|
||||
offset = sp + 0xc;
|
||||
}
|
||||
} else if (data == 0xe3a070ad || data == 0xef9000ad || data == 0xdf0027ad) {
|
||||
uint64_t sp = regs_[ARM_REG_SP];
|
||||
// RT sigreturn call.
|
||||
// __restore_rt:
|
||||
//
|
||||
|
@ -155,15 +166,15 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
|
|||
// Form 3 (thumb):
|
||||
// 0xad 0x27 movs r7, #ad
|
||||
// 0x00 0xdf svc 0
|
||||
if (!process_memory->ReadFully(sp(), &data, sizeof(data))) {
|
||||
if (!process_memory->ReadFully(sp, &data, sizeof(data))) {
|
||||
return false;
|
||||
}
|
||||
if (data == sp() + 8) {
|
||||
if (data == sp + 8) {
|
||||
// SP + 8 + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
|
||||
offset = sp() + 8 + 0x80 + 0x14 + 0xc;
|
||||
offset = sp + 8 + 0x80 + 0x14 + 0xc;
|
||||
} else {
|
||||
// SP + sizeof(siginfo_t) + uc_mcontext_offset + r0 offset
|
||||
offset = sp() + 0x80 + 0x14 + 0xc;
|
||||
offset = sp + 0x80 + 0x14 + 0xc;
|
||||
}
|
||||
}
|
||||
if (offset == 0) {
|
||||
|
@ -173,7 +184,6 @@ bool RegsArm::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_mem
|
|||
if (!process_memory->ReadFully(offset, regs_.data(), sizeof(uint32_t) * ARM_REG_LAST)) {
|
||||
return false;
|
||||
}
|
||||
SetFromRaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,28 @@
|
|||
namespace unwindstack {
|
||||
|
||||
RegsArm64::RegsArm64()
|
||||
: RegsImpl<uint64_t>(ARM64_REG_LAST, ARM64_REG_SP, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
|
||||
: RegsImpl<uint64_t>(ARM64_REG_LAST, Location(LOCATION_REGISTER, ARM64_REG_LR)) {}
|
||||
|
||||
ArchEnum RegsArm64::Arch() {
|
||||
return ARCH_ARM64;
|
||||
}
|
||||
|
||||
uint64_t RegsArm64::pc() {
|
||||
return regs_[ARM64_REG_PC];
|
||||
}
|
||||
|
||||
uint64_t RegsArm64::sp() {
|
||||
return regs_[ARM64_REG_SP];
|
||||
}
|
||||
|
||||
void RegsArm64::set_pc(uint64_t pc) {
|
||||
regs_[ARM64_REG_PC] = pc;
|
||||
}
|
||||
|
||||
void RegsArm64::set_sp(uint64_t sp) {
|
||||
regs_[ARM64_REG_SP] = sp;
|
||||
}
|
||||
|
||||
uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
||||
if (!elf->valid() || rel_pc < 4) {
|
||||
return 0;
|
||||
|
@ -42,17 +58,13 @@ uint64_t RegsArm64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
|||
return 4;
|
||||
}
|
||||
|
||||
void RegsArm64::SetFromRaw() {
|
||||
set_pc(regs_[ARM64_REG_PC]);
|
||||
set_sp(regs_[ARM64_REG_SP]);
|
||||
}
|
||||
|
||||
bool RegsArm64::SetPcFromReturnAddress(Memory*) {
|
||||
if (pc() == regs_[ARM64_REG_LR]) {
|
||||
uint64_t lr = regs_[ARM64_REG_LR];
|
||||
if (regs_[ARM64_REG_PC] == lr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_pc(regs_[ARM64_REG_LR]);
|
||||
regs_[ARM64_REG_PC] = lr;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +112,6 @@ Regs* RegsArm64::Read(void* remote_data) {
|
|||
uint64_t* reg_data = reinterpret_cast<uint64_t*>(regs->RawData());
|
||||
reg_data[ARM64_REG_PC] = user->pc;
|
||||
reg_data[ARM64_REG_SP] = user->sp;
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -109,7 +120,6 @@ Regs* RegsArm64::CreateFromUcontext(void* ucontext) {
|
|||
|
||||
RegsArm64* regs = new RegsArm64();
|
||||
memcpy(regs->RawData(), &arm64_ucontext->uc_mcontext.regs[0], ARM64_REG_LAST * sizeof(uint64_t));
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -131,12 +141,10 @@ bool RegsArm64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_m
|
|||
}
|
||||
|
||||
// SP + sizeof(siginfo_t) + uc_mcontext offset + X0 offset.
|
||||
if (!process_memory->ReadFully(sp() + 0x80 + 0xb0 + 0x08, regs_.data(),
|
||||
if (!process_memory->ReadFully(regs_[ARM64_REG_SP] + 0x80 + 0xb0 + 0x08, regs_.data(),
|
||||
sizeof(uint64_t) * ARM64_REG_LAST)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetFromRaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,12 +29,28 @@
|
|||
namespace unwindstack {
|
||||
|
||||
RegsMips::RegsMips()
|
||||
: RegsImpl<uint32_t>(MIPS_REG_LAST, MIPS_REG_SP, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
|
||||
: RegsImpl<uint32_t>(MIPS_REG_LAST, Location(LOCATION_REGISTER, MIPS_REG_RA)) {}
|
||||
|
||||
ArchEnum RegsMips::Arch() {
|
||||
return ARCH_MIPS;
|
||||
}
|
||||
|
||||
uint64_t RegsMips::pc() {
|
||||
return regs_[MIPS_REG_PC];
|
||||
}
|
||||
|
||||
uint64_t RegsMips::sp() {
|
||||
return regs_[MIPS_REG_SP];
|
||||
}
|
||||
|
||||
void RegsMips::set_pc(uint64_t pc) {
|
||||
regs_[MIPS_REG_PC] = static_cast<uint32_t>(pc);
|
||||
}
|
||||
|
||||
void RegsMips::set_sp(uint64_t sp) {
|
||||
regs_[MIPS_REG_SP] = static_cast<uint32_t>(sp);
|
||||
}
|
||||
|
||||
uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
||||
if (!elf->valid() || rel_pc < 8) {
|
||||
return 0;
|
||||
|
@ -43,17 +59,13 @@ uint64_t RegsMips::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
|||
return 8;
|
||||
}
|
||||
|
||||
void RegsMips::SetFromRaw() {
|
||||
set_pc(regs_[MIPS_REG_PC]);
|
||||
set_sp(regs_[MIPS_REG_SP]);
|
||||
}
|
||||
|
||||
bool RegsMips::SetPcFromReturnAddress(Memory*) {
|
||||
if (pc() == regs_[MIPS_REG_RA]) {
|
||||
uint32_t ra = regs_[MIPS_REG_RA];
|
||||
if (regs_[MIPS_REG_PC] == ra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_pc(regs_[MIPS_REG_RA]);
|
||||
regs_[MIPS_REG_PC] = ra;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -101,7 +113,6 @@ Regs* RegsMips::Read(void* remote_data) {
|
|||
memcpy(regs->RawData(), &user->regs[MIPS32_EF_R0], (MIPS_REG_R31 + 1) * sizeof(uint32_t));
|
||||
|
||||
reg_data[MIPS_REG_PC] = user->regs[MIPS32_EF_CP0_EPC];
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -114,7 +125,6 @@ Regs* RegsMips::CreateFromUcontext(void* ucontext) {
|
|||
(*regs)[MIPS_REG_R0 + i] = mips_ucontext->uc_mcontext.sc_regs[i];
|
||||
}
|
||||
(*regs)[MIPS_REG_PC] = mips_ucontext->uc_mcontext.sc_pc;
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -149,7 +159,7 @@ bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_me
|
|||
|
||||
// read sc_pc and sc_regs[32] from stack
|
||||
uint64_t values[MIPS_REG_LAST];
|
||||
if (!process_memory->Read(sp() + offset, values, sizeof(values))) {
|
||||
if (!process_memory->Read(regs_[MIPS_REG_SP] + offset, values, sizeof(values))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -160,8 +170,6 @@ bool RegsMips::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_me
|
|||
for (int i = 0; i < 32; i++) {
|
||||
regs_[MIPS_REG_R0 + i] = values[1 + i];
|
||||
}
|
||||
|
||||
SetFromRaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,13 +29,28 @@
|
|||
namespace unwindstack {
|
||||
|
||||
RegsMips64::RegsMips64()
|
||||
: RegsImpl<uint64_t>(MIPS64_REG_LAST, MIPS64_REG_SP,
|
||||
Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
|
||||
: RegsImpl<uint64_t>(MIPS64_REG_LAST, Location(LOCATION_REGISTER, MIPS64_REG_RA)) {}
|
||||
|
||||
ArchEnum RegsMips64::Arch() {
|
||||
return ARCH_MIPS64;
|
||||
}
|
||||
|
||||
uint64_t RegsMips64::pc() {
|
||||
return regs_[MIPS64_REG_PC];
|
||||
}
|
||||
|
||||
uint64_t RegsMips64::sp() {
|
||||
return regs_[MIPS64_REG_SP];
|
||||
}
|
||||
|
||||
void RegsMips64::set_pc(uint64_t pc) {
|
||||
regs_[MIPS64_REG_PC] = pc;
|
||||
}
|
||||
|
||||
void RegsMips64::set_sp(uint64_t sp) {
|
||||
regs_[MIPS64_REG_SP] = sp;
|
||||
}
|
||||
|
||||
uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
||||
if (!elf->valid() || rel_pc < 8) {
|
||||
return 0;
|
||||
|
@ -44,17 +59,13 @@ uint64_t RegsMips64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
|||
return 8;
|
||||
}
|
||||
|
||||
void RegsMips64::SetFromRaw() {
|
||||
set_pc(regs_[MIPS64_REG_PC]);
|
||||
set_sp(regs_[MIPS64_REG_SP]);
|
||||
}
|
||||
|
||||
bool RegsMips64::SetPcFromReturnAddress(Memory*) {
|
||||
if (pc() == regs_[MIPS64_REG_RA]) {
|
||||
uint64_t ra = regs_[MIPS64_REG_RA];
|
||||
if (regs_[MIPS64_REG_PC] == ra) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_pc(regs_[MIPS64_REG_RA]);
|
||||
regs_[MIPS64_REG_PC] = ra;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,7 +113,6 @@ Regs* RegsMips64::Read(void* remote_data) {
|
|||
memcpy(regs->RawData(), &user->regs[MIPS64_EF_R0], (MIPS64_REG_R31 + 1) * sizeof(uint64_t));
|
||||
|
||||
reg_data[MIPS64_REG_PC] = user->regs[MIPS64_EF_CP0_EPC];
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -113,7 +123,6 @@ Regs* RegsMips64::CreateFromUcontext(void* ucontext) {
|
|||
// Copy 64 bit sc_regs over to 64 bit regs
|
||||
memcpy(regs->RawData(), &mips64_ucontext->uc_mcontext.sc_regs[0], 32 * sizeof(uint64_t));
|
||||
(*regs)[MIPS64_REG_PC] = mips64_ucontext->uc_mcontext.sc_pc;
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -137,19 +146,17 @@ bool RegsMips64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_
|
|||
// vdso_rt_sigreturn => read rt_sigframe
|
||||
// offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset
|
||||
// read 64 bit sc_regs[32] from stack into 64 bit regs_
|
||||
if (!process_memory->Read(sp() + 24 + 128 + 40, regs_.data(),
|
||||
uint64_t sp = regs_[MIPS64_REG_SP];
|
||||
if (!process_memory->Read(sp + 24 + 128 + 40, regs_.data(),
|
||||
sizeof(uint64_t) * (MIPS64_REG_LAST - 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// offset = siginfo offset + sizeof(siginfo) + uc_mcontext offset + sc_pc offset
|
||||
// read 64 bit sc_pc from stack into 64 bit regs_[MIPS64_REG_PC]
|
||||
if (!process_memory->Read(sp() + 24 + 128 + 40 + 576, ®s_[MIPS64_REG_PC],
|
||||
sizeof(uint64_t))) {
|
||||
if (!process_memory->Read(sp + 24 + 128 + 40 + 576, ®s_[MIPS64_REG_PC], sizeof(uint64_t))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SetFromRaw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -28,13 +28,28 @@
|
|||
|
||||
namespace unwindstack {
|
||||
|
||||
RegsX86_64::RegsX86_64()
|
||||
: RegsImpl<uint64_t>(X86_64_REG_LAST, X86_64_REG_SP, Location(LOCATION_SP_OFFSET, -8)) {}
|
||||
RegsX86_64::RegsX86_64() : RegsImpl<uint64_t>(X86_64_REG_LAST, Location(LOCATION_SP_OFFSET, -8)) {}
|
||||
|
||||
ArchEnum RegsX86_64::Arch() {
|
||||
return ARCH_X86_64;
|
||||
}
|
||||
|
||||
uint64_t RegsX86_64::pc() {
|
||||
return regs_[X86_64_REG_PC];
|
||||
}
|
||||
|
||||
uint64_t RegsX86_64::sp() {
|
||||
return regs_[X86_64_REG_SP];
|
||||
}
|
||||
|
||||
void RegsX86_64::set_pc(uint64_t pc) {
|
||||
regs_[X86_64_REG_PC] = pc;
|
||||
}
|
||||
|
||||
void RegsX86_64::set_sp(uint64_t sp) {
|
||||
regs_[X86_64_REG_SP] = sp;
|
||||
}
|
||||
|
||||
uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
||||
if (!elf->valid() || rel_pc == 0) {
|
||||
return 0;
|
||||
|
@ -42,19 +57,15 @@ uint64_t RegsX86_64::GetPcAdjustment(uint64_t rel_pc, Elf* elf) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void RegsX86_64::SetFromRaw() {
|
||||
set_pc(regs_[X86_64_REG_PC]);
|
||||
set_sp(regs_[X86_64_REG_SP]);
|
||||
}
|
||||
|
||||
bool RegsX86_64::SetPcFromReturnAddress(Memory* process_memory) {
|
||||
// Attempt to get the return address from the top of the stack.
|
||||
uint64_t new_pc;
|
||||
if (!process_memory->ReadFully(sp_, &new_pc, sizeof(new_pc)) || new_pc == pc()) {
|
||||
if (!process_memory->ReadFully(regs_[X86_64_REG_SP], &new_pc, sizeof(new_pc)) ||
|
||||
new_pc == regs_[X86_64_REG_PC]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
set_pc(new_pc);
|
||||
regs_[X86_64_REG_PC] = new_pc;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -100,7 +111,6 @@ Regs* RegsX86_64::Read(void* remote_data) {
|
|||
(*regs)[X86_64_REG_RSP] = user->rsp;
|
||||
(*regs)[X86_64_REG_RIP] = user->rip;
|
||||
|
||||
regs->SetFromRaw();
|
||||
return regs;
|
||||
}
|
||||
|
||||
|
@ -118,8 +128,6 @@ void RegsX86_64::SetFromUcontext(x86_64_ucontext_t* ucontext) {
|
|||
regs_[X86_64_REG_RCX] = ucontext->uc_mcontext.rcx;
|
||||
regs_[X86_64_REG_RSP] = ucontext->uc_mcontext.rsp;
|
||||
regs_[X86_64_REG_RIP] = ucontext->uc_mcontext.rip;
|
||||
|
||||
SetFromRaw();
|
||||
}
|
||||
|
||||
Regs* RegsX86_64::CreateFromUcontext(void* ucontext) {
|
||||
|
@ -152,7 +160,7 @@ bool RegsX86_64::StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_
|
|||
// Read the mcontext data from the stack.
|
||||
// sp points to the ucontext data structure, read only the mcontext part.
|
||||
x86_64_ucontext_t x86_64_ucontext;
|
||||
if (!process_memory->ReadFully(sp() + 0x28, &x86_64_ucontext.uc_mcontext,
|
||||
if (!process_memory->ReadFully(regs_[X86_64_REG_SP] + 0x28, &x86_64_ucontext.uc_mcontext,
|
||||
sizeof(x86_64_mcontext_t))) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ class Regs {
|
|||
int16_t value;
|
||||
};
|
||||
|
||||
Regs(uint16_t total_regs, uint16_t sp_reg, const Location& return_loc)
|
||||
: total_regs_(total_regs), sp_reg_(sp_reg), return_loc_(return_loc) {}
|
||||
Regs(uint16_t total_regs, const Location& return_loc)
|
||||
: total_regs_(total_regs), return_loc_(return_loc) {}
|
||||
virtual ~Regs() = default;
|
||||
|
||||
virtual ArchEnum Arch() = 0;
|
||||
|
@ -57,6 +57,9 @@ class Regs {
|
|||
virtual uint64_t pc() = 0;
|
||||
virtual uint64_t sp() = 0;
|
||||
|
||||
virtual void set_pc(uint64_t pc) = 0;
|
||||
virtual void set_sp(uint64_t sp) = 0;
|
||||
|
||||
uint64_t dex_pc() { return dex_pc_; }
|
||||
void set_dex_pc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
|
||||
|
||||
|
@ -64,13 +67,10 @@ class Regs {
|
|||
|
||||
virtual bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) = 0;
|
||||
|
||||
virtual void SetFromRaw() = 0;
|
||||
|
||||
virtual bool SetPcFromReturnAddress(Memory* process_memory) = 0;
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) = 0;
|
||||
|
||||
uint16_t sp_reg() { return sp_reg_; }
|
||||
uint16_t total_regs() { return total_regs_; }
|
||||
|
||||
static ArchEnum CurrentArch();
|
||||
|
@ -80,7 +80,6 @@ class Regs {
|
|||
|
||||
protected:
|
||||
uint16_t total_regs_;
|
||||
uint16_t sp_reg_;
|
||||
Location return_loc_;
|
||||
uint64_t dex_pc_ = 0;
|
||||
};
|
||||
|
@ -88,16 +87,10 @@ class Regs {
|
|||
template <typename AddressType>
|
||||
class RegsImpl : public Regs {
|
||||
public:
|
||||
RegsImpl(uint16_t total_regs, uint16_t sp_reg, Location return_loc)
|
||||
: Regs(total_regs, sp_reg, return_loc), regs_(total_regs) {}
|
||||
RegsImpl(uint16_t total_regs, Location return_loc)
|
||||
: Regs(total_regs, return_loc), regs_(total_regs) {}
|
||||
virtual ~RegsImpl() = default;
|
||||
|
||||
uint64_t pc() override { return pc_; }
|
||||
uint64_t sp() override { return sp_; }
|
||||
|
||||
void set_pc(AddressType pc) { pc_ = pc; }
|
||||
void set_sp(AddressType sp) { sp_ = sp; }
|
||||
|
||||
bool Is32Bit() override { return sizeof(AddressType) == sizeof(uint32_t); }
|
||||
|
||||
inline AddressType& operator[](size_t reg) { return regs_[reg]; }
|
||||
|
@ -111,8 +104,6 @@ class RegsImpl : public Regs {
|
|||
}
|
||||
|
||||
protected:
|
||||
AddressType pc_;
|
||||
AddressType sp_;
|
||||
std::vector<AddressType> regs_;
|
||||
};
|
||||
|
||||
|
|
|
@ -34,17 +34,21 @@ class RegsArm : public RegsImpl<uint32_t> {
|
|||
RegsArm();
|
||||
virtual ~RegsArm() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -34,17 +34,21 @@ class RegsArm64 : public RegsImpl<uint64_t> {
|
|||
RegsArm64();
|
||||
virtual ~RegsArm64() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -51,8 +51,6 @@ inline __always_inline void RegsGetLocal(Regs* regs) {
|
|||
: [base] "+r"(reg_data)
|
||||
:
|
||||
: "memory");
|
||||
|
||||
regs->SetFromRaw();
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
@ -83,8 +81,6 @@ inline __always_inline void RegsGetLocal(Regs* regs) {
|
|||
: [base] "+r"(reg_data)
|
||||
:
|
||||
: "x12", "x13", "memory");
|
||||
|
||||
regs->SetFromRaw();
|
||||
}
|
||||
|
||||
#elif defined(__i386__) || defined(__x86_64__) || defined(__mips__)
|
||||
|
@ -93,8 +89,6 @@ extern "C" void AsmGetRegs(void* regs);
|
|||
|
||||
inline void RegsGetLocal(Regs* regs) {
|
||||
AsmGetRegs(regs->RawData());
|
||||
|
||||
regs->SetFromRaw();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,17 +34,21 @@ class RegsMips : public RegsImpl<uint32_t> {
|
|||
RegsMips();
|
||||
virtual ~RegsMips() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -34,17 +34,21 @@ class RegsMips64 : public RegsImpl<uint64_t> {
|
|||
RegsMips64();
|
||||
virtual ~RegsMips64() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -35,19 +35,23 @@ class RegsX86 : public RegsImpl<uint32_t> {
|
|||
RegsX86();
|
||||
virtual ~RegsX86() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
void SetFromUcontext(x86_ucontext_t* ucontext);
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -35,19 +35,23 @@ class RegsX86_64 : public RegsImpl<uint64_t> {
|
|||
RegsX86_64();
|
||||
virtual ~RegsX86_64() = default;
|
||||
|
||||
virtual ArchEnum Arch() override final;
|
||||
ArchEnum Arch() override final;
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t rel_pc, Elf* elf) override;
|
||||
|
||||
void SetFromRaw() override;
|
||||
|
||||
bool SetPcFromReturnAddress(Memory* process_memory) override;
|
||||
|
||||
bool StepIfSignalHandler(uint64_t rel_pc, Elf* elf, Memory* process_memory) override;
|
||||
|
||||
void SetFromUcontext(x86_64_ucontext_t* ucontext);
|
||||
|
||||
virtual void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
void IterateRegisters(std::function<void(const char*, uint64_t)>) override final;
|
||||
|
||||
uint64_t pc() override;
|
||||
uint64_t sp() override;
|
||||
|
||||
void set_pc(uint64_t pc) override;
|
||||
void set_sp(uint64_t sp) override;
|
||||
|
||||
static Regs* Read(void* data);
|
||||
|
||||
|
|
|
@ -1468,7 +1468,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg) {
|
|||
}
|
||||
this->op_memory_.SetMemory(0, opcode_buffer);
|
||||
|
||||
RegsImplFake<TypeParam> regs(32, 10);
|
||||
RegsImplFake<TypeParam> regs(32);
|
||||
for (size_t i = 0; i < 32; i++) {
|
||||
regs[i] = i + 10;
|
||||
}
|
||||
|
@ -1499,7 +1499,7 @@ TYPED_TEST_P(DwarfOpTest, op_breg_invalid_register) {
|
|||
};
|
||||
this->op_memory_.SetMemory(0, opcode_buffer);
|
||||
|
||||
RegsImplFake<TypeParam> regs(16, 10);
|
||||
RegsImplFake<TypeParam> regs(16);
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
regs[i] = i + 10;
|
||||
}
|
||||
|
@ -1526,7 +1526,7 @@ TYPED_TEST_P(DwarfOpTest, op_bregx) {
|
|||
0x92, 0x80, 0x15, 0x80, 0x02};
|
||||
this->op_memory_.SetMemory(0, opcode_buffer);
|
||||
|
||||
RegsImplFake<TypeParam> regs(10, 10);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
regs[5] = 0x45;
|
||||
regs[6] = 0x190;
|
||||
RegsInfo<TypeParam> regs_info(®s);
|
||||
|
|
|
@ -92,7 +92,7 @@ TYPED_TEST_CASE_P(DwarfSectionImplTest);
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -108,7 +108,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -124,7 +124,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -142,7 +142,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -160,7 +160,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -176,7 +176,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
|
||||
DwarfCie cie{.return_address_register = 60};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
bool finished;
|
||||
|
@ -186,7 +186,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
bool finished;
|
||||
|
@ -196,7 +196,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
|
||||
|
@ -225,7 +225,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -237,12 +237,12 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
|
|||
ASSERT_TRUE(this->section_->Eval(&cie, &this->memory_, loc_regs, ®s, &finished));
|
||||
EXPECT_FALSE(finished);
|
||||
EXPECT_EQ(0x20U, regs.pc());
|
||||
EXPECT_EQ(0x2000U, regs.sp());
|
||||
EXPECT_EQ(0x3000U, regs.sp());
|
||||
}
|
||||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -260,7 +260,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -281,7 +281,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -312,7 +312,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -331,7 +331,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -346,7 +346,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
if (sizeof(TypeParam) == sizeof(uint64_t)) {
|
||||
|
@ -380,7 +380,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -398,7 +398,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -415,7 +415,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -432,7 +432,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
|
||||
DwarfCie cie{.return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -451,7 +451,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
@ -471,7 +471,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
|
|||
|
||||
TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
|
||||
DwarfCie cie{.version = 3, .return_address_register = 5};
|
||||
RegsImplFake<TypeParam> regs(10, 9);
|
||||
RegsImplFake<TypeParam> regs(10);
|
||||
dwarf_loc_regs_t loc_regs;
|
||||
|
||||
regs.set_pc(0x100);
|
||||
|
|
|
@ -65,8 +65,8 @@ bool ElfInterfaceFake::Step(uint64_t, uint64_t, Regs* regs, Memory*, bool* finis
|
|||
}
|
||||
|
||||
RegsFake* fake_regs = reinterpret_cast<RegsFake*>(regs);
|
||||
fake_regs->FakeSetPc(entry.pc);
|
||||
fake_regs->FakeSetSp(entry.sp);
|
||||
fake_regs->set_pc(entry.pc);
|
||||
fake_regs->set_sp(entry.sp);
|
||||
*finished = entry.finished;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -316,7 +316,6 @@ TEST_F(ElfTest, step_in_signal_map) {
|
|||
RegsArm regs;
|
||||
regs[13] = 0x50000;
|
||||
regs[15] = 0x8000;
|
||||
regs.SetFromRaw();
|
||||
|
||||
ElfInterfaceFake* interface = new ElfInterfaceFake(memory_);
|
||||
elf.FakeSetInterface(interface);
|
||||
|
|
|
@ -27,14 +27,16 @@ namespace unwindstack {
|
|||
|
||||
class RegsFake : public Regs {
|
||||
public:
|
||||
RegsFake(uint16_t total_regs, uint16_t sp_reg)
|
||||
: Regs(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
|
||||
RegsFake(uint16_t total_regs) : Regs(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
|
||||
virtual ~RegsFake() = default;
|
||||
|
||||
ArchEnum Arch() override { return fake_arch_; }
|
||||
void* RawData() override { return nullptr; }
|
||||
uint64_t pc() override { return fake_pc_; }
|
||||
uint64_t sp() override { return fake_sp_; }
|
||||
void set_pc(uint64_t pc) override { fake_pc_ = pc; }
|
||||
void set_sp(uint64_t sp) override { fake_sp_ = sp; }
|
||||
|
||||
bool SetPcFromReturnAddress(Memory*) override {
|
||||
if (!fake_return_address_valid_) {
|
||||
return false;
|
||||
|
@ -51,11 +53,7 @@ class RegsFake : public Regs {
|
|||
|
||||
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
||||
|
||||
void SetFromRaw() override {}
|
||||
|
||||
void FakeSetArch(ArchEnum arch) { fake_arch_ = arch; }
|
||||
void FakeSetPc(uint64_t pc) { fake_pc_ = pc; }
|
||||
void FakeSetSp(uint64_t sp) { fake_sp_ = sp; }
|
||||
void FakeSetDexPc(uint64_t dex_pc) { dex_pc_ = dex_pc; }
|
||||
void FakeSetReturnAddress(uint64_t return_address) { fake_return_address_ = return_address; }
|
||||
void FakeSetReturnAddressValid(bool valid) { fake_return_address_valid_ = valid; }
|
||||
|
@ -71,19 +69,23 @@ class RegsFake : public Regs {
|
|||
template <typename TypeParam>
|
||||
class RegsImplFake : public RegsImpl<TypeParam> {
|
||||
public:
|
||||
RegsImplFake(uint16_t total_regs, uint16_t sp_reg)
|
||||
: RegsImpl<TypeParam>(total_regs, sp_reg, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
|
||||
RegsImplFake(uint16_t total_regs)
|
||||
: RegsImpl<TypeParam>(total_regs, Regs::Location(Regs::LOCATION_UNKNOWN, 0)) {}
|
||||
virtual ~RegsImplFake() = default;
|
||||
|
||||
ArchEnum Arch() override { return ARCH_UNKNOWN; }
|
||||
uint64_t pc() override { return fake_pc_; }
|
||||
uint64_t sp() override { return fake_sp_; }
|
||||
void set_pc(uint64_t pc) override { fake_pc_ = pc; }
|
||||
void set_sp(uint64_t sp) override { fake_sp_ = sp; }
|
||||
|
||||
uint64_t GetPcAdjustment(uint64_t, Elf*) override { return 0; }
|
||||
void SetFromRaw() override {}
|
||||
bool SetPcFromReturnAddress(Memory*) override { return false; }
|
||||
bool StepIfSignalHandler(uint64_t, Elf*, Memory*) override { return false; }
|
||||
|
||||
void FakeSetPc(uint64_t pc) { this->pc_ = pc; }
|
||||
void FakeSetSp(uint64_t sp) { this->sp_ = sp; }
|
||||
private:
|
||||
uint64_t fake_pc_ = 0;
|
||||
uint64_t fake_sp_ = 0;
|
||||
};
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -56,7 +56,6 @@ void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerNonRt(uint32_t pc_data)
|
|||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
|
@ -87,7 +86,6 @@ void RegsStepIfSignalHandlerTest::ArmStepIfSignalHandlerRt(uint32_t pc_data) {
|
|||
RegsArm regs;
|
||||
regs[ARM_REG_PC] = 0x5000;
|
||||
regs[ARM_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData32(0x5000, pc_data);
|
||||
|
||||
|
@ -118,7 +116,6 @@ TEST_F(RegsStepIfSignalHandlerTest, arm64_step_if_signal_handler) {
|
|||
RegsArm64 regs;
|
||||
regs[ARM64_REG_PC] = 0x8000;
|
||||
regs[ARM64_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x8000, 0xd4000001d2801168ULL);
|
||||
|
||||
|
@ -138,7 +135,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_no_siginfo) {
|
|||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x4100, 0x80cd00000077b858ULL);
|
||||
for (uint64_t index = 0; index <= 25; index++) {
|
||||
|
@ -162,7 +158,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_step_if_signal_handler_siginfo) {
|
|||
RegsX86 regs;
|
||||
regs[X86_REG_EIP] = 0x4100;
|
||||
regs[X86_REG_ESP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x4100, 0x0080cd000000adb8ULL);
|
||||
addr += 8;
|
||||
|
@ -191,7 +186,6 @@ TEST_F(RegsStepIfSignalHandlerTest, x86_64_step_if_signal_handler) {
|
|||
RegsX86_64 regs;
|
||||
regs[X86_64_REG_RIP] = 0x7000;
|
||||
regs[X86_64_REG_RSP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x7000, 0x0f0000000fc0c748);
|
||||
elf_memory_->SetData16(0x7008, 0x0f05);
|
||||
|
@ -212,7 +206,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_non_rt) {
|
|||
RegsMips regs;
|
||||
regs[MIPS_REG_PC] = 0x8000;
|
||||
regs[MIPS_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x8000, 0x0000000c24021017ULL);
|
||||
|
||||
|
@ -232,7 +225,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips_step_if_signal_handler_rt) {
|
|||
RegsMips regs;
|
||||
regs[MIPS_REG_PC] = 0x8000;
|
||||
regs[MIPS_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x8000, 0x0000000c24021061ULL);
|
||||
|
||||
|
@ -252,7 +244,6 @@ TEST_F(RegsStepIfSignalHandlerTest, mips64_step_if_signal_handler) {
|
|||
RegsMips64 regs;
|
||||
regs[MIPS64_REG_PC] = 0x8000;
|
||||
regs[MIPS64_REG_SP] = addr;
|
||||
regs.SetFromRaw();
|
||||
|
||||
elf_memory_->SetData64(0x8000, 0x0000000c2402145bULL);
|
||||
|
||||
|
|
|
@ -49,9 +49,8 @@ class RegsTest : public ::testing::Test {
|
|||
};
|
||||
|
||||
TEST_F(RegsTest, regs32) {
|
||||
RegsImplFake<uint32_t> regs32(50, 10);
|
||||
RegsImplFake<uint32_t> regs32(50);
|
||||
ASSERT_EQ(50U, regs32.total_regs());
|
||||
ASSERT_EQ(10U, regs32.sp_reg());
|
||||
|
||||
uint32_t* raw = reinterpret_cast<uint32_t*>(regs32.RawData());
|
||||
for (size_t i = 0; i < 50; i++) {
|
||||
|
@ -72,9 +71,8 @@ TEST_F(RegsTest, regs32) {
|
|||
}
|
||||
|
||||
TEST_F(RegsTest, regs64) {
|
||||
RegsImplFake<uint64_t> regs64(30, 12);
|
||||
RegsImplFake<uint64_t> regs64(30);
|
||||
ASSERT_EQ(30U, regs64.total_regs());
|
||||
ASSERT_EQ(12U, regs64.sp_reg());
|
||||
|
||||
uint64_t* raw = reinterpret_cast<uint64_t*>(regs64.RawData());
|
||||
for (size_t i = 0; i < 30; i++) {
|
||||
|
@ -211,62 +209,56 @@ TEST_F(RegsTest, elf_invalid) {
|
|||
EXPECT_EQ(0U, regs_mips64.GetPcAdjustment(0xa00U, invalid_elf));
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, arm_set_from_raw) {
|
||||
TEST_F(RegsTest, arm_verify_sp_pc) {
|
||||
RegsArm arm;
|
||||
uint32_t* regs = reinterpret_cast<uint32_t*>(arm.RawData());
|
||||
regs[13] = 0x100;
|
||||
regs[15] = 0x200;
|
||||
arm.SetFromRaw();
|
||||
EXPECT_EQ(0x100U, arm.sp());
|
||||
EXPECT_EQ(0x200U, arm.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, arm64_set_from_raw) {
|
||||
TEST_F(RegsTest, arm64_verify_sp_pc) {
|
||||
RegsArm64 arm64;
|
||||
uint64_t* regs = reinterpret_cast<uint64_t*>(arm64.RawData());
|
||||
regs[31] = 0xb100000000ULL;
|
||||
regs[32] = 0xc200000000ULL;
|
||||
arm64.SetFromRaw();
|
||||
EXPECT_EQ(0xb100000000U, arm64.sp());
|
||||
EXPECT_EQ(0xc200000000U, arm64.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, x86_set_from_raw) {
|
||||
TEST_F(RegsTest, x86_verify_sp_pc) {
|
||||
RegsX86 x86;
|
||||
uint32_t* regs = reinterpret_cast<uint32_t*>(x86.RawData());
|
||||
regs[4] = 0x23450000;
|
||||
regs[8] = 0xabcd0000;
|
||||
x86.SetFromRaw();
|
||||
EXPECT_EQ(0x23450000U, x86.sp());
|
||||
EXPECT_EQ(0xabcd0000U, x86.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, x86_64_set_from_raw) {
|
||||
TEST_F(RegsTest, x86_64_verify_sp_pc) {
|
||||
RegsX86_64 x86_64;
|
||||
uint64_t* regs = reinterpret_cast<uint64_t*>(x86_64.RawData());
|
||||
regs[7] = 0x1200000000ULL;
|
||||
regs[16] = 0x4900000000ULL;
|
||||
x86_64.SetFromRaw();
|
||||
EXPECT_EQ(0x1200000000U, x86_64.sp());
|
||||
EXPECT_EQ(0x4900000000U, x86_64.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, mips_set_from_raw) {
|
||||
TEST_F(RegsTest, mips_verify_sp_pc) {
|
||||
RegsMips mips;
|
||||
uint32_t* regs = reinterpret_cast<uint32_t*>(mips.RawData());
|
||||
regs[29] = 0x100;
|
||||
regs[32] = 0x200;
|
||||
mips.SetFromRaw();
|
||||
EXPECT_EQ(0x100U, mips.sp());
|
||||
EXPECT_EQ(0x200U, mips.pc());
|
||||
}
|
||||
|
||||
TEST_F(RegsTest, mips64_set_from_raw) {
|
||||
TEST_F(RegsTest, mips64_verify_sp_pc) {
|
||||
RegsMips64 mips64;
|
||||
uint64_t* regs = reinterpret_cast<uint64_t*>(mips64.RawData());
|
||||
regs[29] = 0xb100000000ULL;
|
||||
regs[32] = 0xc200000000ULL;
|
||||
mips64.SetFromRaw();
|
||||
EXPECT_EQ(0xb100000000U, mips64.sp());
|
||||
EXPECT_EQ(0xc200000000U, mips64.pc());
|
||||
}
|
||||
|
|
|
@ -122,7 +122,6 @@ class UnwindOfflineTest : public ::testing::Test {
|
|||
(*regs)[entry->second] = value;
|
||||
}
|
||||
fclose(fp);
|
||||
regs->SetFromRaw();
|
||||
}
|
||||
|
||||
static std::unordered_map<std::string, uint32_t> arm_regs_;
|
||||
|
@ -956,4 +955,119 @@ TEST_F(UnwindOfflineTest, eh_frame_hdr_begin_x86_64) {
|
|||
EXPECT_EQ(0x7ffcc85971a0U, unwinder.frames()[4].sp);
|
||||
}
|
||||
|
||||
TEST_F(UnwindOfflineTest, art_quick_osr_stub_arm) {
|
||||
Init("art_quick_osr_stub_arm/", ARCH_ARM);
|
||||
|
||||
MemoryOfflineParts* memory = new MemoryOfflineParts;
|
||||
AddMemory(dir_ + "descriptor.data", memory);
|
||||
AddMemory(dir_ + "stack.data", memory);
|
||||
for (size_t i = 0; i < 2; i++) {
|
||||
AddMemory(dir_ + "entry" + std::to_string(i) + ".data", memory);
|
||||
AddMemory(dir_ + "jit" + std::to_string(i) + ".data", memory);
|
||||
}
|
||||
process_memory_.reset(memory);
|
||||
|
||||
JitDebug jit_debug(process_memory_);
|
||||
Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
|
||||
unwinder.SetJitDebug(&jit_debug, regs_->Arch());
|
||||
unwinder.Unwind();
|
||||
|
||||
std::string frame_info(DumpFrames(unwinder));
|
||||
ASSERT_EQ(25U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
|
||||
EXPECT_EQ(
|
||||
" #00 pc 0000c788 <anonymous:d0250000> "
|
||||
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity.access$000)\n"
|
||||
" #01 pc 0000cdd5 <anonymous:d0250000> "
|
||||
"(com.example.simpleperf.simpleperfexamplewithnative.MixActivity$1.run+60)\n"
|
||||
" #02 pc 004135bb libart.so (art_quick_osr_stub+42)\n"
|
||||
" #03 pc 002657a5 libart.so "
|
||||
"(_ZN3art3jit3Jit25MaybeDoOnStackReplacementEPNS_6ThreadEPNS_9ArtMethodEjiPNS_6JValueE+876)\n"
|
||||
" #04 pc 004021a7 libart.so (MterpMaybeDoOnStackReplacement+86)\n"
|
||||
" #05 pc 00412474 libart.so (ExecuteMterpImpl+66164)\n"
|
||||
" #06 pc cd8365b0 <unknown>\n" // symbol in dex file
|
||||
" #07 pc 001d7f1b libart.so "
|
||||
"(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
|
||||
"6JValueEb+374)\n"
|
||||
" #08 pc 001dc593 libart.so "
|
||||
"(_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadERKNS_"
|
||||
"20CodeItemDataAccessorEPNS_11ShadowFrameEPNS_6JValueE+154)\n"
|
||||
" #09 pc 001f4d01 libart.so "
|
||||
"(_ZN3art11interpreter6DoCallILb0ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_"
|
||||
"11InstructionEtPNS_6JValueE+732)\n"
|
||||
" #10 pc 003fe427 libart.so (MterpInvokeInterface+1354)\n"
|
||||
" #11 pc 00405b94 libart.so (ExecuteMterpImpl+14740)\n"
|
||||
" #12 pc 7004873e <unknown>\n" // symbol in dex file
|
||||
" #13 pc 001d7f1b libart.so "
|
||||
"(_ZN3art11interpreterL7ExecuteEPNS_6ThreadERKNS_20CodeItemDataAccessorERNS_11ShadowFrameENS_"
|
||||
"6JValueEb+374)\n"
|
||||
" #14 pc 001dc4d5 libart.so "
|
||||
"(_ZN3art11interpreter30EnterInterpreterFromEntryPointEPNS_6ThreadERKNS_"
|
||||
"20CodeItemDataAccessorEPNS_11ShadowFrameE+92)\n"
|
||||
" #15 pc 003f25ab libart.so (artQuickToInterpreterBridge+970)\n"
|
||||
" #16 pc 00417aff libart.so (art_quick_to_interpreter_bridge+30)\n"
|
||||
" #17 pc 00413575 libart.so (art_quick_invoke_stub_internal+68)\n"
|
||||
" #18 pc 00418531 libart.so (art_quick_invoke_stub+236)\n"
|
||||
" #19 pc 000b468d libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+136)\n"
|
||||
" #20 pc 00362f49 libart.so "
|
||||
"(_ZN3art12_GLOBAL__N_118InvokeWithArgArrayERKNS_33ScopedObjectAccessAlreadyRunnableEPNS_"
|
||||
"9ArtMethodEPNS0_8ArgArrayEPNS_6JValueEPKc+52)\n"
|
||||
" #21 pc 00363cd9 libart.so "
|
||||
"(_ZN3art35InvokeVirtualOrInterfaceWithJValuesERKNS_33ScopedObjectAccessAlreadyRunnableEP8_"
|
||||
"jobjectP10_jmethodIDP6jvalue+332)\n"
|
||||
" #22 pc 003851dd libart.so (_ZN3art6Thread14CreateCallbackEPv+868)\n"
|
||||
" #23 pc 00062925 libc.so (_ZL15__pthread_startPv+22)\n"
|
||||
" #24 pc 0001de39 libc.so (__start_thread+24)\n",
|
||||
frame_info);
|
||||
EXPECT_EQ(0xd025c788U, unwinder.frames()[0].pc);
|
||||
EXPECT_EQ(0xcd4ff140U, unwinder.frames()[0].sp);
|
||||
EXPECT_EQ(0xd025cdd5U, unwinder.frames()[1].pc);
|
||||
EXPECT_EQ(0xcd4ff140U, unwinder.frames()[1].sp);
|
||||
EXPECT_EQ(0xe4a755bbU, unwinder.frames()[2].pc);
|
||||
EXPECT_EQ(0xcd4ff160U, unwinder.frames()[2].sp);
|
||||
EXPECT_EQ(0xe48c77a5U, unwinder.frames()[3].pc);
|
||||
EXPECT_EQ(0xcd4ff190U, unwinder.frames()[3].sp);
|
||||
EXPECT_EQ(0xe4a641a7U, unwinder.frames()[4].pc);
|
||||
EXPECT_EQ(0xcd4ff298U, unwinder.frames()[4].sp);
|
||||
EXPECT_EQ(0xe4a74474U, unwinder.frames()[5].pc);
|
||||
EXPECT_EQ(0xcd4ff2b8U, unwinder.frames()[5].sp);
|
||||
EXPECT_EQ(0xcd8365b0U, unwinder.frames()[6].pc);
|
||||
EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[6].sp);
|
||||
EXPECT_EQ(0xe4839f1bU, unwinder.frames()[7].pc);
|
||||
EXPECT_EQ(0xcd4ff2e0U, unwinder.frames()[7].sp);
|
||||
EXPECT_EQ(0xe483e593U, unwinder.frames()[8].pc);
|
||||
EXPECT_EQ(0xcd4ff330U, unwinder.frames()[8].sp);
|
||||
EXPECT_EQ(0xe4856d01U, unwinder.frames()[9].pc);
|
||||
EXPECT_EQ(0xcd4ff380U, unwinder.frames()[9].sp);
|
||||
EXPECT_EQ(0xe4a60427U, unwinder.frames()[10].pc);
|
||||
EXPECT_EQ(0xcd4ff430U, unwinder.frames()[10].sp);
|
||||
EXPECT_EQ(0xe4a67b94U, unwinder.frames()[11].pc);
|
||||
EXPECT_EQ(0xcd4ff498U, unwinder.frames()[11].sp);
|
||||
EXPECT_EQ(0x7004873eU, unwinder.frames()[12].pc);
|
||||
EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[12].sp);
|
||||
EXPECT_EQ(0xe4839f1bU, unwinder.frames()[13].pc);
|
||||
EXPECT_EQ(0xcd4ff4c0U, unwinder.frames()[13].sp);
|
||||
EXPECT_EQ(0xe483e4d5U, unwinder.frames()[14].pc);
|
||||
EXPECT_EQ(0xcd4ff510U, unwinder.frames()[14].sp);
|
||||
EXPECT_EQ(0xe4a545abU, unwinder.frames()[15].pc);
|
||||
EXPECT_EQ(0xcd4ff538U, unwinder.frames()[15].sp);
|
||||
EXPECT_EQ(0xe4a79affU, unwinder.frames()[16].pc);
|
||||
EXPECT_EQ(0xcd4ff640U, unwinder.frames()[16].sp);
|
||||
EXPECT_EQ(0xe4a75575U, unwinder.frames()[17].pc);
|
||||
EXPECT_EQ(0xcd4ff6b0U, unwinder.frames()[17].sp);
|
||||
EXPECT_EQ(0xe4a7a531U, unwinder.frames()[18].pc);
|
||||
EXPECT_EQ(0xcd4ff6e8U, unwinder.frames()[18].sp);
|
||||
EXPECT_EQ(0xe471668dU, unwinder.frames()[19].pc);
|
||||
EXPECT_EQ(0xcd4ff770U, unwinder.frames()[19].sp);
|
||||
EXPECT_EQ(0xe49c4f49U, unwinder.frames()[20].pc);
|
||||
EXPECT_EQ(0xcd4ff7c8U, unwinder.frames()[20].sp);
|
||||
EXPECT_EQ(0xe49c5cd9U, unwinder.frames()[21].pc);
|
||||
EXPECT_EQ(0xcd4ff850U, unwinder.frames()[21].sp);
|
||||
EXPECT_EQ(0xe49e71ddU, unwinder.frames()[22].pc);
|
||||
EXPECT_EQ(0xcd4ff8e8U, unwinder.frames()[22].sp);
|
||||
EXPECT_EQ(0xe7df3925U, unwinder.frames()[23].pc);
|
||||
EXPECT_EQ(0xcd4ff958U, unwinder.frames()[23].sp);
|
||||
EXPECT_EQ(0xe7daee39U, unwinder.frames()[24].pc);
|
||||
EXPECT_EQ(0xcd4ff960U, unwinder.frames()[24].sp);
|
||||
}
|
||||
|
||||
} // namespace unwindstack
|
||||
|
|
|
@ -133,7 +133,7 @@ class UnwinderTest : public ::testing::Test {
|
|||
};
|
||||
|
||||
MapsFake UnwinderTest::maps_;
|
||||
RegsFake UnwinderTest::regs_(5, 0);
|
||||
RegsFake UnwinderTest::regs_(5);
|
||||
std::shared_ptr<Memory> UnwinderTest::process_memory_(nullptr);
|
||||
|
||||
TEST_F(UnwinderTest, multiple_frames) {
|
||||
|
@ -141,8 +141,8 @@ TEST_F(UnwinderTest, multiple_frames) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
@ -201,8 +201,8 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
@ -260,8 +260,8 @@ TEST_F(UnwinderTest, multiple_frames_dont_resolve_names) {
|
|||
TEST_F(UnwinderTest, non_zero_load_bias) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
|
||||
regs_.FakeSetPc(0xa5500);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0xa5500);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
|
@ -288,8 +288,8 @@ TEST_F(UnwinderTest, non_zero_load_bias) {
|
|||
TEST_F(UnwinderTest, non_zero_elf_offset) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
|
||||
regs_.FakeSetPc(0xa7500);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0xa7500);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
|
@ -316,8 +316,8 @@ TEST_F(UnwinderTest, non_zero_elf_offset) {
|
|||
TEST_F(UnwinderTest, non_zero_map_offset) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
|
||||
regs_.FakeSetPc(0x43000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x43000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
|
@ -349,8 +349,8 @@ TEST_F(UnwinderTest, no_frames_after_finished) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1000, 0x10000, true));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1102, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x1202, 0x10020, false));
|
||||
|
@ -383,8 +383,8 @@ TEST_F(UnwinderTest, max_frames) {
|
|||
ElfInterfaceFake::FakePushStepData(StepData(0x1102 + i * 0x100, 0x10010 + i * 0x10, false));
|
||||
}
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
|
||||
Unwinder unwinder(20, &maps_, ®s_, process_memory_);
|
||||
unwinder.Unwind();
|
||||
|
@ -415,8 +415,8 @@ TEST_F(UnwinderTest, verify_frames_skipped) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
|
||||
regs_.FakeSetPc(0x20000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x20000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x20002, 0x10030, false));
|
||||
|
@ -481,8 +481,8 @@ TEST_F(UnwinderTest, sp_not_in_map) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x63000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x63000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x21002, 0x50020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
||||
|
@ -527,8 +527,8 @@ TEST_F(UnwinderTest, pc_in_device_stops_unwind) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
|
||||
regs_.FakeSetPc(0x13000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x13000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
@ -546,8 +546,8 @@ TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame2", 2));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x13000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x13000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23002, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x23102, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
@ -563,8 +563,8 @@ TEST_F(UnwinderTest, sp_in_device_stops_unwind) {
|
|||
TEST_F(UnwinderTest, pc_without_map) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
|
||||
regs_.FakeSetPc(0x41000);
|
||||
regs_.FakeSetSp(0x13000);
|
||||
regs_.set_pc(0x41000);
|
||||
regs_.set_sp(0x13000);
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
unwinder.Unwind();
|
||||
|
@ -593,8 +593,8 @@ TEST_F(UnwinderTest, speculative_frame) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
|
||||
// Fake as if code called a nullptr function.
|
||||
regs_.FakeSetPc(0);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0);
|
||||
regs_.set_sp(0x10000);
|
||||
regs_.FakeSetReturnAddress(0x1202);
|
||||
regs_.FakeSetReturnAddressValid(true);
|
||||
|
||||
|
@ -657,8 +657,8 @@ TEST_F(UnwinderTest, speculative_frame_removed) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
|
||||
// Fake as if code called a nullptr function.
|
||||
regs_.FakeSetPc(0);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0);
|
||||
regs_.set_sp(0x10000);
|
||||
regs_.FakeSetReturnAddress(0x1202);
|
||||
regs_.FakeSetReturnAddressValid(true);
|
||||
|
||||
|
@ -691,8 +691,8 @@ TEST_F(UnwinderTest, map_ignore_suffixes) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
|
||||
|
||||
// Fake as if code called a nullptr function.
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x43402, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x53502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
@ -745,8 +745,8 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) {
|
|||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame3", 3));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame4", 4));
|
||||
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33502, 0x10020, false));
|
||||
|
@ -805,8 +805,8 @@ TEST_F(UnwinderTest, sp_pc_do_not_change) {
|
|||
|
||||
TEST_F(UnwinderTest, dex_pc_in_map) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
regs_.FakeSetDexPc(0xa3400);
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
|
@ -846,8 +846,8 @@ TEST_F(UnwinderTest, dex_pc_in_map) {
|
|||
|
||||
TEST_F(UnwinderTest, dex_pc_not_in_map) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
regs_.FakeSetDexPc(0x50000);
|
||||
|
||||
Unwinder unwinder(64, &maps_, ®s_, process_memory_);
|
||||
|
@ -888,8 +888,8 @@ TEST_F(UnwinderTest, dex_pc_not_in_map) {
|
|||
TEST_F(UnwinderTest, dex_pc_multiple_frames) {
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame0", 0));
|
||||
ElfInterfaceFake::FakePushFunctionData(FunctionData("Frame1", 1));
|
||||
regs_.FakeSetPc(0x1000);
|
||||
regs_.FakeSetSp(0x10000);
|
||||
regs_.set_pc(0x1000);
|
||||
regs_.set_sp(0x10000);
|
||||
regs_.FakeSetDexPc(0xa3400);
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0x33402, 0x10010, false));
|
||||
ElfInterfaceFake::FakePushStepData(StepData(0, 0, true));
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
d0250000-d2600000 r-xp 0 00:00 0 <anonymous:d0250000>
|
||||
e466e000-e4ae8000 r-xp 0 00:00 0 libart.so
|
||||
e7d91000-e7e31000 r-xp 0 00:00 0 libc.so
|
|
@ -0,0 +1,16 @@
|
|||
r0: e814103c
|
||||
r1: 12dcf218
|
||||
r2: 1a90df75
|
||||
r3: ffffffbf
|
||||
r4: 0
|
||||
r5: 12dc0800
|
||||
r6: 12dcf218
|
||||
r7: 1a90df75
|
||||
r8: 0
|
||||
r9: dd23cc00
|
||||
r10: 1c
|
||||
r11: cd4ff16c
|
||||
ip: 0
|
||||
sp: cd4ff140
|
||||
lr: d025cdd7
|
||||
pc: d025c788
|
Binary file not shown.
Loading…
Reference in a new issue