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 39 bool 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 56 size_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 67 bool 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 86 bool 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 96 static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER; 97 98 static void SignalLogOnly(int, siginfo_t*, void*) { 99 BACK_LOGE("pid %d, tid %d: Received a spurious signal %d\n", getpid(), gettid(), THREAD_SIGNAL); 100 } 101 102 static void SignalHandler(int, siginfo_t*, void* sigcontext) { 103 ThreadEntry* entry = ThreadEntry::Get(getpid(), gettid(), false); 104 if (!entry) { 105 BACK_LOGE("pid %d, tid %d entry not found", getpid(), gettid()); 106 return; 107 } 108 109 entry->CopyUcontextFromSigcontext(sigcontext); 110 111 // Indicate the ucontext is now valid. 112 entry->Wake(); 113 114 // Pause the thread until the unwind is complete. This avoids having 115 // the thread run ahead causing problems. 116 // The number indicates that we are waiting for the second Wake() call 117 // overall which is made by the thread requesting an unwind. 118 if (entry->Wait(2)) { 119 // Do not remove the entry here because that can result in a deadlock 120 // if the code cannot properly send a signal to the thread under test. 121 entry->Wake(); 122 } else { 123 // At this point, it is possible that entry has been freed, so just exit. 124 BACK_LOGE("Timed out waiting for unwind thread to indicate it completed."); 125 } 126 } 127 128 bool BacktraceCurrent::UnwindThread(size_t num_ignore_frames) { 129 // Prevent multiple threads trying to set the trigger action on different 130 // threads at the same time. 131 pthread_mutex_lock(&g_sigaction_mutex); 132 133 ThreadEntry* entry = ThreadEntry::Get(Pid(), Tid()); 134 entry->Lock(); 135 136 struct sigaction act, oldact; 137 memset(&act, 0, sizeof(act)); 138 act.sa_sigaction = SignalHandler; 139 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 140 sigemptyset(&act.sa_mask); 141 if (sigaction(THREAD_SIGNAL, &act, &oldact) != 0) { 142 BACK_LOGE("sigaction failed: %s", strerror(errno)); 143 ThreadEntry::Remove(entry); 144 pthread_mutex_unlock(&g_sigaction_mutex); 145 error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; 146 return false; 147 } 148 149 if (tgkill(Pid(), Tid(), THREAD_SIGNAL) != 0) { 150 // Do not emit an error message, this might be expected. Set the 151 // error and let the caller decide. 152 if (errno == ESRCH) { 153 error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; 154 } else { 155 error_ = BACKTRACE_UNWIND_ERROR_INTERNAL; 156 } 157 158 sigaction(THREAD_SIGNAL, &oldact, nullptr); 159 ThreadEntry::Remove(entry); 160 pthread_mutex_unlock(&g_sigaction_mutex); 161 return false; 162 } 163 164 // Wait for the thread to get the ucontext. The number indicates 165 // that we are waiting for the first Wake() call made by the thread. 166 bool wait_completed = entry->Wait(1); 167 168 if (!wait_completed && oldact.sa_sigaction == nullptr) { 169 // If the wait failed, it could be that the signal could not be delivered 170 // within the timeout. Add a signal handler that's simply going to log 171 // something so that we don't crash if the signal eventually gets 172 // delivered. Only do this if there isn't already an action set up. 173 memset(&act, 0, sizeof(act)); 174 act.sa_sigaction = SignalLogOnly; 175 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 176 sigemptyset(&act.sa_mask); 177 sigaction(THREAD_SIGNAL, &act, nullptr); 178 } else { 179 sigaction(THREAD_SIGNAL, &oldact, nullptr); 180 } 181 // After the thread has received the signal, allow other unwinders to 182 // continue. 183 pthread_mutex_unlock(&g_sigaction_mutex); 184 185 bool unwind_done = false; 186 if (wait_completed) { 187 unwind_done = UnwindFromContext(num_ignore_frames, entry->GetUcontext()); 188 189 // Tell the signal handler to exit and release the entry. 190 entry->Wake(); 191 192 // Wait for the thread to indicate it is done with the ThreadEntry. 193 if (!entry->Wait(3)) { 194 // Send a warning, but do not mark as a failure to unwind. 195 BACK_LOGW("Timed out waiting for signal handler to indicate it finished."); 196 } 197 } else { 198 // Check to see if the thread has disappeared. 199 if (tgkill(Pid(), Tid(), 0) == -1 && errno == ESRCH) { 200 error_ = BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST; 201 } else { 202 error_ = BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT; 203 BACK_LOGE("Timed out waiting for signal handler to get ucontext data."); 204 } 205 } 206 207 ThreadEntry::Remove(entry); 208 209 return unwind_done; 210 } 211