Loading libunwindstack/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,8 @@ cc_defaults { "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*", "tests/files/offline/shared_lib_in_apk_single_map_arm64/*", "tests/files/offline/signal_load_bias_arm/*", "tests/files/offline/signal_fde_x86/*", "tests/files/offline/signal_fde_x86_64/*", "tests/files/offline/straddle_arm/*", "tests/files/offline/straddle_arm64/*", ], Loading libunwindstack/DwarfSection.cpp +11 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ namespace unwindstack { DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { // Lookup the pc in the cache. auto it = loc_regs_.upper_bound(pc); if (it == loc_regs_.end() || pc < it->second.pc_start) { Loading @@ -59,6 +60,8 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first; } *is_signal_frame = it->second.cie->is_signal_frame; // Now eval the actual registers. return Eval(it->second.cie, process_memory, it->second, regs, finished); } Loading Loading @@ -241,6 +244,9 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { return false; } break; case 'S': cie->is_signal_frame = true; break; } } return true; Loading Loading @@ -558,8 +564,10 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me cur_regs->set_pc((*cur_regs)[cie->return_address_register]); } // If the pc was set to zero, consider this the final frame. *finished = (cur_regs->pc() == 0) ? true : false; // If the pc was set to zero, consider this the final frame. Exception: if // this is the sigreturn frame, then we want to try to recover the real PC // using the return address (from LR or the stack), so keep going. *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false; cur_regs->set_sp(eval_info.cfa); Loading libunwindstack/Elf.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -188,14 +188,15 @@ bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memor } // The relative pc is always relative to the start of the map from which it comes. bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) { bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { if (!valid_) { return false; } // Lock during the step which can update information in the object. std::lock_guard<std::mutex> guard(lock_); return interface_->Step(rel_pc, regs, process_memory, finished); return interface_->Step(rel_pc, regs, process_memory, finished, is_signal_frame); } bool Elf::IsValidElf(Memory* memory) { Loading libunwindstack/ElfInterface.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -499,25 +499,27 @@ bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64 return false; } bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { last_error_.code = ERROR_NONE; last_error_.address = 0; // Try the debug_frame first since it contains the most specific unwind // information. DwarfSection* debug_frame = debug_frame_.get(); if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) { if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } // Try the eh_frame next. DwarfSection* eh_frame = eh_frame_.get(); if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) { if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->Step(pc, regs, process_memory, finished)) { gnu_debugdata_interface_->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } Loading libunwindstack/ElfInterfaceArm.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -100,12 +100,13 @@ void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint6 total_entries_ = ph_filesz / 8; } bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { // Dwarf unwind information is precise about whether a pc is covered or not, // but arm unwind information only has ranges of pc. In order to avoid // incorrectly doing a bad unwind using arm unwind information for a // different function, always try and unwind with the dwarf information first. return ElfInterface32::Step(pc, regs, process_memory, finished) || return ElfInterface32::Step(pc, regs, process_memory, finished, is_signal_frame) || StepExidx(pc, regs, process_memory, finished); } Loading Loading
libunwindstack/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,8 @@ cc_defaults { "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*", "tests/files/offline/shared_lib_in_apk_single_map_arm64/*", "tests/files/offline/signal_load_bias_arm/*", "tests/files/offline/signal_fde_x86/*", "tests/files/offline/signal_fde_x86_64/*", "tests/files/offline/straddle_arm/*", "tests/files/offline/straddle_arm64/*", ], Loading
libunwindstack/DwarfSection.cpp +11 −3 Original line number Diff line number Diff line Loading @@ -37,7 +37,8 @@ namespace unwindstack { DwarfSection::DwarfSection(Memory* memory) : memory_(memory) {} bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { // Lookup the pc in the cache. auto it = loc_regs_.upper_bound(pc); if (it == loc_regs_.end() || pc < it->second.pc_start) { Loading @@ -59,6 +60,8 @@ bool DwarfSection::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* f it = loc_regs_.emplace(loc_regs.pc_end, std::move(loc_regs)).first; } *is_signal_frame = it->second.cie->is_signal_frame; // Now eval the actual registers. return Eval(it->second.cie, process_memory, it->second, regs, finished); } Loading Loading @@ -241,6 +244,9 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) { return false; } break; case 'S': cie->is_signal_frame = true; break; } } return true; Loading Loading @@ -558,8 +564,10 @@ bool DwarfSectionImpl<AddressType>::Eval(const DwarfCie* cie, Memory* regular_me cur_regs->set_pc((*cur_regs)[cie->return_address_register]); } // If the pc was set to zero, consider this the final frame. *finished = (cur_regs->pc() == 0) ? true : false; // If the pc was set to zero, consider this the final frame. Exception: if // this is the sigreturn frame, then we want to try to recover the real PC // using the return address (from LR or the stack), so keep going. *finished = (cur_regs->pc() == 0 && !cie->is_signal_frame) ? true : false; cur_regs->set_sp(eval_info.cfa); Loading
libunwindstack/Elf.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -188,14 +188,15 @@ bool Elf::StepIfSignalHandler(uint64_t rel_pc, Regs* regs, Memory* process_memor } // The relative pc is always relative to the start of the map from which it comes. bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished) { bool Elf::Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { if (!valid_) { return false; } // Lock during the step which can update information in the object. std::lock_guard<std::mutex> guard(lock_); return interface_->Step(rel_pc, regs, process_memory, finished); return interface_->Step(rel_pc, regs, process_memory, finished, is_signal_frame); } bool Elf::IsValidElf(Memory* memory) { Loading
libunwindstack/ElfInterface.cpp +6 −4 Original line number Diff line number Diff line Loading @@ -499,25 +499,27 @@ bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64 return false; } bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { last_error_.code = ERROR_NONE; last_error_.address = 0; // Try the debug_frame first since it contains the most specific unwind // information. DwarfSection* debug_frame = debug_frame_.get(); if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) { if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } // Try the eh_frame next. DwarfSection* eh_frame = eh_frame_.get(); if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) { if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } if (gnu_debugdata_interface_ != nullptr && gnu_debugdata_interface_->Step(pc, regs, process_memory, finished)) { gnu_debugdata_interface_->Step(pc, regs, process_memory, finished, is_signal_frame)) { return true; } Loading
libunwindstack/ElfInterfaceArm.cpp +3 −2 Original line number Diff line number Diff line Loading @@ -100,12 +100,13 @@ void ElfInterfaceArm::HandleUnknownType(uint32_t type, uint64_t ph_offset, uint6 total_entries_ = ph_filesz / 8; } bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) { bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished, bool* is_signal_frame) { // Dwarf unwind information is precise about whether a pc is covered or not, // but arm unwind information only has ranges of pc. In order to avoid // incorrectly doing a bad unwind using arm unwind information for a // different function, always try and unwind with the dwarf information first. return ElfInterface32::Step(pc, regs, process_memory, finished) || return ElfInterface32::Step(pc, regs, process_memory, finished, is_signal_frame) || StepExidx(pc, regs, process_memory, finished); } Loading