1501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown/* 2501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Copyright (C) 2011 The Android Open Source Project 3501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 4501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * you may not use this file except in compliance with the License. 6501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * You may obtain a copy of the License at 7501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 8501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * 10501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * Unless required by applicable law or agreed to in writing, software 11501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * See the License for the specific language governing permissions and 14501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown * limitations under the License. 15501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown */ 16501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 17501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#define LOG_TAG "Corkscrew" 18501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown//#define LOG_NDEBUG 0 19501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 20501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include "backtrace-arch.h" 21501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include "backtrace-helper.h" 22501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include "ptrace-arch.h" 23501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <corkscrew/map_info.h> 24501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <corkscrew/symbol_table.h> 25501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <corkscrew/ptrace.h> 26501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <corkscrew/demangle.h> 27501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 28501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <unistd.h> 29501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <signal.h> 3071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <stdlib.h> 3171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <string.h> 32501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <pthread.h> 33501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <unwind.h> 34501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <cutils/log.h> 35f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown#include <cutils/atomic.h> 36501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 3771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#define __USE_GNU // For dladdr(3) in glibc. 38501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#include <dlfcn.h> 39501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 4071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#if defined(__BIONIC__) 4171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 4271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes// Bionic implements and exports gettid but only implements tgkill. 4371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughesextern int tgkill(int tgid, int tid, int sig); 4471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 45bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#elif defined(__APPLE__) 46bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes 47bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#include <sys/syscall.h> 48bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes 49bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes// Mac OS >= 10.6 has a system call equivalent to Linux's gettid(). 50bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughesstatic pid_t gettid() { 51bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes return syscall(SYS_thread_selfid); 52bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes} 53bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes 5471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#else 5571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 5671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes// glibc doesn't implement or export either gettid or tgkill. 5771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 5871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <unistd.h> 5971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#include <sys/syscall.h> 6071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 6171363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughesstatic pid_t gettid() { 6271363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes return syscall(__NR_gettid); 6371363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes} 6471363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 6571363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughesstatic int tgkill(int tgid, int tid, int sig) { 6671363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes return syscall(__NR_tgkill, tgid, tid, sig); 6771363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes} 6871363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 6971363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes#endif 7071363a8075e7916c2166cbdd8a0bf5a180ed4d54Elliott Hughes 71501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Browntypedef struct { 72501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_frame_t* backtrace; 73501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t ignore_depth; 74501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t max_depth; 75501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t ignored_frames; 76501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t returned_frames; 77f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown memory_t memory; 78501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} backtrace_state_t; 79501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 80501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic _Unwind_Reason_Code unwind_backtrace_callback(struct _Unwind_Context* context, void* arg) { 81501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_state_t* state = (backtrace_state_t*)arg; 82501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown uintptr_t pc = _Unwind_GetIP(context); 83501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (pc) { 84501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown // TODO: Get information about the stack layout from the _Unwind_Context. 85501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown // This will require a new architecture-specific function to query 86501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown // the appropriate registers. Current callers of unwind_backtrace 87501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown // don't need this information, so we won't bother collecting it just yet. 88f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown add_backtrace_entry(rewind_pc_arch(&state->memory, pc), state->backtrace, 89501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state->ignore_depth, state->max_depth, 90501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown &state->ignored_frames, &state->returned_frames); 91501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 92501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return state->returned_frames < state->max_depth ? _URC_NO_REASON : _URC_END_OF_STACK; 93501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 94501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 95501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownssize_t unwind_backtrace(backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 96f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown ALOGV("Unwinding current thread %d.", gettid()); 97f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 98f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown map_info_t* milist = acquire_my_map_info_list(); 99f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 100501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_state_t state; 101501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state.backtrace = backtrace; 102501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state.ignore_depth = ignore_depth; 103501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state.max_depth = max_depth; 104501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state.ignored_frames = 0; 105501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown state.returned_frames = 0; 106f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown init_memory(&state.memory, milist); 107501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 108bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes _Unwind_Reason_Code rc = _Unwind_Backtrace(unwind_backtrace_callback, &state); 109f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 110f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown release_my_map_info_list(milist); 111f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 112501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (state.returned_frames) { 113501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return state.returned_frames; 114501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 115501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return rc == _URC_END_OF_STACK ? 0 : -1; 116501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 117501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 118501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#ifdef CORKSCREW_HAVE_ARCH 119677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brownstatic const int32_t STATE_DUMPING = -1; 120677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brownstatic const int32_t STATE_DONE = -2; 121677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brownstatic const int32_t STATE_CANCEL = -3; 122677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown 123501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic pthread_mutex_t g_unwind_signal_mutex = PTHREAD_MUTEX_INITIALIZER; 124501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic volatile struct { 125677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown int32_t tid_state; 126f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown const map_info_t* map_info_list; 127501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_frame_t* backtrace; 128501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t ignore_depth; 129501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t max_depth; 130501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t returned_frames; 131501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} g_unwind_signal_state; 132501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 13346beebea823878218fc0f14723829d83886af978Edwin Vanestatic void unwind_backtrace_thread_signal_handler(int n __attribute__((unused)), siginfo_t* siginfo, void* sigcontext) { 134677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (!android_atomic_acquire_cas(gettid(), STATE_DUMPING, &g_unwind_signal_state.tid_state)) { 135501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown g_unwind_signal_state.returned_frames = unwind_backtrace_signal_arch( 136f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown siginfo, sigcontext, 137f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.map_info_list, 138f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.backtrace, 139501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown g_unwind_signal_state.ignore_depth, 140501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown g_unwind_signal_state.max_depth); 141677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown android_atomic_release_store(STATE_DONE, &g_unwind_signal_state.tid_state); 142f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown } else { 143f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown ALOGV("Received spurious SIGURG on thread %d that was intended for thread %d.", 144677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown gettid(), android_atomic_acquire_load(&g_unwind_signal_state.tid_state)); 145501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 146501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 147501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#endif 148501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 149501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownssize_t unwind_backtrace_thread(pid_t tid, backtrace_frame_t* backtrace, 150501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown size_t ignore_depth, size_t max_depth) { 151f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown if (tid == gettid()) { 152f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown return unwind_backtrace(backtrace, ignore_depth + 1, max_depth); 153f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown } 154f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 155f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown ALOGV("Unwinding thread %d from thread %d.", tid, gettid()); 156f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 157bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes // TODO: there's no tgkill(2) on Mac OS, so we'd either need the 158bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes // mach_port_t or the pthread_t rather than the tid. 159bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes#if defined(CORKSCREW_HAVE_ARCH) && !defined(__APPLE__) 160501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown struct sigaction act; 161501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown struct sigaction oact; 162501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown memset(&act, 0, sizeof(act)); 163501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown act.sa_sigaction = unwind_backtrace_thread_signal_handler; 164677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 165501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown sigemptyset(&act.sa_mask); 166501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 167501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown pthread_mutex_lock(&g_unwind_signal_mutex); 168f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown map_info_t* milist = acquire_my_map_info_list(); 169501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 170501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown ssize_t frames = -1; 171501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (!sigaction(SIGURG, &act, &oact)) { 172f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.map_info_list = milist; 173f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.backtrace = backtrace; 174f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.ignore_depth = ignore_depth; 175f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.max_depth = max_depth; 176f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown g_unwind_signal_state.returned_frames = 0; 177677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown android_atomic_release_store(tid, &g_unwind_signal_state.tid_state); 178f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 179677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // Signal the specific thread that we want to dump. 180677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown int32_t tid_state = tid; 181677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (tgkill(getpid(), tid, SIGURG)) { 182f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown ALOGV("Failed to send SIGURG to thread %d.", tid); 183f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown } else { 184677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // Wait for the other thread to start dumping the stack, or time out. 185677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown int wait_millis = 250; 186677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown for (;;) { 187677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown tid_state = android_atomic_acquire_load(&g_unwind_signal_state.tid_state); 188677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (tid_state != tid) { 189677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown break; 190677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 191677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (wait_millis--) { 192677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown ALOGV("Waiting for thread %d to start dumping the stack...", tid); 193677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown usleep(1000); 194677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } else { 195677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown ALOGV("Timed out waiting for thread %d to start dumping the stack.", tid); 196677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown break; 197677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 198677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 199677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 200677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown 201677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // Try to cancel the dump if it has not started yet. 202677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (tid_state == tid) { 203677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (!android_atomic_acquire_cas(tid, STATE_CANCEL, &g_unwind_signal_state.tid_state)) { 204677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown ALOGV("Canceled thread %d stack dump.", tid); 205677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown tid_state = STATE_CANCEL; 206677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } else { 207677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown tid_state = android_atomic_acquire_load(&g_unwind_signal_state.tid_state); 208501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 209677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 210677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown 211677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // Wait indefinitely for the dump to finish or be canceled. 212677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // We cannot apply a timeout here because the other thread is accessing state that 213677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // is owned by this thread, such as milist. It should not take very 214677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown // long to take the dump once started. 215677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown while (tid_state == STATE_DUMPING) { 216677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown ALOGV("Waiting for thread %d to finish dumping the stack...", tid); 217677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown usleep(1000); 218677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown tid_state = android_atomic_acquire_load(&g_unwind_signal_state.tid_state); 219677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown } 220677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown 221677545639cbc3d3018146534f27c8f5bdcd1bb46Jeff Brown if (tid_state == STATE_DONE) { 222501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown frames = g_unwind_signal_state.returned_frames; 223501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 224f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown 225501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown sigaction(SIGURG, &oact, NULL); 226501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 227501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 228f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown release_my_map_info_list(milist); 229501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown pthread_mutex_unlock(&g_unwind_signal_mutex); 230501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return frames; 231501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#else 232501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return -1; 233501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#endif 234501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 235501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 236501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownssize_t unwind_backtrace_ptrace(pid_t tid, const ptrace_context_t* context, 237501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_frame_t* backtrace, size_t ignore_depth, size_t max_depth) { 238501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#ifdef CORKSCREW_HAVE_ARCH 239501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return unwind_backtrace_ptrace_arch(tid, context, backtrace, ignore_depth, max_depth); 240501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#else 241501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown return -1; 242501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown#endif 243501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 244501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 245501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownstatic void init_backtrace_symbol(backtrace_symbol_t* symbol, uintptr_t pc) { 246501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown symbol->relative_pc = pc; 24719b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->relative_symbol_addr = 0; 248f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown symbol->map_name = NULL; 24919b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->symbol_name = NULL; 250501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown symbol->demangled_name = NULL; 251501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 252501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 253501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownvoid get_backtrace_symbols(const backtrace_frame_t* backtrace, size_t frames, 254501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_symbol_t* backtrace_symbols) { 255f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown map_info_t* milist = acquire_my_map_info_list(); 256501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown for (size_t i = 0; i < frames; i++) { 257501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const backtrace_frame_t* frame = &backtrace[i]; 258501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_symbol_t* symbol = &backtrace_symbols[i]; 259501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown init_backtrace_symbol(symbol, frame->absolute_pc); 260501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 261501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const map_info_t* mi = find_map_info(milist, frame->absolute_pc); 262501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (mi) { 263501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown symbol->relative_pc = frame->absolute_pc - mi->start; 264f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown if (mi->name[0]) { 265f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown symbol->map_name = strdup(mi->name); 266f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown } 267501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown Dl_info info; 268501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (dladdr((const void*)frame->absolute_pc, &info) && info.dli_sname) { 26919b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->relative_symbol_addr = (uintptr_t)info.dli_saddr 27019b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown - (uintptr_t)info.dli_fbase; 27119b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->symbol_name = strdup(info.dli_sname); 27219b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->demangled_name = demangle_symbol_name(symbol->symbol_name); 273501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 274501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 275501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 276f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown release_my_map_info_list(milist); 277501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 278501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 279501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownvoid get_backtrace_symbols_ptrace(const ptrace_context_t* context, 280501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const backtrace_frame_t* backtrace, size_t frames, 281501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_symbol_t* backtrace_symbols) { 282501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown for (size_t i = 0; i < frames; i++) { 283501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const backtrace_frame_t* frame = &backtrace[i]; 284501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_symbol_t* symbol = &backtrace_symbols[i]; 285501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown init_backtrace_symbol(symbol, frame->absolute_pc); 286501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 287501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const map_info_t* mi; 288501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown const symbol_t* s; 289501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown find_symbol_ptrace(context, frame->absolute_pc, &mi, &s); 290501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (mi) { 291501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown symbol->relative_pc = frame->absolute_pc - mi->start; 292f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown if (mi->name[0]) { 293f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown symbol->map_name = strdup(mi->name); 294f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown } 295501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 296501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown if (s) { 29719b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->relative_symbol_addr = s->start; 29819b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->symbol_name = strdup(s->name); 29919b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown symbol->demangled_name = demangle_symbol_name(symbol->symbol_name); 300501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 301501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 302501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 303501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown 304501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brownvoid free_backtrace_symbols(backtrace_symbol_t* backtrace_symbols, size_t frames) { 305501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown for (size_t i = 0; i < frames; i++) { 306501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown backtrace_symbol_t* symbol = &backtrace_symbols[i]; 307f0c5872637a63e28e3cd314cfc915c07f76df9c6Jeff Brown free(symbol->map_name); 30819b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown free(symbol->symbol_name); 309501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown free(symbol->demangled_name); 310501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown init_backtrace_symbol(symbol, 0); 311501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown } 312501edd29b823ce1301d2effdd3a9e4b6e2b20b76Jeff Brown} 31319b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown 31446beebea823878218fc0f14723829d83886af978Edwin Vanevoid format_backtrace_line(unsigned frameNumber, const backtrace_frame_t* frame __attribute__((unused)), 31519b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown const backtrace_symbol_t* symbol, char* buffer, size_t bufferSize) { 31619b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown const char* mapName = symbol->map_name ? symbol->map_name : "<unknown>"; 31719b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown const char* symbolName = symbol->demangled_name ? symbol->demangled_name : symbol->symbol_name; 318bfec3a315000e9fcfc8e2d3fcef25e747e3d2053Elliott Hughes int fieldWidth = (bufferSize - 80) / 2; 31919b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown if (symbolName) { 32019b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown uint32_t pc_offset = symbol->relative_pc - symbol->relative_symbol_addr; 32119b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown if (pc_offset) { 322ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng snprintf(buffer, bufferSize, "#%02u pc %08x %.*s (%.*s+%u)", 323ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng frameNumber, (unsigned int) symbol->relative_pc, 324ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng fieldWidth, mapName, fieldWidth, symbolName, pc_offset); 32519b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown } else { 326ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng snprintf(buffer, bufferSize, "#%02u pc %08x %.*s (%.*s)", 327ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng frameNumber, (unsigned int) symbol->relative_pc, 328ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng fieldWidth, mapName, fieldWidth, symbolName); 32919b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown } 33019b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown } else { 331ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng snprintf(buffer, bufferSize, "#%02u pc %08x %.*s", 332ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng frameNumber, (unsigned int) symbol->relative_pc, 333ddc50e67e2ef33f20e76fca1c3fc04474cd9df9dBen Cheng fieldWidth, mapName); 33419b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown } 33519b39f371be5250e7b9e88016be1e5e665367b3fJeff Brown} 336