blob: 7e2e6d05e6839d7980a71473e27e00c52ea52c4d [file] [log] [blame]
Christopher Ferris6f3981c2017-07-27 09:29:18 -07001/*
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
Christopher Ferris6f3981c2017-07-27 09:29:18 -070018#include <stdint.h>
19#include <stdlib.h>
20#include <string.h>
Christopher Ferris6f3981c2017-07-27 09:29:18 -070021
22#include <memory>
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070023#include <set>
Christopher Ferris6f3981c2017-07-27 09:29:18 -070024#include <string>
25
26#if !defined(__ANDROID__)
27#include <cutils/threads.h>
28#endif
29
30#include <backtrace/Backtrace.h>
Christopher Ferris04fdec02017-08-11 15:17:46 -070031#include <demangle.h>
Christopher Ferris6f3981c2017-07-27 09:29:18 -070032#include <unwindstack/Elf.h>
33#include <unwindstack/MapInfo.h>
34#include <unwindstack/Maps.h>
35#include <unwindstack/Memory.h>
36#include <unwindstack/Regs.h>
37#include <unwindstack/RegsGetLocal.h>
38
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080039#if !defined(NO_LIBDEXFILE_SUPPORT)
40#include <unwindstack/DexFiles.h>
41#endif
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070042#include <unwindstack/Unwinder.h>
43
Christopher Ferris6f3981c2017-07-27 09:29:18 -070044#include "BacktraceLog.h"
45#include "UnwindStack.h"
46#include "UnwindStackMap.h"
47
Josh Gao45c4a562017-09-06 14:35:35 -070048bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
Christopher Ferrisc56a4992017-11-02 16:19:56 -070049 std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -080050 std::vector<std::string>* skip_names, BacktraceUnwindError* error) {
Christopher Ferris5f118512017-09-01 11:17:16 -070051 UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070052 auto process_memory = stack_map->process_memory();
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070053 unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
54 regs, stack_map->process_memory());
Christopher Ferris2486d5a2018-01-22 17:37:59 -080055 if (stack_map->GetJitDebug() != nullptr) {
56 unwinder.SetJitDebug(stack_map->GetJitDebug(), regs->Arch());
57 }
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -080058#if !defined(NO_LIBDEXFILE_SUPPORT)
59 if (stack_map->GetDexFiles() != nullptr) {
60 unwinder.SetDexFiles(stack_map->GetDexFiles(), regs->Arch());
61 }
62#endif
Christopher Ferrisc56a4992017-11-02 16:19:56 -070063 unwinder.Unwind(skip_names, &stack_map->GetSuffixesToIgnore());
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -080064 if (error != nullptr) {
65 switch (unwinder.LastErrorCode()) {
66 case unwindstack::ERROR_NONE:
67 error->error_code = BACKTRACE_UNWIND_NO_ERROR;
68 break;
69
70 case unwindstack::ERROR_MEMORY_INVALID:
71 error->error_code = BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED;
72 error->error_info.addr = unwinder.LastErrorAddress();
73 break;
74
75 case unwindstack::ERROR_UNWIND_INFO:
76 error->error_code = BACKTRACE_UNWIND_ERROR_UNWIND_INFO;
77 break;
78
79 case unwindstack::ERROR_UNSUPPORTED:
80 error->error_code = BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION;
81 break;
82
83 case unwindstack::ERROR_INVALID_MAP:
84 error->error_code = BACKTRACE_UNWIND_ERROR_MAP_MISSING;
85 break;
86
87 case unwindstack::ERROR_MAX_FRAMES_EXCEEDED:
88 error->error_code = BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT;
89 break;
90
91 case unwindstack::ERROR_REPEATED_FRAME:
92 error->error_code = BACKTRACE_UNWIND_ERROR_REPEATED_FRAME;
93 break;
94 }
95 }
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070096
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070097 if (num_ignore_frames >= unwinder.NumFrames()) {
98 frames->resize(0);
99 return true;
100 }
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700101
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700102 auto unwinder_frames = unwinder.frames();
Christopher Ferrisd70ea5e2018-01-30 19:47:24 -0800103 frames->resize(unwinder.NumFrames() - num_ignore_frames);
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700104 size_t cur_frame = 0;
David Srbecky645f8bb2018-01-25 12:21:59 +0000105 for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++) {
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700106 auto frame = &unwinder_frames[i];
David Srbecky645f8bb2018-01-25 12:21:59 +0000107
Christopher Ferris8fe58362018-01-26 14:26:13 -0800108 backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700109
Christopher Ferris8fe58362018-01-26 14:26:13 -0800110 back_frame->num = cur_frame++;
Christopher Ferrisb9de87f2017-09-20 13:37:24 -0700111
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700112 back_frame->rel_pc = frame->rel_pc;
113 back_frame->pc = frame->pc;
114 back_frame->sp = frame->sp;
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700115
Christopher Ferris9a6b3e32017-10-18 09:08:51 -0700116 back_frame->func_name = demangle(frame->function_name.c_str());
Christopher Ferrisf6f691b2017-09-25 19:23:07 -0700117 back_frame->func_offset = frame->function_offset;
118
119 back_frame->map.name = frame->map_name;
120 back_frame->map.start = frame->map_start;
121 back_frame->map.end = frame->map_end;
122 back_frame->map.offset = frame->map_offset;
123 back_frame->map.load_bias = frame->map_load_bias;
124 back_frame->map.flags = frame->map_flags;
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700125 }
126
127 return true;
128}
129
130UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
Christopher Ferris5f118512017-09-01 11:17:16 -0700131 : BacktraceCurrent(pid, tid, map) {}
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700132
Christopher Ferris7937a362018-01-18 11:15:49 -0800133std::string UnwindStackCurrent::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
Josh Gao358de182017-09-06 22:16:09 -0700134 return GetMap()->GetFunctionName(pc, offset);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700135}
136
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -0800137bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, void* ucontext) {
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700138 std::unique_ptr<unwindstack::Regs> regs;
139 if (ucontext == nullptr) {
140 regs.reset(unwindstack::Regs::CreateFromLocal());
141 // Fill in the registers from this function. Do it here to avoid
142 // one extra function call appearing in the unwind.
143 unwindstack::RegsGetLocal(regs.get());
144 } else {
Christopher Ferrisd06001d2017-11-30 18:56:01 -0800145 regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), ucontext));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700146 }
147
Christopher Ferrisc56a4992017-11-02 16:19:56 -0700148 std::vector<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -0800149 return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, &skip_names, &error_);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700150}
151
152UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
Christopher Ferrise3286732017-12-07 17:41:18 -0800153 : BacktracePtrace(pid, tid, map), memory_(pid) {}
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700154
Christopher Ferris7937a362018-01-18 11:15:49 -0800155std::string UnwindStackPtrace::GetFunctionNameRaw(uint64_t pc, uint64_t* offset) {
Josh Gao358de182017-09-06 22:16:09 -0700156 return GetMap()->GetFunctionName(pc, offset);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700157}
158
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -0800159bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, void* context) {
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700160 std::unique_ptr<unwindstack::Regs> regs;
161 if (context == nullptr) {
Josh Gao0953ecd2017-08-25 13:55:06 -0700162 regs.reset(unwindstack::Regs::RemoteGet(Tid()));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700163 } else {
Christopher Ferrisd06001d2017-11-30 18:56:01 -0800164 regs.reset(unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentArch(), context));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700165 }
166
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -0800167 return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700168}
Christopher Ferrise3286732017-12-07 17:41:18 -0800169
Christopher Ferris7937a362018-01-18 11:15:49 -0800170size_t UnwindStackPtrace::Read(uint64_t addr, uint8_t* buffer, size_t bytes) {
Christopher Ferrise3286732017-12-07 17:41:18 -0800171 return memory_.Read(addr, buffer, bytes);
172}
Christopher Ferrisc8bec5a2017-12-11 17:44:33 -0800173
174UnwindStackOffline::UnwindStackOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map,
175 bool map_shared)
176 : Backtrace(pid, tid, map), arch_(arch) {
177 map_shared_ = map_shared;
178}
179
180bool UnwindStackOffline::Unwind(size_t num_ignore_frames, void* ucontext) {
181 if (ucontext == nullptr) {
182 return false;
183 }
184
185 unwindstack::ArchEnum arch;
186 switch (arch_) {
187 case ARCH_ARM:
188 arch = unwindstack::ARCH_ARM;
189 break;
190 case ARCH_ARM64:
191 arch = unwindstack::ARCH_ARM64;
192 break;
193 case ARCH_X86:
194 arch = unwindstack::ARCH_X86;
195 break;
196 case ARCH_X86_64:
197 arch = unwindstack::ARCH_X86_64;
198 break;
199 default:
200 return false;
201 }
202
203 std::unique_ptr<unwindstack::Regs> regs(unwindstack::Regs::CreateFromUcontext(arch, ucontext));
204
205 return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames, nullptr, &error_);
206}
207
208std::string UnwindStackOffline::GetFunctionNameRaw(uint64_t, uint64_t*) {
209 return "";
210}
211
212size_t UnwindStackOffline::Read(uint64_t, uint8_t*, size_t) {
213 return 0;
214}
215
216bool UnwindStackOffline::ReadWord(uint64_t, word_t*) {
217 return false;
218}
219
220Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid,
221 const std::vector<backtrace_map_t>& maps,
222 const backtrace_stackinfo_t& stack) {
223 BacktraceMap* map = BacktraceMap::CreateOffline(pid, maps, stack);
224 if (map == nullptr) {
225 return nullptr;
226 }
227
228 return new UnwindStackOffline(arch, pid, tid, map, false);
229}
230
231Backtrace* Backtrace::CreateOffline(ArchEnum arch, pid_t pid, pid_t tid, BacktraceMap* map) {
232 if (map == nullptr) {
233 return nullptr;
234 }
235 return new UnwindStackOffline(arch, pid, tid, map, true);
236}
237
238void Backtrace::SetGlobalElfCache(bool enable) {
239 unwindstack::Elf::SetCachingEnabled(enable);
240}