tombstone.cpp revision df2906186b6952c57b1f662bfef0b65c9f8c2e0d
1/* 2 * Copyright (C) 2012 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#include <stddef.h> 18#include <stdlib.h> 19#include <signal.h> 20#include <string.h> 21#include <stdio.h> 22#include <fcntl.h> 23#include <errno.h> 24#include <dirent.h> 25#include <time.h> 26#include <sys/ptrace.h> 27#include <sys/stat.h> 28#include <inttypes.h> 29 30#include <private/android_filesystem_config.h> 31 32#include <log/logger.h> 33#include <cutils/properties.h> 34 35#include <backtrace/Backtrace.h> 36#include <backtrace/BacktraceMap.h> 37 38#include <sys/socket.h> 39#include <linux/un.h> 40 41#include <selinux/android.h> 42 43#include <UniquePtr.h> 44 45#include "machine.h" 46#include "tombstone.h" 47#include "backtrace.h" 48 49#define STACK_WORDS 16 50 51#define MAX_TOMBSTONES 10 52#define TOMBSTONE_DIR "/data/tombstones" 53 54// Must match the path defined in NativeCrashListener.java 55#define NCRASH_SOCKET_PATH "/data/system/ndebugsocket" 56 57#define typecheck(x,y) { \ 58 typeof(x) __dummy1; \ 59 typeof(y) __dummy2; \ 60 (void)(&__dummy1 == &__dummy2); } 61 62 63static bool signal_has_address(int sig) { 64 switch (sig) { 65 case SIGILL: 66 case SIGFPE: 67 case SIGSEGV: 68 case SIGBUS: 69 return true; 70 default: 71 return false; 72 } 73} 74 75static const char* get_signame(int sig) { 76 switch(sig) { 77 case SIGILL: return "SIGILL"; 78 case SIGABRT: return "SIGABRT"; 79 case SIGBUS: return "SIGBUS"; 80 case SIGFPE: return "SIGFPE"; 81 case SIGSEGV: return "SIGSEGV"; 82 case SIGPIPE: return "SIGPIPE"; 83#ifdef SIGSTKFLT 84 case SIGSTKFLT: return "SIGSTKFLT"; 85#endif 86 case SIGSTOP: return "SIGSTOP"; 87 default: return "?"; 88 } 89} 90 91static const char* get_sigcode(int signo, int code) { 92 // Try the signal-specific codes... 93 switch (signo) { 94 case SIGILL: 95 switch (code) { 96 case ILL_ILLOPC: return "ILL_ILLOPC"; 97 case ILL_ILLOPN: return "ILL_ILLOPN"; 98 case ILL_ILLADR: return "ILL_ILLADR"; 99 case ILL_ILLTRP: return "ILL_ILLTRP"; 100 case ILL_PRVOPC: return "ILL_PRVOPC"; 101 case ILL_PRVREG: return "ILL_PRVREG"; 102 case ILL_COPROC: return "ILL_COPROC"; 103 case ILL_BADSTK: return "ILL_BADSTK"; 104 } 105 break; 106 case SIGBUS: 107 switch (code) { 108 case BUS_ADRALN: return "BUS_ADRALN"; 109 case BUS_ADRERR: return "BUS_ADRERR"; 110 case BUS_OBJERR: return "BUS_OBJERR"; 111 } 112 break; 113 case SIGFPE: 114 switch (code) { 115 case FPE_INTDIV: return "FPE_INTDIV"; 116 case FPE_INTOVF: return "FPE_INTOVF"; 117 case FPE_FLTDIV: return "FPE_FLTDIV"; 118 case FPE_FLTOVF: return "FPE_FLTOVF"; 119 case FPE_FLTUND: return "FPE_FLTUND"; 120 case FPE_FLTRES: return "FPE_FLTRES"; 121 case FPE_FLTINV: return "FPE_FLTINV"; 122 case FPE_FLTSUB: return "FPE_FLTSUB"; 123 } 124 break; 125 case SIGSEGV: 126 switch (code) { 127 case SEGV_MAPERR: return "SEGV_MAPERR"; 128 case SEGV_ACCERR: return "SEGV_ACCERR"; 129 } 130 break; 131 case SIGTRAP: 132 switch (code) { 133 case TRAP_BRKPT: return "TRAP_BRKPT"; 134 case TRAP_TRACE: return "TRAP_TRACE"; 135 } 136 break; 137 } 138 // Then the other codes... 139 switch (code) { 140 case SI_USER: return "SI_USER"; 141#if defined(SI_KERNEL) 142 case SI_KERNEL: return "SI_KERNEL"; 143#endif 144 case SI_QUEUE: return "SI_QUEUE"; 145 case SI_TIMER: return "SI_TIMER"; 146 case SI_MESGQ: return "SI_MESGQ"; 147 case SI_ASYNCIO: return "SI_ASYNCIO"; 148#if defined(SI_SIGIO) 149 case SI_SIGIO: return "SI_SIGIO"; 150#endif 151#if defined(SI_TKILL) 152 case SI_TKILL: return "SI_TKILL"; 153#endif 154 } 155 // Then give up... 156 return "?"; 157} 158 159static void dump_revision_info(log_t* log) { 160 char revision[PROPERTY_VALUE_MAX]; 161 162 property_get("ro.revision", revision, "unknown"); 163 164 _LOG(log, SCOPE_AT_FAULT, "Revision: '%s'\n", revision); 165} 166 167static void dump_build_info(log_t* log) { 168 char fingerprint[PROPERTY_VALUE_MAX]; 169 170 property_get("ro.build.fingerprint", fingerprint, "unknown"); 171 172 _LOG(log, SCOPE_AT_FAULT, "Build fingerprint: '%s'\n", fingerprint); 173} 174 175static void dump_fault_addr(log_t* log, pid_t tid, int sig) { 176 siginfo_t si; 177 178 memset(&si, 0, sizeof(si)); 179 if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){ 180 _LOG(log, SCOPE_AT_FAULT, "cannot get siginfo: %s\n", strerror(errno)); 181 } else if (signal_has_address(sig)) { 182 _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr %0*" PRIxPTR "\n", 183 sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code), 184 sizeof(uintptr_t)*2, reinterpret_cast<uintptr_t>(si.si_addr)); 185 } else { 186 _LOG(log, SCOPE_AT_FAULT, "signal %d (%s), code %d (%s), fault addr --------\n", 187 sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); 188 } 189} 190 191static void dump_thread_info(log_t* log, pid_t pid, pid_t tid, int scope_flags) { 192 char path[64]; 193 char threadnamebuf[1024]; 194 char* threadname = NULL; 195 FILE *fp; 196 197 snprintf(path, sizeof(path), "/proc/%d/comm", tid); 198 if ((fp = fopen(path, "r"))) { 199 threadname = fgets(threadnamebuf, sizeof(threadnamebuf), fp); 200 fclose(fp); 201 if (threadname) { 202 size_t len = strlen(threadname); 203 if (len && threadname[len - 1] == '\n') { 204 threadname[len - 1] = '\0'; 205 } 206 } 207 } 208 209 if (IS_AT_FAULT(scope_flags)) { 210 char procnamebuf[1024]; 211 char* procname = NULL; 212 213 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid); 214 if ((fp = fopen(path, "r"))) { 215 procname = fgets(procnamebuf, sizeof(procnamebuf), fp); 216 fclose(fp); 217 } 218 219 _LOG(log, SCOPE_AT_FAULT, "pid: %d, tid: %d, name: %s >>> %s <<<\n", pid, tid, 220 threadname ? threadname : "UNKNOWN", procname ? procname : "UNKNOWN"); 221 } else { 222 _LOG(log, 0, "pid: %d, tid: %d, name: %s\n", pid, tid, threadname ? threadname : "UNKNOWN"); 223 } 224} 225 226static void dump_stack_segment( 227 Backtrace* backtrace, log_t* log, int scope_flags, uintptr_t* sp, size_t words, int label) { 228 for (size_t i = 0; i < words; i++) { 229 uint32_t stack_content; 230 if (!backtrace->ReadWord(*sp, &stack_content)) { 231 break; 232 } 233 234 const backtrace_map_t* map = backtrace->FindMap(stack_content); 235 const char* map_name; 236 if (!map) { 237 map_name = ""; 238 } else { 239 map_name = map->name.c_str(); 240 } 241 uintptr_t offset = 0; 242 std::string func_name(backtrace->GetFunctionName(stack_content, &offset)); 243 if (!func_name.empty()) { 244 if (!i && label >= 0) { 245 if (offset) { 246 _LOG(log, scope_flags, " #%02d %08x %08x %s (%s+%u)\n", 247 label, *sp, stack_content, map_name, func_name.c_str(), offset); 248 } else { 249 _LOG(log, scope_flags, " #%02d %08x %08x %s (%s)\n", 250 label, *sp, stack_content, map_name, func_name.c_str()); 251 } 252 } else { 253 if (offset) { 254 _LOG(log, scope_flags, " %08x %08x %s (%s+%u)\n", 255 *sp, stack_content, map_name, func_name.c_str(), offset); 256 } else { 257 _LOG(log, scope_flags, " %08x %08x %s (%s)\n", 258 *sp, stack_content, map_name, func_name.c_str()); 259 } 260 } 261 } else { 262 if (!i && label >= 0) { 263 _LOG(log, scope_flags, " #%02d %08x %08x %s\n", 264 label, *sp, stack_content, map_name); 265 } else { 266 _LOG(log, scope_flags, " %08x %08x %s\n", 267 *sp, stack_content, map_name); 268 } 269 } 270 271 *sp += sizeof(uint32_t); 272 } 273} 274 275static void dump_stack(Backtrace* backtrace, log_t* log, int scope_flags) { 276 size_t first = 0, last; 277 for (size_t i = 0; i < backtrace->NumFrames(); i++) { 278 const backtrace_frame_data_t* frame = backtrace->GetFrame(i); 279 if (frame->sp) { 280 if (!first) { 281 first = i+1; 282 } 283 last = i; 284 } 285 } 286 if (!first) { 287 return; 288 } 289 first--; 290 291 scope_flags |= SCOPE_SENSITIVE; 292 293 // Dump a few words before the first frame. 294 uintptr_t sp = backtrace->GetFrame(first)->sp - STACK_WORDS * sizeof(uint32_t); 295 dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, -1); 296 297 // Dump a few words from all successive frames. 298 // Only log the first 3 frames, put the rest in the tombstone. 299 for (size_t i = first; i <= last; i++) { 300 const backtrace_frame_data_t* frame = backtrace->GetFrame(i); 301 if (sp != frame->sp) { 302 _LOG(log, scope_flags, " ........ ........\n"); 303 sp = frame->sp; 304 } 305 if (i - first == 3) { 306 scope_flags &= (~SCOPE_AT_FAULT); 307 } 308 if (i == last) { 309 dump_stack_segment(backtrace, log, scope_flags, &sp, STACK_WORDS, i); 310 if (sp < frame->sp + frame->stack_size) { 311 _LOG(log, scope_flags, " ........ ........\n"); 312 } 313 } else { 314 size_t words = frame->stack_size / sizeof(uint32_t); 315 if (words == 0) { 316 words = 1; 317 } else if (words > STACK_WORDS) { 318 words = STACK_WORDS; 319 } 320 dump_stack_segment(backtrace, log, scope_flags, &sp, words, i); 321 } 322 } 323} 324 325static void dump_backtrace_and_stack(Backtrace* backtrace, log_t* log, int scope_flags) { 326 if (backtrace->NumFrames()) { 327 _LOG(log, scope_flags, "\nbacktrace:\n"); 328 dump_backtrace_to_log(backtrace, log, scope_flags, " "); 329 330 _LOG(log, scope_flags, "\nstack:\n"); 331 dump_stack(backtrace, log, scope_flags); 332 } 333} 334 335static void dump_map(log_t* log, const backtrace_map_t* map, const char* what, int scope_flags) { 336 if (map != NULL) { 337 _LOG(log, scope_flags, " %08x-%08x %c%c%c %s\n", map->start, map->end, 338 (map->flags & PROT_READ) ? 'r' : '-', (map->flags & PROT_WRITE) ? 'w' : '-', 339 (map->flags & PROT_EXEC) ? 'x' : '-', map->name.c_str()); 340 } else { 341 _LOG(log, scope_flags, " (no %s)\n", what); 342 } 343} 344 345static void dump_nearby_maps(BacktraceMap* map, log_t* log, pid_t tid, int scope_flags) { 346 scope_flags |= SCOPE_SENSITIVE; 347 siginfo_t si; 348 memset(&si, 0, sizeof(si)); 349 if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)) { 350 _LOG(log, scope_flags, "cannot get siginfo for %d: %s\n", tid, strerror(errno)); 351 return; 352 } 353 if (!signal_has_address(si.si_signo)) { 354 return; 355 } 356 357 uintptr_t addr = reinterpret_cast<uintptr_t>(si.si_addr); 358 addr &= ~0xfff; // round to 4K page boundary 359 if (addr == 0) { // null-pointer deref 360 return; 361 } 362 363 _LOG(log, scope_flags, "\nmemory map around fault addr %" PRIxPTR ":\n", 364 reinterpret_cast<uintptr_t>(si.si_addr)); 365 366 // Search for a match, or for a hole where the match would be. The list 367 // is backward from the file content, so it starts at high addresses. 368 const backtrace_map_t* cur_map = NULL; 369 const backtrace_map_t* next_map = NULL; 370 const backtrace_map_t* prev_map = NULL; 371 for (BacktraceMap::const_iterator it = map->begin(); it != map->end(); ++it) { 372 if (addr >= it->start && addr < it->end) { 373 cur_map = &*it; 374 if (it != map->begin()) { 375 prev_map = &*(it-1); 376 } 377 if (++it != map->end()) { 378 next_map = &*it; 379 } 380 break; 381 } 382 } 383 384 // Show the map address in ascending order (like /proc/pid/maps). 385 dump_map(log, prev_map, "map below", scope_flags); 386 dump_map(log, cur_map, "map for address", scope_flags); 387 dump_map(log, next_map, "map above", scope_flags); 388} 389 390static void dump_thread( 391 Backtrace* backtrace, log_t* log, int scope_flags, int* total_sleep_time_usec) { 392 wait_for_stop(backtrace->Tid(), total_sleep_time_usec); 393 394 dump_registers(log, backtrace->Tid(), scope_flags); 395 dump_backtrace_and_stack(backtrace, log, scope_flags); 396 if (IS_AT_FAULT(scope_flags)) { 397 dump_memory_and_code(log, backtrace->Tid(), scope_flags); 398 dump_nearby_maps(backtrace->GetMap(), log, backtrace->Tid(), scope_flags); 399 } 400} 401 402// Return true if some thread is not detached cleanly 403static bool dump_sibling_thread_report( 404 log_t* log, pid_t pid, pid_t tid, int* total_sleep_time_usec, BacktraceMap* map) { 405 char task_path[64]; 406 snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid); 407 408 DIR* d = opendir(task_path); 409 // Bail early if the task directory cannot be opened 410 if (d == NULL) { 411 XLOG("Cannot open /proc/%d/task\n", pid); 412 return false; 413 } 414 415 bool detach_failed = false; 416 struct dirent* de; 417 while ((de = readdir(d)) != NULL) { 418 // Ignore "." and ".." 419 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { 420 continue; 421 } 422 423 // The main thread at fault has been handled individually 424 char* end; 425 pid_t new_tid = strtoul(de->d_name, &end, 10); 426 if (*end || new_tid == tid) { 427 continue; 428 } 429 430 // Skip this thread if cannot ptrace it 431 if (ptrace(PTRACE_ATTACH, new_tid, 0, 0) < 0) { 432 continue; 433 } 434 435 _LOG(log, 0, "--- --- --- --- --- --- --- --- --- --- --- --- --- --- --- ---\n"); 436 dump_thread_info(log, pid, new_tid, 0); 437 438 UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, new_tid, map)); 439 if (backtrace->Unwind(0)) { 440 dump_thread(backtrace.get(), log, 0, total_sleep_time_usec); 441 } 442 443 if (ptrace(PTRACE_DETACH, new_tid, 0, 0) != 0) { 444 LOG("ptrace detach from %d failed: %s\n", new_tid, strerror(errno)); 445 detach_failed = true; 446 } 447 } 448 449 closedir(d); 450 return detach_failed; 451} 452 453// Reads the contents of the specified log device, filters out the entries 454// that don't match the specified pid, and writes them to the tombstone file. 455// 456// If "tailOnly" is set, we only print the last few lines. 457static void dump_log_file(log_t* log, pid_t pid, const char* filename, bool tailOnly) { 458 bool first = true; 459 460 // circular buffer, for "tailOnly" mode 461 const int kShortLogMaxLines = 5; 462 const int kShortLogLineLen = 256; 463 char shortLog[kShortLogMaxLines][kShortLogLineLen]; 464 int shortLogCount = 0; 465 int shortLogNext = 0; 466 467 int logfd = open(filename, O_RDONLY | O_NONBLOCK); 468 if (logfd < 0) { 469 XLOG("Unable to open %s: %s\n", filename, strerror(errno)); 470 return; 471 } 472 473 union { 474 unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1]; 475 struct logger_entry entry; 476 } log_entry; 477 478 while (true) { 479 ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN); 480 if (actual < 0) { 481 if (errno == EINTR) { 482 // interrupted by signal, retry 483 continue; 484 } else if (errno == EAGAIN) { 485 // non-blocking EOF; we're done 486 break; 487 } else { 488 _LOG(log, 0, "Error while reading log: %s\n", strerror(errno)); 489 break; 490 } 491 } else if (actual == 0) { 492 _LOG(log, 0, "Got zero bytes while reading log: %s\n", strerror(errno)); 493 break; 494 } 495 496 // NOTE: if you XLOG something here, this will spin forever, 497 // because you will be writing as fast as you're reading. Any 498 // high-frequency debug diagnostics should just be written to 499 // the tombstone file. 500 struct logger_entry* entry = &log_entry.entry; 501 502 if (entry->pid != static_cast<int32_t>(pid)) { 503 // wrong pid, ignore 504 continue; 505 } 506 507 if (first) { 508 _LOG(log, 0, "--------- %slog %s\n", tailOnly ? "tail end of " : "", filename); 509 first = false; 510 } 511 512 // Msg format is: <priority:1><tag:N>\0<message:N>\0 513 // 514 // We want to display it in the same format as "logcat -v threadtime" 515 // (although in this case the pid is redundant). 516 // 517 // TODO: scan for line breaks ('\n') and display each text line 518 // on a separate line, prefixed with the header, like logcat does. 519 static const char* kPrioChars = "!.VDIWEFS"; 520 unsigned char prio = entry->msg[0]; 521 char* tag = entry->msg + 1; 522 char* msg = tag + strlen(tag) + 1; 523 524 // consume any trailing newlines 525 char* eatnl = msg + strlen(msg) - 1; 526 while (eatnl >= msg && *eatnl == '\n') { 527 *eatnl-- = '\0'; 528 } 529 530 char prioChar = (prio < strlen(kPrioChars) ? kPrioChars[prio] : '?'); 531 532 char timeBuf[32]; 533 time_t sec = static_cast<time_t>(entry->sec); 534 struct tm tmBuf; 535 struct tm* ptm; 536 ptm = localtime_r(&sec, &tmBuf); 537 strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm); 538 539 if (tailOnly) { 540 snprintf(shortLog[shortLogNext], kShortLogLineLen, 541 "%s.%03d %5d %5d %c %-8s: %s", 542 timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, 543 prioChar, tag, msg); 544 shortLogNext = (shortLogNext + 1) % kShortLogMaxLines; 545 shortLogCount++; 546 } else { 547 _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n", 548 timeBuf, entry->nsec / 1000000, entry->pid, entry->tid, prioChar, tag, msg); 549 } 550 } 551 552 if (tailOnly) { 553 int i; 554 555 // If we filled the buffer, we want to start at "next", which has 556 // the oldest entry. If we didn't, we want to start at zero. 557 if (shortLogCount < kShortLogMaxLines) { 558 shortLogNext = 0; 559 } else { 560 shortLogCount = kShortLogMaxLines; // cap at window size 561 } 562 563 for (i = 0; i < shortLogCount; i++) { 564 _LOG(log, 0, "%s\n", shortLog[shortLogNext]); 565 shortLogNext = (shortLogNext + 1) % kShortLogMaxLines; 566 } 567 } 568 569 close(logfd); 570} 571 572// Dumps the logs generated by the specified pid to the tombstone, from both 573// "system" and "main" log devices. Ideally we'd interleave the output. 574static void dump_logs(log_t* log, pid_t pid, bool tailOnly) { 575 dump_log_file(log, pid, "/dev/log/system", tailOnly); 576 dump_log_file(log, pid, "/dev/log/main", tailOnly); 577} 578 579static void dump_abort_message(Backtrace* backtrace, log_t* log, uintptr_t address) { 580 if (address == 0) { 581 return; 582 } 583 584 address += sizeof(size_t); // Skip the buffer length. 585 586 char msg[512]; 587 memset(msg, 0, sizeof(msg)); 588 char* p = &msg[0]; 589 while (p < &msg[sizeof(msg)]) { 590 uint32_t data; 591 if (!backtrace->ReadWord(address, &data)) { 592 break; 593 } 594 address += sizeof(uint32_t); 595 596 if ((*p++ = (data >> 0) & 0xff) == 0) { 597 break; 598 } 599 if ((*p++ = (data >> 8) & 0xff) == 0) { 600 break; 601 } 602 if ((*p++ = (data >> 16) & 0xff) == 0) { 603 break; 604 } 605 if ((*p++ = (data >> 24) & 0xff) == 0) { 606 break; 607 } 608 } 609 msg[sizeof(msg) - 1] = '\0'; 610 611 _LOG(log, SCOPE_AT_FAULT, "Abort message: '%s'\n", msg); 612} 613 614// Dumps all information about the specified pid to the tombstone. 615static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address, 616 bool dump_sibling_threads, int* total_sleep_time_usec) { 617 // don't copy log messages to tombstone unless this is a dev device 618 char value[PROPERTY_VALUE_MAX]; 619 property_get("ro.debuggable", value, "0"); 620 bool want_logs = (value[0] == '1'); 621 622 if (log->amfd >= 0) { 623 // Activity Manager protocol: binary 32-bit network-byte-order ints for the 624 // pid and signal number, followed by the raw text of the dump, culminating 625 // in a zero byte that marks end-of-data. 626 uint32_t datum = htonl(pid); 627 TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); 628 datum = htonl(signal); 629 TEMP_FAILURE_RETRY( write(log->amfd, &datum, 4) ); 630 } 631 632 _LOG(log, SCOPE_AT_FAULT, 633 "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n"); 634 dump_build_info(log); 635 dump_revision_info(log); 636 dump_thread_info(log, pid, tid, SCOPE_AT_FAULT); 637 if (signal) { 638 dump_fault_addr(log, tid, signal); 639 } 640 641 UniquePtr<BacktraceMap> map(BacktraceMap::Create(pid)); 642 UniquePtr<Backtrace> backtrace(Backtrace::Create(pid, tid, map.get())); 643 if (backtrace->Unwind(0)) { 644 dump_abort_message(backtrace.get(), log, abort_msg_address); 645 dump_thread(backtrace.get(), log, SCOPE_AT_FAULT, total_sleep_time_usec); 646 } 647 648 if (want_logs) { 649 dump_logs(log, pid, true); 650 } 651 652 bool detach_failed = false; 653 if (dump_sibling_threads) { 654 detach_failed = dump_sibling_thread_report(log, pid, tid, total_sleep_time_usec, map.get()); 655 } 656 657 if (want_logs) { 658 dump_logs(log, pid, false); 659 } 660 661 // send EOD to the Activity Manager, then wait for its ack to avoid racing ahead 662 // and killing the target out from under it 663 if (log->amfd >= 0) { 664 uint8_t eodMarker = 0; 665 TEMP_FAILURE_RETRY( write(log->amfd, &eodMarker, 1) ); 666 // 3 sec timeout reading the ack; we're fine if that happens 667 TEMP_FAILURE_RETRY( read(log->amfd, &eodMarker, 1) ); 668 } 669 670 return detach_failed; 671} 672 673// find_and_open_tombstone - find an available tombstone slot, if any, of the 674// form tombstone_XX where XX is 00 to MAX_TOMBSTONES-1, inclusive. If no 675// file is available, we reuse the least-recently-modified file. 676// 677// Returns the path of the tombstone file, allocated using malloc(). Caller must free() it. 678static char* find_and_open_tombstone(int* fd) { 679 unsigned long mtime = ULONG_MAX; 680 struct stat sb; 681 682 // XXX: Our stat.st_mtime isn't time_t. If it changes, as it probably ought 683 // to, our logic breaks. This check will generate a warning if that happens. 684 typecheck(mtime, sb.st_mtime); 685 686 // In a single wolf-like pass, find an available slot and, in case none 687 // exist, find and record the least-recently-modified file. 688 char path[128]; 689 int oldest = 0; 690 for (int i = 0; i < MAX_TOMBSTONES; i++) { 691 snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", i); 692 693 if (!stat(path, &sb)) { 694 if (sb.st_mtime < mtime) { 695 oldest = i; 696 mtime = sb.st_mtime; 697 } 698 continue; 699 } 700 if (errno != ENOENT) 701 continue; 702 703 *fd = open(path, O_CREAT | O_EXCL | O_WRONLY, 0600); 704 if (*fd < 0) 705 continue; // raced ? 706 707 fchown(*fd, AID_SYSTEM, AID_SYSTEM); 708 return strdup(path); 709 } 710 711 // we didn't find an available file, so we clobber the oldest one 712 snprintf(path, sizeof(path), TOMBSTONE_DIR"/tombstone_%02d", oldest); 713 *fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); 714 if (*fd < 0) { 715 LOG("failed to open tombstone file '%s': %s\n", path, strerror(errno)); 716 return NULL; 717 } 718 fchown(*fd, AID_SYSTEM, AID_SYSTEM); 719 return strdup(path); 720} 721 722static int activity_manager_connect() { 723 int amfd = socket(PF_UNIX, SOCK_STREAM, 0); 724 if (amfd >= 0) { 725 struct sockaddr_un address; 726 int err; 727 728 memset(&address, 0, sizeof(address)); 729 address.sun_family = AF_UNIX; 730 strncpy(address.sun_path, NCRASH_SOCKET_PATH, sizeof(address.sun_path)); 731 err = TEMP_FAILURE_RETRY(connect( 732 amfd, reinterpret_cast<struct sockaddr*>(&address), sizeof(address))); 733 if (!err) { 734 struct timeval tv; 735 memset(&tv, 0, sizeof(tv)); 736 tv.tv_sec = 1; // tight leash 737 err = setsockopt(amfd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); 738 if (!err) { 739 tv.tv_sec = 3; // 3 seconds on handshake read 740 err = setsockopt(amfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); 741 } 742 } 743 if (err) { 744 close(amfd); 745 amfd = -1; 746 } 747 } 748 749 return amfd; 750} 751 752char* engrave_tombstone( 753 pid_t pid, pid_t tid, int signal, uintptr_t abort_msg_address, bool dump_sibling_threads, 754 bool quiet, bool* detach_failed, int* total_sleep_time_usec) { 755 mkdir(TOMBSTONE_DIR, 0755); 756 chown(TOMBSTONE_DIR, AID_SYSTEM, AID_SYSTEM); 757 758 if (selinux_android_restorecon(TOMBSTONE_DIR) == -1) { 759 *detach_failed = false; 760 return NULL; 761 } 762 763 int fd; 764 char* path = find_and_open_tombstone(&fd); 765 if (!path) { 766 *detach_failed = false; 767 return NULL; 768 } 769 770 log_t log; 771 log.tfd = fd; 772 log.amfd = activity_manager_connect(); 773 log.quiet = quiet; 774 *detach_failed = dump_crash( 775 &log, pid, tid, signal, abort_msg_address, dump_sibling_threads, total_sleep_time_usec); 776 777 close(log.amfd); 778 close(fd); 779 return path; 780} 781