blob: 4dda68ccc60211dab865abc0453d8bfead9a5c84 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21#include <sys/stat.h>
22#include <limits.h>
San Mehat30b9f572009-09-01 13:27:20 -070023#include <errno.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024#include <fcntl.h>
25#include <sys/time.h>
26#include <sys/resource.h>
27
Mike Lockwood8d533732009-09-02 18:01:05 -040028#include <cutils/sockets.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029#include "private/android_filesystem_config.h"
30
31#include "dumpstate.h"
32
33static char* const gzip_args[] = { "gzip", "-6", 0 };
34static int start_pattern[] = { 150, 0 };
35static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
36
37static struct tm now;
38
San Mehat30b9f572009-09-01 13:27:20 -070039static void dump_kernel_log(const char *path, const char *title) ;
40
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041/* dumps the current system state to stdout */
42static void dumpstate(int full) {
43 if (full) {
44 PRINT("========================================================");
45 PRINT("== dumpstate");
46 PRINT("========================================================");
47 PRINT("------ MEMORY INFO ------");
48 DUMP("/proc/meminfo");
49 PRINT("------ CPU INFO ------");
50 EXEC7("top", "-n", "1", "-d", "1", "-m", "30", "-t");
51 PRINT("------ PROCRANK ------");
52 EXEC_XBIN("procrank");
53 PRINT("------ VIRTUAL MEMORY STATS ------");
54 DUMP("/proc/vmstat");
55 PRINT("------ SLAB INFO ------");
56 DUMP("/proc/slabinfo");
57 PRINT("------ ZONEINFO ------");
58 DUMP("/proc/zoneinfo");
59 PRINT("------ SYSTEM LOG ------");
60 EXEC4("logcat", "-v", "time", "-d", "*:v");
61 PRINT("------ VM TRACES ------");
62 DUMP("/data/anr/traces.txt");
63 PRINT("------ EVENT LOG TAGS ------");
64 DUMP("/etc/event-log-tags");
65 PRINT("------ EVENT LOG ------");
66 EXEC6("logcat", "-b", "events", "-v", "time", "-d", "*:v");
67 PRINT("------ RADIO LOG ------");
68 EXEC6("logcat", "-b", "radio", "-v", "time", "-d", "*:v");
69 PRINT("------ NETWORK STATE ------");
70 PRINT("Interfaces:");
71 EXEC("netcfg");
72 PRINT("");
73 PRINT("Routes:");
74 DUMP("/proc/net/route");
75 PRINT("------ SYSTEM PROPERTIES ------");
76 print_properties();
77 PRINT("------ KERNEL LOG ------");
78 EXEC("dmesg");
79 PRINT("------ KERNEL WAKELOCKS ------");
80 DUMP("/proc/wakelocks");
81 PRINT("");
82 PRINT("------ PROCESSES ------");
83 EXEC("ps");
84 PRINT("------ PROCESSES AND THREADS ------");
85 EXEC2("ps", "-t", "-p");
86 PRINT("------ LIBRANK ------");
87 EXEC_XBIN("librank");
88 PRINT("------ BINDER FAILED TRANSACTION LOG ------");
89 DUMP("/proc/binder/failed_transaction_log");
90 PRINT("");
91 PRINT("------ BINDER TRANSACTION LOG ------");
92 DUMP("/proc/binder/transaction_log");
93 PRINT("");
94 PRINT("------ BINDER TRANSACTIONS ------");
95 DUMP("/proc/binder/transactions");
96 PRINT("");
97 PRINT("------ BINDER STATS ------");
98 DUMP("/proc/binder/stats");
99 PRINT("");
100 PRINT("------ BINDER PROCESS STATE: $i ------");
101 DUMP_FILES("/proc/binder/proc");
102 PRINT("------ FILESYSTEMS ------");
103 EXEC("df");
104 PRINT("------ PACKAGE SETTINGS ------");
105 DUMP("/data/system/packages.xml");
106 PRINT("------ PACKAGE UID ERRORS ------");
107 DUMP("/data/system/uiderrors.txt");
San Mehat30b9f572009-09-01 13:27:20 -0700108
109 dump_kernel_log("/data/dontpanic/last_kmsg", "RAMCONSOLE");
110 dump_kernel_log("/data/dontpanic/apanic_console",
111 "PANIC CONSOLE");
112 dump_kernel_log("/data/dontpanic/apanic_threads",
113 "PANIC THREADS");
Mike Lockwood2ecf3f5e02009-10-04 17:21:05 -0400114
115 PRINT("------ BACKLIGHTS ------");
116 DUMP_PROMPT("LCD brightness=", "/sys/class/leds/lcd-backlight/brightness");
117 DUMP_PROMPT("Button brightness=", "/sys/class/leds/button-backlight/brightness");
118 DUMP_PROMPT("Keyboard brightness=", "/sys/class/leds/keyboard-backlight/brightness");
119 DUMP_PROMPT("ALS mode=", "/sys/class/leds/lcd-backlight/als");
120 DUMP_PROMPT("LCD driver registers:\n", "/sys/class/leds/lcd-backlight/registers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 }
122 PRINT("========================================================");
123 PRINT("== build.prop");
124 PRINT("========================================================");
125
126 /* the crash server parses key-value pairs between the VERSION INFO and
127 * END lines so we can aggregate crash reports based on this data.
128 */
129 PRINT("------ VERSION INFO ------");
130 print_date("currenttime=", &now);
131 DUMP_PROMPT("kernel.version=", "/proc/version");
132 DUMP_PROMPT("kernel.cmdline=", "/proc/cmdline");
133 DUMP("/system/build.prop");
134 PROPERTY("gsm.version.ril-impl");
135 PROPERTY("gsm.version.baseband");
136 PROPERTY("gsm.imei");
137 PROPERTY("gsm.sim.operator.numeric");
138 PROPERTY("gsm.operator.alpha");
139 PRINT("------ END ------");
140
141 if (full) {
142 PRINT("========================================================");
143 PRINT("== dumpsys");
144 PRINT("========================================================");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800145 /* the full dumpsys is starting to take a long time, so we need
146 to increase its timeout. we really need to do the timeouts in
147 dumpsys itself... */
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700148 EXEC_TIMEOUT("dumpsys", 60);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 }
150}
151
152/* used to check the file name passed via argv[0] */
153static int check_command_name(const char* name, const char* test) {
154 int name_length, test_length;
155
156 if (!strcmp(name, test))
157 return 1;
158
159 name_length = strlen(name);
160 test_length = strlen(test);
161
162 if (name_length > test_length + 2) {
163 name += (name_length - test_length);
164 if (name[-1] != '/')
165 return 0;
166 if (!strcmp(name, test))
167 return 1;
168 }
169
170 return 0;
171}
172
173int main(int argc, char *argv[]) {
174 int dumpcrash = check_command_name(argv[0], "dumpcrash");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 int add_date = 0;
176 char* outfile = 0;
177 int vibrate = 0;
178 int compress = 0;
Mike Lockwood8d533732009-09-02 18:01:05 -0400179 int socket = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800180 int c, fd, vibrate_fd, fds[2];
181 char path[PATH_MAX];
182 pid_t pid;
Mike Lockwood472be482009-05-22 13:31:42 -0400183 gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184
185 /* set as high priority, and protect from OOM killer */
186 setpriority(PRIO_PROCESS, 0, -20);
187 protect_from_oom_killer();
188
189 get_time(&now);
190
Mike Lockwood8d533732009-09-02 18:01:05 -0400191 do {
192 c = getopt(argc, argv, "do:svz");
193 if (c == EOF)
194 break;
195 switch (c) {
196 case 'd':
197 add_date = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 break;
Mike Lockwood8d533732009-09-02 18:01:05 -0400199 case 'o':
200 outfile = optarg;
201 break;
202 case 'v':
203 vibrate = 1;
204 break;
205 case 'z':
206 compress = 1;
207 break;
208 case 's':
209 socket = 1;
210 break;
211 case '?':
212 fprintf(stderr, "%s: invalid option -%c\n",
213 argv[0], optopt);
214 exit(1);
215 }
216 } while (1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217
218 /* open vibrator before switching user */
219 if (vibrate) {
220 vibrate_fd = open("/sys/class/timed_output/vibrator/enable", O_WRONLY);
221 if (vibrate_fd > 0)
222 fcntl(vibrate_fd, F_SETFD, FD_CLOEXEC);
223 } else
224 vibrate_fd = -1;
225
226 /* switch to non-root user and group */
Mike Lockwood472be482009-05-22 13:31:42 -0400227 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 setuid(AID_SHELL);
229
230 /* make it safe to use both printf and STDOUT_FILENO */
231 setvbuf(stdout, 0, _IONBF, 0);
232
Mike Lockwood8d533732009-09-02 18:01:05 -0400233 if (socket) {
234 struct sockaddr addr;
235 socklen_t alen;
236
237 int s = android_get_control_socket("dumpstate");
238 if (s < 0) {
239 fprintf(stderr, "could not open dumpstate socket\n");
240 exit(1);
241 }
242 if (listen(s, 4) < 0) {
243 fprintf(stderr, "could not listen on dumpstate socket\n");
244 exit(1);
245 }
246
247 alen = sizeof(addr);
248 fd = accept(s, &addr, &alen);
249 if (fd < 0) {
250 fprintf(stderr, "could not accept dumpstate socket\n");
251 exit(1);
252 }
253
254 /* redirect stdout to the socket */
255 dup2(fd, STDOUT_FILENO);
256 close(fd);
257 } else if (outfile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 if (strlen(outfile) > sizeof(path) - 100)
259 exit(1);
260
261 strcpy(path, outfile);
262 if (add_date) {
263 char date[260];
264 strftime(date, sizeof(date),
265 "-%Y-%m-%d-%H-%M-%S",
266 &now);
267 strcat(path, date);
268 }
269 if (compress)
270 strcat(path, ".gz");
271 else
272 strcat(path, ".txt");
273
274 /* ensure that all directories in the path exist */
275 create_directories(path);
276 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
277 if (fd < 0)
278 return fd;
279
280 if (compress) {
281 pipe(fds);
282
283 /* redirect our stdout to the pipe */
284 dup2(fds[1], STDOUT_FILENO);
285 close(fds[1]);
286
287 if ((pid = fork()) < 0)
288 {
289 fprintf(stderr, "fork error\n");
290 exit(1);
291 }
292
293 if (pid) {
294 /* parent case */
295
296 /* close our copy of the input to gzip */
297 close(fds[0]);
298 /* close our copy of the output file */
299 close(fd);
300 } else {
301 /* child case */
302
303 /* redirect our input pipe to stdin */
304 dup2(fds[0], STDIN_FILENO);
305 close(fds[0]);
306
307 /* redirect stdout to the output file */
308 dup2(fd, STDOUT_FILENO);
309 close(fd);
310
311 /* run gzip to postprocess our output */
312 execv("/system/bin/gzip", gzip_args);
313 fprintf(stderr, "execv returned\n");
314 }
315 } else {
316 /* redirect stdout to the output file */
317 dup2(fd, STDOUT_FILENO);
318 close(fd);
319 }
320 }
321 /* else everything will print to stdout */
322
323 if (vibrate) {
324 vibrate_pattern(vibrate_fd, start_pattern);
325 }
326 dumpstate(!dumpcrash);
327 if (vibrate) {
328 vibrate_pattern(vibrate_fd, end_pattern);
329 close(vibrate_fd);
330 }
331
332 /* so gzip will terminate */
333 close(STDOUT_FILENO);
334
335 return 0;
336}
337
San Mehat30b9f572009-09-01 13:27:20 -0700338static void dump_kernel_log(const char *path, const char *title)
339
340{
San Mehata4eb91d2009-09-05 15:20:20 -0700341 printf("------ KERNEL %s LOG ------\n", title);
342 if (access(path, R_OK) < 0)
343 printf("%s: %s\n", path, strerror(errno));
344 else {
345 struct stat sbuf;
346
347 if (stat(path, &sbuf) < 0)
348 printf("%s: stat failed (%s)\n", path, strerror(errno));
349 else
San Mehataf686342009-10-02 13:15:53 -0700350 printf("Harvested %s", ctime(&sbuf.st_mtime));
San Mehata4eb91d2009-09-05 15:20:20 -0700351
352 DUMP(path);
353 }
San Mehat30b9f572009-09-01 13:27:20 -0700354}
355