OSDN Git Service

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