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