/src/perfetto/buildtools/android-unwinding/libunwindstack/Unwinder.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2017 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 | | #define _GNU_SOURCE 1 |
18 | | #include <elf.h> |
19 | | #include <inttypes.h> |
20 | | #include <stdint.h> |
21 | | #include <string.h> |
22 | | #include <sys/mman.h> |
23 | | #include <sys/types.h> |
24 | | #include <unistd.h> |
25 | | |
26 | | #include <algorithm> |
27 | | #include <memory> |
28 | | #include <string> |
29 | | |
30 | | #include <android-base/file.h> |
31 | | #include <android-base/stringprintf.h> |
32 | | |
33 | | #include <unwindstack/Demangle.h> |
34 | | #include <unwindstack/DexFiles.h> |
35 | | #include <unwindstack/Elf.h> |
36 | | #include <unwindstack/JitDebug.h> |
37 | | #include <unwindstack/MapInfo.h> |
38 | | #include <unwindstack/Maps.h> |
39 | | #include <unwindstack/Memory.h> |
40 | | #include <unwindstack/Unwinder.h> |
41 | | |
42 | | #include "Check.h" |
43 | | |
44 | | namespace unwindstack { |
45 | | |
46 | | // Inject extra 'virtual' frame that represents the dex pc data. |
47 | | // The dex pc is a magic register defined in the Mterp interpreter, |
48 | | // and thus it will be restored/observed in the frame after it. |
49 | | // Adding the dex frame first here will create something like: |
50 | | // #7 pc 0015fa20 core.vdex java.util.Arrays.binarySearch+8 |
51 | | // #8 pc 006b1ba1 libartd.so ExecuteMterpImpl+14625 |
52 | | // #9 pc 0039a1ef libartd.so art::interpreter::Execute+719 |
53 | 0 | void Unwinder::FillInDexFrame() { |
54 | 0 | size_t frame_num = frames_.size(); |
55 | 0 | frames_.resize(frame_num + 1); |
56 | 0 | FrameData* frame = &frames_.at(frame_num); |
57 | 0 | frame->num = frame_num; |
58 | |
|
59 | 0 | uint64_t dex_pc = regs_->dex_pc(); |
60 | 0 | frame->pc = dex_pc; |
61 | 0 | frame->sp = regs_->sp(); |
62 | |
|
63 | 0 | frame->map_info = maps_->Find(dex_pc); |
64 | 0 | if (frame->map_info != nullptr) { |
65 | 0 | frame->rel_pc = dex_pc - frame->map_info->start(); |
66 | | // Initialize the load bias for this map so subsequent calls |
67 | | // to GetLoadBias() will always return data. |
68 | 0 | frame->map_info->set_load_bias(0); |
69 | 0 | } else { |
70 | 0 | frame->rel_pc = dex_pc; |
71 | 0 | warnings_ |= WARNING_DEX_PC_NOT_IN_MAP; |
72 | 0 | return; |
73 | 0 | } |
74 | | |
75 | 0 | if (!resolve_names_) { |
76 | 0 | return; |
77 | 0 | } |
78 | |
|
79 | | #if defined(DEXFILE_SUPPORT) |
80 | | if (dex_files_ == nullptr) { |
81 | | return; |
82 | | } |
83 | | |
84 | | dex_files_->GetFunctionName(maps_, dex_pc, &frame->function_name, &frame->function_offset); |
85 | | #endif |
86 | 0 | } |
87 | | |
88 | | FrameData* Unwinder::FillInFrame(std::shared_ptr<MapInfo>& map_info, Elf* /*elf*/, uint64_t rel_pc, |
89 | 4.59k | uint64_t pc_adjustment) { |
90 | 4.59k | size_t frame_num = frames_.size(); |
91 | 4.59k | frames_.resize(frame_num + 1); |
92 | 4.59k | FrameData* frame = &frames_.at(frame_num); |
93 | 4.59k | frame->num = frame_num; |
94 | 4.59k | frame->sp = regs_->sp(); |
95 | 4.59k | frame->rel_pc = rel_pc - pc_adjustment; |
96 | 4.59k | frame->pc = regs_->pc() - pc_adjustment; |
97 | | |
98 | 4.59k | if (map_info == nullptr) { |
99 | | // Nothing else to update. |
100 | 4.44k | return nullptr; |
101 | 4.44k | } |
102 | | |
103 | 152 | frame->map_info = map_info; |
104 | | |
105 | 152 | return frame; |
106 | 4.59k | } |
107 | | |
108 | | static bool ShouldStop(const std::vector<std::string>* map_suffixes_to_ignore, |
109 | 152 | const std::string& map_name) { |
110 | 152 | if (map_suffixes_to_ignore == nullptr) { |
111 | 152 | return false; |
112 | 152 | } |
113 | 0 | auto pos = map_name.find_last_of('.'); |
114 | 0 | if (pos == std::string::npos) { |
115 | 0 | return false; |
116 | 0 | } |
117 | | |
118 | 0 | return std::find(map_suffixes_to_ignore->begin(), map_suffixes_to_ignore->end(), |
119 | 0 | map_name.substr(pos + 1)) != map_suffixes_to_ignore->end(); |
120 | 0 | } |
121 | | |
122 | | void Unwinder::Unwind(const std::vector<std::string>* initial_map_names_to_skip, |
123 | 2.32k | const std::vector<std::string>* map_suffixes_to_ignore) { |
124 | 2.32k | CHECK(arch_ != ARCH_UNKNOWN); |
125 | 2.32k | ClearErrors(); |
126 | | |
127 | 2.32k | frames_.clear(); |
128 | | |
129 | | // Clear any cached data from previous unwinds. |
130 | 2.32k | process_memory_->Clear(); |
131 | | |
132 | 2.32k | if (maps_->Find(regs_->pc()) == nullptr) { |
133 | 2.17k | regs_->fallback_pc(); |
134 | 2.17k | } |
135 | | |
136 | 2.32k | bool return_address_attempt = false; |
137 | 2.32k | bool adjust_pc = false; |
138 | 4.59k | for (; frames_.size() < max_frames_;) { |
139 | 4.59k | uint64_t cur_pc = regs_->pc(); |
140 | 4.59k | uint64_t cur_sp = regs_->sp(); |
141 | | |
142 | 4.59k | std::shared_ptr<MapInfo> map_info = maps_->Find(regs_->pc()); |
143 | 4.59k | uint64_t pc_adjustment = 0; |
144 | 4.59k | uint64_t step_pc; |
145 | 4.59k | uint64_t rel_pc; |
146 | 4.59k | Elf* elf; |
147 | 4.59k | bool ignore_frame = false; |
148 | 4.59k | if (map_info == nullptr) { |
149 | 4.44k | step_pc = regs_->pc(); |
150 | 4.44k | rel_pc = step_pc; |
151 | | // If we get invalid map via return_address_attempt, don't hide error for the previous frame. |
152 | 4.44k | if (!return_address_attempt || last_error_.code == ERROR_NONE) { |
153 | 2.25k | last_error_.code = ERROR_INVALID_MAP; |
154 | 2.25k | last_error_.address = step_pc; |
155 | 2.25k | } |
156 | 4.44k | elf = nullptr; |
157 | 4.44k | } else { |
158 | 152 | ignore_frame = |
159 | 152 | initial_map_names_to_skip != nullptr && |
160 | 152 | std::find(initial_map_names_to_skip->begin(), initial_map_names_to_skip->end(), |
161 | 148 | android::base::Basename(map_info->name())) != initial_map_names_to_skip->end(); |
162 | 152 | if (!ignore_frame && ShouldStop(map_suffixes_to_ignore, map_info->name())) { |
163 | 0 | break; |
164 | 0 | } |
165 | 152 | elf = map_info->GetElf(process_memory_, arch_); |
166 | 152 | step_pc = regs_->pc(); |
167 | 152 | rel_pc = elf->GetRelPc(step_pc, map_info.get()); |
168 | | // Everyone except elf data in gdb jit debug maps uses the relative pc. |
169 | 152 | if (!(map_info->flags() & MAPS_FLAGS_JIT_SYMFILE_MAP)) { |
170 | 152 | step_pc = rel_pc; |
171 | 152 | } |
172 | 152 | if (adjust_pc) { |
173 | 4 | pc_adjustment = GetPcAdjustment(rel_pc, elf, arch_); |
174 | 148 | } else { |
175 | 148 | pc_adjustment = 0; |
176 | 148 | } |
177 | 152 | step_pc -= pc_adjustment; |
178 | | |
179 | | // If the pc is in an invalid elf file, try and get an Elf object |
180 | | // using the jit debug information. |
181 | 152 | if (!elf->valid() && jit_debug_ != nullptr && (map_info->flags() & PROT_EXEC)) { |
182 | 0 | uint64_t adjusted_jit_pc = regs_->pc() - pc_adjustment; |
183 | 0 | Elf* jit_elf = jit_debug_->Find(maps_, adjusted_jit_pc); |
184 | 0 | if (jit_elf != nullptr) { |
185 | | // The jit debug information requires a non relative adjusted pc. |
186 | 0 | step_pc = adjusted_jit_pc; |
187 | 0 | elf = jit_elf; |
188 | 0 | } |
189 | 0 | } |
190 | 152 | } |
191 | | |
192 | 4.59k | FrameData* frame = nullptr; |
193 | 4.59k | if (!ignore_frame) { |
194 | 4.59k | if (regs_->dex_pc() != 0) { |
195 | | // Add a frame to represent the dex file. |
196 | 0 | FillInDexFrame(); |
197 | | // Clear the dex pc so that we don't repeat this frame later. |
198 | 0 | regs_->set_dex_pc(0); |
199 | | |
200 | | // Make sure there is enough room for the real frame. |
201 | 0 | if (frames_.size() == max_frames_) { |
202 | 0 | last_error_.code = ERROR_MAX_FRAMES_EXCEEDED; |
203 | 0 | break; |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | 4.59k | frame = FillInFrame(map_info, elf, rel_pc, pc_adjustment); |
208 | | |
209 | | // Once a frame is added, stop skipping frames. |
210 | 4.59k | initial_map_names_to_skip = nullptr; |
211 | 4.59k | } |
212 | 4.59k | adjust_pc = true; |
213 | | |
214 | 4.59k | bool stepped = false; |
215 | 4.59k | bool in_device_map = false; |
216 | 4.59k | bool finished = false; |
217 | 4.59k | if (map_info != nullptr) { |
218 | 152 | if (map_info->flags() & MAPS_FLAGS_DEVICE_MAP) { |
219 | | // Do not stop here, fall through in case we are |
220 | | // in the speculative unwind path and need to remove |
221 | | // some of the speculative frames. |
222 | 0 | in_device_map = true; |
223 | 152 | } else { |
224 | 152 | auto sp_info = maps_->Find(regs_->sp()); |
225 | 152 | if (sp_info != nullptr && sp_info->flags() & MAPS_FLAGS_DEVICE_MAP) { |
226 | | // Do not stop here, fall through in case we are |
227 | | // in the speculative unwind path and need to remove |
228 | | // some of the speculative frames. |
229 | 0 | in_device_map = true; |
230 | 152 | } else { |
231 | 152 | bool is_signal_frame = false; |
232 | 152 | if (elf->StepIfSignalHandler(rel_pc, regs_, process_memory_.get())) { |
233 | 0 | stepped = true; |
234 | 0 | is_signal_frame = true; |
235 | 152 | } else if (elf->Step(step_pc, regs_, process_memory_.get(), &finished, |
236 | 152 | &is_signal_frame)) { |
237 | 0 | stepped = true; |
238 | 0 | } |
239 | 152 | if (is_signal_frame && frame != nullptr) { |
240 | | // Need to adjust the relative pc because the signal handler |
241 | | // pc should not be adjusted. |
242 | 0 | frame->rel_pc = rel_pc; |
243 | 0 | frame->pc += pc_adjustment; |
244 | 0 | step_pc = rel_pc; |
245 | 0 | } |
246 | 152 | elf->GetLastError(&last_error_); |
247 | 152 | } |
248 | 152 | } |
249 | 152 | } |
250 | | |
251 | 4.59k | if (frame != nullptr) { |
252 | 152 | if (!resolve_names_ || |
253 | 152 | !elf->GetFunctionName(step_pc, &frame->function_name, &frame->function_offset)) { |
254 | 152 | frame->function_name = ""; |
255 | 152 | frame->function_offset = 0; |
256 | 152 | } |
257 | 152 | } |
258 | | |
259 | 4.59k | if (finished) { |
260 | 0 | break; |
261 | 0 | } |
262 | | |
263 | 4.59k | if (!stepped) { |
264 | 4.59k | if (return_address_attempt) { |
265 | | // Only remove the speculative frame if there are more than two frames |
266 | | // or the pc in the first frame is in a valid map. |
267 | | // This allows for a case where the code jumps into the middle of |
268 | | // nowhere, but there is no other unwind information after that. |
269 | 2.27k | if (frames_.size() > 2 || (frames_.size() > 0 && maps_->Find(frames_[0].pc) != nullptr)) { |
270 | | // Remove the speculative frame. |
271 | 106 | frames_.pop_back(); |
272 | 106 | } |
273 | 2.27k | break; |
274 | 2.32k | } else if (in_device_map) { |
275 | | // Do not attempt any other unwinding, pc or sp is in a device |
276 | | // map. |
277 | 0 | break; |
278 | 2.32k | } else { |
279 | | // Steping didn't work, try this secondary method. |
280 | 2.32k | if (!regs_->SetPcFromReturnAddress(process_memory_.get())) { |
281 | 48 | break; |
282 | 48 | } |
283 | 2.27k | return_address_attempt = true; |
284 | 2.27k | } |
285 | 4.59k | } else { |
286 | 0 | return_address_attempt = false; |
287 | 0 | if (max_frames_ == frames_.size()) { |
288 | 0 | last_error_.code = ERROR_MAX_FRAMES_EXCEEDED; |
289 | 0 | } |
290 | 0 | } |
291 | | |
292 | | // If the pc and sp didn't change, then consider everything stopped. |
293 | 2.27k | if (cur_pc == regs_->pc() && cur_sp == regs_->sp()) { |
294 | 0 | last_error_.code = ERROR_REPEATED_FRAME; |
295 | 0 | break; |
296 | 0 | } |
297 | 2.27k | } |
298 | 2.32k | } |
299 | | |
300 | 0 | std::string Unwinder::FormatFrame(const FrameData& frame) const { |
301 | 0 | return FormatFrame(arch_, frame, display_build_id_); |
302 | 0 | } |
303 | | |
304 | 0 | std::string Unwinder::FormatFrame(ArchEnum arch, const FrameData& frame, bool display_build_id) { |
305 | 0 | std::string data; |
306 | 0 | if (ArchIs32Bit(arch)) { |
307 | 0 | data += android::base::StringPrintf(" #%02zu pc %08" PRIx64, frame.num, frame.rel_pc); |
308 | 0 | } else { |
309 | 0 | data += android::base::StringPrintf(" #%02zu pc %016" PRIx64, frame.num, frame.rel_pc); |
310 | 0 | } |
311 | |
|
312 | 0 | auto map_info = frame.map_info; |
313 | 0 | if (map_info == nullptr) { |
314 | | // No valid map associated with this frame. |
315 | 0 | data += " <unknown>"; |
316 | 0 | } else if (!map_info->name().empty()) { |
317 | 0 | data += " "; |
318 | 0 | data += map_info->GetFullName(); |
319 | 0 | } else { |
320 | 0 | data += android::base::StringPrintf(" <anonymous:%" PRIx64 ">", map_info->start()); |
321 | 0 | } |
322 | |
|
323 | 0 | if (map_info != nullptr && map_info->elf_start_offset() != 0) { |
324 | 0 | data += android::base::StringPrintf(" (offset 0x%" PRIx64 ")", map_info->elf_start_offset()); |
325 | 0 | } |
326 | |
|
327 | 0 | if (!frame.function_name.empty()) { |
328 | 0 | data += " (" + DemangleNameIfNeeded(frame.function_name); |
329 | 0 | if (frame.function_offset != 0) { |
330 | 0 | data += android::base::StringPrintf("+%" PRId64, frame.function_offset); |
331 | 0 | } |
332 | 0 | data += ')'; |
333 | 0 | } |
334 | |
|
335 | 0 | if (map_info != nullptr && display_build_id) { |
336 | 0 | std::string build_id = map_info->GetPrintableBuildID(); |
337 | 0 | if (!build_id.empty()) { |
338 | 0 | data += " (BuildId: " + build_id + ')'; |
339 | 0 | } |
340 | 0 | } |
341 | 0 | return data; |
342 | 0 | } |
343 | | |
344 | 0 | std::string Unwinder::FormatFrame(size_t frame_num) const { |
345 | 0 | if (frame_num >= frames_.size()) { |
346 | 0 | return ""; |
347 | 0 | } |
348 | 0 | return FormatFrame(arch_, frames_[frame_num], display_build_id_); |
349 | 0 | } |
350 | | |
351 | 0 | void Unwinder::SetJitDebug(JitDebug* jit_debug) { |
352 | 0 | jit_debug_ = jit_debug; |
353 | 0 | } |
354 | | |
355 | 0 | void Unwinder::SetDexFiles(DexFiles* dex_files) { |
356 | 0 | dex_files_ = dex_files; |
357 | 0 | } |
358 | | |
359 | 0 | bool UnwinderFromPid::Init() { |
360 | 0 | CHECK(arch_ != ARCH_UNKNOWN); |
361 | 0 | if (initted_) { |
362 | 0 | return true; |
363 | 0 | } |
364 | 0 | initted_ = true; |
365 | |
|
366 | 0 | if (maps_ == nullptr) { |
367 | 0 | if (pid_ == getpid()) { |
368 | 0 | maps_ptr_.reset(new LocalMaps()); |
369 | 0 | } else { |
370 | 0 | maps_ptr_.reset(new RemoteMaps(pid_)); |
371 | 0 | } |
372 | 0 | if (!maps_ptr_->Parse()) { |
373 | 0 | ClearErrors(); |
374 | 0 | last_error_.code = ERROR_INVALID_MAP; |
375 | 0 | return false; |
376 | 0 | } |
377 | 0 | maps_ = maps_ptr_.get(); |
378 | 0 | } |
379 | | |
380 | 0 | if (process_memory_ == nullptr) { |
381 | 0 | if (pid_ == getpid()) { |
382 | | // Local unwind, so use thread cache to allow multiple threads |
383 | | // to cache data even when multiple threads access the same object. |
384 | 0 | process_memory_ = Memory::CreateProcessMemoryThreadCached(pid_); |
385 | 0 | } else { |
386 | | // Remote unwind should be safe to cache since the unwind will |
387 | | // be occurring on a stopped process. |
388 | 0 | process_memory_ = Memory::CreateProcessMemoryCached(pid_); |
389 | 0 | } |
390 | 0 | } |
391 | | |
392 | | // jit_debug_ and dex_files_ may have already been set, for example in |
393 | | // AndroidLocalUnwinder::InternalUnwind. |
394 | 0 | if (jit_debug_ == nullptr) { |
395 | 0 | jit_debug_ptr_ = CreateJitDebug(arch_, process_memory_); |
396 | 0 | SetJitDebug(jit_debug_ptr_.get()); |
397 | 0 | } |
398 | | #if defined(DEXFILE_SUPPORT) |
399 | | if (dex_files_ == nullptr) { |
400 | | dex_files_ptr_ = CreateDexFiles(arch_, process_memory_); |
401 | | SetDexFiles(dex_files_ptr_.get()); |
402 | | } |
403 | | #endif |
404 | |
|
405 | 0 | return true; |
406 | 0 | } |
407 | | |
408 | | void UnwinderFromPid::Unwind(const std::vector<std::string>* initial_map_names_to_skip, |
409 | 0 | const std::vector<std::string>* map_suffixes_to_ignore) { |
410 | 0 | if (!Init()) { |
411 | 0 | return; |
412 | 0 | } |
413 | 0 | Unwinder::Unwind(initial_map_names_to_skip, map_suffixes_to_ignore); |
414 | 0 | } |
415 | | |
416 | | FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc, ArchEnum arch, Maps* maps, |
417 | | JitDebug* jit_debug, |
418 | | std::shared_ptr<Memory> process_memory, |
419 | 0 | bool resolve_names) { |
420 | 0 | FrameData frame; |
421 | |
|
422 | 0 | std::shared_ptr<MapInfo> map_info = maps->Find(pc); |
423 | 0 | if (map_info == nullptr || arch == ARCH_UNKNOWN) { |
424 | 0 | frame.pc = pc; |
425 | 0 | frame.rel_pc = pc; |
426 | 0 | return frame; |
427 | 0 | } |
428 | | |
429 | 0 | Elf* elf = map_info->GetElf(process_memory, arch); |
430 | |
|
431 | 0 | uint64_t relative_pc = elf->GetRelPc(pc, map_info.get()); |
432 | |
|
433 | 0 | uint64_t pc_adjustment = GetPcAdjustment(relative_pc, elf, arch); |
434 | 0 | relative_pc -= pc_adjustment; |
435 | | // The debug PC may be different if the PC comes from the JIT. |
436 | 0 | uint64_t debug_pc = relative_pc; |
437 | | |
438 | | // If we don't have a valid ELF file, check the JIT. |
439 | 0 | if (!elf->valid() && jit_debug != nullptr) { |
440 | 0 | uint64_t jit_pc = pc - pc_adjustment; |
441 | 0 | Elf* jit_elf = jit_debug->Find(maps, jit_pc); |
442 | 0 | if (jit_elf != nullptr) { |
443 | 0 | debug_pc = jit_pc; |
444 | 0 | elf = jit_elf; |
445 | 0 | } |
446 | 0 | } |
447 | | |
448 | | // Copy all the things we need into the frame for symbolization. |
449 | 0 | frame.rel_pc = relative_pc; |
450 | 0 | frame.pc = pc - pc_adjustment; |
451 | 0 | frame.map_info = map_info; |
452 | |
|
453 | 0 | if (!resolve_names || |
454 | 0 | !elf->GetFunctionName(debug_pc, &frame.function_name, &frame.function_offset)) { |
455 | 0 | frame.function_name = ""; |
456 | 0 | frame.function_offset = 0; |
457 | 0 | } |
458 | 0 | return frame; |
459 | 0 | } |
460 | | |
461 | 0 | FrameData Unwinder::BuildFrameFromPcOnly(uint64_t pc) { |
462 | 0 | return BuildFrameFromPcOnly(pc, arch_, maps_, jit_debug_, process_memory_, resolve_names_); |
463 | 0 | } |
464 | | |
465 | | } // namespace unwindstack |