1053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown/* 2053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 4053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * you may not use this file except in compliance with the License. 6053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * You may obtain a copy of the License at 7053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 8053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * 10053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Unless required by applicable law or agreed to in writing, software 11053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * See the License for the specific language governing permissions and 14053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * limitations under the License. 15053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */ 16053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 17053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stddef.h> 18053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdbool.h> 19053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdlib.h> 20053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <signal.h> 21053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <string.h> 22053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <stdio.h> 23053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <fcntl.h> 24053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <errno.h> 25053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <dirent.h> 26053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <time.h> 27053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/ptrace.h> 28053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <sys/stat.h> 29053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 30053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <private/android_filesystem_config.h> 31053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 32053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <cutils/logger.h> 33053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <cutils/properties.h> 34053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 35053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <corkscrew/demangle.h> 36053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include <corkscrew/backtrace.h> 37053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 38f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig#ifdef HAVE_SELINUX 39f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig#include <selinux/android.h> 40f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig#endif 41f1186f3e980f5ebcc3380d8a7f746bf8a45e3531rpcraig 42053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "machine.h" 43053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "tombstone.h" 44053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#include "utility.h" 45053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 46053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_DEPTH 32 47053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define STACK_WORDS 16 48053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 49053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define MAX_TOMBSTONES 10 50053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define TOMBSTONE_DIR "/data/tombstones" 51053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 52053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown#define typecheck(x,y) { \ 53053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown typeof(x) __dummy1; \ 54053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown typeof(y) __dummy2; \ 55053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown (void)(&__dummy1 == &__dummy2); } 56053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 57053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 58053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic bool signal_has_address(int sig) { 59053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (sig) { 60053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGILL: 61053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGFPE: 62053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGSEGV: 63053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGBUS: 64053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return true; 65053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown default: 66053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return false; 67053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 68053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 69053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 70053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic const char *get_signame(int sig) 71053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{ 72053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch(sig) { 73053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGILL: return "SIGILL"; 74053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGABRT: return "SIGABRT"; 75053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGBUS: return "SIGBUS"; 76053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGFPE: return "SIGFPE"; 77053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGSEGV: return "SIGSEGV"; 78053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGPIPE: return "SIGPIPE"; 79231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#ifdef SIGSTKFLT 80053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGSTKFLT: return "SIGSTKFLT"; 81231e3c83a3a70b11160fb0da108ebf2e0e7470e2Chris Dearman#endif 82053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGSTOP: return "SIGSTOP"; 83053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown default: return "?"; 84053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 85053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 86053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 87053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic const char *get_sigcode(int signo, int code) 88053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{ 89053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (signo) { 90053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGILL: 91053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (code) { 92053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_ILLOPC: return "ILL_ILLOPC"; 93053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_ILLOPN: return "ILL_ILLOPN"; 94053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_ILLADR: return "ILL_ILLADR"; 95053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_ILLTRP: return "ILL_ILLTRP"; 96053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_PRVOPC: return "ILL_PRVOPC"; 97053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_PRVREG: return "ILL_PRVREG"; 98053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_COPROC: return "ILL_COPROC"; 99053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case ILL_BADSTK: return "ILL_BADSTK"; 100053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 101053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 102053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGBUS: 103053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (code) { 104053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case BUS_ADRALN: return "BUS_ADRALN"; 105053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case BUS_ADRERR: return "BUS_ADRERR"; 106053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case BUS_OBJERR: return "BUS_OBJERR"; 107053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 108053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 109053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGFPE: 110053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (code) { 111053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_INTDIV: return "FPE_INTDIV"; 112053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_INTOVF: return "FPE_INTOVF"; 113053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTDIV: return "FPE_FLTDIV"; 114053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTOVF: return "FPE_FLTOVF"; 115053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTUND: return "FPE_FLTUND"; 116053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTRES: return "FPE_FLTRES"; 117053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTINV: return "FPE_FLTINV"; 118053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case FPE_FLTSUB: return "FPE_FLTSUB"; 119053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 120053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 121053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SIGSEGV: 122053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown switch (code) { 123053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SEGV_MAPERR: return "SEGV_MAPERR"; 124053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown case SEGV_ACCERR: return "SEGV_ACCERR"; 125053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 126053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 127053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 128053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return "?"; 129053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 130053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 131d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Chengstatic void dump_revision_info(log_t* log) 132d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng{ 133d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng char revision[PROPERTY_VALUE_MAX]; 134d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng 135d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng property_get("ro.revision", revision, "unknown"); 136d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng 137d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng _LOG(log, false, "Revision: '%s'\n", revision); 138d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng} 139d7760c1688f8276a05e33345d81639f8cb5e7c3fBen Cheng 140053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_build_info(log_t* log) 141053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{ 142053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char fingerprint[PROPERTY_VALUE_MAX]; 143053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 144053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown property_get("ro.build.fingerprint", fingerprint, "unknown"); 145053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 146053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "Build fingerprint: '%s'\n", fingerprint); 147053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 148053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 149053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_fault_addr(log_t* log, pid_t tid, int sig) 150053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown{ 151053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown siginfo_t si; 152053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 153053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown memset(&si, 0, sizeof(si)); 154053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if(ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){ 155053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno)); 156053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else if (signal_has_address(sig)) { 157053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n", 158053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown sig, get_signame(sig), 159053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown si.si_code, get_sigcode(sig, si.si_code), 160053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown (uintptr_t) si.si_addr); 161053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 162053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n", 163053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); 164053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 165053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 166053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 167053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_thread_info(log_t* log, pid_t pid, pid_t tid, bool at_fault) { 168053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char path[64]; 169053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char threadnamebuf[1024]; 170053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* threadname = NULL; 171053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown FILE *fp; 172053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 173053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown snprintf(path, sizeof(path), "/proc/%d/comm", tid); 174053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if ((fp = fopen(path, "r"))) { 175053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp); 176053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown fclose(fp); 177053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (threadname) { 178053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown size_t len = strlen(threadname); 179053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (len && threadname[len - 1] == '\n') { 180053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname[len - 1] = '\0'; 181053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 182053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 183053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 184053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 185053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (at_fault) { 186053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char procnamebuf[1024]; 187053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* procname = NULL; 188053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 189053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 190053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if ((fp = fopen(path, "r"))) { 191053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown procname = fgets(procnamebuf, sizeof(procnamebuf), fp); 192053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown fclose(fp); 193053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 194053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 195053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid, 196053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname ? threadname : "UNKNOWN", 197053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown procname ? procname : "UNKNOWN"); 198053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 199053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, true, "pid: %d, tid: %d, name: %s\n", pid, tid, 200053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown threadname ? threadname : "UNKNOWN"); 201053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 202053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 203053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 204053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_backtrace(const ptrace_context_t* context __attribute((unused)), 205053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown log_t* log, pid_t tid __attribute((unused)), bool at_fault, 206053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const backtrace_frame_t* backtrace, size_t frames) { 207053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, !at_fault, "\nbacktrace:\n"); 208053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 209053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown backtrace_symbol_t backtrace_symbols[STACK_DEPTH]; 210053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown get_backtrace_symbols_ptrace(context, backtrace, frames, backtrace_symbols); 211053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown for (size_t i = 0; i < frames; i++) { 212053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char line[MAX_BACKTRACE_LINE_LENGTH]; 213053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown format_backtrace_line(i, &backtrace[i], &backtrace_symbols[i], 214053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown line, MAX_BACKTRACE_LINE_LENGTH); 215053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, !at_fault, " %s\n", line); 216053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 217053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown free_backtrace_symbols(backtrace_symbols, frames); 218053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 219053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 220053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_stack_segment(const ptrace_context_t* context, log_t* log, pid_t tid, 221053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown bool only_in_tombstone, uintptr_t* sp, size_t words, int label) { 222053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown for (size_t i = 0; i < words; i++) { 223053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown uint32_t stack_content; 224053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!try_get_word_ptrace(tid, *sp, &stack_content)) { 225053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 226053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 227053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 228053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const map_info_t* mi; 229053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const symbol_t* symbol; 230053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown find_symbol_ptrace(context, stack_content, &mi, &symbol); 231053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 232053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (symbol) { 233053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown char* demangled_name = demangle_symbol_name(symbol->name); 234053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const char* symbol_name = demangled_name ? demangled_name : symbol->name; 235053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown uint32_t offset = stack_content - (mi->start + symbol->start); 236053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!i && label >= 0) { 237053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (offset) { 238053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s+%u)\n", 239053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown label, *sp, stack_content, mi ? mi->name : "", symbol_name, offset); 240053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 241053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " #%02d %08x %08x %s (%s)\n", 242053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown label, *sp, stack_content, mi ? mi->name : "", symbol_name); 243053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 244053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 245053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (offset) { 246053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " %08x %08x %s (%s+%u)\n", 247053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *sp, stack_content, mi ? mi->name : "", symbol_name, offset); 248053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 249053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " %08x %08x %s (%s)\n", 250053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *sp, stack_content, mi ? mi->name : "", symbol_name); 251053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 252053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 253053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown free(demangled_name); 254053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 255053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!i && label >= 0) { 256053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " #%02d %08x %08x %s\n", 257053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown label, *sp, stack_content, mi ? mi->name : ""); 258053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 259053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " %08x %08x %s\n", 260053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *sp, stack_content, mi ? mi->name : ""); 261053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 262053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 263053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 264053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown *sp += sizeof(uint32_t); 265053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 266053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 267053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 268053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_stack(const ptrace_context_t* context, log_t* log, pid_t tid, bool at_fault, 269053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const backtrace_frame_t* backtrace, size_t frames) { 270053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown bool have_first = false; 271053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown size_t first, last; 272053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown for (size_t i = 0; i < frames; i++) { 273053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (backtrace[i].stack_top) { 274053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!have_first) { 275053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown have_first = true; 276053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown first = i; 277053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 278053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown last = i; 279053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 280053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 281053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!have_first) { 282053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return; 283053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 284053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 285053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, !at_fault, "\nstack:\n"); 286053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 287053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown // Dump a few words before the first frame. 288053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown bool only_in_tombstone = !at_fault; 289053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown uintptr_t sp = backtrace[first].stack_top - STACK_WORDS * sizeof(uint32_t); 290053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, -1); 291053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 292053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown // Dump a few words from all successive frames. 293053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown // Only log the first 3 frames, put the rest in the tombstone. 294053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown for (size_t i = first; i <= last; i++) { 295053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown const backtrace_frame_t* frame = &backtrace[i]; 296053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (sp != frame->stack_top) { 297053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " ........ ........\n"); 298053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown sp = frame->stack_top; 299053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 300053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (i - first == 3) { 301053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown only_in_tombstone = true; 302053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 303053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (i == last) { 304053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_stack_segment(context, log, tid, only_in_tombstone, &sp, STACK_WORDS, i); 305053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (sp < frame->stack_top + frame->stack_size) { 306053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, only_in_tombstone, " ........ ........\n"); 307053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 308053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else { 309053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown size_t words = frame->stack_size / sizeof(uint32_t); 310053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (words == 0) { 311053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown words = 1; 312053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else if (words > STACK_WORDS) { 313053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown words = STACK_WORDS; 314053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 315053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_stack_segment(context, log, tid, only_in_tombstone, &sp, words, i); 316053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 317053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 318053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 319053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 320053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_backtrace_and_stack(const ptrace_context_t* context, log_t* log, pid_t tid, 321053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown bool at_fault) { 322053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown backtrace_frame_t backtrace[STACK_DEPTH]; 323053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown ssize_t frames = unwind_backtrace_ptrace(tid, context, backtrace, 0, STACK_DEPTH); 324053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (frames > 0) { 325053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_backtrace(context, log, tid, at_fault, backtrace, frames); 326053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown dump_stack(context, log, tid, at_fault, backtrace, frames); 327053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 328053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown} 329053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 330053b865412d1982ad1dc0e840898d82527deeb99Jeff Brownstatic void dump_nearby_maps(const ptrace_context_t* context, log_t* log, pid_t tid) { 331053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown siginfo_t si; 332053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown memset(&si, 0, sizeof(si)); 333053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) { 334053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "cannot get siginfo for %d: %s\n", 335053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown tid, strerror(errno)); 336053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return; 337053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 338053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (!signal_has_address(si.si_signo)) { 339053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return; 340053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 341053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 342053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown uintptr_t addr = (uintptr_t) si.si_addr; 343053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown addr &= ~0xfff; /* round to 4K page boundary */ 344053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (addr == 0) { /* null-pointer deref */ 345053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown return; 346053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } 347053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 348053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown _LOG(log, false, "\nmemory map around fault addr %08x:\n", (int)si.si_addr); 349053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown 350053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown /* 351053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * Search for a match, or for a hole where the match would be. The list 352053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown * is backward from the file content, so it starts at high addresses. 353053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown */ 354053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown map_info_t* map = context->map_info_list; 355053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown map_info_t *next = NULL; 356053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown map_info_t *prev = NULL; 357053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown while (map != NULL) { 358053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown if (addr >= map->start && addr < map->end) { 359053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown next = map->next; 360053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown break; 361053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown } else if (addr >= map->end) { 362053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown /* map would be between "prev" and this entry */ 363053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown next = map; 364053b865412d1982ad1dc0e840898d82527deeb99Jeff Brown map = NULL; 365