blob: 469360075c36193787c051c138db4605af46cd5e [file] [log] [blame]
Christopher Ferris17e91d42013-10-21 13:30:52 -07001/*
2 * Copyright (C) 2013 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 <errno.h>
18#include <stdlib.h>
19#include <string.h>
20#include <sys/ptrace.h>
21#include <sys/types.h>
Christopher Ferrisc58287d2014-05-09 16:59:06 -070022#include <ucontext.h>
Christopher Ferris17e91d42013-10-21 13:30:52 -070023#include <unistd.h>
24
Christopher Ferris17e91d42013-10-21 13:30:52 -070025#include <string>
26
27#include <backtrace/Backtrace.h>
Christopher Ferris46756822014-01-14 20:16:30 -080028#include <backtrace/BacktraceMap.h>
Christopher Ferris17e91d42013-10-21 13:30:52 -070029
Christopher Ferrisdf290612014-01-22 19:21:07 -080030#include "BacktraceImpl.h"
Christopher Ferrise2960912014-03-07 19:42:19 -080031#include "BacktraceLog.h"
Christopher Ferris17e91d42013-10-21 13:30:52 -070032#include "thread_utils.h"
33
34//-------------------------------------------------------------------------
Christopher Ferris17e91d42013-10-21 13:30:52 -070035// Backtrace functions.
36//-------------------------------------------------------------------------
Christopher Ferris46756822014-01-14 20:16:30 -080037Backtrace::Backtrace(BacktraceImpl* impl, pid_t pid, BacktraceMap* map)
38 : pid_(pid), tid_(-1), map_(map), map_shared_(true), impl_(impl) {
Christopher Ferris17e91d42013-10-21 13:30:52 -070039 impl_->SetParent(this);
Christopher Ferris98464972014-01-06 19:16:33 -080040
Christopher Ferris46756822014-01-14 20:16:30 -080041 if (map_ == NULL) {
Christopher Ferrisdf290612014-01-22 19:21:07 -080042 map_ = BacktraceMap::Create(pid);
Christopher Ferris46756822014-01-14 20:16:30 -080043 map_shared_ = false;
Christopher Ferris98464972014-01-06 19:16:33 -080044 }
Christopher Ferris17e91d42013-10-21 13:30:52 -070045}
46
47Backtrace::~Backtrace() {
Christopher Ferris17e91d42013-10-21 13:30:52 -070048 if (impl_) {
49 delete impl_;
50 impl_ = NULL;
51 }
Christopher Ferrisdf290612014-01-22 19:21:07 -080052
53 if (map_ && !map_shared_) {
54 delete map_;
55 map_ = NULL;
56 }
Christopher Ferris17e91d42013-10-21 13:30:52 -070057}
58
Christopher Ferrisa2efd3a2014-05-06 15:23:59 -070059bool Backtrace::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) {
60 return impl_->Unwind(num_ignore_frames, ucontext);
Christopher Ferris17e91d42013-10-21 13:30:52 -070061}
62
Christopher Ferris17e91d42013-10-21 13:30:52 -070063std::string Backtrace::GetFunctionName(uintptr_t pc, uintptr_t* offset) {
64 std::string func_name = impl_->GetFunctionNameRaw(pc, offset);
Christopher Ferris17e91d42013-10-21 13:30:52 -070065 return func_name;
66}
67
Pavel Chupinc6c194c2013-11-21 23:17:20 +040068bool Backtrace::VerifyReadWordArgs(uintptr_t ptr, word_t* out_value) {
69 if (ptr & (sizeof(word_t)-1)) {
Christopher Ferris8ed46272013-10-29 15:44:25 -070070 BACK_LOGW("invalid pointer %p", (void*)ptr);
Pavel Chupinc6c194c2013-11-21 23:17:20 +040071 *out_value = (word_t)-1;
Christopher Ferris17e91d42013-10-21 13:30:52 -070072 return false;
73 }
74 return true;
75}
76
Christopher Ferris17e91d42013-10-21 13:30:52 -070077std::string Backtrace::FormatFrameData(size_t frame_num) {
Christopher Ferris46756822014-01-14 20:16:30 -080078 if (frame_num >= frames_.size()) {
79 return "";
80 }
81 return FormatFrameData(&frames_[frame_num]);
Christopher Ferris20303f82014-01-10 16:33:16 -080082}
83
84std::string Backtrace::FormatFrameData(const backtrace_frame_data_t* frame) {
Christopher Ferris17e91d42013-10-21 13:30:52 -070085 const char* map_name;
Christopher Ferris46756822014-01-14 20:16:30 -080086 if (frame->map && !frame->map->name.empty()) {
87 map_name = frame->map->name.c_str();
Christopher Ferris17e91d42013-10-21 13:30:52 -070088 } else {
89 map_name = "<unknown>";
90 }
Christopher Ferris46756822014-01-14 20:16:30 -080091
Christopher Ferris17e91d42013-10-21 13:30:52 -070092 uintptr_t relative_pc;
Christopher Ferris46756822014-01-14 20:16:30 -080093 if (frame->map) {
94 relative_pc = frame->pc - frame->map->start;
Christopher Ferris17e91d42013-10-21 13:30:52 -070095 } else {
96 relative_pc = frame->pc;
97 }
98
99 char buf[512];
Christopher Ferris46756822014-01-14 20:16:30 -0800100 if (!frame->func_name.empty() && frame->func_offset) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700101 snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s (%s+%" PRIuPTR ")",
Christopher Ferris20303f82014-01-10 16:33:16 -0800102 frame->num, (int)sizeof(uintptr_t)*2, relative_pc, map_name,
Christopher Ferris46756822014-01-14 20:16:30 -0800103 frame->func_name.c_str(), frame->func_offset);
104 } else if (!frame->func_name.empty()) {
Christopher Ferris20303f82014-01-10 16:33:16 -0800105 snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s (%s)", frame->num,
Christopher Ferris46756822014-01-14 20:16:30 -0800106 (int)sizeof(uintptr_t)*2, relative_pc, map_name, frame->func_name.c_str());
Christopher Ferris17e91d42013-10-21 13:30:52 -0700107 } else {
Christopher Ferris20303f82014-01-10 16:33:16 -0800108 snprintf(buf, sizeof(buf), "#%02zu pc %0*" PRIxPTR " %s", frame->num,
Christopher Ferris17e91d42013-10-21 13:30:52 -0700109 (int)sizeof(uintptr_t)*2, relative_pc, map_name);
110 }
111
112 return buf;
113}
114
Christopher Ferris46756822014-01-14 20:16:30 -0800115const backtrace_map_t* Backtrace::FindMap(uintptr_t pc) {
Christopher Ferris46756822014-01-14 20:16:30 -0800116 return map_->Find(pc);
117}
118
Christopher Ferris17e91d42013-10-21 13:30:52 -0700119//-------------------------------------------------------------------------
120// BacktraceCurrent functions.
121//-------------------------------------------------------------------------
Christopher Ferris98464972014-01-06 19:16:33 -0800122BacktraceCurrent::BacktraceCurrent(
Christopher Ferris46756822014-01-14 20:16:30 -0800123 BacktraceImpl* impl, BacktraceMap* map) : Backtrace(impl, getpid(), map) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700124}
125
126BacktraceCurrent::~BacktraceCurrent() {
127}
128
Pavel Chupinc6c194c2013-11-21 23:17:20 +0400129bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700130 if (!VerifyReadWordArgs(ptr, out_value)) {
131 return false;
132 }
133
Christopher Ferris46756822014-01-14 20:16:30 -0800134 const backtrace_map_t* map = FindMap(ptr);
135 if (map && map->flags & PROT_READ) {
Pavel Chupinc6c194c2013-11-21 23:17:20 +0400136 *out_value = *reinterpret_cast<word_t*>(ptr);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700137 return true;
138 } else {
Christopher Ferris8ed46272013-10-29 15:44:25 -0700139 BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr));
Pavel Chupinc6c194c2013-11-21 23:17:20 +0400140 *out_value = static_cast<word_t>(-1);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700141 return false;
142 }
143}
144
145//-------------------------------------------------------------------------
146// BacktracePtrace functions.
147//-------------------------------------------------------------------------
Christopher Ferris98464972014-01-06 19:16:33 -0800148BacktracePtrace::BacktracePtrace(
Christopher Ferris46756822014-01-14 20:16:30 -0800149 BacktraceImpl* impl, pid_t pid, pid_t tid, BacktraceMap* map)
150 : Backtrace(impl, pid, map) {
151 tid_ = tid;
Christopher Ferris17e91d42013-10-21 13:30:52 -0700152}
153
154BacktracePtrace::~BacktracePtrace() {
155}
156
Pavel Chupinc6c194c2013-11-21 23:17:20 +0400157bool BacktracePtrace::ReadWord(uintptr_t ptr, word_t* out_value) {
Christopher Ferris17e91d42013-10-21 13:30:52 -0700158 if (!VerifyReadWordArgs(ptr, out_value)) {
159 return false;
160 }
161
162#if defined(__APPLE__)
Christopher Ferris8ed46272013-10-29 15:44:25 -0700163 BACK_LOGW("MacOS does not support reading from another pid.");
Christopher Ferris17e91d42013-10-21 13:30:52 -0700164 return false;
165#else
166 // ptrace() returns -1 and sets errno when the operation fails.
167 // To disambiguate -1 from a valid result, we clear errno beforehand.
168 errno = 0;
169 *out_value = ptrace(PTRACE_PEEKTEXT, Tid(), reinterpret_cast<void*>(ptr), NULL);
Pavel Chupinc6c194c2013-11-21 23:17:20 +0400170 if (*out_value == static_cast<word_t>(-1) && errno) {
Christopher Ferris8ed46272013-10-29 15:44:25 -0700171 BACK_LOGW("invalid pointer %p reading from tid %d, ptrace() strerror(errno)=%s",
172 reinterpret_cast<void*>(ptr), Tid(), strerror(errno));
Christopher Ferris17e91d42013-10-21 13:30:52 -0700173 return false;
174 }
175 return true;
176#endif
177}
178
Christopher Ferris46756822014-01-14 20:16:30 -0800179Backtrace* Backtrace::Create(pid_t pid, pid_t tid, BacktraceMap* map) {
Christopher Ferriscbfc7302013-11-05 11:04:12 -0800180 if (pid == BACKTRACE_CURRENT_PROCESS || pid == getpid()) {
Christopher Ferrisbc12d632013-11-12 10:54:16 -0800181 if (tid == BACKTRACE_CURRENT_THREAD || tid == gettid()) {
Christopher Ferris46756822014-01-14 20:16:30 -0800182 return CreateCurrentObj(map);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700183 } else {
Christopher Ferris46756822014-01-14 20:16:30 -0800184 return CreateThreadObj(tid, map);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700185 }
Christopher Ferrisbc12d632013-11-12 10:54:16 -0800186 } else if (tid == BACKTRACE_CURRENT_THREAD) {
Christopher Ferris46756822014-01-14 20:16:30 -0800187 return CreatePtraceObj(pid, pid, map);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700188 } else {
Christopher Ferris46756822014-01-14 20:16:30 -0800189 return CreatePtraceObj(pid, tid, map);
Christopher Ferris17e91d42013-10-21 13:30:52 -0700190 }
191}