dumpstate.cpp revision afc38fe263c0997385529d72d9211189b3d6d075
1/* 2 * Copyright (C) 2008 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 <dirent.h> 18#include <errno.h> 19#include <fcntl.h> 20#include <libgen.h> 21#include <limits.h> 22#include <memory> 23#include <regex> 24#include <set> 25#include <stdbool.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <string> 29#include <string.h> 30#include <sys/prctl.h> 31#include <sys/resource.h> 32#include <sys/stat.h> 33#include <sys/time.h> 34#include <sys/wait.h> 35#include <unistd.h> 36 37#include <android-base/stringprintf.h> 38#include <android-base/file.h> 39#include <cutils/properties.h> 40 41#include "private/android_filesystem_config.h" 42 43#define LOG_TAG "dumpstate" 44#include <cutils/log.h> 45 46#include "dumpstate.h" 47#include "ScopedFd.h" 48#include "ziparchive/zip_writer.h" 49 50#include "mincrypt/sha256.h" 51 52using android::base::StringPrintf; 53 54/* read before root is shed */ 55static char cmdline_buf[16384] = "(unknown)"; 56static const char *dump_traces_path = NULL; 57 58// TODO: variables below should be part of dumpstate object 59static unsigned long id; 60static char build_type[PROPERTY_VALUE_MAX]; 61static time_t now; 62static std::unique_ptr<ZipWriter> zip_writer; 63static std::set<std::string> mount_points; 64void add_mountinfo(); 65int control_socket_fd = -1; 66/* suffix of the bugreport files - it's typically the date (when invoked with -d), 67 * although it could be changed by the user using a system property */ 68static std::string suffix; 69 70#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" 71#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0" 72 73#define RAFT_DIR "/data/misc/raft" 74#define RECOVERY_DIR "/cache/recovery" 75#define RECOVERY_DATA_DIR "/data/misc/recovery" 76#define LOGPERSIST_DATA_DIR "/data/misc/logd" 77#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur" 78#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref" 79#define TOMBSTONE_DIR "/data/tombstones" 80#define TOMBSTONE_FILE_PREFIX TOMBSTONE_DIR "/tombstone_" 81/* Can accomodate a tombstone number up to 9999. */ 82#define TOMBSTONE_MAX_LEN (sizeof(TOMBSTONE_FILE_PREFIX) + 4) 83#define NUM_TOMBSTONES 10 84#define WLUTIL "/vendor/xbin/wlutil" 85 86typedef struct { 87 char name[TOMBSTONE_MAX_LEN]; 88 int fd; 89} tombstone_data_t; 90 91static tombstone_data_t tombstone_data[NUM_TOMBSTONES]; 92 93const std::string ZIP_ROOT_DIR = "FS"; 94std::string bugreport_dir; 95 96/* 97 * List of supported zip format versions. 98 * 99 * See bugreport-format.txt for more info. 100 */ 101static std::string VERSION_DEFAULT = "1.0"; 102 103bool is_user_build() { 104 return 0 == strncmp(build_type, "user", PROPERTY_VALUE_MAX - 1); 105} 106 107/* gets the tombstone data, according to the bugreport type: if zipped gets all tombstones, 108 * otherwise gets just those modified in the last half an hour. */ 109static void get_tombstone_fds(tombstone_data_t data[NUM_TOMBSTONES]) { 110 time_t thirty_minutes_ago = now - 60*30; 111 for (size_t i = 0; i < NUM_TOMBSTONES; i++) { 112 snprintf(data[i].name, sizeof(data[i].name), "%s%02zu", TOMBSTONE_FILE_PREFIX, i); 113 int fd = TEMP_FAILURE_RETRY(open(data[i].name, 114 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); 115 struct stat st; 116 if (fstat(fd, &st) == 0 && S_ISREG(st.st_mode) && 117 (zip_writer || (time_t) st.st_mtime >= thirty_minutes_ago)) { 118 data[i].fd = fd; 119 } else { 120 close(fd); 121 data[i].fd = -1; 122 } 123 } 124} 125 126// for_each_pid() callback to get mount info about a process. 127void do_mountinfo(int pid, const char *name) { 128 char path[PATH_MAX]; 129 130 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points 131 // are added. 132 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); 133 char linkname[PATH_MAX]; 134 ssize_t r = readlink(path, linkname, PATH_MAX); 135 if (r == -1) { 136 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno)); 137 return; 138 } 139 linkname[r] = '\0'; 140 141 if (mount_points.find(linkname) == mount_points.end()) { 142 // First time this mount point was found: add it 143 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid); 144 if (add_zip_entry(ZIP_ROOT_DIR + path, path)) { 145 mount_points.insert(linkname); 146 } else { 147 MYLOGE("Unable to add mountinfo %s to zip file\n", path); 148 } 149 } 150} 151 152void add_mountinfo() { 153 if (!zip_writer) return; 154 const char *title = "MOUNT INFO"; 155 mount_points.clear(); 156 DurationReporter duration_reporter(title, NULL); 157 for_each_pid(do_mountinfo, NULL); 158 MYLOGD("%s: %d entries added to zip file\n", title, (int) mount_points.size()); 159} 160 161static void dump_dev_files(const char *title, const char *driverpath, const char *filename) 162{ 163 DIR *d; 164 struct dirent *de; 165 char path[PATH_MAX]; 166 167 d = opendir(driverpath); 168 if (d == NULL) { 169 return; 170 } 171 172 while ((de = readdir(d))) { 173 if (de->d_type != DT_LNK) { 174 continue; 175 } 176 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename); 177 dump_file(title, path); 178 } 179 180 closedir(d); 181} 182 183// return pid of a userspace process. If not found or error, return 0. 184static unsigned int pid_of_process(const char* ps_name) { 185 DIR *proc_dir; 186 struct dirent *ps; 187 unsigned int pid; 188 std::string cmdline; 189 190 if (!(proc_dir = opendir("/proc"))) { 191 MYLOGE("Can't open /proc\n"); 192 return 0; 193 } 194 195 while ((ps = readdir(proc_dir))) { 196 if (!(pid = atoi(ps->d_name))) { 197 continue; 198 } 199 android::base::ReadFileToString("/proc/" 200 + std::string(ps->d_name) + "/cmdline", &cmdline); 201 if (cmdline.find(ps_name) == std::string::npos) { 202 continue; 203 } else { 204 closedir(proc_dir); 205 return pid; 206 } 207 } 208 closedir(proc_dir); 209 return 0; 210} 211 212// dump anrd's trace and add to the zip file. 213// 1. check if anrd is running on this device. 214// 2. send a SIGUSR1 to its pid which will dump anrd's trace. 215// 3. wait until the trace generation completes and add to the zip file. 216static bool dump_anrd_trace() { 217 unsigned int pid; 218 char buf[50], path[PATH_MAX]; 219 struct dirent *trace; 220 struct stat st; 221 DIR *trace_dir; 222 int retry = 5; 223 long max_ctime = 0, old_mtime; 224 long long cur_size = 0; 225 const char *trace_path = "/data/misc/anrd/"; 226 227 if (!zip_writer) { 228 MYLOGE("Not dumping anrd trace because zip_writer is not set\n"); 229 return false; 230 } 231 232 // find anrd's pid if it is running. 233 pid = pid_of_process("/system/xbin/anrd"); 234 235 if (pid > 0) { 236 if (stat(trace_path, &st) == 0) { 237 old_mtime = st.st_mtime; 238 } else { 239 MYLOGE("Failed to find: %s\n", trace_path); 240 return false; 241 } 242 243 // send SIGUSR1 to the anrd to generate a trace. 244 sprintf(buf, "%u", pid); 245 if (run_command("ANRD_DUMP", 1, "kill", "-SIGUSR1", buf, NULL)) { 246 MYLOGE("anrd signal timed out. Please manually collect trace\n"); 247 return false; 248 } 249 250 while (retry-- > 0 && old_mtime == st.st_mtime) { 251 sleep(1); 252 stat(trace_path, &st); 253 } 254 255 if (retry < 0 && old_mtime == st.st_mtime) { 256 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path); 257 return false; 258 } 259 260 // identify the trace file by its creation time. 261 if (!(trace_dir = opendir(trace_path))) { 262 MYLOGE("Can't open trace file under %s\n", trace_path); 263 } 264 while ((trace = readdir(trace_dir))) { 265 if (strcmp(trace->d_name, ".") == 0 266 || strcmp(trace->d_name, "..") == 0) { 267 continue; 268 } 269 sprintf(path, "%s%s", trace_path, trace->d_name); 270 if (stat(path, &st) == 0) { 271 if (st.st_ctime > max_ctime) { 272 max_ctime = st.st_ctime; 273 sprintf(buf, "%s", trace->d_name); 274 } 275 } 276 } 277 closedir(trace_dir); 278 279 // Wait until the dump completes by checking the size of the trace. 280 if (max_ctime > 0) { 281 sprintf(path, "%s%s", trace_path, buf); 282 while(true) { 283 sleep(1); 284 if (stat(path, &st) == 0) { 285 if (st.st_size == cur_size) { 286 break; 287 } else if (st.st_size > cur_size) { 288 cur_size = st.st_size; 289 } else { 290 return false; 291 } 292 } else { 293 MYLOGE("Cant stat() %s anymore\n", path); 294 return false; 295 } 296 } 297 // Add to the zip file. 298 if (!add_zip_entry("anrd_trace.txt", path)) { 299 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path); 300 } else { 301 if (remove(path)) { 302 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno)); 303 } 304 return true; 305 } 306 } else { 307 MYLOGE("Can't stats any trace file under %s\n", trace_path); 308 } 309 } 310 return false; 311} 312 313static void dump_systrace() { 314 if (!zip_writer) { 315 MYLOGD("Not dumping systrace because zip_writer is not set\n"); 316 return; 317 } 318 std::string systrace_path = bugreport_dir + "/systrace-" + suffix + ".txt"; 319 if (systrace_path.empty()) { 320 MYLOGE("Not dumping systrace because path is empty\n"); 321 return; 322 } 323 const char* path = "/sys/kernel/debug/tracing/tracing_on"; 324 long int is_tracing; 325 if (read_file_as_long(path, &is_tracing)) { 326 return; // error already logged 327 } 328 if (is_tracing <= 0) { 329 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing); 330 return; 331 } 332 333 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes", 334 systrace_path.c_str()); 335 if (run_command("SYSTRACE", 120, "/system/bin/atrace", "--async_dump", "-o", 336 systrace_path.c_str(), NULL)) { 337 MYLOGE("systrace timed out, its zip entry will be incomplete\n"); 338 // TODO: run_command tries to kill the process, but atrace doesn't die peacefully; ideally, 339 // we should call strace to stop itself, but there is no such option yet (just a 340 // --async_stop, which stops and dump 341 // if (run_command("SYSTRACE", 10, "/system/bin/atrace", "--kill", NULL)) { 342 // MYLOGE("could not stop systrace "); 343 // } 344 } 345 if (!add_zip_entry("systrace.txt", systrace_path)) { 346 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str()); 347 } else { 348 if (remove(systrace_path.c_str())) { 349 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno)); 350 } 351 } 352} 353 354static void dump_raft() { 355 if (is_user_build()) { 356 return; 357 } 358 359 std::string raft_log_path = bugreport_dir + "/raft_log.txt"; 360 if (raft_log_path.empty()) { 361 MYLOGD("raft_log_path is empty\n"); 362 return; 363 } 364 365 struct stat s; 366 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) { 367 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR); 368 return; 369 } 370 371 if (!zip_writer) { 372 // Write compressed and encoded raft logs to stdout if not zip_writer. 373 run_command("RAFT LOGS", 600, "logcompressor", "-r", RAFT_DIR, NULL); 374 return; 375 } 376 377 run_command("RAFT LOGS", 600, "logcompressor", "-n", "-r", RAFT_DIR, 378 "-o", raft_log_path.c_str(), NULL); 379 if (!add_zip_entry("raft_log.txt", raft_log_path)) { 380 MYLOGE("Unable to add raft log %s to zip file\n", raft_log_path.c_str()); 381 } else { 382 if (remove(raft_log_path.c_str())) { 383 MYLOGE("Error removing raft file %s: %s\n", raft_log_path.c_str(), strerror(errno)); 384 } 385 } 386} 387 388static bool skip_not_stat(const char *path) { 389 static const char stat[] = "/stat"; 390 size_t len = strlen(path); 391 if (path[len - 1] == '/') { /* Directory? */ 392 return false; 393 } 394 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ 395} 396 397static bool skip_none(const char *path) { 398 return false; 399} 400 401static const char mmcblk0[] = "/sys/block/mmcblk0/"; 402unsigned long worst_write_perf = 20000; /* in KB/s */ 403 404// 405// stat offsets 406// Name units description 407// ---- ----- ----------- 408// read I/Os requests number of read I/Os processed 409#define __STAT_READ_IOS 0 410// read merges requests number of read I/Os merged with in-queue I/O 411#define __STAT_READ_MERGES 1 412// read sectors sectors number of sectors read 413#define __STAT_READ_SECTORS 2 414// read ticks milliseconds total wait time for read requests 415#define __STAT_READ_TICKS 3 416// write I/Os requests number of write I/Os processed 417#define __STAT_WRITE_IOS 4 418// write merges requests number of write I/Os merged with in-queue I/O 419#define __STAT_WRITE_MERGES 5 420// write sectors sectors number of sectors written 421#define __STAT_WRITE_SECTORS 6 422// write ticks milliseconds total wait time for write requests 423#define __STAT_WRITE_TICKS 7 424// in_flight requests number of I/Os currently in flight 425#define __STAT_IN_FLIGHT 8 426// io_ticks milliseconds total time this block device has been active 427#define __STAT_IO_TICKS 9 428// time_in_queue milliseconds total wait time for all requests 429#define __STAT_IN_QUEUE 10 430#define __STAT_NUMBER_FIELD 11 431// 432// read I/Os, write I/Os 433// ===================== 434// 435// These values increment when an I/O request completes. 436// 437// read merges, write merges 438// ========================= 439// 440// These values increment when an I/O request is merged with an 441// already-queued I/O request. 442// 443// read sectors, write sectors 444// =========================== 445// 446// These values count the number of sectors read from or written to this 447// block device. The "sectors" in question are the standard UNIX 512-byte 448// sectors, not any device- or filesystem-specific block size. The 449// counters are incremented when the I/O completes. 450#define SECTOR_SIZE 512 451// 452// read ticks, write ticks 453// ======================= 454// 455// These values count the number of milliseconds that I/O requests have 456// waited on this block device. If there are multiple I/O requests waiting, 457// these values will increase at a rate greater than 1000/second; for 458// example, if 60 read requests wait for an average of 30 ms, the read_ticks 459// field will increase by 60*30 = 1800. 460// 461// in_flight 462// ========= 463// 464// This value counts the number of I/O requests that have been issued to 465// the device driver but have not yet completed. It does not include I/O 466// requests that are in the queue but not yet issued to the device driver. 467// 468// io_ticks 469// ======== 470// 471// This value counts the number of milliseconds during which the device has 472// had I/O requests queued. 473// 474// time_in_queue 475// ============= 476// 477// This value counts the number of milliseconds that I/O requests have waited 478// on this block device. If there are multiple I/O requests waiting, this 479// value will increase as the product of the number of milliseconds times the 480// number of requests waiting (see "read ticks" above for an example). 481#define S_TO_MS 1000 482// 483 484static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) { 485 unsigned long long fields[__STAT_NUMBER_FIELD]; 486 bool z; 487 char *cp, *buffer = NULL; 488 size_t i = 0; 489 FILE *fp = fdopen(fd, "rb"); 490 getline(&buffer, &i, fp); 491 fclose(fp); 492 if (!buffer) { 493 return -errno; 494 } 495 i = strlen(buffer); 496 while ((i > 0) && (buffer[i - 1] == '\n')) { 497 buffer[--i] = '\0'; 498 } 499 if (!*buffer) { 500 free(buffer); 501 return 0; 502 } 503 z = true; 504 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) { 505 fields[i] = strtoull(cp, &cp, 10); 506 if (fields[i] != 0) { 507 z = false; 508 } 509 } 510 if (z) { /* never accessed */ 511 free(buffer); 512 return 0; 513 } 514 515 if (!strncmp(path, mmcblk0, sizeof(mmcblk0) - 1)) { 516 path += sizeof(mmcblk0) - 1; 517 } 518 519 printf("%s: %s\n", path, buffer); 520 free(buffer); 521 522 if (fields[__STAT_IO_TICKS]) { 523 unsigned long read_perf = 0; 524 unsigned long read_ios = 0; 525 if (fields[__STAT_READ_TICKS]) { 526 unsigned long long divisor = fields[__STAT_READ_TICKS] 527 * fields[__STAT_IO_TICKS]; 528 read_perf = ((unsigned long long)SECTOR_SIZE 529 * fields[__STAT_READ_SECTORS] 530 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 531 / divisor; 532 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS] 533 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 534 / divisor; 535 } 536 537 unsigned long write_perf = 0; 538 unsigned long write_ios = 0; 539 if (fields[__STAT_WRITE_TICKS]) { 540 unsigned long long divisor = fields[__STAT_WRITE_TICKS] 541 * fields[__STAT_IO_TICKS]; 542 write_perf = ((unsigned long long)SECTOR_SIZE 543 * fields[__STAT_WRITE_SECTORS] 544 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 545 / divisor; 546 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS] 547 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 548 / divisor; 549 } 550 551 unsigned queue = (fields[__STAT_IN_QUEUE] 552 + (fields[__STAT_IO_TICKS] >> 1)) 553 / fields[__STAT_IO_TICKS]; 554 555 if (!write_perf && !write_ios) { 556 printf("%s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", 557 path, read_perf, read_ios, queue); 558 } else { 559 printf("%s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", 560 path, read_perf, read_ios, write_perf, write_ios, queue); 561 } 562 563 /* bugreport timeout factor adjustment */ 564 if ((write_perf > 1) && (write_perf < worst_write_perf)) { 565 worst_write_perf = write_perf; 566 } 567 } 568 return 0; 569} 570 571/* Copied policy from system/core/logd/LogBuffer.cpp */ 572 573#define LOG_BUFFER_SIZE (256 * 1024) 574#define LOG_BUFFER_MIN_SIZE (64 * 1024UL) 575#define LOG_BUFFER_MAX_SIZE (256 * 1024 * 1024UL) 576 577static bool valid_size(unsigned long value) { 578 if ((value < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < value)) { 579 return false; 580 } 581 582 long pages = sysconf(_SC_PHYS_PAGES); 583 if (pages < 1) { 584 return true; 585 } 586 587 long pagesize = sysconf(_SC_PAGESIZE); 588 if (pagesize <= 1) { 589 pagesize = PAGE_SIZE; 590 } 591 592 // maximum memory impact a somewhat arbitrary ~3% 593 pages = (pages + 31) / 32; 594 unsigned long maximum = pages * pagesize; 595 596 if ((maximum < LOG_BUFFER_MIN_SIZE) || (LOG_BUFFER_MAX_SIZE < maximum)) { 597 return true; 598 } 599 600 return value <= maximum; 601} 602 603static unsigned long property_get_size(const char *key) { 604 unsigned long value; 605 char *cp, property[PROPERTY_VALUE_MAX]; 606 607 property_get(key, property, ""); 608 value = strtoul(property, &cp, 10); 609 610 switch(*cp) { 611 case 'm': 612 case 'M': 613 value *= 1024; 614 /* FALLTHRU */ 615 case 'k': 616 case 'K': 617 value *= 1024; 618 /* FALLTHRU */ 619 case '\0': 620 break; 621 622 default: 623 value = 0; 624 } 625 626 if (!valid_size(value)) { 627 value = 0; 628 } 629 630 return value; 631} 632 633/* timeout in ms */ 634static unsigned long logcat_timeout(const char *name) { 635 static const char global_tuneable[] = "persist.logd.size"; // Settings App 636 static const char global_default[] = "ro.logd.size"; // BoardConfig.mk 637 char key[PROP_NAME_MAX]; 638 unsigned long property_size, default_size; 639 640 default_size = property_get_size(global_tuneable); 641 if (!default_size) { 642 default_size = property_get_size(global_default); 643 } 644 645 snprintf(key, sizeof(key), "%s.%s", global_tuneable, name); 646 property_size = property_get_size(key); 647 648 if (!property_size) { 649 snprintf(key, sizeof(key), "%s.%s", global_default, name); 650 property_size = property_get_size(key); 651 } 652 653 if (!property_size) { 654 property_size = default_size; 655 } 656 657 if (!property_size) { 658 property_size = LOG_BUFFER_SIZE; 659 } 660 661 /* Engineering margin is ten-fold our guess */ 662 return 10 * (property_size + worst_write_perf) / worst_write_perf; 663} 664 665/* End copy from system/core/logd/LogBuffer.cpp */ 666 667/* dumps the current system state to stdout */ 668static void print_header(std::string version) { 669 char build[PROPERTY_VALUE_MAX], fingerprint[PROPERTY_VALUE_MAX]; 670 char radio[PROPERTY_VALUE_MAX], bootloader[PROPERTY_VALUE_MAX]; 671 char network[PROPERTY_VALUE_MAX], date[80]; 672 673 property_get("ro.build.display.id", build, "(unknown)"); 674 property_get("ro.build.fingerprint", fingerprint, "(unknown)"); 675 property_get("ro.build.type", build_type, "(unknown)"); 676 property_get("gsm.version.baseband", radio, "(unknown)"); 677 property_get("ro.bootloader", bootloader, "(unknown)"); 678 property_get("gsm.operator.alpha", network, "(unknown)"); 679 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now)); 680 681 printf("========================================================\n"); 682 printf("== dumpstate: %s\n", date); 683 printf("========================================================\n"); 684 685 printf("\n"); 686 printf("Build: %s\n", build); 687 printf("Build fingerprint: '%s'\n", fingerprint); /* format is important for other tools */ 688 printf("Bootloader: %s\n", bootloader); 689 printf("Radio: %s\n", radio); 690 printf("Network: %s\n", network); 691 692 printf("Kernel: "); 693 dump_file(NULL, "/proc/version"); 694 printf("Command line: %s\n", strtok(cmdline_buf, "\n")); 695 printf("Bugreport format version: %s\n", version.c_str()); 696 printf("Dumpstate info: id=%lu pid=%d\n", id, getpid()); 697 printf("\n"); 698} 699 700// List of file extensions that can cause a zip file attachment to be rejected by some email 701// service providers. 702static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = { 703 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp", 704 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct", 705 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh" 706}; 707 708bool add_zip_entry_from_fd(const std::string& entry_name, int fd) { 709 if (!zip_writer) { 710 MYLOGD("Not adding zip entry %s from fd because zip_writer is not set\n", 711 entry_name.c_str()); 712 return false; 713 } 714 std::string valid_name = entry_name; 715 716 // Rename extension if necessary. 717 size_t idx = entry_name.rfind("."); 718 if (idx != std::string::npos) { 719 std::string extension = entry_name.substr(idx); 720 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); 721 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) { 722 valid_name = entry_name + ".renamed"; 723 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str()); 724 } 725 } 726 727 // Logging statement below is useful to time how long each entry takes, but it's too verbose. 728 // MYLOGD("Adding zip entry %s\n", entry_name.c_str()); 729 int32_t err = zip_writer->StartEntryWithTime(valid_name.c_str(), 730 ZipWriter::kCompress, get_mtime(fd, now)); 731 if (err) { 732 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", valid_name.c_str(), 733 ZipWriter::ErrorCodeString(err)); 734 return false; 735 } 736 737 std::vector<uint8_t> buffer(65536); 738 while (1) { 739 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), sizeof(buffer))); 740 if (bytes_read == 0) { 741 break; 742 } else if (bytes_read == -1) { 743 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno)); 744 return false; 745 } 746 err = zip_writer->WriteBytes(buffer.data(), bytes_read); 747 if (err) { 748 MYLOGE("zip_writer->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err)); 749 return false; 750 } 751 } 752 753 err = zip_writer->FinishEntry(); 754 if (err) { 755 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 756 return false; 757 } 758 759 return true; 760} 761 762bool add_zip_entry(const std::string& entry_name, const std::string& entry_path) { 763 ScopedFd fd(TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC))); 764 if (fd.get() == -1) { 765 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno)); 766 return false; 767 } 768 769 return add_zip_entry_from_fd(entry_name, fd.get()); 770} 771 772/* adds a file to the existing zipped bugreport */ 773static int _add_file_from_fd(const char *title, const char *path, int fd) { 774 return add_zip_entry_from_fd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; 775} 776 777// TODO: move to util.cpp 778void add_dir(const char *dir, bool recursive) { 779 if (!zip_writer) { 780 MYLOGD("Not adding dir %s because zip_writer is not set\n", dir); 781 return; 782 } 783 MYLOGD("Adding dir %s (recursive: %d)\n", dir, recursive); 784 DurationReporter duration_reporter(dir, NULL); 785 dump_files(NULL, dir, recursive ? skip_none : is_dir, _add_file_from_fd); 786} 787 788/* adds a text entry entry to the existing zip file. */ 789static bool add_text_zip_entry(const std::string& entry_name, const std::string& content) { 790 if (!zip_writer) { 791 MYLOGD("Not adding text zip entry %s because zip_writer is not set\n", entry_name.c_str()); 792 return false; 793 } 794 MYLOGD("Adding zip text entry %s\n", entry_name.c_str()); 795 int32_t err = zip_writer->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, now); 796 if (err) { 797 MYLOGE("zip_writer->StartEntryWithTime(%s): %s\n", entry_name.c_str(), 798 ZipWriter::ErrorCodeString(err)); 799 return false; 800 } 801 802 err = zip_writer->WriteBytes(content.c_str(), content.length()); 803 if (err) { 804 MYLOGE("zip_writer->WriteBytes(%s): %s\n", entry_name.c_str(), 805 ZipWriter::ErrorCodeString(err)); 806 return false; 807 } 808 809 err = zip_writer->FinishEntry(); 810 if (err) { 811 MYLOGE("zip_writer->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 812 return false; 813 } 814 815 return true; 816} 817 818static void dump_iptables() { 819 run_command("IPTABLES", 10, "iptables", "-L", "-nvx", NULL); 820 run_command("IP6TABLES", 10, "ip6tables", "-L", "-nvx", NULL); 821 run_command("IPTABLE NAT", 10, "iptables", "-t", "nat", "-L", "-nvx", NULL); 822 /* no ip6 nat */ 823 run_command("IPTABLE MANGLE", 10, "iptables", "-t", "mangle", "-L", "-nvx", NULL); 824 run_command("IP6TABLE MANGLE", 10, "ip6tables", "-t", "mangle", "-L", "-nvx", NULL); 825 run_command("IPTABLE RAW", 10, "iptables", "-t", "raw", "-L", "-nvx", NULL); 826 run_command("IP6TABLE RAW", 10, "ip6tables", "-t", "raw", "-L", "-nvx", NULL); 827} 828 829static void dumpstate(const std::string& screenshot_path, const std::string& version) { 830 DurationReporter duration_reporter("DUMPSTATE"); 831 unsigned long timeout; 832 833 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); 834 run_command("UPTIME", 10, "uptime", NULL); 835 dump_files("UPTIME MMC PERF", mmcblk0, skip_not_stat, dump_stat_from_fd); 836 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd"); 837 dump_file("MEMORY INFO", "/proc/meminfo"); 838 run_command("CPU INFO", 10, "top", "-n", "1", "-d", "1", "-m", "30", "-H", NULL); 839 run_command("PROCRANK", 20, SU_PATH, "root", "procrank", NULL); 840 dump_file("VIRTUAL MEMORY STATS", "/proc/vmstat"); 841 dump_file("VMALLOC INFO", "/proc/vmallocinfo"); 842 dump_file("SLAB INFO", "/proc/slabinfo"); 843 dump_file("ZONEINFO", "/proc/zoneinfo"); 844 dump_file("PAGETYPEINFO", "/proc/pagetypeinfo"); 845 dump_file("BUDDYINFO", "/proc/buddyinfo"); 846 dump_file("FRAGMENTATION INFO", "/d/extfrag/unusable_index"); 847 848 dump_file("KERNEL WAKE SOURCES", "/d/wakeup_sources"); 849 dump_file("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); 850 dump_file("KERNEL SYNC", "/d/sync"); 851 852 run_command("PROCESSES AND THREADS", 10, "ps", "-Z", "-t", "-p", "-P", NULL); 853 run_command("LIBRANK", 10, SU_PATH, "root", "librank", NULL); 854 855 run_command("PRINTENV", 10, "printenv", NULL); 856 run_command("NETSTAT", 10, "netstat", "-n", NULL); 857 run_command("LSMOD", 10, "lsmod", NULL); 858 859 do_dmesg(); 860 861 run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL); 862 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES"); 863 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); 864 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); 865 866 if (!screenshot_path.empty()) { 867 MYLOGI("taking late screenshot\n"); 868 take_screenshot(screenshot_path); 869 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str()); 870 } 871 872 // dump_file("EVENT LOG TAGS", "/etc/event-log-tags"); 873 // calculate timeout 874 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash"); 875 if (timeout < 20000) { 876 timeout = 20000; 877 } 878 run_command("SYSTEM LOG", timeout / 1000, "logcat", "-v", "threadtime", 879 "-v", "printable", 880 "-d", 881 "*:v", NULL); 882 timeout = logcat_timeout("events"); 883 if (timeout < 20000) { 884 timeout = 20000; 885 } 886 run_command("EVENT LOG", timeout / 1000, "logcat", "-b", "events", 887 "-v", "threadtime", 888 "-v", "printable", 889 "-d", 890 "*:v", NULL); 891 timeout = logcat_timeout("radio"); 892 if (timeout < 20000) { 893 timeout = 20000; 894 } 895 run_command("RADIO LOG", timeout / 1000, "logcat", "-b", "radio", 896 "-v", "threadtime", 897 "-v", "printable", 898 "-d", 899 "*:v", NULL); 900 901 run_command("LOG STATISTICS", 10, "logcat", "-b", "all", "-S", NULL); 902 903 /* show the traces we collected in main(), if that was done */ 904 if (dump_traces_path != NULL) { 905 dump_file("VM TRACES JUST NOW", dump_traces_path); 906 } 907 908 /* only show ANR traces if they're less than 15 minutes old */ 909 struct stat st; 910 char anr_traces_path[PATH_MAX]; 911 property_get("dalvik.vm.stack-trace-file", anr_traces_path, ""); 912 if (!anr_traces_path[0]) { 913 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); 914 } else { 915 int fd = TEMP_FAILURE_RETRY(open(anr_traces_path, 916 O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); 917 if (fd < 0) { 918 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_path, strerror(errno)); 919 } else { 920 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_path, fd); 921 } 922 } 923 924 /* slow traces for slow operations */ 925 if (anr_traces_path[0] != 0) { 926 int tail = strlen(anr_traces_path)-1; 927 while (tail > 0 && anr_traces_path[tail] != '/') { 928 tail--; 929 } 930 int i = 0; 931 while (1) { 932 sprintf(anr_traces_path+tail+1, "slow%02d.txt", i); 933 if (stat(anr_traces_path, &st)) { 934 // No traces file at this index, done with the files. 935 break; 936 } 937 dump_file("VM TRACES WHEN SLOW", anr_traces_path); 938 i++; 939 } 940 } 941 942 int dumped = 0; 943 for (size_t i = 0; i < NUM_TOMBSTONES; i++) { 944 if (tombstone_data[i].fd != -1) { 945 const char *name = tombstone_data[i].name; 946 int fd = tombstone_data[i].fd; 947 dumped = 1; 948 if (zip_writer) { 949 if (!add_zip_entry_from_fd(ZIP_ROOT_DIR + name, fd)) { 950 MYLOGE("Unable to add tombstone %s to zip file\n", name); 951 } 952 } else { 953 dump_file_from_fd("TOMBSTONE", name, fd); 954 } 955 close(fd); 956 tombstone_data[i].fd = -1; 957 } 958 } 959 if (!dumped) { 960 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR); 961 } 962 963 dump_file("NETWORK DEV INFO", "/proc/net/dev"); 964 dump_file("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all"); 965 dump_file("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt"); 966 dump_file("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl"); 967 dump_file("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats"); 968 969 if (!stat(PSTORE_LAST_KMSG, &st)) { 970 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */ 971 dump_file("LAST KMSG", PSTORE_LAST_KMSG); 972 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) { 973 dump_file("LAST KMSG", ALT_PSTORE_LAST_KMSG); 974 } else { 975 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ 976 dump_file("LAST KMSG", "/proc/last_kmsg"); 977 } 978 979 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */ 980 run_command("LAST LOGCAT", 10, "logcat", "-L", 981 "-b", "all", 982 "-v", "threadtime", 983 "-v", "printable", 984 "-d", 985 "*:v", NULL); 986 987 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */ 988 989 run_command("NETWORK INTERFACES", 10, "ip", "link", NULL); 990 991 run_command("IPv4 ADDRESSES", 10, "ip", "-4", "addr", "show", NULL); 992 run_command("IPv6 ADDRESSES", 10, "ip", "-6", "addr", "show", NULL); 993 994 run_command("IP RULES", 10, "ip", "rule", "show", NULL); 995 run_command("IP RULES v6", 10, "ip", "-6", "rule", "show", NULL); 996 997 dump_route_tables(); 998 999 run_command("ARP CACHE", 10, "ip", "-4", "neigh", "show", NULL); 1000 run_command("IPv6 ND CACHE", 10, "ip", "-6", "neigh", "show", NULL); 1001 run_command("MULTICAST ADDRESSES", 10, "ip", "maddr", NULL); 1002 run_command("WIFI NETWORKS", 20, "wpa_cli", "IFNAME=wlan0", "list_networks", NULL); 1003 1004#ifdef FWDUMP_bcmdhd 1005 run_command("ND OFFLOAD TABLE", 5, 1006 SU_PATH, "root", WLUTIL, "nd_hostip", NULL); 1007 1008 run_command("DUMP WIFI INTERNAL COUNTERS (1)", 20, 1009 SU_PATH, "root", WLUTIL, "counters", NULL); 1010 1011 run_command("ND OFFLOAD STATUS (1)", 5, 1012 SU_PATH, "root", WLUTIL, "nd_status", NULL); 1013 1014#endif 1015 dump_file("INTERRUPTS (1)", "/proc/interrupts"); 1016 1017 run_command("NETWORK DIAGNOSTICS", 10, "dumpsys", "-t", "10", "connectivity", "--diag", NULL); 1018 1019#ifdef FWDUMP_bcmdhd 1020 run_command("DUMP WIFI STATUS", 20, 1021 SU_PATH, "root", "dhdutil", "-i", "wlan0", "dump", NULL); 1022 1023 run_command("DUMP WIFI INTERNAL COUNTERS (2)", 20, 1024 SU_PATH, "root", WLUTIL, "counters", NULL); 1025 1026 run_command("ND OFFLOAD STATUS (2)", 5, 1027 SU_PATH, "root", WLUTIL, "nd_status", NULL); 1028#endif 1029 dump_file("INTERRUPTS (2)", "/proc/interrupts"); 1030 1031 print_properties(); 1032 1033 run_command("VOLD DUMP", 10, "vdc", "dump", NULL); 1034 run_command("SECURE CONTAINERS", 10, "vdc", "asec", "list", NULL); 1035 1036 run_command("FILESYSTEMS & FREE SPACE", 10, "df", NULL); 1037 1038 run_command("LAST RADIO LOG", 10, "parse_radio_log", "/proc/last_radio_log", NULL); 1039 1040 printf("------ BACKLIGHTS ------\n"); 1041 printf("LCD brightness="); 1042 dump_file(NULL, "/sys/class/leds/lcd-backlight/brightness"); 1043 printf("Button brightness="); 1044 dump_file(NULL, "/sys/class/leds/button-backlight/brightness"); 1045 printf("Keyboard brightness="); 1046 dump_file(NULL, "/sys/class/leds/keyboard-backlight/brightness"); 1047 printf("ALS mode="); 1048 dump_file(NULL, "/sys/class/leds/lcd-backlight/als"); 1049 printf("LCD driver registers:\n"); 1050 dump_file(NULL, "/sys/class/leds/lcd-backlight/registers"); 1051 printf("\n"); 1052 1053 /* Binder state is expensive to look at as it uses a lot of memory. */ 1054 dump_file("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log"); 1055 dump_file("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log"); 1056 dump_file("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions"); 1057 dump_file("BINDER STATS", "/sys/kernel/debug/binder/stats"); 1058 dump_file("BINDER STATE", "/sys/kernel/debug/binder/state"); 1059 1060 printf("========================================================\n"); 1061 printf("== Board\n"); 1062 printf("========================================================\n"); 1063 1064 dumpstate_board(); 1065 printf("\n"); 1066 1067 /* Migrate the ril_dumpstate to a dumpstate_board()? */ 1068 char ril_dumpstate_timeout[PROPERTY_VALUE_MAX] = {0}; 1069 property_get("ril.dumpstate.timeout", ril_dumpstate_timeout, "30"); 1070 if (strnlen(ril_dumpstate_timeout, PROPERTY_VALUE_MAX - 1) > 0) { 1071 if (is_user_build()) { 1072 // su does not exist on user builds, so try running without it. 1073 // This way any implementations of vril-dump that do not require 1074 // root can run on user builds. 1075 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout), 1076 "vril-dump", NULL); 1077 } else { 1078 run_command("DUMP VENDOR RIL LOGS", atoi(ril_dumpstate_timeout), 1079 SU_PATH, "root", "vril-dump", NULL); 1080 } 1081 } 1082 1083 printf("========================================================\n"); 1084 printf("== Android Framework Services\n"); 1085 printf("========================================================\n"); 1086 1087 run_command("DUMPSYS", 60, "dumpsys", "-t", "60", "--skip", "meminfo", "cpuinfo", NULL); 1088 1089 printf("========================================================\n"); 1090 printf("== Checkins\n"); 1091 printf("========================================================\n"); 1092 1093 run_command("CHECKIN BATTERYSTATS", 30, "dumpsys", "-t", "30", "batterystats", "-c", NULL); 1094 run_command("CHECKIN MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "--checkin", NULL); 1095 run_command("CHECKIN NETSTATS", 30, "dumpsys", "-t", "30", "netstats", "--checkin", NULL); 1096 run_command("CHECKIN PROCSTATS", 30, "dumpsys", "-t", "30", "procstats", "-c", NULL); 1097 run_command("CHECKIN USAGESTATS", 30, "dumpsys", "-t", "30", "usagestats", "-c", NULL); 1098 run_command("CHECKIN PACKAGE", 30, "dumpsys", "-t", "30", "package", "--checkin", NULL); 1099 1100 printf("========================================================\n"); 1101 printf("== Running Application Activities\n"); 1102 printf("========================================================\n"); 1103 1104 run_command("APP ACTIVITIES", 30, "dumpsys", "-t", "30", "activity", "all", NULL); 1105 1106 printf("========================================================\n"); 1107 printf("== Running Application Services\n"); 1108 printf("========================================================\n"); 1109 1110 run_command("APP SERVICES", 30, "dumpsys", "-t", "30", "activity", "service", "all", NULL); 1111 1112 printf("========================================================\n"); 1113 printf("== Running Application Providers\n"); 1114 printf("========================================================\n"); 1115 1116 run_command("APP PROVIDERS", 30, "dumpsys", "-t", "30", "activity", "provider", "all", NULL); 1117 1118 1119 printf("========================================================\n"); 1120 printf("== Final progress (pid %d): %d/%d (originally %d)\n", 1121 getpid(), progress, weight_total, WEIGHT_TOTAL); 1122 printf("========================================================\n"); 1123 printf("== dumpstate: done\n"); 1124 printf("========================================================\n"); 1125} 1126 1127static void usage() { 1128 fprintf(stderr, 1129 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file [-d] [-p] " 1130 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n" 1131 " -h: display this help message\n" 1132 " -b: play sound file instead of vibrate, at beginning of job\n" 1133 " -e: play sound file instead of vibrate, at end of job\n" 1134 " -o: write to file (instead of stdout)\n" 1135 " -d: append date to filename (requires -o)\n" 1136 " -p: capture screenshot to filename.png (requires -o)\n" 1137 " -z: generate zipped file (requires -o)\n" 1138 " -s: write output to control socket (for init)\n" 1139 " -S: write file location to control socket (for init; requires -o and -z)" 1140 " -q: disable vibrate\n" 1141 " -B: send broadcast when finished (requires -o)\n" 1142 " -P: send broadcast when started and update system properties on " 1143 "progress (requires -o and -B)\n" 1144 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " 1145 "shouldn't be used with -P)\n" 1146 " -V: sets the bugreport format version (valid values: %s)\n", 1147 VERSION_DEFAULT.c_str()); 1148} 1149 1150static void sigpipe_handler(int n) { 1151 // don't complain to stderr or stdout 1152 _exit(EXIT_FAILURE); 1153} 1154 1155/* adds the temporary report to the existing .zip file, closes the .zip file, and removes the 1156 temporary file. 1157 */ 1158static bool finish_zip_file(const std::string& bugreport_name, const std::string& bugreport_path, 1159 time_t now) { 1160 if (!add_zip_entry(bugreport_name, bugreport_path)) { 1161 MYLOGE("Failed to add text entry to .zip file\n"); 1162 return false; 1163 } 1164 if (!add_text_zip_entry("main_entry.txt", bugreport_name)) { 1165 MYLOGE("Failed to add main_entry.txt to .zip file\n"); 1166 return false; 1167 } 1168 1169 int32_t err = zip_writer->Finish(); 1170 if (err) { 1171 MYLOGE("zip_writer->Finish(): %s\n", ZipWriter::ErrorCodeString(err)); 1172 return false; 1173 } 1174 1175 if (is_user_build()) { 1176 MYLOGD("Removing temporary file %s\n", bugreport_path.c_str()) 1177 if (remove(bugreport_path.c_str())) { 1178 ALOGW("remove(%s): %s\n", bugreport_path.c_str(), strerror(errno)); 1179 } 1180 } else { 1181 MYLOGD("Keeping temporary file %s on non-user build\n", bugreport_path.c_str()) 1182 } 1183 1184 return true; 1185} 1186 1187static std::string SHA256_file_hash(std::string filepath) { 1188 ScopedFd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC 1189 | O_NOFOLLOW))); 1190 if (fd.get() == -1) { 1191 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno)); 1192 return NULL; 1193 } 1194 1195 SHA256_CTX ctx; 1196 SHA256_init(&ctx); 1197 1198 std::vector<uint8_t> buffer(65536); 1199 while (1) { 1200 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size())); 1201 if (bytes_read == 0) { 1202 break; 1203 } else if (bytes_read == -1) { 1204 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno)); 1205 return NULL; 1206 } 1207 1208 SHA256_update(&ctx, buffer.data(), bytes_read); 1209 } 1210 1211 uint8_t hash[SHA256_DIGEST_SIZE]; 1212 memcpy(hash, SHA256_final(&ctx), SHA256_DIGEST_SIZE); 1213 char hash_buffer[SHA256_DIGEST_SIZE * 2 + 1]; 1214 for(size_t i = 0; i < SHA256_DIGEST_SIZE; i++) { 1215 sprintf(hash_buffer + (i * 2), "%02x", hash[i]); 1216 } 1217 hash_buffer[sizeof(hash_buffer) - 1] = 0; 1218 return std::string(hash_buffer); 1219} 1220 1221int main(int argc, char *argv[]) { 1222 struct sigaction sigact; 1223 int do_add_date = 0; 1224 int do_zip_file = 0; 1225 int do_vibrate = 1; 1226 char* use_outfile = 0; 1227 int use_socket = 0; 1228 int use_control_socket = 0; 1229 int do_fb = 0; 1230 int do_broadcast = 0; 1231 int do_early_screenshot = 0; 1232 int is_remote_mode = 0; 1233 std::string version = VERSION_DEFAULT; 1234 1235 now = time(NULL); 1236 1237 MYLOGI("begin\n"); 1238 1239 /* gets the sequential id */ 1240 char last_id[PROPERTY_VALUE_MAX]; 1241 property_get("dumpstate.last_id", last_id, "0"); 1242 id = strtoul(last_id, NULL, 10) + 1; 1243 snprintf(last_id, sizeof(last_id), "%lu", id); 1244 property_set("dumpstate.last_id", last_id); 1245 MYLOGI("dumpstate id: %lu\n", id); 1246 1247 /* clear SIGPIPE handler */ 1248 memset(&sigact, 0, sizeof(sigact)); 1249 sigact.sa_handler = sigpipe_handler; 1250 sigaction(SIGPIPE, &sigact, NULL); 1251 1252 /* set as high priority, and protect from OOM killer */ 1253 setpriority(PRIO_PROCESS, 0, -20); 1254 1255 FILE *oom_adj = fopen("/proc/self/oom_score_adj", "we"); 1256 if (oom_adj) { 1257 fputs("-1000", oom_adj); 1258 fclose(oom_adj); 1259 } else { 1260 /* fallback to kernels <= 2.6.35 */ 1261 oom_adj = fopen("/proc/self/oom_adj", "we"); 1262 if (oom_adj) { 1263 fputs("-17", oom_adj); 1264 fclose(oom_adj); 1265 } 1266 } 1267 1268 /* parse arguments */ 1269 std::string args; 1270 format_args(argc, const_cast<const char **>(argv), &args); 1271 MYLOGD("Dumpstate command line: %s\n", args.c_str()); 1272 int c; 1273 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) { 1274 switch (c) { 1275 case 'd': do_add_date = 1; break; 1276 case 'z': do_zip_file = 1; break; 1277 case 'o': use_outfile = optarg; break; 1278 case 's': use_socket = 1; break; 1279 case 'S': use_control_socket = 1; break; 1280 case 'v': break; // compatibility no-op 1281 case 'q': do_vibrate = 0; break; 1282 case 'p': do_fb = 1; break; 1283 case 'P': do_update_progress = 1; break; 1284 case 'R': is_remote_mode = 1; break; 1285 case 'B': do_broadcast = 1; break; 1286 case 'V': version = optarg; break; 1287 case '?': printf("\n"); 1288 case 'h': 1289 usage(); 1290 exit(1); 1291 } 1292 } 1293 1294 if ((do_zip_file || do_add_date || do_update_progress || do_broadcast) && !use_outfile) { 1295 usage(); 1296 exit(1); 1297 } 1298 1299 if (use_control_socket && !do_zip_file) { 1300 usage(); 1301 exit(1); 1302 } 1303 1304 if (do_update_progress && !do_broadcast) { 1305 usage(); 1306 exit(1); 1307 } 1308 1309 if (is_remote_mode && (do_update_progress || !do_broadcast || !do_zip_file || !do_add_date)) { 1310 usage(); 1311 exit(1); 1312 } 1313 1314 if (version != VERSION_DEFAULT) { 1315 usage(); 1316 exit(1); 1317 } 1318 1319 MYLOGI("bugreport format version: %s\n", version.c_str()); 1320 1321 do_early_screenshot = do_update_progress; 1322 1323 // If we are going to use a socket, do it as early as possible 1324 // to avoid timeouts from bugreport. 1325 if (use_socket) { 1326 redirect_to_socket(stdout, "dumpstate"); 1327 } 1328 1329 if (use_control_socket) { 1330 MYLOGD("Opening control socket\n"); 1331 control_socket_fd = open_socket("dumpstate"); 1332 do_update_progress = 1; 1333 } 1334 1335 /* full path of the temporary file containing the bugreport */ 1336 std::string tmp_path; 1337 1338 /* full path of the file containing the dumpstate logs*/ 1339 std::string log_path; 1340 1341 /* full path of the systrace file, when enabled */ 1342 std::string systrace_path; 1343 1344 /* full path of the temporary file containing the screenshot (when requested) */ 1345 std::string screenshot_path; 1346 1347 /* base name (without suffix or extensions) of the bugreport files */ 1348 std::string base_name; 1349 1350 /* pointer to the actual path, be it zip or text */ 1351 std::string path; 1352 1353 /* pointer to the zipped file */ 1354 std::unique_ptr<FILE, int(*)(FILE*)> zip_file(NULL, fclose); 1355 1356 /* redirect output if needed */ 1357 bool is_redirecting = !use_socket && use_outfile; 1358 1359 if (is_redirecting) { 1360 bugreport_dir = dirname(use_outfile); 1361 base_name = basename(use_outfile); 1362 if (do_add_date) { 1363 char date[80]; 1364 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&now)); 1365 suffix = date; 1366 } else { 1367 suffix = "undated"; 1368 } 1369 char build_id[PROPERTY_VALUE_MAX]; 1370 property_get("ro.build.id", build_id, "UNKNOWN_BUILD"); 1371 base_name = base_name + "-" + build_id; 1372 if (do_fb) { 1373 // TODO: if dumpstate was an object, the paths could be internal variables and then 1374 // we could have a function to calculate the derived values, such as: 1375 // screenshot_path = GetPath(".png"); 1376 screenshot_path = bugreport_dir + "/" + base_name + "-" + suffix + ".png"; 1377 } 1378 tmp_path = bugreport_dir + "/" + base_name + "-" + suffix + ".tmp"; 1379 log_path = bugreport_dir + "/dumpstate_log-" + suffix + "-" 1380 + std::to_string(getpid()) + ".txt"; 1381 1382 MYLOGD("Bugreport dir: %s\n" 1383 "Base name: %s\n" 1384 "Suffix: %s\n" 1385 "Log path: %s\n" 1386 "Temporary path: %s\n" 1387 "Screenshot path: %s\n", 1388 bugreport_dir.c_str(), base_name.c_str(), suffix.c_str(), 1389 log_path.c_str(), tmp_path.c_str(), screenshot_path.c_str()); 1390 1391 if (do_zip_file) { 1392 path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip"; 1393 MYLOGD("Creating initial .zip file (%s)\n", path.c_str()); 1394 create_parent_dirs(path.c_str()); 1395 zip_file.reset(fopen(path.c_str(), "wb")); 1396 if (!zip_file) { 1397 MYLOGE("fopen(%s, 'wb'): %s\n", path.c_str(), strerror(errno)); 1398 do_zip_file = 0; 1399 } else { 1400 zip_writer.reset(new ZipWriter(zip_file.get())); 1401 } 1402 add_text_zip_entry("version.txt", version); 1403 } 1404 1405 if (do_update_progress) { 1406 if (do_broadcast) { 1407 // clang-format off 1408 std::vector<std::string> am_args = { 1409 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground", 1410 "--es", "android.intent.extra.NAME", suffix, 1411 "--ei", "android.intent.extra.ID", std::to_string(id), 1412 "--ei", "android.intent.extra.PID", std::to_string(getpid()), 1413 "--ei", "android.intent.extra.MAX", std::to_string(WEIGHT_TOTAL), 1414 }; 1415 // clang-format on 1416 send_broadcast("android.intent.action.BUGREPORT_STARTED", am_args); 1417 } 1418 if (use_control_socket) { 1419 dprintf(control_socket_fd, "BEGIN:%s\n", path.c_str()); 1420 } 1421 } 1422 } 1423 1424 /* read /proc/cmdline before dropping root */ 1425 FILE *cmdline = fopen("/proc/cmdline", "re"); 1426 if (cmdline) { 1427 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline); 1428 fclose(cmdline); 1429 } 1430 1431 /* open the vibrator before dropping root */ 1432 std::unique_ptr<FILE, int(*)(FILE*)> vibrator(NULL, fclose); 1433 if (do_vibrate) { 1434 vibrator.reset(fopen("/sys/class/timed_output/vibrator/enable", "we")); 1435 if (vibrator) { 1436 vibrate(vibrator.get(), 150); 1437 } 1438 } 1439 1440 if (do_fb && do_early_screenshot) { 1441 if (screenshot_path.empty()) { 1442 // should not have happened 1443 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); 1444 } else { 1445 MYLOGI("taking early screenshot\n"); 1446 take_screenshot(screenshot_path); 1447 MYLOGI("wrote screenshot: %s\n", screenshot_path.c_str()); 1448 if (chown(screenshot_path.c_str(), AID_SHELL, AID_SHELL)) { 1449 MYLOGE("Unable to change ownership of screenshot file %s: %s\n", 1450 screenshot_path.c_str(), strerror(errno)); 1451 } 1452 } 1453 } 1454 1455 if (do_zip_file) { 1456 if (chown(path.c_str(), AID_SHELL, AID_SHELL)) { 1457 MYLOGE("Unable to change ownership of zip file %s: %s\n", path.c_str(), strerror(errno)); 1458 } 1459 } 1460 1461 if (is_redirecting) { 1462 redirect_to_file(stderr, const_cast<char*>(log_path.c_str())); 1463 if (chown(log_path.c_str(), AID_SHELL, AID_SHELL)) { 1464 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", 1465 log_path.c_str(), strerror(errno)); 1466 } 1467 /* TODO: rather than generating a text file now and zipping it later, 1468 it would be more efficient to redirect stdout to the zip entry 1469 directly, but the libziparchive doesn't support that option yet. */ 1470 redirect_to_file(stdout, const_cast<char*>(tmp_path.c_str())); 1471 if (chown(tmp_path.c_str(), AID_SHELL, AID_SHELL)) { 1472 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n", 1473 tmp_path.c_str(), strerror(errno)); 1474 } 1475 } 1476 // NOTE: there should be no stdout output until now, otherwise it would break the header. 1477 // In particular, DurationReport objects should be created passing 'title, NULL', so their 1478 // duration is logged into MYLOG instead. 1479 print_header(version); 1480 1481 // Dumps systrace right away, otherwise it will be filled with unnecessary events. 1482 // First try to dump anrd trace if the daemon is running. Otherwise, dump 1483 // the raw trace. 1484 if (!dump_anrd_trace()) { 1485 dump_systrace(); 1486 } 1487 1488 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed. 1489 dump_raft(); 1490 1491 // Invoking the following dumpsys calls before dump_traces() to try and 1492 // keep the system stats as close to its initial state as possible. 1493 run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "-t", "30", "meminfo", "-a", NULL); 1494 run_command_as_shell("DUMPSYS CPUINFO", 10, "dumpsys", "-t", "10", "cpuinfo", "-a", NULL); 1495 1496 /* collect stack traces from Dalvik and native processes (needs root) */ 1497 dump_traces_path = dump_traces(); 1498 1499 /* Run some operations that require root. */ 1500 get_tombstone_fds(tombstone_data); 1501 add_dir(RECOVERY_DIR, true); 1502 add_dir(RECOVERY_DATA_DIR, true); 1503 add_dir(LOGPERSIST_DATA_DIR, false); 1504 if (!is_user_build()) { 1505 add_dir(PROFILE_DATA_DIR_CUR, true); 1506 add_dir(PROFILE_DATA_DIR_REF, true); 1507 } 1508 add_mountinfo(); 1509 dump_iptables(); 1510 1511 if (!drop_root_user()) { 1512 return -1; 1513 } 1514 1515 dumpstate(do_early_screenshot ? "": screenshot_path, version); 1516 1517 /* close output if needed */ 1518 if (is_redirecting) { 1519 fclose(stdout); 1520 } 1521 1522 /* rename or zip the (now complete) .tmp file to its final location */ 1523 if (use_outfile) { 1524 1525 /* check if user changed the suffix using system properties */ 1526 char key[PROPERTY_KEY_MAX]; 1527 char value[PROPERTY_VALUE_MAX]; 1528 snprintf(key, sizeof(key), "dumpstate.%d.name", getpid()); 1529 property_get(key, value, ""); 1530 bool change_suffix= false; 1531 if (value[0]) { 1532 /* must whitelist which characters are allowed, otherwise it could cross directories */ 1533 std::regex valid_regex("^[-_a-zA-Z0-9]+$"); 1534 if (std::regex_match(value, valid_regex)) { 1535 change_suffix = true; 1536 } else { 1537 MYLOGE("invalid suffix provided by user: %s\n", value); 1538 } 1539 } 1540 if (change_suffix) { 1541 MYLOGI("changing suffix from %s to %s\n", suffix.c_str(), value); 1542 suffix = value; 1543 if (!screenshot_path.empty()) { 1544 std::string new_screenshot_path = 1545 bugreport_dir + "/" + base_name + "-" + suffix + ".png"; 1546 if (rename(screenshot_path.c_str(), new_screenshot_path.c_str())) { 1547 MYLOGE("rename(%s, %s): %s\n", screenshot_path.c_str(), 1548 new_screenshot_path.c_str(), strerror(errno)); 1549 } else { 1550 screenshot_path = new_screenshot_path; 1551 } 1552 } 1553 } 1554 1555 bool do_text_file = true; 1556 if (do_zip_file) { 1557 std::string entry_name = base_name + "-" + suffix + ".txt"; 1558 MYLOGD("Adding main entry (%s) to .zip bugreport\n", entry_name.c_str()); 1559 if (!finish_zip_file(entry_name, tmp_path, now)) { 1560 MYLOGE("Failed to finish zip file; sending text bugreport instead\n"); 1561 do_text_file = true; 1562 } else { 1563 do_text_file = false; 1564 // Since zip file is already created, it needs to be renamed. 1565 std::string new_path = bugreport_dir + "/" + base_name + "-" + suffix + ".zip"; 1566 if (path != new_path) { 1567 MYLOGD("Renaming zip file from %s to %s\n", path.c_str(), new_path.c_str()); 1568 if (rename(path.c_str(), new_path.c_str())) { 1569 MYLOGE("rename(%s, %s): %s\n", path.c_str(), 1570 new_path.c_str(), strerror(errno)); 1571 } else { 1572 path = new_path; 1573 } 1574 } 1575 } 1576 } 1577 if (do_text_file) { 1578 path = bugreport_dir + "/" + base_name + "-" + suffix + ".txt"; 1579 MYLOGD("Generating .txt bugreport at %s from %s\n", path.c_str(), tmp_path.c_str()); 1580 if (rename(tmp_path.c_str(), path.c_str())) { 1581 MYLOGE("rename(%s, %s): %s\n", tmp_path.c_str(), path.c_str(), strerror(errno)); 1582 path.clear(); 1583 } 1584 } 1585 if (use_control_socket) { 1586 if (do_text_file) { 1587 dprintf(control_socket_fd, "FAIL:could not create zip file, check %s " 1588 "for more details\n", log_path.c_str()); 1589 } else { 1590 dprintf(control_socket_fd, "OK:%s\n", path.c_str()); 1591 } 1592 } 1593 } 1594 1595 /* vibrate a few but shortly times to let user know it's finished */ 1596 if (vibrator) { 1597 for (int i = 0; i < 3; i++) { 1598 vibrate(vibrator.get(), 75); 1599 usleep((75 + 50) * 1000); 1600 } 1601 } 1602 1603 /* tell activity manager we're done */ 1604 if (do_broadcast) { 1605 if (!path.empty()) { 1606 MYLOGI("Final bugreport path: %s\n", path.c_str()); 1607 // clang-format off 1608 std::vector<std::string> am_args = { 1609 "--receiver-permission", "android.permission.DUMP", "--receiver-foreground", 1610 "--ei", "android.intent.extra.ID", std::to_string(id), 1611 "--ei", "android.intent.extra.PID", std::to_string(getpid()), 1612 "--ei", "android.intent.extra.MAX", std::to_string(weight_total), 1613 "--es", "android.intent.extra.BUGREPORT", path, 1614 "--es", "android.intent.extra.DUMPSTATE_LOG", log_path 1615 }; 1616 // clang-format on 1617 if (do_fb) { 1618 am_args.push_back("--es"); 1619 am_args.push_back("android.intent.extra.SCREENSHOT"); 1620 am_args.push_back(screenshot_path); 1621 } 1622 if (is_remote_mode) { 1623 am_args.push_back("--es"); 1624 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); 1625 am_args.push_back(SHA256_file_hash(path)); 1626 send_broadcast("android.intent.action.REMOTE_BUGREPORT_FINISHED", am_args); 1627 } else { 1628 send_broadcast("android.intent.action.BUGREPORT_FINISHED", am_args); 1629 } 1630 } else { 1631 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n"); 1632 } 1633 } 1634 1635 MYLOGD("Final progress: %d/%d (originally %d)\n", progress, weight_total, WEIGHT_TOTAL); 1636 MYLOGI("done\n"); 1637 1638 if (is_redirecting) { 1639 fclose(stderr); 1640 } 1641 1642 if (use_control_socket && control_socket_fd != -1) { 1643 MYLOGD("Closing control socket\n"); 1644 close(control_socket_fd); 1645 } 1646 1647 return 0; 1648} 1649