Loading libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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/*", Loading libunwindstack/DwarfSection.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 += loc->values[1]; break; case DWARF_LOCATION_VAL_EXPRESSION: { Loading libunwindstack/ElfInterfaceArm.cpp +2 −6 Original line number Diff line number Diff line Loading @@ -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. Loading libunwindstack/RegsArm.cpp +29 −19 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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: // Loading @@ -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: // Loading @@ -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) { Loading @@ -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; } Loading libunwindstack/RegsArm64.cpp +21 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading Loading
libunwindstack/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -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/*", Loading
libunwindstack/DwarfSection.cpp +1 −10 Original line number Diff line number Diff line Loading @@ -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, Loading @@ -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 += loc->values[1]; break; case DWARF_LOCATION_VAL_EXPRESSION: { Loading
libunwindstack/ElfInterfaceArm.cpp +2 −6 Original line number Diff line number Diff line Loading @@ -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. Loading
libunwindstack/RegsArm.cpp +29 −19 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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: // Loading @@ -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: // Loading @@ -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) { Loading @@ -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; } Loading
libunwindstack/RegsArm64.cpp +21 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; } Loading @@ -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; } Loading @@ -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; } Loading