diff options
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/backtrace_helper.cc | 80 |
2 files changed, 47 insertions, 34 deletions
diff --git a/runtime/Android.bp b/runtime/Android.bp index 2d15e4a6ab..d73d93fb09 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -400,6 +400,7 @@ libart_cc_defaults { "liblog", // For common macros. "libbase", + "libunwindstack", ], static: { static_libs: ["libsigchain_dummy"], diff --git a/runtime/backtrace_helper.cc b/runtime/backtrace_helper.cc index 21a0568033..0fa39cfb67 100644 --- a/runtime/backtrace_helper.cc +++ b/runtime/backtrace_helper.cc @@ -18,11 +18,11 @@ #if defined(__linux__) -#include <backtrace/Backtrace.h> -#include <backtrace/BacktraceMap.h> - -#include <unistd.h> #include <sys/types.h> +#include <unistd.h> + +#include "unwindstack/Unwinder.h" +#include "unwindstack/RegsGetLocal.h" #include "thread-inl.h" @@ -39,41 +39,53 @@ namespace art { // gcstress this isn't a huge deal. #if defined(__linux__) -static const char* kBacktraceCollectorTlsKey = "BacktraceCollectorTlsKey"; - -struct BacktraceMapHolder : public TLSData { - BacktraceMapHolder() : map_(BacktraceMap::Create(getpid())) {} - - std::unique_ptr<BacktraceMap> map_; -}; +struct UnwindHelper : public TLSData { + static constexpr const char* kTlsKey = "UnwindHelper::kTlsKey"; + + explicit UnwindHelper(size_t max_depth) + : memory_(new unwindstack::MemoryLocal()), + jit_(memory_), + dex_(memory_), + unwinder_(max_depth, &maps_, memory_) { + CHECK(maps_.Parse()); + unwinder_.SetJitDebug(&jit_, unwindstack::Regs::CurrentArch()); + unwinder_.SetDexFiles(&dex_, unwindstack::Regs::CurrentArch()); + unwinder_.SetResolveNames(false); + unwindstack::Elf::SetCachingEnabled(true); + } -static BacktraceMap* GetMap(Thread* self) { - BacktraceMapHolder* map_holder = - reinterpret_cast<BacktraceMapHolder*>(self->GetCustomTLS(kBacktraceCollectorTlsKey)); - if (map_holder == nullptr) { - map_holder = new BacktraceMapHolder; - // We don't care about the function names. Turning this off makes everything significantly - // faster. - map_holder->map_->SetResolveNames(false); - // Only created and queried on Thread::Current so no sync needed. - self->SetCustomTLS(kBacktraceCollectorTlsKey, map_holder); + static UnwindHelper* Get(Thread* self, size_t max_depth) { + UnwindHelper* tls = reinterpret_cast<UnwindHelper*>(self->GetCustomTLS(kTlsKey)); + if (tls == nullptr) { + tls = new UnwindHelper(max_depth); + self->SetCustomTLS(kTlsKey, tls); + } + return tls; } - return map_holder->map_.get(); -} + unwindstack::Unwinder* Unwinder() { return &unwinder_; } + + private: + unwindstack::LocalMaps maps_; + std::shared_ptr<unwindstack::Memory> memory_; + unwindstack::JitDebug jit_; + unwindstack::DexFiles dex_; + unwindstack::Unwinder unwinder_; +}; void BacktraceCollector::Collect() { - std::unique_ptr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, - BACKTRACE_CURRENT_THREAD, - GetMap(Thread::Current()))); - backtrace->SetSkipFrames(true); - if (!backtrace->Unwind(skip_count_, nullptr)) { - return; - } - for (Backtrace::const_iterator it = backtrace->begin(); - max_depth_ > num_frames_ && it != backtrace->end(); - ++it) { - out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc); + unwindstack::Unwinder* unwinder = UnwindHelper::Get(Thread::Current(), max_depth_)->Unwinder(); + std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal()); + RegsGetLocal(regs.get()); + unwinder->SetRegs(regs.get()); + unwinder->Unwind(); + num_frames_ = 0; + if (unwinder->NumFrames() > skip_count_) { + for (auto it = unwinder->frames().begin() + skip_count_; + max_depth_ > num_frames_ && it != unwinder->frames().end(); + ++it) { + out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc); + } } } |