dumpstate.cpp revision 1dc1ef5af577d0cacc7b86a83d243d9750b0dd6d
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#define LOG_TAG "dumpstate" 18 19#include <dirent.h> 20#include <errno.h> 21#include <fcntl.h> 22#include <libgen.h> 23#include <limits.h> 24#include <stdbool.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <sys/prctl.h> 29#include <sys/resource.h> 30#include <sys/stat.h> 31#include <sys/time.h> 32#include <sys/wait.h> 33#include <unistd.h> 34#include <memory> 35#include <regex> 36#include <set> 37#include <string> 38#include <vector> 39 40#include <android-base/file.h> 41#include <android-base/properties.h> 42#include <android-base/stringprintf.h> 43#include <android-base/strings.h> 44#include <android-base/unique_fd.h> 45#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h> 46#include <cutils/native_handle.h> 47#include <cutils/properties.h> 48#include <openssl/sha.h> 49#include <private/android_filesystem_config.h> 50#include <private/android_logger.h> 51 52#include "DumpstateInternal.h" 53#include "DumpstateService.h" 54#include "dumpstate.h" 55 56using ::android::hardware::dumpstate::V1_0::IDumpstateDevice; 57 58// TODO: remove once moved to namespace 59using android::os::dumpstate::CommandOptions; 60using android::os::dumpstate::DumpFileToFd; 61using android::os::dumpstate::PropertiesHelper; 62using android::os::dumpstate::GetPidByName; 63 64/* read before root is shed */ 65static char cmdline_buf[16384] = "(unknown)"; 66static const char *dump_traces_path = NULL; 67 68// TODO: variables and functions below should be part of dumpstate object 69 70static std::set<std::string> mount_points; 71void add_mountinfo(); 72 73#define PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops" 74#define ALT_PSTORE_LAST_KMSG "/sys/fs/pstore/console-ramoops-0" 75#define BLK_DEV_SYS_DIR "/sys/block" 76 77#define RAFT_DIR "/data/misc/raft" 78#define RECOVERY_DIR "/cache/recovery" 79#define RECOVERY_DATA_DIR "/data/misc/recovery" 80#define LOGPERSIST_DATA_DIR "/data/misc/logd" 81#define PROFILE_DATA_DIR_CUR "/data/misc/profiles/cur" 82#define PROFILE_DATA_DIR_REF "/data/misc/profiles/ref" 83#define WLUTIL "/vendor/xbin/wlutil" 84 85// TODO(narayan): Since this information has to be kept in sync 86// with tombstoned, we should just put it in a common header. 87// 88// File: system/core/debuggerd/tombstoned/tombstoned.cpp 89static const std::string TOMBSTONE_DIR = "/data/tombstones/"; 90static const std::string TOMBSTONE_FILE_PREFIX = "tombstone_"; 91static const std::string ANR_DIR = "/data/anr/"; 92static const std::string ANR_FILE_PREFIX = "anr_"; 93 94struct DumpData { 95 std::string name; 96 int fd; 97 time_t mtime; 98}; 99 100static bool operator<(const DumpData& d1, const DumpData& d2) { 101 return d1.mtime > d2.mtime; 102} 103 104static std::unique_ptr<std::vector<DumpData>> tombstone_data; 105static std::unique_ptr<std::vector<DumpData>> anr_data; 106 107// TODO: temporary variables and functions used during C++ refactoring 108static Dumpstate& ds = Dumpstate::GetInstance(); 109static int RunCommand(const std::string& title, const std::vector<std::string>& fullCommand, 110 const CommandOptions& options = CommandOptions::DEFAULT) { 111 return ds.RunCommand(title, fullCommand, options); 112} 113static void RunDumpsys(const std::string& title, const std::vector<std::string>& dumpsysArgs, 114 const CommandOptions& options = Dumpstate::DEFAULT_DUMPSYS, 115 long dumpsysTimeout = 0) { 116 return ds.RunDumpsys(title, dumpsysArgs, options, dumpsysTimeout); 117} 118static int DumpFile(const std::string& title, const std::string& path) { 119 return ds.DumpFile(title, path); 120} 121 122// Relative directory (inside the zip) for all files copied as-is into the bugreport. 123static const std::string ZIP_ROOT_DIR = "FS"; 124 125// Must be hardcoded because dumpstate HAL implementation need SELinux access to it 126static const std::string kDumpstateBoardPath = "/bugreports/dumpstate_board.txt"; 127static const std::string kLsHalDebugPath = "/bugreports/dumpstate_lshal.txt"; 128 129static constexpr char PROPERTY_EXTRA_OPTIONS[] = "dumpstate.options"; 130static constexpr char PROPERTY_LAST_ID[] = "dumpstate.last_id"; 131static constexpr char PROPERTY_VERSION[] = "dumpstate.version"; 132static constexpr char PROPERTY_EXTRA_TITLE[] = "dumpstate.options.title"; 133static constexpr char PROPERTY_EXTRA_DESCRIPTION[] = "dumpstate.options.description"; 134 135static const CommandOptions AS_ROOT_20 = CommandOptions::WithTimeout(20).AsRoot().Build(); 136 137/* 138 * Returns a vector of dump fds under |dir_path| with a given |file_prefix|. 139 * The returned vector is sorted by the mtimes of the dumps. If |limit_by_mtime| 140 * is set, the vector only contains files that were written in the last 30 minutes. 141 */ 142static std::vector<DumpData>* GetDumpFds(const std::string& dir_path, 143 const std::string& file_prefix, 144 bool limit_by_mtime) { 145 const time_t thirty_minutes_ago = ds.now_ - 60 * 30; 146 147 std::unique_ptr<std::vector<DumpData>> dump_data(new std::vector<DumpData>()); 148 std::unique_ptr<DIR, decltype(&closedir)> dump_dir(opendir(dir_path.c_str()), closedir); 149 150 struct dirent* entry = nullptr; 151 while ((entry = readdir(dump_dir.get()))) { 152 if (entry->d_type != DT_REG) { 153 continue; 154 } 155 156 const std::string base_name(entry->d_name); 157 if (base_name.find(file_prefix) != 0) { 158 continue; 159 } 160 161 const std::string abs_path = dir_path + base_name; 162 android::base::unique_fd fd( 163 TEMP_FAILURE_RETRY(open(abs_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK))); 164 if (fd == -1) { 165 MYLOGW("Unable to open dump file: %s %s\n", abs_path.c_str(), strerror(errno)); 166 break; 167 } 168 169 struct stat st = {}; 170 if (fstat(fd, &st) == -1) { 171 MYLOGW("Unable to stat dump file: %s %s\n", abs_path.c_str(), strerror(errno)); 172 continue; 173 } 174 175 if (limit_by_mtime && st.st_mtime >= thirty_minutes_ago) { 176 MYLOGI("Excluding stale dump file: %s\n", abs_path.c_str()); 177 continue; 178 } 179 180 DumpData data = {.name = abs_path, .fd = fd.release(), .mtime = st.st_mtime}; 181 182 dump_data->push_back(data); 183 } 184 185 std::sort(dump_data->begin(), dump_data->end()); 186 187 return dump_data.release(); 188} 189 190static bool AddDumps(const std::vector<DumpData>::const_iterator start, 191 const std::vector<DumpData>::const_iterator end, 192 const char* type_name, const bool add_to_zip) { 193 bool dumped = false; 194 for (auto it = start; it != end; ++it) { 195 const std::string& name = it->name; 196 const int fd = it->fd; 197 dumped = true; 198 if (ds.IsZipping() && add_to_zip) { 199 if (!ds.AddZipEntryFromFd(ZIP_ROOT_DIR + name, fd)) { 200 MYLOGE("Unable to add %s %s to zip file\n", name.c_str(), type_name); 201 } 202 } else { 203 dump_file_from_fd(type_name, name.c_str(), fd); 204 } 205 206 close(fd); 207 } 208 209 return dumped; 210} 211 212// for_each_pid() callback to get mount info about a process. 213void do_mountinfo(int pid, const char* name __attribute__((unused))) { 214 char path[PATH_MAX]; 215 216 // Gets the the content of the /proc/PID/ns/mnt link, so only unique mount points 217 // are added. 218 snprintf(path, sizeof(path), "/proc/%d/ns/mnt", pid); 219 char linkname[PATH_MAX]; 220 ssize_t r = readlink(path, linkname, PATH_MAX); 221 if (r == -1) { 222 MYLOGE("Unable to read link for %s: %s\n", path, strerror(errno)); 223 return; 224 } 225 linkname[r] = '\0'; 226 227 if (mount_points.find(linkname) == mount_points.end()) { 228 // First time this mount point was found: add it 229 snprintf(path, sizeof(path), "/proc/%d/mountinfo", pid); 230 if (ds.AddZipEntry(ZIP_ROOT_DIR + path, path)) { 231 mount_points.insert(linkname); 232 } else { 233 MYLOGE("Unable to add mountinfo %s to zip file\n", path); 234 } 235 } 236} 237 238void add_mountinfo() { 239 if (!ds.IsZipping()) return; 240 std::string title = "MOUNT INFO"; 241 mount_points.clear(); 242 DurationReporter duration_reporter(title, true); 243 for_each_pid(do_mountinfo, nullptr); 244 MYLOGD("%s: %d entries added to zip file\n", title.c_str(), (int)mount_points.size()); 245} 246 247static void dump_dev_files(const char *title, const char *driverpath, const char *filename) 248{ 249 DIR *d; 250 struct dirent *de; 251 char path[PATH_MAX]; 252 253 d = opendir(driverpath); 254 if (d == NULL) { 255 return; 256 } 257 258 while ((de = readdir(d))) { 259 if (de->d_type != DT_LNK) { 260 continue; 261 } 262 snprintf(path, sizeof(path), "%s/%s/%s", driverpath, de->d_name, filename); 263 DumpFile(title, path); 264 } 265 266 closedir(d); 267} 268 269 270 271// dump anrd's trace and add to the zip file. 272// 1. check if anrd is running on this device. 273// 2. send a SIGUSR1 to its pid which will dump anrd's trace. 274// 3. wait until the trace generation completes and add to the zip file. 275static bool dump_anrd_trace() { 276 unsigned int pid; 277 char buf[50], path[PATH_MAX]; 278 struct dirent *trace; 279 struct stat st; 280 DIR *trace_dir; 281 int retry = 5; 282 long max_ctime = 0, old_mtime; 283 long long cur_size = 0; 284 const char *trace_path = "/data/misc/anrd/"; 285 286 if (!ds.IsZipping()) { 287 MYLOGE("Not dumping anrd trace because it's not a zipped bugreport\n"); 288 return false; 289 } 290 291 // find anrd's pid if it is running. 292 pid = GetPidByName("/system/xbin/anrd"); 293 294 if (pid > 0) { 295 if (stat(trace_path, &st) == 0) { 296 old_mtime = st.st_mtime; 297 } else { 298 MYLOGE("Failed to find: %s\n", trace_path); 299 return false; 300 } 301 302 // send SIGUSR1 to the anrd to generate a trace. 303 sprintf(buf, "%u", pid); 304 if (RunCommand("ANRD_DUMP", {"kill", "-SIGUSR1", buf}, 305 CommandOptions::WithTimeout(1).Build())) { 306 MYLOGE("anrd signal timed out. Please manually collect trace\n"); 307 return false; 308 } 309 310 while (retry-- > 0 && old_mtime == st.st_mtime) { 311 sleep(1); 312 stat(trace_path, &st); 313 } 314 315 if (retry < 0 && old_mtime == st.st_mtime) { 316 MYLOGE("Failed to stat %s or trace creation timeout\n", trace_path); 317 return false; 318 } 319 320 // identify the trace file by its creation time. 321 if (!(trace_dir = opendir(trace_path))) { 322 MYLOGE("Can't open trace file under %s\n", trace_path); 323 } 324 while ((trace = readdir(trace_dir))) { 325 if (strcmp(trace->d_name, ".") == 0 326 || strcmp(trace->d_name, "..") == 0) { 327 continue; 328 } 329 sprintf(path, "%s%s", trace_path, trace->d_name); 330 if (stat(path, &st) == 0) { 331 if (st.st_ctime > max_ctime) { 332 max_ctime = st.st_ctime; 333 sprintf(buf, "%s", trace->d_name); 334 } 335 } 336 } 337 closedir(trace_dir); 338 339 // Wait until the dump completes by checking the size of the trace. 340 if (max_ctime > 0) { 341 sprintf(path, "%s%s", trace_path, buf); 342 while(true) { 343 sleep(1); 344 if (stat(path, &st) == 0) { 345 if (st.st_size == cur_size) { 346 break; 347 } else if (st.st_size > cur_size) { 348 cur_size = st.st_size; 349 } else { 350 return false; 351 } 352 } else { 353 MYLOGE("Cant stat() %s anymore\n", path); 354 return false; 355 } 356 } 357 // Add to the zip file. 358 if (!ds.AddZipEntry("anrd_trace.txt", path)) { 359 MYLOGE("Unable to add anrd_trace file %s to zip file\n", path); 360 } else { 361 if (remove(path)) { 362 MYLOGE("Error removing anrd_trace file %s: %s", path, strerror(errno)); 363 } 364 return true; 365 } 366 } else { 367 MYLOGE("Can't stats any trace file under %s\n", trace_path); 368 } 369 } 370 return false; 371} 372 373static void dump_systrace() { 374 if (!ds.IsZipping()) { 375 MYLOGD("Not dumping systrace because it's not a zipped bugreport\n"); 376 return; 377 } 378 std::string systrace_path = ds.GetPath("-systrace.txt"); 379 if (systrace_path.empty()) { 380 MYLOGE("Not dumping systrace because path is empty\n"); 381 return; 382 } 383 const char* path = "/sys/kernel/debug/tracing/tracing_on"; 384 long int is_tracing; 385 if (read_file_as_long(path, &is_tracing)) { 386 return; // error already logged 387 } 388 if (is_tracing <= 0) { 389 MYLOGD("Skipping systrace because '%s' content is '%ld'\n", path, is_tracing); 390 return; 391 } 392 393 MYLOGD("Running '/system/bin/atrace --async_dump -o %s', which can take several minutes", 394 systrace_path.c_str()); 395 if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--async_dump", "-o", systrace_path}, 396 CommandOptions::WithTimeout(120).Build())) { 397 MYLOGE("systrace timed out, its zip entry will be incomplete\n"); 398 // TODO: RunCommand tries to kill the process, but atrace doesn't die 399 // peacefully; ideally, we should call strace to stop itself, but there is no such option 400 // yet (just a --async_stop, which stops and dump 401 // if (RunCommand("SYSTRACE", {"/system/bin/atrace", "--kill"})) { 402 // MYLOGE("could not stop systrace "); 403 // } 404 } 405 if (!ds.AddZipEntry("systrace.txt", systrace_path)) { 406 MYLOGE("Unable to add systrace file %s to zip file\n", systrace_path.c_str()); 407 } else { 408 if (remove(systrace_path.c_str())) { 409 MYLOGE("Error removing systrace file %s: %s", systrace_path.c_str(), strerror(errno)); 410 } 411 } 412} 413 414static void dump_raft() { 415 if (PropertiesHelper::IsUserBuild()) { 416 return; 417 } 418 419 std::string raft_path = ds.GetPath("-raft_log.txt"); 420 if (raft_path.empty()) { 421 MYLOGD("raft_path is empty\n"); 422 return; 423 } 424 425 struct stat s; 426 if (stat(RAFT_DIR, &s) != 0 || !S_ISDIR(s.st_mode)) { 427 MYLOGD("%s does not exist or is not a directory\n", RAFT_DIR); 428 return; 429 } 430 431 CommandOptions options = CommandOptions::WithTimeout(600).Build(); 432 if (!ds.IsZipping()) { 433 // Write compressed and encoded raft logs to stdout if it's not a zipped bugreport. 434 RunCommand("RAFT LOGS", {"logcompressor", "-r", RAFT_DIR}, options); 435 return; 436 } 437 438 RunCommand("RAFT LOGS", {"logcompressor", "-n", "-r", RAFT_DIR, "-o", raft_path}, options); 439 if (!ds.AddZipEntry("raft_log.txt", raft_path)) { 440 MYLOGE("Unable to add raft log %s to zip file\n", raft_path.c_str()); 441 } else { 442 if (remove(raft_path.c_str())) { 443 MYLOGE("Error removing raft file %s: %s\n", raft_path.c_str(), strerror(errno)); 444 } 445 } 446} 447 448/** 449 * Finds the last modified file in the directory dir whose name starts with file_prefix. 450 * 451 * Function returns empty string when it does not find a file 452 */ 453static std::string GetLastModifiedFileWithPrefix(const std::string& dir, 454 const std::string& file_prefix) { 455 std::unique_ptr<DIR, decltype(&closedir)> d(opendir(dir.c_str()), closedir); 456 if (d == nullptr) { 457 MYLOGD("Error %d opening %s\n", errno, dir.c_str()); 458 return ""; 459 } 460 461 // Find the newest file matching the file_prefix in dir 462 struct dirent *de; 463 time_t last_modified_time = 0; 464 std::string last_modified_file = ""; 465 struct stat s; 466 467 while ((de = readdir(d.get()))) { 468 std::string file = std::string(de->d_name); 469 if (!file_prefix.empty()) { 470 if (!android::base::StartsWith(file, file_prefix.c_str())) continue; 471 } 472 file = dir + "/" + file; 473 int ret = stat(file.c_str(), &s); 474 475 if ((ret == 0) && (s.st_mtime > last_modified_time)) { 476 last_modified_file = file; 477 last_modified_time = s.st_mtime; 478 } 479 } 480 481 return last_modified_file; 482} 483 484static void DumpModemLogs() { 485 DurationReporter durationReporter("DUMP MODEM LOGS"); 486 if (PropertiesHelper::IsUserBuild()) { 487 return; 488 } 489 490 if (!ds.IsZipping()) { 491 MYLOGD("Not dumping modem logs. dumpstate is not generating a zipping bugreport\n"); 492 return; 493 } 494 495 std::string file_prefix = android::base::GetProperty("ro.radio.log_prefix", ""); 496 497 if(file_prefix.empty()) { 498 MYLOGD("No modem log : file_prefix is empty\n"); 499 return; 500 } 501 502 // TODO: b/33820081 we need to provide a right way to dump modem logs. 503 std::string radio_bugreport_dir = android::base::GetProperty("ro.radio.log_loc", ""); 504 if (radio_bugreport_dir.empty()) { 505 radio_bugreport_dir = dirname(ds.GetPath("").c_str()); 506 } 507 508 MYLOGD("DumpModemLogs: directory is %s and file_prefix is %s\n", 509 radio_bugreport_dir.c_str(), file_prefix.c_str()); 510 511 std::string modem_log_file = GetLastModifiedFileWithPrefix(radio_bugreport_dir, file_prefix); 512 513 struct stat s; 514 if (modem_log_file.empty() || stat(modem_log_file.c_str(), &s) != 0) { 515 MYLOGD("Modem log %s does not exist\n", modem_log_file.c_str()); 516 return; 517 } 518 519 std::string filename = basename(modem_log_file.c_str()); 520 if (!ds.AddZipEntry(filename, modem_log_file)) { 521 MYLOGE("Unable to add modem log %s to zip file\n", modem_log_file.c_str()); 522 } else { 523 MYLOGD("Modem Log %s is added to zip\n", modem_log_file.c_str()); 524 if (remove(modem_log_file.c_str())) { 525 MYLOGE("Error removing modem log %s\n", modem_log_file.c_str()); 526 } 527 } 528} 529 530static bool skip_not_stat(const char *path) { 531 static const char stat[] = "/stat"; 532 size_t len = strlen(path); 533 if (path[len - 1] == '/') { /* Directory? */ 534 return false; 535 } 536 return strcmp(path + len - sizeof(stat) + 1, stat); /* .../stat? */ 537} 538 539static bool skip_none(const char* path __attribute__((unused))) { 540 return false; 541} 542 543unsigned long worst_write_perf = 20000; /* in KB/s */ 544 545// 546// stat offsets 547// Name units description 548// ---- ----- ----------- 549// read I/Os requests number of read I/Os processed 550#define __STAT_READ_IOS 0 551// read merges requests number of read I/Os merged with in-queue I/O 552#define __STAT_READ_MERGES 1 553// read sectors sectors number of sectors read 554#define __STAT_READ_SECTORS 2 555// read ticks milliseconds total wait time for read requests 556#define __STAT_READ_TICKS 3 557// write I/Os requests number of write I/Os processed 558#define __STAT_WRITE_IOS 4 559// write merges requests number of write I/Os merged with in-queue I/O 560#define __STAT_WRITE_MERGES 5 561// write sectors sectors number of sectors written 562#define __STAT_WRITE_SECTORS 6 563// write ticks milliseconds total wait time for write requests 564#define __STAT_WRITE_TICKS 7 565// in_flight requests number of I/Os currently in flight 566#define __STAT_IN_FLIGHT 8 567// io_ticks milliseconds total time this block device has been active 568#define __STAT_IO_TICKS 9 569// time_in_queue milliseconds total wait time for all requests 570#define __STAT_IN_QUEUE 10 571#define __STAT_NUMBER_FIELD 11 572// 573// read I/Os, write I/Os 574// ===================== 575// 576// These values increment when an I/O request completes. 577// 578// read merges, write merges 579// ========================= 580// 581// These values increment when an I/O request is merged with an 582// already-queued I/O request. 583// 584// read sectors, write sectors 585// =========================== 586// 587// These values count the number of sectors read from or written to this 588// block device. The "sectors" in question are the standard UNIX 512-byte 589// sectors, not any device- or filesystem-specific block size. The 590// counters are incremented when the I/O completes. 591#define SECTOR_SIZE 512 592// 593// read ticks, write ticks 594// ======================= 595// 596// These values count the number of milliseconds that I/O requests have 597// waited on this block device. If there are multiple I/O requests waiting, 598// these values will increase at a rate greater than 1000/second; for 599// example, if 60 read requests wait for an average of 30 ms, the read_ticks 600// field will increase by 60*30 = 1800. 601// 602// in_flight 603// ========= 604// 605// This value counts the number of I/O requests that have been issued to 606// the device driver but have not yet completed. It does not include I/O 607// requests that are in the queue but not yet issued to the device driver. 608// 609// io_ticks 610// ======== 611// 612// This value counts the number of milliseconds during which the device has 613// had I/O requests queued. 614// 615// time_in_queue 616// ============= 617// 618// This value counts the number of milliseconds that I/O requests have waited 619// on this block device. If there are multiple I/O requests waiting, this 620// value will increase as the product of the number of milliseconds times the 621// number of requests waiting (see "read ticks" above for an example). 622#define S_TO_MS 1000 623// 624 625static int dump_stat_from_fd(const char *title __unused, const char *path, int fd) { 626 unsigned long long fields[__STAT_NUMBER_FIELD]; 627 bool z; 628 char *cp, *buffer = NULL; 629 size_t i = 0; 630 FILE *fp = fdopen(fd, "rb"); 631 getline(&buffer, &i, fp); 632 fclose(fp); 633 if (!buffer) { 634 return -errno; 635 } 636 i = strlen(buffer); 637 while ((i > 0) && (buffer[i - 1] == '\n')) { 638 buffer[--i] = '\0'; 639 } 640 if (!*buffer) { 641 free(buffer); 642 return 0; 643 } 644 z = true; 645 for (cp = buffer, i = 0; i < (sizeof(fields) / sizeof(fields[0])); ++i) { 646 fields[i] = strtoull(cp, &cp, 10); 647 if (fields[i] != 0) { 648 z = false; 649 } 650 } 651 if (z) { /* never accessed */ 652 free(buffer); 653 return 0; 654 } 655 656 if (!strncmp(path, BLK_DEV_SYS_DIR, sizeof(BLK_DEV_SYS_DIR) - 1)) { 657 path += sizeof(BLK_DEV_SYS_DIR) - 1; 658 } 659 660 printf("%-30s:%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s%9s\n%-30s:\t%s\n", "Block-Dev", 661 "R-IOs", "R-merg", "R-sect", "R-wait", "W-IOs", "W-merg", "W-sect", 662 "W-wait", "in-fli", "activ", "T-wait", path, buffer); 663 free(buffer); 664 665 if (fields[__STAT_IO_TICKS]) { 666 unsigned long read_perf = 0; 667 unsigned long read_ios = 0; 668 if (fields[__STAT_READ_TICKS]) { 669 unsigned long long divisor = fields[__STAT_READ_TICKS] 670 * fields[__STAT_IO_TICKS]; 671 read_perf = ((unsigned long long)SECTOR_SIZE 672 * fields[__STAT_READ_SECTORS] 673 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 674 / divisor; 675 read_ios = ((unsigned long long)S_TO_MS * fields[__STAT_READ_IOS] 676 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 677 / divisor; 678 } 679 680 unsigned long write_perf = 0; 681 unsigned long write_ios = 0; 682 if (fields[__STAT_WRITE_TICKS]) { 683 unsigned long long divisor = fields[__STAT_WRITE_TICKS] 684 * fields[__STAT_IO_TICKS]; 685 write_perf = ((unsigned long long)SECTOR_SIZE 686 * fields[__STAT_WRITE_SECTORS] 687 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 688 / divisor; 689 write_ios = ((unsigned long long)S_TO_MS * fields[__STAT_WRITE_IOS] 690 * fields[__STAT_IN_QUEUE] + (divisor >> 1)) 691 / divisor; 692 } 693 694 unsigned queue = (fields[__STAT_IN_QUEUE] 695 + (fields[__STAT_IO_TICKS] >> 1)) 696 / fields[__STAT_IO_TICKS]; 697 698 if (!write_perf && !write_ios) { 699 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) q: %u\n", path, read_perf, read_ios, queue); 700 } else { 701 printf("%-30s: perf(ios) rd: %luKB/s(%lu/s) wr: %luKB/s(%lu/s) q: %u\n", path, read_perf, 702 read_ios, write_perf, write_ios, queue); 703 } 704 705 /* bugreport timeout factor adjustment */ 706 if ((write_perf > 1) && (write_perf < worst_write_perf)) { 707 worst_write_perf = write_perf; 708 } 709 } 710 return 0; 711} 712 713/* timeout in ms */ 714static unsigned long logcat_timeout(const char *name) { 715 log_id_t id = android_name_to_log_id(name); 716 unsigned long property_size = __android_logger_get_buffer_size(id); 717 /* Engineering margin is ten-fold our guess */ 718 return 10 * (property_size + worst_write_perf) / worst_write_perf; 719} 720 721void Dumpstate::PrintHeader() const { 722 std::string build, fingerprint, radio, bootloader, network; 723 char date[80]; 724 725 build = android::base::GetProperty("ro.build.display.id", "(unknown)"); 726 fingerprint = android::base::GetProperty("ro.build.fingerprint", "(unknown)"); 727 radio = android::base::GetProperty("gsm.version.baseband", "(unknown)"); 728 bootloader = android::base::GetProperty("ro.bootloader", "(unknown)"); 729 network = android::base::GetProperty("gsm.operator.alpha", "(unknown)"); 730 strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_)); 731 732 printf("========================================================\n"); 733 printf("== dumpstate: %s\n", date); 734 printf("========================================================\n"); 735 736 printf("\n"); 737 printf("Build: %s\n", build.c_str()); 738 // NOTE: fingerprint entry format is important for other tools. 739 printf("Build fingerprint: '%s'\n", fingerprint.c_str()); 740 printf("Bootloader: %s\n", bootloader.c_str()); 741 printf("Radio: %s\n", radio.c_str()); 742 printf("Network: %s\n", network.c_str()); 743 744 printf("Kernel: "); 745 DumpFileToFd(STDOUT_FILENO, "", "/proc/version"); 746 printf("Command line: %s\n", strtok(cmdline_buf, "\n")); 747 printf("Bugreport format version: %s\n", version_.c_str()); 748 printf("Dumpstate info: id=%d pid=%d dry_run=%d args=%s extra_options=%s\n", id_, pid_, 749 PropertiesHelper::IsDryRun(), args_.c_str(), extra_options_.c_str()); 750 printf("\n"); 751} 752 753// List of file extensions that can cause a zip file attachment to be rejected by some email 754// service providers. 755static const std::set<std::string> PROBLEMATIC_FILE_EXTENSIONS = { 756 ".ade", ".adp", ".bat", ".chm", ".cmd", ".com", ".cpl", ".exe", ".hta", ".ins", ".isp", 757 ".jar", ".jse", ".lib", ".lnk", ".mde", ".msc", ".msp", ".mst", ".pif", ".scr", ".sct", 758 ".shb", ".sys", ".vb", ".vbe", ".vbs", ".vxd", ".wsc", ".wsf", ".wsh" 759}; 760 761bool Dumpstate::AddZipEntryFromFd(const std::string& entry_name, int fd) { 762 if (!IsZipping()) { 763 MYLOGD("Not adding zip entry %s from fd because it's not a zipped bugreport\n", 764 entry_name.c_str()); 765 return false; 766 } 767 std::string valid_name = entry_name; 768 769 // Rename extension if necessary. 770 size_t idx = entry_name.rfind("."); 771 if (idx != std::string::npos) { 772 std::string extension = entry_name.substr(idx); 773 std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); 774 if (PROBLEMATIC_FILE_EXTENSIONS.count(extension) != 0) { 775 valid_name = entry_name + ".renamed"; 776 MYLOGI("Renaming entry %s to %s\n", entry_name.c_str(), valid_name.c_str()); 777 } 778 } 779 780 // Logging statement below is useful to time how long each entry takes, but it's too verbose. 781 // MYLOGD("Adding zip entry %s\n", entry_name.c_str()); 782 int32_t err = zip_writer_->StartEntryWithTime(valid_name.c_str(), ZipWriter::kCompress, 783 get_mtime(fd, ds.now_)); 784 if (err != 0) { 785 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", valid_name.c_str(), 786 ZipWriter::ErrorCodeString(err)); 787 return false; 788 } 789 790 std::vector<uint8_t> buffer(65536); 791 while (1) { 792 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer.data(), buffer.size())); 793 if (bytes_read == 0) { 794 break; 795 } else if (bytes_read == -1) { 796 MYLOGE("read(%s): %s\n", entry_name.c_str(), strerror(errno)); 797 return false; 798 } 799 err = zip_writer_->WriteBytes(buffer.data(), bytes_read); 800 if (err) { 801 MYLOGE("zip_writer_->WriteBytes(): %s\n", ZipWriter::ErrorCodeString(err)); 802 return false; 803 } 804 } 805 806 err = zip_writer_->FinishEntry(); 807 if (err != 0) { 808 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 809 return false; 810 } 811 812 return true; 813} 814 815bool Dumpstate::AddZipEntry(const std::string& entry_name, const std::string& entry_path) { 816 android::base::unique_fd fd( 817 TEMP_FAILURE_RETRY(open(entry_path.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC))); 818 if (fd == -1) { 819 MYLOGE("open(%s): %s\n", entry_path.c_str(), strerror(errno)); 820 return false; 821 } 822 823 return AddZipEntryFromFd(entry_name, fd.get()); 824} 825 826/* adds a file to the existing zipped bugreport */ 827static int _add_file_from_fd(const char* title __attribute__((unused)), const char* path, int fd) { 828 return ds.AddZipEntryFromFd(ZIP_ROOT_DIR + path, fd) ? 0 : 1; 829} 830 831void Dumpstate::AddDir(const std::string& dir, bool recursive) { 832 if (!IsZipping()) { 833 MYLOGD("Not adding dir %s because it's not a zipped bugreport\n", dir.c_str()); 834 return; 835 } 836 MYLOGD("Adding dir %s (recursive: %d)\n", dir.c_str(), recursive); 837 DurationReporter duration_reporter(dir, true); 838 dump_files("", dir.c_str(), recursive ? skip_none : is_dir, _add_file_from_fd); 839} 840 841bool Dumpstate::AddTextZipEntry(const std::string& entry_name, const std::string& content) { 842 if (!IsZipping()) { 843 MYLOGD("Not adding text zip entry %s because it's not a zipped bugreport\n", 844 entry_name.c_str()); 845 return false; 846 } 847 MYLOGD("Adding zip text entry %s\n", entry_name.c_str()); 848 int32_t err = zip_writer_->StartEntryWithTime(entry_name.c_str(), ZipWriter::kCompress, ds.now_); 849 if (err != 0) { 850 MYLOGE("zip_writer_->StartEntryWithTime(%s): %s\n", entry_name.c_str(), 851 ZipWriter::ErrorCodeString(err)); 852 return false; 853 } 854 855 err = zip_writer_->WriteBytes(content.c_str(), content.length()); 856 if (err != 0) { 857 MYLOGE("zip_writer_->WriteBytes(%s): %s\n", entry_name.c_str(), 858 ZipWriter::ErrorCodeString(err)); 859 return false; 860 } 861 862 err = zip_writer_->FinishEntry(); 863 if (err != 0) { 864 MYLOGE("zip_writer_->FinishEntry(): %s\n", ZipWriter::ErrorCodeString(err)); 865 return false; 866 } 867 868 return true; 869} 870 871static void DoKmsg() { 872 struct stat st; 873 if (!stat(PSTORE_LAST_KMSG, &st)) { 874 /* Also TODO: Make console-ramoops CAP_SYSLOG protected. */ 875 DumpFile("LAST KMSG", PSTORE_LAST_KMSG); 876 } else if (!stat(ALT_PSTORE_LAST_KMSG, &st)) { 877 DumpFile("LAST KMSG", ALT_PSTORE_LAST_KMSG); 878 } else { 879 /* TODO: Make last_kmsg CAP_SYSLOG protected. b/5555691 */ 880 DumpFile("LAST KMSG", "/proc/last_kmsg"); 881 } 882} 883 884static void DoLogcat() { 885 unsigned long timeout; 886 // DumpFile("EVENT LOG TAGS", "/etc/event-log-tags"); 887 // calculate timeout 888 timeout = logcat_timeout("main") + logcat_timeout("system") + logcat_timeout("crash"); 889 if (timeout < 20000) { 890 timeout = 20000; 891 } 892 RunCommand("SYSTEM LOG", 893 {"logcat", "-v", "threadtime", "-v", "printable", "-v", "uid", 894 "-d", "*:v"}, 895 CommandOptions::WithTimeout(timeout / 1000).Build()); 896 timeout = logcat_timeout("events"); 897 if (timeout < 20000) { 898 timeout = 20000; 899 } 900 RunCommand("EVENT LOG", 901 {"logcat", "-b", "events", "-v", "threadtime", "-v", "printable", "-v", "uid", 902 "-d", "*:v"}, 903 CommandOptions::WithTimeout(timeout / 1000).Build()); 904 timeout = logcat_timeout("radio"); 905 if (timeout < 20000) { 906 timeout = 20000; 907 } 908 RunCommand("RADIO LOG", 909 {"logcat", "-b", "radio", "-v", "threadtime", "-v", "printable", "-v", "uid", 910 "-d", "*:v"}, 911 CommandOptions::WithTimeout(timeout / 1000).Build()); 912 913 RunCommand("LOG STATISTICS", {"logcat", "-b", "all", "-S"}); 914 915 /* kernels must set CONFIG_PSTORE_PMSG, slice up pstore with device tree */ 916 RunCommand("LAST LOGCAT", 917 {"logcat", "-L", "-b", "all", "-v", "threadtime", "-v", "printable", "-v", "uid", 918 "-d", "*:v"}); 919} 920 921static void DumpIpTables() { 922 RunCommand("IPTABLES", {"iptables", "-L", "-nvx"}); 923 RunCommand("IP6TABLES", {"ip6tables", "-L", "-nvx"}); 924 RunCommand("IPTABLES NAT", {"iptables", "-t", "nat", "-L", "-nvx"}); 925 /* no ip6 nat */ 926 RunCommand("IPTABLES MANGLE", {"iptables", "-t", "mangle", "-L", "-nvx"}); 927 RunCommand("IP6TABLES MANGLE", {"ip6tables", "-t", "mangle", "-L", "-nvx"}); 928 RunCommand("IPTABLES RAW", {"iptables", "-t", "raw", "-L", "-nvx"}); 929 RunCommand("IP6TABLES RAW", {"ip6tables", "-t", "raw", "-L", "-nvx"}); 930} 931 932static void AddGlobalAnrTraceFile(const bool add_to_zip, const std::string& anr_traces_file, 933 const std::string& anr_traces_dir) { 934 std::string dump_traces_dir; 935 936 if (dump_traces_path != nullptr) { 937 if (add_to_zip) { 938 dump_traces_dir = dirname(dump_traces_path); 939 MYLOGD("Adding ANR traces (directory %s) to the zip file\n", dump_traces_dir.c_str()); 940 ds.AddDir(dump_traces_dir, true); 941 } else { 942 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n", 943 dump_traces_path); 944 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path); 945 } 946 } 947 948 949 // Make sure directory is not added twice. 950 // TODO: this is an overzealous check because it's relying on dump_traces_path - which is 951 // generated by dump_traces() - and anr_traces_path - which is retrieved from a system 952 // property - but in reality they're the same path (although the former could be nullptr). 953 // Anyways, once dump_traces() is refactored as a private Dumpstate function, this logic should 954 // be revisited. 955 bool already_dumped = anr_traces_dir == dump_traces_dir; 956 957 MYLOGD("AddGlobalAnrTraceFile(): dump_traces_dir=%s, anr_traces_dir=%s, already_dumped=%d\n", 958 dump_traces_dir.c_str(), anr_traces_dir.c_str(), already_dumped); 959 960 int fd = TEMP_FAILURE_RETRY( 961 open(anr_traces_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW | O_NONBLOCK)); 962 if (fd < 0) { 963 printf("*** NO ANR VM TRACES FILE (%s): %s\n\n", anr_traces_file.c_str(), strerror(errno)); 964 } else { 965 if (add_to_zip) { 966 if (!already_dumped) { 967 MYLOGD("Adding dalvik ANR traces (directory %s) to the zip file\n", 968 anr_traces_dir.c_str()); 969 ds.AddDir(anr_traces_dir, true); 970 } 971 } else { 972 MYLOGD("Dumping last ANR traces (%s) to the main bugreport entry\n", 973 anr_traces_file.c_str()); 974 dump_file_from_fd("VM TRACES AT LAST ANR", anr_traces_file.c_str(), fd); 975 } 976 } 977} 978 979static void AddAnrTraceDir(const bool add_to_zip, const std::string& anr_traces_dir) { 980 MYLOGD("AddAnrTraceDir(): dump_traces_file=%s, anr_traces_dir=%s\n", dump_traces_path, 981 anr_traces_dir.c_str()); 982 983 // If we're here, dump_traces_path will always be a temporary file 984 // (created with mkostemp or similar) that contains dumps taken earlier 985 // on in the process. 986 if (dump_traces_path != nullptr) { 987 if (add_to_zip) { 988 ds.AddZipEntry(ZIP_ROOT_DIR + anr_traces_dir + "/traces-just-now.txt", dump_traces_path); 989 } else { 990 MYLOGD("Dumping current ANR traces (%s) to the main bugreport entry\n", 991 dump_traces_path); 992 ds.DumpFile("VM TRACES JUST NOW", dump_traces_path); 993 } 994 995 const int ret = unlink(dump_traces_path); 996 if (ret == -1) { 997 MYLOGW("Error unlinking temporary trace path %s: %s\n", dump_traces_path, 998 strerror(errno)); 999 } 1000 } 1001 1002 // Add a specific message for the first ANR Dump. 1003 if (anr_data->size() > 0) { 1004 AddDumps(anr_data->begin(), anr_data->begin() + 1, 1005 "VM TRACES AT LAST ANR", add_to_zip); 1006 1007 if (anr_data->size() > 1) { 1008 AddDumps(anr_data->begin() + 1, anr_data->end(), 1009 "HISTORICAL ANR", add_to_zip); 1010 } 1011 } else { 1012 printf("*** NO ANRs to dump in %s\n\n", ANR_DIR.c_str()); 1013 } 1014} 1015 1016static void AddAnrTraceFiles() { 1017 const bool add_to_zip = ds.IsZipping() && ds.version_ == VERSION_SPLIT_ANR; 1018 1019 std::string anr_traces_file; 1020 std::string anr_traces_dir; 1021 bool is_global_trace_file = true; 1022 1023 // First check whether the stack-trace-dir property is set. When it's set, 1024 // each ANR trace will be written to a separate file and not to a global 1025 // stack trace file. 1026 anr_traces_dir = android::base::GetProperty("dalvik.vm.stack-trace-dir", ""); 1027 if (anr_traces_dir.empty()) { 1028 anr_traces_file = android::base::GetProperty("dalvik.vm.stack-trace-file", ""); 1029 if (!anr_traces_file.empty()) { 1030 anr_traces_dir = dirname(anr_traces_file.c_str()); 1031 } 1032 } else { 1033 is_global_trace_file = false; 1034 } 1035 1036 // We have neither configured a global trace file nor a trace directory, 1037 // there will be nothing to dump. 1038 if (anr_traces_file.empty() && anr_traces_dir.empty()) { 1039 printf("*** NO VM TRACES FILE DEFINED (dalvik.vm.stack-trace-file)\n\n"); 1040 return; 1041 } 1042 1043 if (is_global_trace_file) { 1044 AddGlobalAnrTraceFile(add_to_zip, anr_traces_file, anr_traces_dir); 1045 } else { 1046 AddAnrTraceDir(add_to_zip, anr_traces_dir); 1047 } 1048 1049 /* slow traces for slow operations */ 1050 struct stat st; 1051 if (!anr_traces_dir.empty()) { 1052 int i = 0; 1053 while (true) { 1054 const std::string slow_trace_path = 1055 anr_traces_dir + android::base::StringPrintf("slow%02d.txt", i); 1056 if (stat(slow_trace_path.c_str(), &st)) { 1057 // No traces file at this index, done with the files. 1058 break; 1059 } 1060 ds.DumpFile("VM TRACES WHEN SLOW", slow_trace_path.c_str()); 1061 i++; 1062 } 1063 } 1064} 1065 1066static void DumpBlockStatFiles() { 1067 DurationReporter duration_reporter("DUMP BLOCK STAT"); 1068 1069 std::unique_ptr<DIR, std::function<int(DIR*)>> dirptr(opendir(BLK_DEV_SYS_DIR), closedir); 1070 1071 if (dirptr == nullptr) { 1072 MYLOGE("Failed to open %s: %s\n", BLK_DEV_SYS_DIR, strerror(errno)); 1073 return; 1074 } 1075 1076 printf("------ DUMP BLOCK STAT ------\n\n"); 1077 while (struct dirent *d = readdir(dirptr.get())) { 1078 if ((d->d_name[0] == '.') 1079 && (((d->d_name[1] == '.') && (d->d_name[2] == '\0')) 1080 || (d->d_name[1] == '\0'))) { 1081 continue; 1082 } 1083 const std::string new_path = 1084 android::base::StringPrintf("%s/%s", BLK_DEV_SYS_DIR, d->d_name); 1085 printf("------ BLOCK STAT (%s) ------\n", new_path.c_str()); 1086 dump_files("", new_path.c_str(), skip_not_stat, dump_stat_from_fd); 1087 printf("\n"); 1088 } 1089 return; 1090} 1091static void dumpstate() { 1092 DurationReporter duration_reporter("DUMPSTATE"); 1093 1094 dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version"); 1095 RunCommand("UPTIME", {"uptime"}); 1096 DumpBlockStatFiles(); 1097 dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd"); 1098 DumpFile("MEMORY INFO", "/proc/meminfo"); 1099 RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o", 1100 "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"}); 1101 RunCommand("PROCRANK", {"procrank"}, AS_ROOT_20); 1102 DumpFile("VIRTUAL MEMORY STATS", "/proc/vmstat"); 1103 DumpFile("VMALLOC INFO", "/proc/vmallocinfo"); 1104 DumpFile("SLAB INFO", "/proc/slabinfo"); 1105 DumpFile("ZONEINFO", "/proc/zoneinfo"); 1106 DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo"); 1107 DumpFile("BUDDYINFO", "/proc/buddyinfo"); 1108 DumpFile("FRAGMENTATION INFO", "/d/extfrag/unusable_index"); 1109 1110 DumpFile("KERNEL WAKE SOURCES", "/d/wakeup_sources"); 1111 DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); 1112 DumpFile("KERNEL SYNC", "/d/sync"); 1113 1114 RunCommand("PROCESSES AND THREADS", 1115 {"ps", "-A", "-T", "-Z", "-O", "pri,nice,rtprio,sched,pcy"}); 1116 RunCommand("LIBRANK", {"librank"}, CommandOptions::AS_ROOT); 1117 1118 if (ds.IsZipping()) { 1119 RunCommand( 1120 "HARDWARE HALS", 1121 {"lshal", std::string("--debug=") + kLsHalDebugPath}, 1122 CommandOptions::AS_ROOT); 1123 1124 ds.AddZipEntry("lshal-debug.txt", kLsHalDebugPath); 1125 1126 unlink(kLsHalDebugPath.c_str()); 1127 } else { 1128 RunCommand( 1129 "HARDWARE HALS", {"lshal", "--debug"}, CommandOptions::AS_ROOT); 1130 } 1131 1132 RunCommand("PRINTENV", {"printenv"}); 1133 RunCommand("NETSTAT", {"netstat", "-nW"}); 1134 struct stat s; 1135 if (stat("/proc/modules", &s) != 0) { 1136 MYLOGD("Skipping 'lsmod' because /proc/modules does not exist\n"); 1137 } else { 1138 RunCommand("LSMOD", {"lsmod"}); 1139 } 1140 1141 do_dmesg(); 1142 1143 RunCommand("LIST OF OPEN FILES", {"lsof"}, CommandOptions::AS_ROOT); 1144 for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES"); 1145 for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); 1146 for_each_pid(show_showtime, "PROCESS TIMES (pid cmd user system iowait+percentage)"); 1147 1148 /* Dump Bluetooth HCI logs */ 1149 ds.AddDir("/data/misc/bluetooth/logs", true); 1150 1151 if (!ds.do_early_screenshot_) { 1152 MYLOGI("taking late screenshot\n"); 1153 ds.TakeScreenshot(); 1154 } 1155 1156 DoLogcat(); 1157 1158 AddAnrTraceFiles(); 1159 1160 // NOTE: tombstones are always added as separate entries in the zip archive 1161 // and are not interspersed with the main report. 1162 const bool tombstones_dumped = AddDumps(tombstone_data->begin(), tombstone_data->end(), 1163 "TOMBSTONE", true /* add_to_zip */); 1164 if (!tombstones_dumped) { 1165 printf("*** NO TOMBSTONES to dump in %s\n\n", TOMBSTONE_DIR.c_str()); 1166 } 1167 1168 DumpFile("NETWORK DEV INFO", "/proc/net/dev"); 1169 DumpFile("QTAGUID NETWORK INTERFACES INFO", "/proc/net/xt_qtaguid/iface_stat_all"); 1170 DumpFile("QTAGUID NETWORK INTERFACES INFO (xt)", "/proc/net/xt_qtaguid/iface_stat_fmt"); 1171 DumpFile("QTAGUID CTRL INFO", "/proc/net/xt_qtaguid/ctrl"); 1172 DumpFile("QTAGUID STATS INFO", "/proc/net/xt_qtaguid/stats"); 1173 1174 DoKmsg(); 1175 1176 /* The following have a tendency to get wedged when wifi drivers/fw goes belly-up. */ 1177 1178 RunCommand("NETWORK INTERFACES", {"ip", "link"}); 1179 1180 RunCommand("IPv4 ADDRESSES", {"ip", "-4", "addr", "show"}); 1181 RunCommand("IPv6 ADDRESSES", {"ip", "-6", "addr", "show"}); 1182 1183 RunCommand("IP RULES", {"ip", "rule", "show"}); 1184 RunCommand("IP RULES v6", {"ip", "-6", "rule", "show"}); 1185 1186 dump_route_tables(); 1187 1188 RunCommand("ARP CACHE", {"ip", "-4", "neigh", "show"}); 1189 RunCommand("IPv6 ND CACHE", {"ip", "-6", "neigh", "show"}); 1190 RunCommand("MULTICAST ADDRESSES", {"ip", "maddr"}); 1191 1192 RunDumpsys("NETWORK DIAGNOSTICS", {"connectivity", "--diag"}, 1193 CommandOptions::WithTimeout(10).Build()); 1194 1195 RunCommand("SYSTEM PROPERTIES", {"getprop"}); 1196 1197 RunCommand("VOLD DUMP", {"vdc", "dump"}); 1198 RunCommand("SECURE CONTAINERS", {"vdc", "asec", "list"}); 1199 1200 RunCommand("STORAGED TASKIOINFO", {"storaged", "-u"}, CommandOptions::WithTimeout(10).Build()); 1201 1202 RunCommand("FILESYSTEMS & FREE SPACE", {"df"}); 1203 1204 RunCommand("LAST RADIO LOG", {"parse_radio_log", "/proc/last_radio_log"}); 1205 1206 printf("------ BACKLIGHTS ------\n"); 1207 printf("LCD brightness="); 1208 DumpFile("", "/sys/class/leds/lcd-backlight/brightness"); 1209 printf("Button brightness="); 1210 DumpFile("", "/sys/class/leds/button-backlight/brightness"); 1211 printf("Keyboard brightness="); 1212 DumpFile("", "/sys/class/leds/keyboard-backlight/brightness"); 1213 printf("ALS mode="); 1214 DumpFile("", "/sys/class/leds/lcd-backlight/als"); 1215 printf("LCD driver registers:\n"); 1216 DumpFile("", "/sys/class/leds/lcd-backlight/registers"); 1217 printf("\n"); 1218 1219 /* Binder state is expensive to look at as it uses a lot of memory. */ 1220 DumpFile("BINDER FAILED TRANSACTION LOG", "/sys/kernel/debug/binder/failed_transaction_log"); 1221 DumpFile("BINDER TRANSACTION LOG", "/sys/kernel/debug/binder/transaction_log"); 1222 DumpFile("BINDER TRANSACTIONS", "/sys/kernel/debug/binder/transactions"); 1223 DumpFile("BINDER STATS", "/sys/kernel/debug/binder/stats"); 1224 DumpFile("BINDER STATE", "/sys/kernel/debug/binder/state"); 1225 1226 ds.DumpstateBoard(); 1227 1228 /* Migrate the ril_dumpstate to a device specific dumpstate? */ 1229 int rilDumpstateTimeout = android::base::GetIntProperty("ril.dumpstate.timeout", 0); 1230 if (rilDumpstateTimeout > 0) { 1231 // su does not exist on user builds, so try running without it. 1232 // This way any implementations of vril-dump that do not require 1233 // root can run on user builds. 1234 CommandOptions::CommandOptionsBuilder options = 1235 CommandOptions::WithTimeout(rilDumpstateTimeout); 1236 if (!PropertiesHelper::IsUserBuild()) { 1237 options.AsRoot(); 1238 } 1239 RunCommand("DUMP VENDOR RIL LOGS", {"vril-dump"}, options.Build()); 1240 } 1241 1242 printf("========================================================\n"); 1243 printf("== Android Framework Services\n"); 1244 printf("========================================================\n"); 1245 1246 RunDumpsys("DUMPSYS", {"--skip", "meminfo", "cpuinfo"}, CommandOptions::WithTimeout(90).Build(), 1247 10); 1248 1249 printf("========================================================\n"); 1250 printf("== Checkins\n"); 1251 printf("========================================================\n"); 1252 1253 RunDumpsys("CHECKIN BATTERYSTATS", {"batterystats", "-c"}); 1254 RunDumpsys("CHECKIN MEMINFO", {"meminfo", "--checkin"}); 1255 RunDumpsys("CHECKIN NETSTATS", {"netstats", "--checkin"}); 1256 RunDumpsys("CHECKIN PROCSTATS", {"procstats", "-c"}); 1257 RunDumpsys("CHECKIN USAGESTATS", {"usagestats", "-c"}); 1258 RunDumpsys("CHECKIN PACKAGE", {"package", "--checkin"}); 1259 1260 printf("========================================================\n"); 1261 printf("== Running Application Activities\n"); 1262 printf("========================================================\n"); 1263 1264 RunDumpsys("APP ACTIVITIES", {"activity", "-v", "all"}); 1265 1266 printf("========================================================\n"); 1267 printf("== Running Application Services\n"); 1268 printf("========================================================\n"); 1269 1270 RunDumpsys("APP SERVICES", {"activity", "service", "all"}); 1271 1272 printf("========================================================\n"); 1273 printf("== Running Application Providers\n"); 1274 printf("========================================================\n"); 1275 1276 RunDumpsys("APP PROVIDERS", {"activity", "provider", "all"}); 1277 1278 printf("========================================================\n"); 1279 printf("== Dropbox crashes\n"); 1280 printf("========================================================\n"); 1281 1282 RunDumpsys("DROPBOX SYSTEM SERVER CRASHES", {"dropbox", "-p", "system_server_crash"}); 1283 RunDumpsys("DROPBOX SYSTEM APP CRASHES", {"dropbox", "-p", "system_app_crash"}); 1284 1285 // DumpModemLogs adds the modem logs if available to the bugreport. 1286 // Do this at the end to allow for sufficient time for the modem logs to be 1287 // collected. 1288 DumpModemLogs(); 1289 1290 printf("========================================================\n"); 1291 printf("== Final progress (pid %d): %d/%d (estimated %d)\n", ds.pid_, ds.progress_->Get(), 1292 ds.progress_->GetMax(), ds.progress_->GetInitialMax()); 1293 printf("========================================================\n"); 1294 printf("== dumpstate: done (id %d)\n", ds.id_); 1295 printf("========================================================\n"); 1296} 1297 1298void Dumpstate::DumpstateBoard() { 1299 DurationReporter duration_reporter("dumpstate_board()"); 1300 printf("========================================================\n"); 1301 printf("== Board\n"); 1302 printf("========================================================\n"); 1303 1304 ::android::sp<IDumpstateDevice> dumpstate_device(IDumpstateDevice::getService()); 1305 if (dumpstate_device == nullptr) { 1306 MYLOGE("No IDumpstateDevice implementation\n"); 1307 return; 1308 } 1309 1310 if (!IsZipping()) { 1311 MYLOGD("Not dumping board info because it's not a zipped bugreport\n"); 1312 return; 1313 } 1314 1315 std::string path = kDumpstateBoardPath; 1316 MYLOGI("Calling IDumpstateDevice implementation using path %s\n", path.c_str()); 1317 1318 int fd = 1319 TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 1320 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); 1321 if (fd < 0) { 1322 MYLOGE("Could not open file %s: %s\n", path.c_str(), strerror(errno)); 1323 return; 1324 } 1325 1326 native_handle_t* handle = native_handle_create(1, 0); 1327 if (handle == nullptr) { 1328 MYLOGE("Could not create native_handle\n"); 1329 return; 1330 } 1331 handle->data[0] = fd; 1332 1333 // TODO: need a timeout mechanism so dumpstate does not hang on device implementation call. 1334 android::hardware::Return<void> status = dumpstate_device->dumpstateBoard(handle); 1335 if (!status.isOk()) { 1336 MYLOGE("dumpstateBoard failed: %s\n", status.description().c_str()); 1337 native_handle_close(handle); 1338 native_handle_delete(handle); 1339 return; 1340 } 1341 1342 AddZipEntry("dumpstate-board.txt", path); 1343 printf("*** See dumpstate-board.txt entry ***\n"); 1344 1345 native_handle_close(handle); 1346 native_handle_delete(handle); 1347 1348 if (remove(path.c_str()) != 0) { 1349 MYLOGE("Could not remove(%s): %s\n", path.c_str(), strerror(errno)); 1350 } 1351} 1352 1353static void ShowUsageAndExit(int exitCode = 1) { 1354 fprintf(stderr, 1355 "usage: dumpstate [-h] [-b soundfile] [-e soundfile] [-o file] [-d] [-p] " 1356 "[-z]] [-s] [-S] [-q] [-B] [-P] [-R] [-V version]\n" 1357 " -h: display this help message\n" 1358 " -b: play sound file instead of vibrate, at beginning of job\n" 1359 " -e: play sound file instead of vibrate, at end of job\n" 1360 " -o: write to file (instead of stdout)\n" 1361 " -d: append date to filename (requires -o)\n" 1362 " -p: capture screenshot to filename.png (requires -o)\n" 1363 " -z: generate zipped file (requires -o)\n" 1364 " -s: write output to control socket (for init)\n" 1365 " -S: write file location to control socket (for init; requires -o and -z)" 1366 " -q: disable vibrate\n" 1367 " -B: send broadcast when finished (requires -o)\n" 1368 " -P: send broadcast when started and update system properties on " 1369 "progress (requires -o and -B)\n" 1370 " -R: take bugreport in remote mode (requires -o, -z, -d and -B, " 1371 "shouldn't be used with -P)\n" 1372 " -v: prints the dumpstate header and exit\n"); 1373 exit(exitCode); 1374} 1375 1376static void ExitOnInvalidArgs() { 1377 fprintf(stderr, "invalid combination of args\n"); 1378 ShowUsageAndExit(); 1379} 1380 1381static void sig_handler(int) { 1382 _exit(EXIT_FAILURE); 1383} 1384 1385static void register_sig_handler() { 1386 struct sigaction sa; 1387 sigemptyset(&sa.sa_mask); 1388 sa.sa_flags = 0; 1389 sa.sa_handler = sig_handler; 1390 sigaction(SIGPIPE, &sa, NULL); // broken pipe 1391 sigaction(SIGSEGV, &sa, NULL); // segment fault 1392 sigaction(SIGINT, &sa, NULL); // ctrl-c 1393 sigaction(SIGTERM, &sa, NULL); // killed 1394 sigaction(SIGQUIT, &sa, NULL); // quit 1395} 1396 1397bool Dumpstate::FinishZipFile() { 1398 std::string entry_name = base_name_ + "-" + name_ + ".txt"; 1399 MYLOGD("Adding main entry (%s) from %s to .zip bugreport\n", entry_name.c_str(), 1400 tmp_path_.c_str()); 1401 // Final timestamp 1402 char date[80]; 1403 time_t the_real_now_please_stand_up = time(nullptr); 1404 strftime(date, sizeof(date), "%Y/%m/%d %H:%M:%S", localtime(&the_real_now_please_stand_up)); 1405 MYLOGD("dumpstate id %d finished around %s (%ld s)\n", ds.id_, date, 1406 the_real_now_please_stand_up - ds.now_); 1407 1408 if (!ds.AddZipEntry(entry_name, tmp_path_)) { 1409 MYLOGE("Failed to add text entry to .zip file\n"); 1410 return false; 1411 } 1412 if (!AddTextZipEntry("main_entry.txt", entry_name)) { 1413 MYLOGE("Failed to add main_entry.txt to .zip file\n"); 1414 return false; 1415 } 1416 1417 // Add log file (which contains stderr output) to zip... 1418 fprintf(stderr, "dumpstate_log.txt entry on zip file logged up to here\n"); 1419 if (!ds.AddZipEntry("dumpstate_log.txt", ds.log_path_.c_str())) { 1420 MYLOGE("Failed to add dumpstate log to .zip file\n"); 1421 return false; 1422 } 1423 // ... and re-opens it for further logging. 1424 redirect_to_existing_file(stderr, const_cast<char*>(ds.log_path_.c_str())); 1425 fprintf(stderr, "\n"); 1426 1427 int32_t err = zip_writer_->Finish(); 1428 if (err != 0) { 1429 MYLOGE("zip_writer_->Finish(): %s\n", ZipWriter::ErrorCodeString(err)); 1430 return false; 1431 } 1432 1433 // TODO: remove once FinishZipFile() is automatically handled by Dumpstate's destructor. 1434 ds.zip_file.reset(nullptr); 1435 1436 MYLOGD("Removing temporary file %s\n", tmp_path_.c_str()) 1437 if (remove(tmp_path_.c_str()) != 0) { 1438 MYLOGE("Failed to remove temporary file (%s): %s\n", tmp_path_.c_str(), strerror(errno)); 1439 } 1440 1441 return true; 1442} 1443 1444static std::string SHA256_file_hash(std::string filepath) { 1445 android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(filepath.c_str(), O_RDONLY | O_NONBLOCK 1446 | O_CLOEXEC | O_NOFOLLOW))); 1447 if (fd == -1) { 1448 MYLOGE("open(%s): %s\n", filepath.c_str(), strerror(errno)); 1449 return NULL; 1450 } 1451 1452 SHA256_CTX ctx; 1453 SHA256_Init(&ctx); 1454 1455 std::vector<uint8_t> buffer(65536); 1456 while (1) { 1457 ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd.get(), buffer.data(), buffer.size())); 1458 if (bytes_read == 0) { 1459 break; 1460 } else if (bytes_read == -1) { 1461 MYLOGE("read(%s): %s\n", filepath.c_str(), strerror(errno)); 1462 return NULL; 1463 } 1464 1465 SHA256_Update(&ctx, buffer.data(), bytes_read); 1466 } 1467 1468 uint8_t hash[SHA256_DIGEST_LENGTH]; 1469 SHA256_Final(hash, &ctx); 1470 1471 char hash_buffer[SHA256_DIGEST_LENGTH * 2 + 1]; 1472 for(size_t i = 0; i < SHA256_DIGEST_LENGTH; i++) { 1473 sprintf(hash_buffer + (i * 2), "%02x", hash[i]); 1474 } 1475 hash_buffer[sizeof(hash_buffer) - 1] = 0; 1476 return std::string(hash_buffer); 1477} 1478 1479static void SendBroadcast(const std::string& action, const std::vector<std::string>& args) { 1480 // clang-format off 1481 std::vector<std::string> am = {"/system/bin/cmd", "activity", "broadcast", "--user", "0", 1482 "--receiver-foreground", "--receiver-include-background", "-a", action}; 1483 // clang-format on 1484 1485 am.insert(am.end(), args.begin(), args.end()); 1486 1487 RunCommand("", am, 1488 CommandOptions::WithTimeout(20) 1489 .Log("Sending broadcast: '%s'\n") 1490 .Always() 1491 .DropRoot() 1492 .RedirectStderr() 1493 .Build()); 1494} 1495 1496static void Vibrate(int duration_ms) { 1497 // clang-format off 1498 RunCommand("", {"cmd", "vibrator", "vibrate", std::to_string(duration_ms), "dumpstate"}, 1499 CommandOptions::WithTimeout(10) 1500 .Log("Vibrate: '%s'\n") 1501 .Always() 1502 .Build()); 1503 // clang-format on 1504} 1505 1506int main(int argc, char *argv[]) { 1507 int do_add_date = 0; 1508 int do_zip_file = 0; 1509 int do_vibrate = 1; 1510 char* use_outfile = 0; 1511 int use_socket = 0; 1512 int use_control_socket = 0; 1513 int do_fb = 0; 1514 int do_broadcast = 0; 1515 int is_remote_mode = 0; 1516 bool show_header_only = false; 1517 bool do_start_service = false; 1518 bool telephony_only = false; 1519 1520 /* set as high priority, and protect from OOM killer */ 1521 setpriority(PRIO_PROCESS, 0, -20); 1522 1523 FILE* oom_adj = fopen("/proc/self/oom_score_adj", "we"); 1524 if (oom_adj) { 1525 fputs("-1000", oom_adj); 1526 fclose(oom_adj); 1527 } else { 1528 /* fallback to kernels <= 2.6.35 */ 1529 oom_adj = fopen("/proc/self/oom_adj", "we"); 1530 if (oom_adj) { 1531 fputs("-17", oom_adj); 1532 fclose(oom_adj); 1533 } 1534 } 1535 1536 /* parse arguments */ 1537 int c; 1538 while ((c = getopt(argc, argv, "dho:svqzpPBRSV:")) != -1) { 1539 switch (c) { 1540 // clang-format off 1541 case 'd': do_add_date = 1; break; 1542 case 'z': do_zip_file = 1; break; 1543 case 'o': use_outfile = optarg; break; 1544 case 's': use_socket = 1; break; 1545 case 'S': use_control_socket = 1; break; 1546 case 'v': show_header_only = true; break; 1547 case 'q': do_vibrate = 0; break; 1548 case 'p': do_fb = 1; break; 1549 case 'P': ds.update_progress_ = true; break; 1550 case 'R': is_remote_mode = 1; break; 1551 case 'B': do_broadcast = 1; break; 1552 case 'V': break; // compatibility no-op 1553 case 'h': 1554 ShowUsageAndExit(0); 1555 break; 1556 default: 1557 fprintf(stderr, "Invalid option: %c\n", c); 1558 ShowUsageAndExit(); 1559 // clang-format on 1560 } 1561 } 1562 1563 // TODO: use helper function to convert argv into a string 1564 for (int i = 0; i < argc; i++) { 1565 ds.args_ += argv[i]; 1566 if (i < argc - 1) { 1567 ds.args_ += " "; 1568 } 1569 } 1570 1571 ds.extra_options_ = android::base::GetProperty(PROPERTY_EXTRA_OPTIONS, ""); 1572 if (!ds.extra_options_.empty()) { 1573 // Framework uses a system property to override some command-line args. 1574 // Currently, it contains the type of the requested bugreport. 1575 if (ds.extra_options_ == "bugreportplus") { 1576 // Currently, the dumpstate binder is only used by Shell to update progress. 1577 do_start_service = true; 1578 ds.update_progress_ = true; 1579 do_fb = 0; 1580 } else if (ds.extra_options_ == "bugreportremote") { 1581 do_vibrate = 0; 1582 is_remote_mode = 1; 1583 do_fb = 0; 1584 } else if (ds.extra_options_ == "bugreportwear") { 1585 ds.update_progress_ = true; 1586 } else if (ds.extra_options_ == "bugreporttelephony") { 1587 telephony_only = true; 1588 } else { 1589 MYLOGE("Unknown extra option: %s\n", ds.extra_options_.c_str()); 1590 } 1591 // Reset the property 1592 android::base::SetProperty(PROPERTY_EXTRA_OPTIONS, ""); 1593 } 1594 1595 ds.notification_title = android::base::GetProperty(PROPERTY_EXTRA_TITLE, ""); 1596 if (!ds.notification_title.empty()) { 1597 // Reset the property 1598 android::base::SetProperty(PROPERTY_EXTRA_TITLE, ""); 1599 1600 ds.notification_description = android::base::GetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); 1601 if (!ds.notification_description.empty()) { 1602 // Reset the property 1603 android::base::SetProperty(PROPERTY_EXTRA_DESCRIPTION, ""); 1604 } 1605 MYLOGD("notification (title: %s, description: %s)\n", 1606 ds.notification_title.c_str(), ds.notification_description.c_str()); 1607 } 1608 1609 if ((do_zip_file || do_add_date || ds.update_progress_ || do_broadcast) && !use_outfile) { 1610 ExitOnInvalidArgs(); 1611 } 1612 1613 if (use_control_socket && !do_zip_file) { 1614 ExitOnInvalidArgs(); 1615 } 1616 1617 if (ds.update_progress_ && !do_broadcast) { 1618 ExitOnInvalidArgs(); 1619 } 1620 1621 if (is_remote_mode && (ds.update_progress_ || !do_broadcast || !do_zip_file || !do_add_date)) { 1622 ExitOnInvalidArgs(); 1623 } 1624 1625 if (ds.version_ == VERSION_DEFAULT) { 1626 ds.version_ = VERSION_CURRENT; 1627 } 1628 1629 if (ds.version_ != VERSION_CURRENT && ds.version_ != VERSION_SPLIT_ANR) { 1630 MYLOGE("invalid version requested ('%s'); suppported values are: ('%s', '%s', '%s')\n", 1631 ds.version_.c_str(), VERSION_DEFAULT.c_str(), VERSION_CURRENT.c_str(), 1632 VERSION_SPLIT_ANR.c_str()); 1633 exit(1); 1634 } 1635 1636 if (show_header_only) { 1637 ds.PrintHeader(); 1638 exit(0); 1639 } 1640 1641 /* redirect output if needed */ 1642 bool is_redirecting = !use_socket && use_outfile; 1643 1644 // TODO: temporarily set progress until it's part of the Dumpstate constructor 1645 std::string stats_path = 1646 is_redirecting ? android::base::StringPrintf("%s/dumpstate-stats.txt", dirname(use_outfile)) 1647 : ""; 1648 ds.progress_.reset(new Progress(stats_path)); 1649 1650 /* gets the sequential id */ 1651 uint32_t last_id = android::base::GetIntProperty(PROPERTY_LAST_ID, 0); 1652 ds.id_ = ++last_id; 1653 android::base::SetProperty(PROPERTY_LAST_ID, std::to_string(last_id)); 1654 1655 MYLOGI("begin\n"); 1656 1657 register_sig_handler(); 1658 1659 if (do_start_service) { 1660 MYLOGI("Starting 'dumpstate' service\n"); 1661 android::status_t ret; 1662 if ((ret = android::os::DumpstateService::Start()) != android::OK) { 1663 MYLOGE("Unable to start DumpstateService: %d\n", ret); 1664 } 1665 } 1666 1667 if (PropertiesHelper::IsDryRun()) { 1668 MYLOGI("Running on dry-run mode (to disable it, call 'setprop dumpstate.dry_run false')\n"); 1669 } 1670 1671 MYLOGI("dumpstate info: id=%d, args='%s', extra_options= %s)\n", ds.id_, ds.args_.c_str(), 1672 ds.extra_options_.c_str()); 1673 1674 MYLOGI("bugreport format version: %s\n", ds.version_.c_str()); 1675 1676 ds.do_early_screenshot_ = ds.update_progress_; 1677 1678 // If we are going to use a socket, do it as early as possible 1679 // to avoid timeouts from bugreport. 1680 if (use_socket) { 1681 redirect_to_socket(stdout, "dumpstate"); 1682 } 1683 1684 if (use_control_socket) { 1685 MYLOGD("Opening control socket\n"); 1686 ds.control_socket_fd_ = open_socket("dumpstate"); 1687 ds.update_progress_ = 1; 1688 } 1689 1690 if (is_redirecting) { 1691 ds.bugreport_dir_ = dirname(use_outfile); 1692 std::string build_id = android::base::GetProperty("ro.build.id", "UNKNOWN_BUILD"); 1693 std::string device_name = android::base::GetProperty("ro.product.name", "UNKNOWN_DEVICE"); 1694 ds.base_name_ = android::base::StringPrintf("%s-%s-%s", basename(use_outfile), 1695 device_name.c_str(), build_id.c_str()); 1696 if (do_add_date) { 1697 char date[80]; 1698 strftime(date, sizeof(date), "%Y-%m-%d-%H-%M-%S", localtime(&ds.now_)); 1699 ds.name_ = date; 1700 } else { 1701 ds.name_ = "undated"; 1702 } 1703 1704 if (telephony_only) { 1705 ds.base_name_ += "-telephony"; 1706 } 1707 1708 if (do_fb) { 1709 ds.screenshot_path_ = ds.GetPath(".png"); 1710 } 1711 ds.tmp_path_ = ds.GetPath(".tmp"); 1712 ds.log_path_ = ds.GetPath("-dumpstate_log-" + std::to_string(ds.pid_) + ".txt"); 1713 1714 MYLOGD( 1715 "Bugreport dir: %s\n" 1716 "Base name: %s\n" 1717 "Suffix: %s\n" 1718 "Log path: %s\n" 1719 "Temporary path: %s\n" 1720 "Screenshot path: %s\n", 1721 ds.bugreport_dir_.c_str(), ds.base_name_.c_str(), ds.name_.c_str(), 1722 ds.log_path_.c_str(), ds.tmp_path_.c_str(), ds.screenshot_path_.c_str()); 1723 1724 if (do_zip_file) { 1725 ds.path_ = ds.GetPath(".zip"); 1726 MYLOGD("Creating initial .zip file (%s)\n", ds.path_.c_str()); 1727 create_parent_dirs(ds.path_.c_str()); 1728 ds.zip_file.reset(fopen(ds.path_.c_str(), "wb")); 1729 if (ds.zip_file == nullptr) { 1730 MYLOGE("fopen(%s, 'wb'): %s\n", ds.path_.c_str(), strerror(errno)); 1731 do_zip_file = 0; 1732 } else { 1733 ds.zip_writer_.reset(new ZipWriter(ds.zip_file.get())); 1734 } 1735 ds.AddTextZipEntry("version.txt", ds.version_); 1736 } 1737 1738 if (ds.update_progress_) { 1739 if (do_broadcast) { 1740 // clang-format off 1741 1742 std::vector<std::string> am_args = { 1743 "--receiver-permission", "android.permission.DUMP", 1744 "--es", "android.intent.extra.NAME", ds.name_, 1745 "--ei", "android.intent.extra.ID", std::to_string(ds.id_), 1746 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), 1747 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), 1748 }; 1749 // clang-format on 1750 SendBroadcast("com.android.internal.intent.action.BUGREPORT_STARTED", am_args); 1751 } 1752 if (use_control_socket) { 1753 dprintf(ds.control_socket_fd_, "BEGIN:%s\n", ds.path_.c_str()); 1754 } 1755 } 1756 } 1757 1758 /* read /proc/cmdline before dropping root */ 1759 FILE *cmdline = fopen("/proc/cmdline", "re"); 1760 if (cmdline) { 1761 fgets(cmdline_buf, sizeof(cmdline_buf), cmdline); 1762 fclose(cmdline); 1763 } 1764 1765 if (do_vibrate) { 1766 Vibrate(150); 1767 } 1768 1769 if (do_fb && ds.do_early_screenshot_) { 1770 if (ds.screenshot_path_.empty()) { 1771 // should not have happened 1772 MYLOGE("INTERNAL ERROR: skipping early screenshot because path was not set\n"); 1773 } else { 1774 MYLOGI("taking early screenshot\n"); 1775 ds.TakeScreenshot(); 1776 } 1777 } 1778 1779 if (do_zip_file) { 1780 if (chown(ds.path_.c_str(), AID_SHELL, AID_SHELL)) { 1781 MYLOGE("Unable to change ownership of zip file %s: %s\n", ds.path_.c_str(), 1782 strerror(errno)); 1783 } 1784 } 1785 1786 if (is_redirecting) { 1787 redirect_to_file(stderr, const_cast<char*>(ds.log_path_.c_str())); 1788 if (chown(ds.log_path_.c_str(), AID_SHELL, AID_SHELL)) { 1789 MYLOGE("Unable to change ownership of dumpstate log file %s: %s\n", 1790 ds.log_path_.c_str(), strerror(errno)); 1791 } 1792 /* TODO: rather than generating a text file now and zipping it later, 1793 it would be more efficient to redirect stdout to the zip entry 1794 directly, but the libziparchive doesn't support that option yet. */ 1795 redirect_to_file(stdout, const_cast<char*>(ds.tmp_path_.c_str())); 1796 if (chown(ds.tmp_path_.c_str(), AID_SHELL, AID_SHELL)) { 1797 MYLOGE("Unable to change ownership of temporary bugreport file %s: %s\n", 1798 ds.tmp_path_.c_str(), strerror(errno)); 1799 } 1800 } 1801 1802 // Don't buffer stdout 1803 setvbuf(stdout, nullptr, _IONBF, 0); 1804 1805 // NOTE: there should be no stdout output until now, otherwise it would break the header. 1806 // In particular, DurationReport objects should be created passing 'title, NULL', so their 1807 // duration is logged into MYLOG instead. 1808 ds.PrintHeader(); 1809 1810 if (telephony_only) { 1811 DumpIpTables(); 1812 if (!DropRootUser()) { 1813 return -1; 1814 } 1815 do_dmesg(); 1816 DoLogcat(); 1817 DoKmsg(); 1818 ds.DumpstateBoard(); 1819 DumpModemLogs(); 1820 } else { 1821 // Dumps systrace right away, otherwise it will be filled with unnecessary events. 1822 // First try to dump anrd trace if the daemon is running. Otherwise, dump 1823 // the raw trace. 1824 if (!dump_anrd_trace()) { 1825 dump_systrace(); 1826 } 1827 1828 // Invoking the following dumpsys calls before dump_traces() to try and 1829 // keep the system stats as close to its initial state as possible. 1830 RunDumpsys("DUMPSYS MEMINFO", {"meminfo", "-a"}, 1831 CommandOptions::WithTimeout(90).DropRoot().Build()); 1832 RunDumpsys("DUMPSYS CPUINFO", {"cpuinfo", "-a"}, 1833 CommandOptions::WithTimeout(10).DropRoot().Build()); 1834 1835 // TODO: Drop root user and move into dumpstate() once b/28633932 is fixed. 1836 dump_raft(); 1837 1838 /* collect stack traces from Dalvik and native processes (needs root) */ 1839 dump_traces_path = dump_traces(); 1840 1841 /* Run some operations that require root. */ 1842 tombstone_data.reset(GetDumpFds(TOMBSTONE_DIR, TOMBSTONE_FILE_PREFIX, !ds.IsZipping())); 1843 anr_data.reset(GetDumpFds(ANR_DIR, ANR_FILE_PREFIX, !ds.IsZipping())); 1844 1845 ds.AddDir(RECOVERY_DIR, true); 1846 ds.AddDir(RECOVERY_DATA_DIR, true); 1847 ds.AddDir(LOGPERSIST_DATA_DIR, false); 1848 if (!PropertiesHelper::IsUserBuild()) { 1849 ds.AddDir(PROFILE_DATA_DIR_CUR, true); 1850 ds.AddDir(PROFILE_DATA_DIR_REF, true); 1851 } 1852 add_mountinfo(); 1853 DumpIpTables(); 1854 1855 // Capture any IPSec policies in play. No keys are exposed here. 1856 RunCommand("IP XFRM POLICY", {"ip", "xfrm", "policy"}, 1857 CommandOptions::WithTimeout(10).Build()); 1858 1859 // Run ss as root so we can see socket marks. 1860 RunCommand("DETAILED SOCKET STATE", {"ss", "-eionptu"}, 1861 CommandOptions::WithTimeout(10).Build()); 1862 1863 if (!DropRootUser()) { 1864 return -1; 1865 } 1866 1867 dumpstate(); 1868 } 1869 1870 /* close output if needed */ 1871 if (is_redirecting) { 1872 fclose(stdout); 1873 } 1874 1875 /* rename or zip the (now complete) .tmp file to its final location */ 1876 if (use_outfile) { 1877 1878 /* check if user changed the suffix using system properties */ 1879 std::string name = android::base::GetProperty( 1880 android::base::StringPrintf("dumpstate.%d.name", ds.pid_), ""); 1881 bool change_suffix= false; 1882 if (!name.empty()) { 1883 /* must whitelist which characters are allowed, otherwise it could cross directories */ 1884 std::regex valid_regex("^[-_a-zA-Z0-9]+$"); 1885 if (std::regex_match(name.c_str(), valid_regex)) { 1886 change_suffix = true; 1887 } else { 1888 MYLOGE("invalid suffix provided by user: %s\n", name.c_str()); 1889 } 1890 } 1891 if (change_suffix) { 1892 MYLOGI("changing suffix from %s to %s\n", ds.name_.c_str(), name.c_str()); 1893 ds.name_ = name; 1894 if (!ds.screenshot_path_.empty()) { 1895 std::string new_screenshot_path = ds.GetPath(".png"); 1896 if (rename(ds.screenshot_path_.c_str(), new_screenshot_path.c_str())) { 1897 MYLOGE("rename(%s, %s): %s\n", ds.screenshot_path_.c_str(), 1898 new_screenshot_path.c_str(), strerror(errno)); 1899 } else { 1900 ds.screenshot_path_ = new_screenshot_path; 1901 } 1902 } 1903 } 1904 1905 bool do_text_file = true; 1906 if (do_zip_file) { 1907 if (!ds.FinishZipFile()) { 1908 MYLOGE("Failed to finish zip file; sending text bugreport instead\n"); 1909 do_text_file = true; 1910 } else { 1911 do_text_file = false; 1912 // Since zip file is already created, it needs to be renamed. 1913 std::string new_path = ds.GetPath(".zip"); 1914 if (ds.path_ != new_path) { 1915 MYLOGD("Renaming zip file from %s to %s\n", ds.path_.c_str(), new_path.c_str()); 1916 if (rename(ds.path_.c_str(), new_path.c_str())) { 1917 MYLOGE("rename(%s, %s): %s\n", ds.path_.c_str(), new_path.c_str(), 1918 strerror(errno)); 1919 } else { 1920 ds.path_ = new_path; 1921 } 1922 } 1923 } 1924 } 1925 if (do_text_file) { 1926 ds.path_ = ds.GetPath(".txt"); 1927 MYLOGD("Generating .txt bugreport at %s from %s\n", ds.path_.c_str(), 1928 ds.tmp_path_.c_str()); 1929 if (rename(ds.tmp_path_.c_str(), ds.path_.c_str())) { 1930 MYLOGE("rename(%s, %s): %s\n", ds.tmp_path_.c_str(), ds.path_.c_str(), 1931 strerror(errno)); 1932 ds.path_.clear(); 1933 } 1934 } 1935 if (use_control_socket) { 1936 if (do_text_file) { 1937 dprintf(ds.control_socket_fd_, 1938 "FAIL:could not create zip file, check %s " 1939 "for more details\n", 1940 ds.log_path_.c_str()); 1941 } else { 1942 dprintf(ds.control_socket_fd_, "OK:%s\n", ds.path_.c_str()); 1943 } 1944 } 1945 } 1946 1947 /* vibrate a few but shortly times to let user know it's finished */ 1948 for (int i = 0; i < 3; i++) { 1949 Vibrate(75); 1950 usleep((75 + 50) * 1000); 1951 } 1952 1953 /* tell activity manager we're done */ 1954 if (do_broadcast) { 1955 if (!ds.path_.empty()) { 1956 MYLOGI("Final bugreport path: %s\n", ds.path_.c_str()); 1957 // clang-format off 1958 1959 std::vector<std::string> am_args = { 1960 "--receiver-permission", "android.permission.DUMP", 1961 "--ei", "android.intent.extra.ID", std::to_string(ds.id_), 1962 "--ei", "android.intent.extra.PID", std::to_string(ds.pid_), 1963 "--ei", "android.intent.extra.MAX", std::to_string(ds.progress_->GetMax()), 1964 "--es", "android.intent.extra.BUGREPORT", ds.path_, 1965 "--es", "android.intent.extra.DUMPSTATE_LOG", ds.log_path_ 1966 }; 1967 // clang-format on 1968 if (do_fb) { 1969 am_args.push_back("--es"); 1970 am_args.push_back("android.intent.extra.SCREENSHOT"); 1971 am_args.push_back(ds.screenshot_path_); 1972 } 1973 if (!ds.notification_title.empty()) { 1974 am_args.push_back("--es"); 1975 am_args.push_back("android.intent.extra.TITLE"); 1976 am_args.push_back(ds.notification_title); 1977 if (!ds.notification_description.empty()) { 1978 am_args.push_back("--es"); 1979 am_args.push_back("android.intent.extra.DESCRIPTION"); 1980 am_args.push_back(ds.notification_description); 1981 } 1982 } 1983 if (is_remote_mode) { 1984 am_args.push_back("--es"); 1985 am_args.push_back("android.intent.extra.REMOTE_BUGREPORT_HASH"); 1986 am_args.push_back(SHA256_file_hash(ds.path_)); 1987 SendBroadcast("com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED", 1988 am_args); 1989 } else { 1990 SendBroadcast("com.android.internal.intent.action.BUGREPORT_FINISHED", am_args); 1991 } 1992 } else { 1993 MYLOGE("Skipping finished broadcast because bugreport could not be generated\n"); 1994 } 1995 } 1996 1997 MYLOGD("Final progress: %d/%d (estimated %d)\n", ds.progress_->Get(), ds.progress_->GetMax(), 1998 ds.progress_->GetInitialMax()); 1999 ds.progress_->Save(); 2000 MYLOGI("done (id %d)\n", ds.id_); 2001 2002 if (is_redirecting) { 2003 fclose(stderr); 2004 } 2005 2006 if (use_control_socket && ds.control_socket_fd_ != -1) { 2007 MYLOGD("Closing control socket\n"); 2008 close(ds.control_socket_fd_); 2009 } 2010 2011 return 0; 2012} 2013