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