blob: 98280c779f98c7985ef1c5e276ff869eeaee14f3 [file] [log] [blame]
Alex Light543d8452018-07-13 16:25:58 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "backtrace_helper.h"
18
19#if defined(__linux__)
20
Alex Light543d8452018-07-13 16:25:58 +000021#include <sys/types.h>
David Srbeckyf1603942019-04-05 12:06:36 +010022#include <unistd.h>
23
Christopher Ferrisec232912019-05-28 16:18:18 -070024#include "unwindstack/Regs.h"
David Srbeckyf1603942019-04-05 12:06:36 +010025#include "unwindstack/RegsGetLocal.h"
Christopher Ferrisec232912019-05-28 16:18:18 -070026#include "unwindstack/Memory.h"
27#include "unwindstack/Unwinder.h"
Alex Light543d8452018-07-13 16:25:58 +000028
29#include "thread-inl.h"
30
31#else
32
33// For UNUSED
34#include "base/macros.h"
35
36#endif
37
38namespace art {
39
Christopher Ferrisec232912019-05-28 16:18:18 -070040// We only really support libunwindstack on linux which is unfortunate but since this is only for
Alex Light543d8452018-07-13 16:25:58 +000041// gcstress this isn't a huge deal.
42#if defined(__linux__)
43
David Srbeckyf1603942019-04-05 12:06:36 +010044struct UnwindHelper : public TLSData {
45 static constexpr const char* kTlsKey = "UnwindHelper::kTlsKey";
Alex Light543d8452018-07-13 16:25:58 +000046
David Srbeckyf1603942019-04-05 12:06:36 +010047 explicit UnwindHelper(size_t max_depth)
Christopher Ferrisec232912019-05-28 16:18:18 -070048 : memory_(unwindstack::Memory::CreateProcessMemory(getpid())),
David Srbeckyf1603942019-04-05 12:06:36 +010049 jit_(memory_),
50 dex_(memory_),
51 unwinder_(max_depth, &maps_, memory_) {
52 CHECK(maps_.Parse());
53 unwinder_.SetJitDebug(&jit_, unwindstack::Regs::CurrentArch());
54 unwinder_.SetDexFiles(&dex_, unwindstack::Regs::CurrentArch());
55 unwinder_.SetResolveNames(false);
56 unwindstack::Elf::SetCachingEnabled(true);
57 }
Alex Light543d8452018-07-13 16:25:58 +000058
David Srbeckyf1603942019-04-05 12:06:36 +010059 static UnwindHelper* Get(Thread* self, size_t max_depth) {
60 UnwindHelper* tls = reinterpret_cast<UnwindHelper*>(self->GetCustomTLS(kTlsKey));
61 if (tls == nullptr) {
62 tls = new UnwindHelper(max_depth);
63 self->SetCustomTLS(kTlsKey, tls);
64 }
65 return tls;
66 }
67
68 unwindstack::Unwinder* Unwinder() { return &unwinder_; }
69
70 private:
71 unwindstack::LocalMaps maps_;
72 std::shared_ptr<unwindstack::Memory> memory_;
73 unwindstack::JitDebug jit_;
74 unwindstack::DexFiles dex_;
75 unwindstack::Unwinder unwinder_;
Alex Light543d8452018-07-13 16:25:58 +000076};
77
Alex Light543d8452018-07-13 16:25:58 +000078void BacktraceCollector::Collect() {
David Srbeckyf1603942019-04-05 12:06:36 +010079 unwindstack::Unwinder* unwinder = UnwindHelper::Get(Thread::Current(), max_depth_)->Unwinder();
80 std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
81 RegsGetLocal(regs.get());
82 unwinder->SetRegs(regs.get());
83 unwinder->Unwind();
84 num_frames_ = 0;
85 if (unwinder->NumFrames() > skip_count_) {
86 for (auto it = unwinder->frames().begin() + skip_count_;
87 max_depth_ > num_frames_ && it != unwinder->frames().end();
88 ++it) {
89 out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc);
90 }
Alex Light543d8452018-07-13 16:25:58 +000091 }
92}
93
94#else
95
96#pragma clang diagnostic push
97#pragma clang diagnostic warning "-W#warnings"
98#warning "Backtrace collector is not implemented. GCStress cannot be used."
99#pragma clang diagnostic pop
100
101// We only have an implementation for linux. On other plaforms just return nothing. This is not
102// really correct but we only use this for hashing and gcstress so it's not too big a deal.
103void BacktraceCollector::Collect() {
104 UNUSED(skip_count_);
105 UNUSED(out_frames_);
106 UNUSED(max_depth_);
107 num_frames_ = 0;
108}
109
110#endif
111
112} // namespace art