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 <string> 28 29#include <backtrace/Backtrace.h> 30#include <backtrace/BacktraceMap.h> 31 32#include <cutils/threads.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 return false; 71 } 72 73 if (ucontext) { 74 return UnwindFromContext(num_ignore_frames, ucontext); 75 } 76 77 if (Tid() != gettid()) { 78 return UnwindThread(num_ignore_frames); 79 } 80 81 return UnwindFromContext(num_ignore_frames, nullptr); 82} 83 84bool BacktraceCurrent::DiscardFrame(const backtrace_frame_data_t& frame) { 85 if (BacktraceMap::IsValid(frame.map)) { 86 const std::string library = basename(frame.map.name.c_str()); 87 if (library == "libunwind.so" || library == "libbacktrace.so") { 88 return true; 89 } 90 } 91 return false; 92} 93 94static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; 95 96static void SignalHandler(int, siginfo_t*, void* sigcontext) { 97 ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); 98 if (!entry) { 99 BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); 100 return; 101 } 102 103 entry->CopyUcontextFromSigcontext(sigcontext); 104 105 // Indicate the ucontext is now valid. 106 entry->Wake(); 107 108 // Pause the thread until the unwind is complete. This avoids having 109 // the thread run ahead causing problems. 110 // The number indicates that we are waiting for the second Wake() call 111 // overall which is made by the thread requesting an unwind. 112 if (entry->Wait(2)) { 113 // Do not remove the entry here because that can result in a deadlock 114 // if the code cannot properly send a signal to the thread under test. 115 entry->Wake(); 116 } else { 117 // At this point, it is possible that entry has been freed, so just exit. 118 BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); 119 } 120} 121 122bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { 123 // Prevent multiple threads trying to set the trigger action on different 124 // threads at the same time. 125 pthread_mutex_lock(&g_sigaction_mutex); 126 127 ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid()); 128 entry->Lock(); 129 130 struct sigaction act, oldact; 131 memset(&act, 0, sizeof(act)); 132 act.sa_sigaction = SignalHandler; 133 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 134 sigemptyset(&act.sa_mask); 135 if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { 136 BACK_LOGE("sigaction failed: %s", strerror(errno)); 137 ThreadEntry::Remove(entry); 138 pthread_mutex_unlock(&g_sigaction_mutex); 139 return false; 140 } 141 142 if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { 143 BACK_LOGE("tgkill %d failed: %s", Tid(), strerror(errno)); 144 sigaction(THREAD_SIGNAL, &oldact, nullptr); 145 ThreadEntry::Remove(entry); 146 pthread_mutex_unlock(&g_sigaction_mutex); 147 return false; 148 } 149 150 // Wait for the thread to get the ucontext. The number indicates 151 // that we are waiting for the first Wake() call made by the thread. 152 bool wait_completed = entry->Wait(1); 153 154 // After the thread has received the signal, allow other unwinders to 155 // continue. 156 sigaction(THREAD_SIGNAL, &oldact, nullptr); 157 pthread_mutex_unlock(&g_sigaction_mutex); 158 159 bool unwind_done = false; 160 if (wait_completed) { 161 unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext()); 162 163 // Tell the signal handler to exit and release the entry. 164 entry->Wake(); 165 166 // Wait for the thread to indicate it is done with the ThreadEntry. 167 if (!entry->Wait(3)) { 168 // Send a warning, but do not mark as a failure to unwind. 169 BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); 170 } 171 } else { 172 BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); 173 } 174 175 ThreadEntry::Remove(entry); 176 177 return unwind_done; 178} 179