summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/backtrace_helper.cc80
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);
+ }
}
}