1/* 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#define _GNU_SOURCE 1 18#include <errno.h> 19#include <stdint.h> 20#include <string.h> 21#include <sys/param.h> 22#include <sys/ptrace.h> 23#include <sys/types.h> 24#include <ucontext.h> 25#include <unistd.h> 26 27#include <stdlib.h> 28 29#include <string> 30 31#include <backtrace/Backtrace.h> 32#include <backtrace/BacktraceMap.h> 33 34#include "BacktraceCurrent.h" 35#include "BacktraceLog.h" 36#include "ThreadEntry.h" 37#include "thread_utils.h" 38 39bool BacktraceCurrent::ReadWord(uintptr_t ptr, word_t* out_value) { 40 if (!VerifyReadWordArgs(ptr, out_value)) { 41 return false; 42 } 43 44 backtrace_map_t map; 45 FillInMap(ptr, &map); 46 if (BacktraceMap::IsValid(map) && map.flags & PROT_READ) { 47 *out_value = *reinterpret_cast<word_t*>(ptr); 48 return true; 49 } else { 50 BACK_LOGW("pointer %p not in a readable map", reinterpret_cast<void*>(ptr)); 51 *out_value = static_cast<word_t>(-1); 52 return false; 53 } 54} 55 56size_t BacktraceCurrent::Read(uintptr_t addr, uint8_t* buffer, size_t bytes) { 57 backtrace_map_t map; 58 FillInMap(addr, &map); 59 if (!BacktraceMap::IsValid(map) || !(map.flags & PROT_READ)) { 60 return 0; 61 } 62 bytes = MIN(map.end - addr, bytes); 63 memcpy(buffer, reinterpret_cast<uint8_t*>(addr), bytes); 64 return bytes; 65} 66 67bool BacktraceCurrent::Unwind(size_t num_ignore_frames, ucontext_t* ucontext) { 68 if (GetMap() == nullptr) { 69 // Without a map object, we can't do anything. 70 error_ = BACKTRACE_UNWIND_ERROR_MAP_MISSING; 71 return false; 72 } 73 74 error_ = BACKTRACE_UNWIND_NO_ERROR; 75 if (ucontext) { 76 return UnwindFromContext(num_ignore_frames, ucontext); 77 } 78 79 if (Tid() != gettid()) { 80 return UnwindThread(num_ignore_frames); 81 } 82 83 return UnwindFromContext(num_ignore_frames, nullptr); 84} 85 86bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { 87 if (BacktraceMap::IsValid(frame.map)) { 88 const std::string library = basename(frame.map.name.c_str()); 89 if (library == "libunwind.so" || library == "libbacktrace.so") { 90 return true; 91 } 92 } 93 return false; 94} 95 96static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; 97 98// Since errno is stored per thread, changing it in the signal handler 99// modifies the value on the thread in which the signal handler executes. 100// If a signal occurs between a call and an errno check, it's possible 101// to get the errno set here. Always save and restore it just in case 102// code would modify it. 103class ErrnoRestorer { 104 public: 105 ErrnoRestorer() : saved_errno_(errno) {} 106 ~ErrnoRestorer() { 107 errno = saved_errno_; 108 } 109 110 private: 111 int saved_errno_; 112}; 113 114static void SignalLogOnly(int, siginfo_t*, void*) { 115 ErrnoRestorer restore; 116 117 BACK_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); 118} 119 120static void SignalHandler(int, siginfo_t*, void* sigcontext) { 121 ErrnoRestorer restore; 122 123 ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); 124 if (!entry) { 125 BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); 126 return; 127 } 128 129 entry->CopyUcontextFromSigcontext(sigcontext); 130 131 // Indicate the ucontext is now valid. 132 entry->Wake(); 133 134 // Pause the thread until the unwind is complete. This avoids having 135 // the thread run ahead causing problems. 136 // The number indicates that we are waiting for the second Wake() call 137 // overall which is made by the thread requesting an unwind. 138 if (entry->Wait(2)) { 139 // Do not remove the entry here because that can result in a deadlock 140 // if the code cannot properly send a signal to the thread under test. 141 entry->Wake(); 142 } else { 143 // At this point, it is possible that entry has been freed, so just exit. 144 BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); 145 } 146} 147 148bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { 149 // Prevent multiple threads trying to set the trigger action on different 150 // threads at the same time. 151 pthread_mutex_lock(&g_sigaction_mutex); 152 153 ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid()); 154 entry->Lock(); 155 156 struct sigaction act, oldact; 157 memset(&act, 0, sizeof(act)); 158 act.sa_sigaction = SignalHandler; 159 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 160 sigemptyset(&act.sa_mask); 161 if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { 162 BACK_LOGE("sigaction failed: %s", strerror(errno)); 163 ThreadEntry::Remove(entry); 164 pthread_mutex_unlock(&g_sigaction_mutex); 165 error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; 166 return false; 167 } 168 169 if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { 170 // Do not emit an error message, this might be expected. Set the 171 // error and let the caller decide. 172 if (errno == ESRCH) { 173 error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; 174 } else { 175 error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; 176 } 177 178 sigaction(THREAD_SIGNAL, &oldact, nullptr); 179 ThreadEntry::Remove(entry); 180 pthread_mutex_unlock(&g_sigaction_mutex); 181 return false; 182 } 183 184 // Wait for the thread to get the ucontext. The number indicates 185 // that we are waiting for the first Wake() call made by the thread. 186 bool wait_completed = entry->Wait(1); 187 188 if (!wait_completed && oldact.sa_sigaction == nullptr) { 189 // If the wait failed, it could be that the signal could not be delivered 190 // within the timeout. Add a signal handler that's simply going to log 191 // something so that we don't crash if the signal eventually gets 192 // delivered. Only do this if there isn't already an action set up. 193 memset(&act, 0, sizeof(act)); 194 act.sa_sigaction = SignalLogOnly; 195 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 196 sigemptyset(&act.sa_mask); 197 sigaction(THREAD_SIGNAL, &act, nullptr); 198 } else { 199 sigaction(THREAD_SIGNAL, &oldact, nullptr); 200 } 201 // After the thread has received the signal, allow other unwinders to 202 // continue. 203 pthread_mutex_unlock(&g_sigaction_mutex); 204 205 bool unwind_done = false; 206 if (wait_completed) { 207 unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext()); 208 209 // Tell the signal handler to exit and release the entry. 210 entry->Wake(); 211 212 // Wait for the thread to indicate it is done with the ThreadEntry. 213 if (!entry->Wait(3)) { 214 // Send a warning, but do not mark as a failure to unwind. 215 BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); 216 } 217 } else { 218 // Check to see if the thread has disappeared. 219 if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) { 220 error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; 221 } else { 222 error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; 223 BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); 224 } 225 } 226 227 ThreadEntry::Remove(entry); 228 229 return unwind_done; 230} 231