xref: /aosp_15_r20/art/runtime/backtrace_helper.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "backtrace_helper.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #if defined(__linux__)
20*795d594fSAndroid Build Coastguard Worker 
21*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
22*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
23*795d594fSAndroid Build Coastguard Worker #include <iomanip>
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker #include "unwindstack/Regs.h"
26*795d594fSAndroid Build Coastguard Worker #include "unwindstack/RegsGetLocal.h"
27*795d594fSAndroid Build Coastguard Worker #include "unwindstack/Memory.h"
28*795d594fSAndroid Build Coastguard Worker #include "unwindstack/Unwinder.h"
29*795d594fSAndroid Build Coastguard Worker 
30*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
31*795d594fSAndroid Build Coastguard Worker #include "entrypoints/runtime_asm_entrypoints.h"
32*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker #else
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker // For UNUSED
37*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
38*795d594fSAndroid Build Coastguard Worker 
39*795d594fSAndroid Build Coastguard Worker #endif
40*795d594fSAndroid Build Coastguard Worker 
41*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
42*795d594fSAndroid Build Coastguard Worker 
43*795d594fSAndroid Build Coastguard Worker // We only really support libunwindstack on linux which is unfortunate but since this is only for
44*795d594fSAndroid Build Coastguard Worker // gcstress this isn't a huge deal.
45*795d594fSAndroid Build Coastguard Worker #if defined(__linux__)
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker // Strict integrity check of the backtrace:
48*795d594fSAndroid Build Coastguard Worker // All methods must have a name, all the way to "main".
49*795d594fSAndroid Build Coastguard Worker static constexpr bool kStrictUnwindChecks = false;
50*795d594fSAndroid Build Coastguard Worker 
51*795d594fSAndroid Build Coastguard Worker struct UnwindHelper : public TLSData {
52*795d594fSAndroid Build Coastguard Worker   static constexpr const char* kTlsKey = "UnwindHelper::kTlsKey";
53*795d594fSAndroid Build Coastguard Worker 
UnwindHelperart::UnwindHelper54*795d594fSAndroid Build Coastguard Worker   explicit UnwindHelper(size_t max_depth)
55*795d594fSAndroid Build Coastguard Worker       : arch_(unwindstack::Regs::CurrentArch()),
56*795d594fSAndroid Build Coastguard Worker         memory_(unwindstack::Memory::CreateProcessMemoryThreadCached(getpid())),
57*795d594fSAndroid Build Coastguard Worker         jit_(unwindstack::CreateJitDebug(arch_, memory_)),
58*795d594fSAndroid Build Coastguard Worker         dex_(unwindstack::CreateDexFiles(arch_, memory_)),
59*795d594fSAndroid Build Coastguard Worker         unwinder_(max_depth, &maps_, memory_) {
60*795d594fSAndroid Build Coastguard Worker     CHECK(maps_.Parse());
61*795d594fSAndroid Build Coastguard Worker     unwinder_.SetArch(arch_);
62*795d594fSAndroid Build Coastguard Worker     unwinder_.SetJitDebug(jit_.get());
63*795d594fSAndroid Build Coastguard Worker     unwinder_.SetDexFiles(dex_.get());
64*795d594fSAndroid Build Coastguard Worker     unwinder_.SetResolveNames(kStrictUnwindChecks);
65*795d594fSAndroid Build Coastguard Worker     unwindstack::Elf::SetCachingEnabled(true);
66*795d594fSAndroid Build Coastguard Worker   }
67*795d594fSAndroid Build Coastguard Worker 
68*795d594fSAndroid Build Coastguard Worker   // Reparse process mmaps to detect newly loaded libraries.
Reparseart::UnwindHelper69*795d594fSAndroid Build Coastguard Worker   bool Reparse(bool* any_changed) { return maps_.Reparse(any_changed); }
70*795d594fSAndroid Build Coastguard Worker 
Getart::UnwindHelper71*795d594fSAndroid Build Coastguard Worker   static UnwindHelper* Get(Thread* self, size_t max_depth) {
72*795d594fSAndroid Build Coastguard Worker     UnwindHelper* tls = reinterpret_cast<UnwindHelper*>(self->GetCustomTLS(kTlsKey));
73*795d594fSAndroid Build Coastguard Worker     if (tls == nullptr) {
74*795d594fSAndroid Build Coastguard Worker       tls = new UnwindHelper(max_depth);
75*795d594fSAndroid Build Coastguard Worker       self->SetCustomTLS(kTlsKey, tls);
76*795d594fSAndroid Build Coastguard Worker     }
77*795d594fSAndroid Build Coastguard Worker     return tls;
78*795d594fSAndroid Build Coastguard Worker   }
79*795d594fSAndroid Build Coastguard Worker 
Unwinderart::UnwindHelper80*795d594fSAndroid Build Coastguard Worker   unwindstack::Unwinder* Unwinder() { return &unwinder_; }
81*795d594fSAndroid Build Coastguard Worker 
82*795d594fSAndroid Build Coastguard Worker  private:
83*795d594fSAndroid Build Coastguard Worker   unwindstack::LocalUpdatableMaps maps_;
84*795d594fSAndroid Build Coastguard Worker   unwindstack::ArchEnum arch_;
85*795d594fSAndroid Build Coastguard Worker   std::shared_ptr<unwindstack::Memory> memory_;
86*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<unwindstack::JitDebug> jit_;
87*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<unwindstack::DexFiles> dex_;
88*795d594fSAndroid Build Coastguard Worker   unwindstack::Unwinder unwinder_;
89*795d594fSAndroid Build Coastguard Worker };
90*795d594fSAndroid Build Coastguard Worker 
Collect()91*795d594fSAndroid Build Coastguard Worker void BacktraceCollector::Collect() {
92*795d594fSAndroid Build Coastguard Worker   unwindstack::Unwinder* unwinder = UnwindHelper::Get(Thread::Current(), max_depth_)->Unwinder();
93*795d594fSAndroid Build Coastguard Worker   if (!CollectImpl(unwinder)) {
94*795d594fSAndroid Build Coastguard Worker     // Reparse process mmaps to detect newly loaded libraries and retry,
95*795d594fSAndroid Build Coastguard Worker     // but only if any maps changed (we don't want to hide racy failures).
96*795d594fSAndroid Build Coastguard Worker     bool any_changed;
97*795d594fSAndroid Build Coastguard Worker     UnwindHelper::Get(Thread::Current(), max_depth_)->Reparse(&any_changed);
98*795d594fSAndroid Build Coastguard Worker     if (!any_changed || !CollectImpl(unwinder)) {
99*795d594fSAndroid Build Coastguard Worker       if (kStrictUnwindChecks) {
100*795d594fSAndroid Build Coastguard Worker         std::vector<unwindstack::FrameData>& frames = unwinder->frames();
101*795d594fSAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to unwind stack (error " << unwinder->LastErrorCodeString() << "):";
102*795d594fSAndroid Build Coastguard Worker         std::string prev_name;
103*795d594fSAndroid Build Coastguard Worker         for (auto& frame : frames) {
104*795d594fSAndroid Build Coastguard Worker           if (frame.map_info != nullptr) {
105*795d594fSAndroid Build Coastguard Worker             std::string full_name = frame.map_info->GetFullName();
106*795d594fSAndroid Build Coastguard Worker             if (prev_name != full_name) {
107*795d594fSAndroid Build Coastguard Worker               LOG(ERROR) << " in " << full_name;
108*795d594fSAndroid Build Coastguard Worker             }
109*795d594fSAndroid Build Coastguard Worker             prev_name = full_name;
110*795d594fSAndroid Build Coastguard Worker           } else {
111*795d594fSAndroid Build Coastguard Worker             prev_name = "";
112*795d594fSAndroid Build Coastguard Worker           }
113*795d594fSAndroid Build Coastguard Worker           LOG(ERROR) << " pc " << std::setw(8) << std::setfill('0') << std::hex <<
114*795d594fSAndroid Build Coastguard Worker             frame.rel_pc << " " << frame.function_name.c_str();
115*795d594fSAndroid Build Coastguard Worker         }
116*795d594fSAndroid Build Coastguard Worker         LOG(FATAL);
117*795d594fSAndroid Build Coastguard Worker       }
118*795d594fSAndroid Build Coastguard Worker     }
119*795d594fSAndroid Build Coastguard Worker   }
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker 
CollectImpl(unwindstack::Unwinder * unwinder)122*795d594fSAndroid Build Coastguard Worker bool BacktraceCollector::CollectImpl(unwindstack::Unwinder* unwinder) {
123*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromLocal());
124*795d594fSAndroid Build Coastguard Worker   RegsGetLocal(regs.get());
125*795d594fSAndroid Build Coastguard Worker   unwinder->SetRegs(regs.get());
126*795d594fSAndroid Build Coastguard Worker   unwinder->Unwind();
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker   num_frames_ = 0;
129*795d594fSAndroid Build Coastguard Worker   if (unwinder->NumFrames() > skip_count_) {
130*795d594fSAndroid Build Coastguard Worker     for (auto it = unwinder->frames().begin() + skip_count_; it != unwinder->frames().end(); ++it) {
131*795d594fSAndroid Build Coastguard Worker       CHECK_LT(num_frames_, max_depth_);
132*795d594fSAndroid Build Coastguard Worker       out_frames_[num_frames_++] = static_cast<uintptr_t>(it->pc);
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker       if (kStrictUnwindChecks) {
135*795d594fSAndroid Build Coastguard Worker         if (it->function_name.empty()) {
136*795d594fSAndroid Build Coastguard Worker           return false;
137*795d594fSAndroid Build Coastguard Worker         }
138*795d594fSAndroid Build Coastguard Worker         if (it->function_name == "main" ||
139*795d594fSAndroid Build Coastguard Worker             it->function_name == "start_thread" ||
140*795d594fSAndroid Build Coastguard Worker             it->function_name == "__start_thread") {
141*795d594fSAndroid Build Coastguard Worker           return true;
142*795d594fSAndroid Build Coastguard Worker         }
143*795d594fSAndroid Build Coastguard Worker       }
144*795d594fSAndroid Build Coastguard Worker     }
145*795d594fSAndroid Build Coastguard Worker   }
146*795d594fSAndroid Build Coastguard Worker 
147*795d594fSAndroid Build Coastguard Worker   unwindstack::ErrorCode error = unwinder->LastErrorCode();
148*795d594fSAndroid Build Coastguard Worker   return error == unwindstack::ERROR_NONE || error == unwindstack::ERROR_MAX_FRAMES_EXCEEDED;
149*795d594fSAndroid Build Coastguard Worker }
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker #else
152*795d594fSAndroid Build Coastguard Worker 
153*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic push
154*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic warning "-W#warnings"
155*795d594fSAndroid Build Coastguard Worker #warning "Backtrace collector is not implemented. GCStress cannot be used."
156*795d594fSAndroid Build Coastguard Worker #pragma clang diagnostic pop
157*795d594fSAndroid Build Coastguard Worker 
158*795d594fSAndroid Build Coastguard Worker // We only have an implementation for linux. On other plaforms just return nothing. This is not
159*795d594fSAndroid Build Coastguard Worker // really correct but we only use this for hashing and gcstress so it's not too big a deal.
160*795d594fSAndroid Build Coastguard Worker void BacktraceCollector::Collect() {
161*795d594fSAndroid Build Coastguard Worker   UNUSED(skip_count_);
162*795d594fSAndroid Build Coastguard Worker   UNUSED(out_frames_);
163*795d594fSAndroid Build Coastguard Worker   UNUSED(max_depth_);
164*795d594fSAndroid Build Coastguard Worker   num_frames_ = 0;
165*795d594fSAndroid Build Coastguard Worker }
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker #endif
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker }  // namespace art
170