xref: /aosp_15_r20/system/unwinding/libunwindstack/AndroidUnwinder.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <inttypes.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <sys/types.h>
19*eb293b8fSAndroid Build Coastguard Worker #include <unistd.h>
20*eb293b8fSAndroid Build Coastguard Worker 
21*eb293b8fSAndroid Build Coastguard Worker #include <memory>
22*eb293b8fSAndroid Build Coastguard Worker #include <mutex>
23*eb293b8fSAndroid Build Coastguard Worker #include <string>
24*eb293b8fSAndroid Build Coastguard Worker #include <vector>
25*eb293b8fSAndroid Build Coastguard Worker 
26*eb293b8fSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
27*eb293b8fSAndroid Build Coastguard Worker #include <android-base/threads.h>
28*eb293b8fSAndroid Build Coastguard Worker 
29*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/AndroidUnwinder.h>
30*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Arch.h>
31*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Demangle.h>
32*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DexFiles.h>
33*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Error.h>
34*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/JitDebug.h>
35*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
36*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Memory.h>
37*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Regs.h>
38*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/RegsGetLocal.h>
39*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Unwinder.h>
40*eb293b8fSAndroid Build Coastguard Worker 
41*eb293b8fSAndroid Build Coastguard Worker #if defined(__BIONIC__)
42*eb293b8fSAndroid Build Coastguard Worker #include <bionic/reserved_signals.h>
43*eb293b8fSAndroid Build Coastguard Worker static constexpr int kThreadUnwindSignal = BIONIC_SIGNAL_BACKTRACE;
44*eb293b8fSAndroid Build Coastguard Worker #else
45*eb293b8fSAndroid Build Coastguard Worker #include <signal.h>
46*eb293b8fSAndroid Build Coastguard Worker static int kThreadUnwindSignal = SIGRTMIN;
47*eb293b8fSAndroid Build Coastguard Worker #endif
48*eb293b8fSAndroid Build Coastguard Worker 
49*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
50*eb293b8fSAndroid Build Coastguard Worker 
DemangleFunctionNames()51*eb293b8fSAndroid Build Coastguard Worker void AndroidUnwinderData::DemangleFunctionNames() {
52*eb293b8fSAndroid Build Coastguard Worker   for (auto& frame : frames) {
53*eb293b8fSAndroid Build Coastguard Worker     frame.function_name = DemangleNameIfNeeded(frame.function_name);
54*eb293b8fSAndroid Build Coastguard Worker   }
55*eb293b8fSAndroid Build Coastguard Worker }
56*eb293b8fSAndroid Build Coastguard Worker 
GetErrorString()57*eb293b8fSAndroid Build Coastguard Worker std::string AndroidUnwinderData::GetErrorString() {
58*eb293b8fSAndroid Build Coastguard Worker   std::string error_msg(GetErrorCodeString(error.code));
59*eb293b8fSAndroid Build Coastguard Worker   if (error.address != 0) {
60*eb293b8fSAndroid Build Coastguard Worker     error_msg += android::base::StringPrintf(" at address 0x%" PRIx64, error.address);
61*eb293b8fSAndroid Build Coastguard Worker   }
62*eb293b8fSAndroid Build Coastguard Worker   return error_msg;
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker 
Create(pid_t pid)65*eb293b8fSAndroid Build Coastguard Worker AndroidUnwinder* AndroidUnwinder::Create(pid_t pid) {
66*eb293b8fSAndroid Build Coastguard Worker   if (pid == getpid()) {
67*eb293b8fSAndroid Build Coastguard Worker     return new AndroidLocalUnwinder;
68*eb293b8fSAndroid Build Coastguard Worker   } else {
69*eb293b8fSAndroid Build Coastguard Worker     return new AndroidRemoteUnwinder(pid);
70*eb293b8fSAndroid Build Coastguard Worker   }
71*eb293b8fSAndroid Build Coastguard Worker }
72*eb293b8fSAndroid Build Coastguard Worker 
Initialize(ErrorData & error)73*eb293b8fSAndroid Build Coastguard Worker bool AndroidUnwinder::Initialize(ErrorData& error) {
74*eb293b8fSAndroid Build Coastguard Worker   // Android stores the jit and dex file location only in the library
75*eb293b8fSAndroid Build Coastguard Worker   // libart.so or libartd.so.
76*eb293b8fSAndroid Build Coastguard Worker   static std::vector<std::string> search_libs [[clang::no_destroy]] = {"libart.so", "libartd.so"};
77*eb293b8fSAndroid Build Coastguard Worker 
78*eb293b8fSAndroid Build Coastguard Worker   std::call_once(initialize_, [this, &error]() {
79*eb293b8fSAndroid Build Coastguard Worker     if (!InternalInitialize(error)) {
80*eb293b8fSAndroid Build Coastguard Worker       initialize_status_ = false;
81*eb293b8fSAndroid Build Coastguard Worker       return;
82*eb293b8fSAndroid Build Coastguard Worker     }
83*eb293b8fSAndroid Build Coastguard Worker 
84*eb293b8fSAndroid Build Coastguard Worker     jit_debug_ = CreateJitDebug(arch_, process_memory_, search_libs);
85*eb293b8fSAndroid Build Coastguard Worker 
86*eb293b8fSAndroid Build Coastguard Worker #if defined(DEXFILE_SUPPORT)
87*eb293b8fSAndroid Build Coastguard Worker     dex_files_ = CreateDexFiles(arch_, process_memory_, search_libs);
88*eb293b8fSAndroid Build Coastguard Worker #endif
89*eb293b8fSAndroid Build Coastguard Worker     initialize_status_ = true;
90*eb293b8fSAndroid Build Coastguard Worker   });
91*eb293b8fSAndroid Build Coastguard Worker 
92*eb293b8fSAndroid Build Coastguard Worker   return initialize_status_;
93*eb293b8fSAndroid Build Coastguard Worker }
94*eb293b8fSAndroid Build Coastguard Worker 
FormatFrame(const FrameData & frame) const95*eb293b8fSAndroid Build Coastguard Worker std::string AndroidUnwinder::FormatFrame(const FrameData& frame) const {
96*eb293b8fSAndroid Build Coastguard Worker   if (arch_ == ARCH_UNKNOWN) {
97*eb293b8fSAndroid Build Coastguard Worker     return "";
98*eb293b8fSAndroid Build Coastguard Worker   }
99*eb293b8fSAndroid Build Coastguard Worker   return Unwinder::FormatFrame(arch_, frame);
100*eb293b8fSAndroid Build Coastguard Worker }
101*eb293b8fSAndroid Build Coastguard Worker 
InternalInitialize(ErrorData & error)102*eb293b8fSAndroid Build Coastguard Worker bool AndroidLocalUnwinder::InternalInitialize(ErrorData& error) {
103*eb293b8fSAndroid Build Coastguard Worker   arch_ = Regs::CurrentArch();
104*eb293b8fSAndroid Build Coastguard Worker 
105*eb293b8fSAndroid Build Coastguard Worker   maps_.reset(new LocalUpdatableMaps);
106*eb293b8fSAndroid Build Coastguard Worker   if (!maps_->Parse()) {
107*eb293b8fSAndroid Build Coastguard Worker     error.code = ERROR_MAPS_PARSE;
108*eb293b8fSAndroid Build Coastguard Worker     return false;
109*eb293b8fSAndroid Build Coastguard Worker   }
110*eb293b8fSAndroid Build Coastguard Worker 
111*eb293b8fSAndroid Build Coastguard Worker   if (process_memory_ == nullptr) {
112*eb293b8fSAndroid Build Coastguard Worker     process_memory_ = Memory::CreateProcessMemoryThreadCached(getpid());
113*eb293b8fSAndroid Build Coastguard Worker   }
114*eb293b8fSAndroid Build Coastguard Worker 
115*eb293b8fSAndroid Build Coastguard Worker   return true;
116*eb293b8fSAndroid Build Coastguard Worker }
117*eb293b8fSAndroid Build Coastguard Worker 
BuildFrameFromPcOnly(uint64_t pc)118*eb293b8fSAndroid Build Coastguard Worker FrameData AndroidUnwinder::BuildFrameFromPcOnly(uint64_t pc) {
119*eb293b8fSAndroid Build Coastguard Worker   return Unwinder::BuildFrameFromPcOnly(pc, arch_, maps_.get(), jit_debug_.get(), process_memory_,
120*eb293b8fSAndroid Build Coastguard Worker                                         true);
121*eb293b8fSAndroid Build Coastguard Worker }
122*eb293b8fSAndroid Build Coastguard Worker 
Unwind(AndroidUnwinderData & data)123*eb293b8fSAndroid Build Coastguard Worker bool AndroidUnwinder::Unwind(AndroidUnwinderData& data) {
124*eb293b8fSAndroid Build Coastguard Worker   return Unwind(std::nullopt, data);
125*eb293b8fSAndroid Build Coastguard Worker }
126*eb293b8fSAndroid Build Coastguard Worker 
Unwind(std::optional<pid_t> tid,AndroidUnwinderData & data)127*eb293b8fSAndroid Build Coastguard Worker bool AndroidUnwinder::Unwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
128*eb293b8fSAndroid Build Coastguard Worker   if (!Initialize(data.error)) {
129*eb293b8fSAndroid Build Coastguard Worker     return false;
130*eb293b8fSAndroid Build Coastguard Worker   }
131*eb293b8fSAndroid Build Coastguard Worker 
132*eb293b8fSAndroid Build Coastguard Worker   return InternalUnwind(tid, data);
133*eb293b8fSAndroid Build Coastguard Worker }
134*eb293b8fSAndroid Build Coastguard Worker 
Unwind(void * ucontext,AndroidUnwinderData & data)135*eb293b8fSAndroid Build Coastguard Worker bool AndroidUnwinder::Unwind(void* ucontext, AndroidUnwinderData& data) {
136*eb293b8fSAndroid Build Coastguard Worker   if (ucontext == nullptr) {
137*eb293b8fSAndroid Build Coastguard Worker     data.error.code = ERROR_INVALID_PARAMETER;
138*eb293b8fSAndroid Build Coastguard Worker     return false;
139*eb293b8fSAndroid Build Coastguard Worker   }
140*eb293b8fSAndroid Build Coastguard Worker 
141*eb293b8fSAndroid Build Coastguard Worker   if (!Initialize(data.error)) {
142*eb293b8fSAndroid Build Coastguard Worker     return false;
143*eb293b8fSAndroid Build Coastguard Worker   }
144*eb293b8fSAndroid Build Coastguard Worker 
145*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<Regs> regs(Regs::CreateFromUcontext(arch_, ucontext));
146*eb293b8fSAndroid Build Coastguard Worker   return Unwind(regs.get(), data);
147*eb293b8fSAndroid Build Coastguard Worker }
148*eb293b8fSAndroid Build Coastguard Worker 
Unwind(Regs * initial_regs,AndroidUnwinderData & data)149*eb293b8fSAndroid Build Coastguard Worker bool AndroidUnwinder::Unwind(Regs* initial_regs, AndroidUnwinderData& data) {
150*eb293b8fSAndroid Build Coastguard Worker   if (initial_regs == nullptr) {
151*eb293b8fSAndroid Build Coastguard Worker     data.error.code = ERROR_INVALID_PARAMETER;
152*eb293b8fSAndroid Build Coastguard Worker     return false;
153*eb293b8fSAndroid Build Coastguard Worker   }
154*eb293b8fSAndroid Build Coastguard Worker 
155*eb293b8fSAndroid Build Coastguard Worker   if (!Initialize(data.error)) {
156*eb293b8fSAndroid Build Coastguard Worker     return false;
157*eb293b8fSAndroid Build Coastguard Worker   }
158*eb293b8fSAndroid Build Coastguard Worker 
159*eb293b8fSAndroid Build Coastguard Worker   if (arch_ != initial_regs->Arch()) {
160*eb293b8fSAndroid Build Coastguard Worker     data.error.code = ERROR_BAD_ARCH;
161*eb293b8fSAndroid Build Coastguard Worker     return false;
162*eb293b8fSAndroid Build Coastguard Worker   }
163*eb293b8fSAndroid Build Coastguard Worker 
164*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<Regs> regs(initial_regs->Clone());
165*eb293b8fSAndroid Build Coastguard Worker   if (data.saved_initial_regs) {
166*eb293b8fSAndroid Build Coastguard Worker     (*data.saved_initial_regs).reset(initial_regs->Clone());
167*eb293b8fSAndroid Build Coastguard Worker   }
168*eb293b8fSAndroid Build Coastguard Worker   Unwinder unwinder(data.max_frames.value_or(max_frames_), maps_.get(), regs.get(),
169*eb293b8fSAndroid Build Coastguard Worker                     process_memory_);
170*eb293b8fSAndroid Build Coastguard Worker   unwinder.SetJitDebug(jit_debug_.get());
171*eb293b8fSAndroid Build Coastguard Worker   unwinder.SetDexFiles(dex_files_.get());
172*eb293b8fSAndroid Build Coastguard Worker   unwinder.Unwind(data.show_all_frames ? nullptr : &initial_map_names_to_skip_,
173*eb293b8fSAndroid Build Coastguard Worker                   &map_suffixes_to_ignore_);
174*eb293b8fSAndroid Build Coastguard Worker   data.frames = unwinder.ConsumeFrames();
175*eb293b8fSAndroid Build Coastguard Worker   data.error = unwinder.LastError();
176*eb293b8fSAndroid Build Coastguard Worker   return data.frames.size() != 0;
177*eb293b8fSAndroid Build Coastguard Worker }
178*eb293b8fSAndroid Build Coastguard Worker 
InternalUnwind(std::optional<pid_t> tid,AndroidUnwinderData & data)179*eb293b8fSAndroid Build Coastguard Worker bool AndroidLocalUnwinder::InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
180*eb293b8fSAndroid Build Coastguard Worker   if (!tid) {
181*eb293b8fSAndroid Build Coastguard Worker     tid = android::base::GetThreadId();
182*eb293b8fSAndroid Build Coastguard Worker   }
183*eb293b8fSAndroid Build Coastguard Worker 
184*eb293b8fSAndroid Build Coastguard Worker   if (static_cast<uint64_t>(*tid) == android::base::GetThreadId()) {
185*eb293b8fSAndroid Build Coastguard Worker     // Unwind current thread.
186*eb293b8fSAndroid Build Coastguard Worker     std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
187*eb293b8fSAndroid Build Coastguard Worker     RegsGetLocal(regs.get());
188*eb293b8fSAndroid Build Coastguard Worker     return AndroidUnwinder::Unwind(regs.get(), data);
189*eb293b8fSAndroid Build Coastguard Worker   }
190*eb293b8fSAndroid Build Coastguard Worker 
191*eb293b8fSAndroid Build Coastguard Worker   ThreadUnwinder unwinder(data.max_frames.value_or(max_frames_), maps_.get(), process_memory_);
192*eb293b8fSAndroid Build Coastguard Worker   unwinder.SetJitDebug(jit_debug_.get());
193*eb293b8fSAndroid Build Coastguard Worker   unwinder.SetDexFiles(dex_files_.get());
194*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<Regs>* initial_regs = nullptr;
195*eb293b8fSAndroid Build Coastguard Worker   if (data.saved_initial_regs) {
196*eb293b8fSAndroid Build Coastguard Worker     initial_regs = &data.saved_initial_regs.value();
197*eb293b8fSAndroid Build Coastguard Worker   }
198*eb293b8fSAndroid Build Coastguard Worker   unwinder.UnwindWithSignal(kThreadUnwindSignal, *tid, initial_regs,
199*eb293b8fSAndroid Build Coastguard Worker                             data.show_all_frames ? nullptr : &initial_map_names_to_skip_,
200*eb293b8fSAndroid Build Coastguard Worker                             &map_suffixes_to_ignore_);
201*eb293b8fSAndroid Build Coastguard Worker   data.frames = unwinder.ConsumeFrames();
202*eb293b8fSAndroid Build Coastguard Worker   data.error = unwinder.LastError();
203*eb293b8fSAndroid Build Coastguard Worker   return data.frames.size() != 0;
204*eb293b8fSAndroid Build Coastguard Worker }
205*eb293b8fSAndroid Build Coastguard Worker 
InternalInitialize(ErrorData & error)206*eb293b8fSAndroid Build Coastguard Worker bool AndroidRemoteUnwinder::InternalInitialize(ErrorData& error) {
207*eb293b8fSAndroid Build Coastguard Worker   if (arch_ == ARCH_UNKNOWN) {
208*eb293b8fSAndroid Build Coastguard Worker     arch_ = Regs::RemoteGetArch(pid_, &error.code);
209*eb293b8fSAndroid Build Coastguard Worker   }
210*eb293b8fSAndroid Build Coastguard Worker   if (arch_ == ARCH_UNKNOWN) {
211*eb293b8fSAndroid Build Coastguard Worker     return false;
212*eb293b8fSAndroid Build Coastguard Worker   }
213*eb293b8fSAndroid Build Coastguard Worker 
214*eb293b8fSAndroid Build Coastguard Worker   maps_.reset(new RemoteMaps(pid_));
215*eb293b8fSAndroid Build Coastguard Worker   if (!maps_->Parse()) {
216*eb293b8fSAndroid Build Coastguard Worker     error.code = ERROR_MAPS_PARSE;
217*eb293b8fSAndroid Build Coastguard Worker     return false;
218*eb293b8fSAndroid Build Coastguard Worker   }
219*eb293b8fSAndroid Build Coastguard Worker 
220*eb293b8fSAndroid Build Coastguard Worker   if (process_memory_ == nullptr) {
221*eb293b8fSAndroid Build Coastguard Worker     process_memory_ = Memory::CreateProcessMemoryCached(pid_);
222*eb293b8fSAndroid Build Coastguard Worker   }
223*eb293b8fSAndroid Build Coastguard Worker 
224*eb293b8fSAndroid Build Coastguard Worker   return true;
225*eb293b8fSAndroid Build Coastguard Worker }
226*eb293b8fSAndroid Build Coastguard Worker 
InternalUnwind(std::optional<pid_t> tid,AndroidUnwinderData & data)227*eb293b8fSAndroid Build Coastguard Worker bool AndroidRemoteUnwinder::InternalUnwind(std::optional<pid_t> tid, AndroidUnwinderData& data) {
228*eb293b8fSAndroid Build Coastguard Worker   if (!tid) {
229*eb293b8fSAndroid Build Coastguard Worker     tid = pid_;
230*eb293b8fSAndroid Build Coastguard Worker   }
231*eb293b8fSAndroid Build Coastguard Worker 
232*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<Regs> regs(Regs::RemoteGet(*tid, &data.error.code));
233*eb293b8fSAndroid Build Coastguard Worker   if (regs == nullptr) {
234*eb293b8fSAndroid Build Coastguard Worker     return false;
235*eb293b8fSAndroid Build Coastguard Worker   }
236*eb293b8fSAndroid Build Coastguard Worker   return AndroidUnwinder::Unwind(regs.get(), data);
237*eb293b8fSAndroid Build Coastguard Worker }
238*eb293b8fSAndroid Build Coastguard Worker 
239*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
240