diff options
Diffstat (limited to 'simpleperf/OfflineUnwinder.cpp')
-rw-r--r-- | simpleperf/OfflineUnwinder.cpp | 72 |
1 files changed, 22 insertions, 50 deletions
diff --git a/simpleperf/OfflineUnwinder.cpp b/simpleperf/OfflineUnwinder.cpp index 07eda11f..b6b7d91f 100644 --- a/simpleperf/OfflineUnwinder.cpp +++ b/simpleperf/OfflineUnwinder.cpp @@ -18,8 +18,6 @@ #include <sys/mman.h> -#include <unordered_map> - #include <android-base/logging.h> #include <unwindstack/MachineArm.h> #include <unwindstack/MachineArm64.h> @@ -121,29 +119,22 @@ static unwindstack::Regs* GetBacktraceRegs(const RegSet& regs) { static unwindstack::MapInfo* CreateMapInfo(const MapEntry* entry) { const char* name = entry->dso->GetDebugFilePath().c_str(); uint64_t pgoff = entry->pgoff; - auto tuple = SplitUrlInApk(entry->dso->GetDebugFilePath()); - if (std::get<0>(tuple)) { - // The unwinder does not understand the ! format, so change back to - // the previous format (apk, offset). - EmbeddedElf* elf = ApkInspector::FindElfInApkByName(std::get<1>(tuple), std::get<2>(tuple)); - if (elf != nullptr) { - name = elf->filepath().c_str(); - pgoff += elf->entry_offset(); + if (entry->pgoff == 0) { + auto tuple = SplitUrlInApk(entry->dso->GetDebugFilePath()); + if (std::get<0>(tuple)) { + // The unwinder does not understand the ! format, so change back to + // the previous format (apk, offset). + EmbeddedElf* elf = ApkInspector::FindElfInApkByName(std::get<1>(tuple), std::get<2>(tuple)); + if (elf != nullptr) { + name = elf->filepath().c_str(); + pgoff = elf->entry_offset(); + } } } return new unwindstack::MapInfo(nullptr, entry->start_addr, entry->get_end_addr(), pgoff, - PROT_READ | entry->flags, name); + PROT_READ | PROT_EXEC | entry->flags, name); } -class UnwindMaps : public unwindstack::Maps { - public: - void UpdateMaps(const MapSet& map_set); - - private: - uint64_t version_ = 0u; - std::vector<const MapEntry*> entries_; -}; - void UnwindMaps::UpdateMaps(const MapSet& map_set) { if (version_ == map_set.version) { return; @@ -186,31 +177,15 @@ void UnwindMaps::UpdateMaps(const MapSet& map_set) { }); entries_.resize(map_set.maps.size()); maps_.resize(map_set.maps.size()); - // prev_map is needed by libunwindstack to find the start of an embedded lib in an apk. - // See http://b/120981155. - for (size_t i = 1; i < maps_.size(); ++i) { - maps_[i]->prev_map = maps_[i-1].get(); - } } -class OfflineUnwinderImpl : public OfflineUnwinder { - public: - OfflineUnwinderImpl(bool collect_stat) : collect_stat_(collect_stat) { - unwindstack::Elf::SetCachingEnabled(true); - } - - bool UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, const char* stack, - size_t stack_size, std::vector<uint64_t>* ips, - std::vector<uint64_t>* sps) override; - - private: - bool collect_stat_; - std::unordered_map<pid_t, UnwindMaps> cached_maps_; -}; +OfflineUnwinder::OfflineUnwinder(bool collect_stat) : collect_stat_(collect_stat) { + unwindstack::Elf::SetCachingEnabled(true); +} -bool OfflineUnwinderImpl::UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, - const char* stack, size_t stack_size, - std::vector<uint64_t>* ips, std::vector<uint64_t>* sps) { +bool OfflineUnwinder::UnwindCallChain(const ThreadEntry& thread, const RegSet& regs, + const char* stack, size_t stack_size, + std::vector<uint64_t>* ips, std::vector<uint64_t>* sps) { uint64_t start_time; if (collect_stat_) { start_time = GetSystemClock(); @@ -228,14 +203,15 @@ bool OfflineUnwinderImpl::UnwindCallChain(const ThreadEntry& thread, const RegSe UnwindMaps& cached_map = cached_maps_[thread.pid]; cached_map.UpdateMaps(*thread.maps); + std::shared_ptr<unwindstack::MemoryOfflineBuffer> stack_memory( + new unwindstack::MemoryOfflineBuffer(reinterpret_cast<const uint8_t*>(stack), + stack_addr, stack_addr + stack_size)); std::unique_ptr<unwindstack::Regs> unwind_regs(GetBacktraceRegs(regs)); if (!unwind_regs) { return false; } - unwindstack::Unwinder unwinder( - MAX_UNWINDING_FRAMES, &cached_map, unwind_regs.get(), - unwindstack::Memory::CreateOfflineMemory(reinterpret_cast<const uint8_t*>(stack), stack_addr, - stack_addr + stack_size)); + unwindstack::Unwinder unwinder(MAX_UNWINDING_FRAMES, &cached_map, unwind_regs.get(), + stack_memory); unwinder.SetResolveNames(false); unwinder.Unwind(); size_t last_jit_method_frame = UINT_MAX; @@ -307,8 +283,4 @@ bool OfflineUnwinderImpl::UnwindCallChain(const ThreadEntry& thread, const RegSe return true; } -std::unique_ptr<OfflineUnwinder> OfflineUnwinder::Create(bool collect_stat) { - return std::unique_ptr<OfflineUnwinder>(new OfflineUnwinderImpl(collect_stat)); -} - } // namespace simpleperf |