blob: dcd3d09cf09a7c8281781efd0b2b0f91a3f0bf59 [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
18#include <assert.h>
19#include <stdint.h>
20#include <stdlib.h>
21#include <string.h>
22#include <ucontext.h>
23
24#include <memory>
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070025#include <set>
Christopher Ferris6f3981c2017-07-27 09:29:18 -070026#include <string>
27
28#if !defined(__ANDROID__)
29#include <cutils/threads.h>
30#endif
31
32#include <backtrace/Backtrace.h>
Christopher Ferris04fdec02017-08-11 15:17:46 -070033#include <demangle.h>
Christopher Ferris6f3981c2017-07-27 09:29:18 -070034#include <unwindstack/Elf.h>
35#include <unwindstack/MapInfo.h>
36#include <unwindstack/Maps.h>
37#include <unwindstack/Memory.h>
38#include <unwindstack/Regs.h>
39#include <unwindstack/RegsGetLocal.h>
40
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070041#include <unwindstack/Unwinder.h>
42
Christopher Ferris6f3981c2017-07-27 09:29:18 -070043#include "BacktraceLog.h"
44#include "UnwindStack.h"
45#include "UnwindStackMap.h"
46
Josh Gao45c4a562017-09-06 14:35:35 -070047bool Backtrace::Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
48 std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames) {
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070049 static std::set<std::string> skip_names{"libunwindstack.so", "libbacktrace.so"};
Christopher Ferris5f118512017-09-01 11:17:16 -070050 UnwindStackMap* stack_map = reinterpret_cast<UnwindStackMap*>(back_map);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070051 auto process_memory = stack_map->process_memory();
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070052 unwindstack::Unwinder unwinder(MAX_BACKTRACE_FRAMES + num_ignore_frames, stack_map->stack_maps(),
53 regs, stack_map->process_memory());
54 unwinder.Unwind(&skip_names);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070055
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070056 if (num_ignore_frames >= unwinder.NumFrames()) {
57 frames->resize(0);
58 return true;
59 }
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070060
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070061 frames->resize(unwinder.NumFrames() - num_ignore_frames);
62 auto unwinder_frames = unwinder.frames();
63 size_t cur_frame = 0;
64 for (size_t i = num_ignore_frames; i < unwinder.NumFrames(); i++, cur_frame++) {
65 auto frame = &unwinder_frames[i];
66 backtrace_frame_data_t* back_frame = &frames->at(cur_frame);
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070067
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070068 back_frame->num = frame->num;
Christopher Ferrisb9de87f2017-09-20 13:37:24 -070069
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070070 back_frame->rel_pc = frame->rel_pc;
71 back_frame->pc = frame->pc;
72 back_frame->sp = frame->sp;
Christopher Ferris6f3981c2017-07-27 09:29:18 -070073
Christopher Ferrisf6f691b2017-09-25 19:23:07 -070074 back_frame->func_name = frame->function_name;
75 back_frame->func_offset = frame->function_offset;
76
77 back_frame->map.name = frame->map_name;
78 back_frame->map.start = frame->map_start;
79 back_frame->map.end = frame->map_end;
80 back_frame->map.offset = frame->map_offset;
81 back_frame->map.load_bias = frame->map_load_bias;
82 back_frame->map.flags = frame->map_flags;
Christopher Ferris6f3981c2017-07-27 09:29:18 -070083 }
84
85 return true;
86}
87
88UnwindStackCurrent::UnwindStackCurrent(pid_t pid, pid_t tid, BacktraceMap* map)
Christopher Ferris5f118512017-09-01 11:17:16 -070089 : BacktraceCurrent(pid, tid, map) {}
Christopher Ferris6f3981c2017-07-27 09:29:18 -070090
91std::string UnwindStackCurrent::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
Josh Gao358de182017-09-06 22:16:09 -070092 return GetMap()->GetFunctionName(pc, offset);
Christopher Ferris6f3981c2017-07-27 09:29:18 -070093}
94
95bool UnwindStackCurrent::UnwindFromContext(size_t num_ignore_frames, ucontext_t* ucontext) {
96 std::unique_ptr<unwindstack::Regs> regs;
97 if (ucontext == nullptr) {
98 regs.reset(unwindstack::Regs::CreateFromLocal());
99 // Fill in the registers from this function. Do it here to avoid
100 // one extra function call appearing in the unwind.
101 unwindstack::RegsGetLocal(regs.get());
102 } else {
Josh Gao0953ecd2017-08-25 13:55:06 -0700103 regs.reset(
104 unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentMachineType(), ucontext));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700105 }
106
107 error_ = BACKTRACE_UNWIND_NO_ERROR;
Josh Gao45c4a562017-09-06 14:35:35 -0700108 return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700109}
110
111UnwindStackPtrace::UnwindStackPtrace(pid_t pid, pid_t tid, BacktraceMap* map)
Christopher Ferris5f118512017-09-01 11:17:16 -0700112 : BacktracePtrace(pid, tid, map) {}
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700113
114std::string UnwindStackPtrace::GetFunctionNameRaw(uintptr_t pc, uintptr_t* offset) {
Josh Gao358de182017-09-06 22:16:09 -0700115 return GetMap()->GetFunctionName(pc, offset);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700116}
117
118bool UnwindStackPtrace::Unwind(size_t num_ignore_frames, ucontext_t* context) {
119 std::unique_ptr<unwindstack::Regs> regs;
120 if (context == nullptr) {
Josh Gao0953ecd2017-08-25 13:55:06 -0700121 regs.reset(unwindstack::Regs::RemoteGet(Tid()));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700122 } else {
Josh Gao0953ecd2017-08-25 13:55:06 -0700123 regs.reset(
124 unwindstack::Regs::CreateFromUcontext(unwindstack::Regs::CurrentMachineType(), context));
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700125 }
126
127 error_ = BACKTRACE_UNWIND_NO_ERROR;
Josh Gao45c4a562017-09-06 14:35:35 -0700128 return Backtrace::Unwind(regs.get(), GetMap(), &frames_, num_ignore_frames);
Christopher Ferris6f3981c2017-07-27 09:29:18 -0700129}
130
131Backtrace* Backtrace::CreateNew(pid_t pid, pid_t tid, BacktraceMap* map) {
132 if (pid == BACKTRACE_CURRENT_PROCESS) {
133 pid = getpid();
134 if (tid == BACKTRACE_CURRENT_THREAD) {
135 tid = gettid();
136 }
137 } else if (tid == BACKTRACE_CURRENT_THREAD) {
138 tid = pid;
139 }
140
141 if (map == nullptr) {
142// This would cause the wrong type of map object to be created, so disallow.
143#if defined(__ANDROID__)
144 __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__,
145 "Backtrace::CreateNew() must be called with a real map pointer.");
146#else
147 BACK_LOGE("Backtrace::CreateNew() must be called with a real map pointer.");
148 abort();
149#endif
150 }
151
152 if (pid == getpid()) {
153 return new UnwindStackCurrent(pid, tid, map);
154 } else {
155 return new UnwindStackPtrace(pid, tid, map);
156 }
157}