blob: 236c0fe675d4ea0dabfb6498d9dafd97dad8f8ba [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
Mike Lockwoodbb6fa172009-10-05 23:23:40 -040031#define LOG_NDEBUG 0
32#define LOG_TAG "dumpstate"
33#include <utils/Log.h>
34
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035#include "dumpstate.h"
36
37static char* const gzip_args[] = { "gzip", "-6", 0 };
38static int start_pattern[] = { 150, 0 };
39static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
40
41static struct tm now;
42
San Mehat30b9f572009-09-01 13:27:20 -070043static void dump_kernel_log(const char *path, const char *title) ;
44
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045/* dumps the current system state to stdout */
46static void dumpstate(int full) {
47 if (full) {
48 PRINT("========================================================");
49 PRINT("== dumpstate");
50 PRINT("========================================================");
51 PRINT("------ MEMORY INFO ------");
52 DUMP("/proc/meminfo");
53 PRINT("------ CPU INFO ------");
54 EXEC7("top", "-n", "1", "-d", "1", "-m", "30", "-t");
55 PRINT("------ PROCRANK ------");
56 EXEC_XBIN("procrank");
57 PRINT("------ VIRTUAL MEMORY STATS ------");
58 DUMP("/proc/vmstat");
Dianne Hackbornb80b8d52009-10-08 10:49:12 -070059 PRINT("------ VMALLOC INFO ------");
60 DUMP("/proc/vmallocinfo");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061 PRINT("------ SLAB INFO ------");
62 DUMP("/proc/slabinfo");
63 PRINT("------ ZONEINFO ------");
64 DUMP("/proc/zoneinfo");
65 PRINT("------ SYSTEM LOG ------");
66 EXEC4("logcat", "-v", "time", "-d", "*:v");
67 PRINT("------ VM TRACES ------");
68 DUMP("/data/anr/traces.txt");
69 PRINT("------ EVENT LOG TAGS ------");
70 DUMP("/etc/event-log-tags");
71 PRINT("------ EVENT LOG ------");
72 EXEC6("logcat", "-b", "events", "-v", "time", "-d", "*:v");
73 PRINT("------ RADIO LOG ------");
74 EXEC6("logcat", "-b", "radio", "-v", "time", "-d", "*:v");
75 PRINT("------ NETWORK STATE ------");
76 PRINT("Interfaces:");
77 EXEC("netcfg");
78 PRINT("");
79 PRINT("Routes:");
80 DUMP("/proc/net/route");
Dmitry Shmidt64bf3d52009-12-16 16:05:08 -080081#ifdef FWDUMP_bcm4329
82 PRINT("Dump wlan FW log");
83 EXEC_XBIN6("su", "root","dhdutil","-i","eth0","upload","/data/local/tmp/wlan_crash.dump");
84#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085 PRINT("------ SYSTEM PROPERTIES ------");
86 print_properties();
87 PRINT("------ KERNEL LOG ------");
88 EXEC("dmesg");
89 PRINT("------ KERNEL WAKELOCKS ------");
90 DUMP("/proc/wakelocks");
Mike Chanc6b406f2009-11-19 16:01:05 -080091 PRINT("------ KERNEL CPUFREQ ------");
92 DUMP("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 PRINT("");
94 PRINT("------ PROCESSES ------");
Evan Millar26a2d822009-10-29 12:41:39 -070095 EXEC1("ps", "-P");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096 PRINT("------ PROCESSES AND THREADS ------");
Evan Millar26a2d822009-10-29 12:41:39 -070097 EXEC3("ps", "-t", "-p", "-P");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080098 PRINT("------ LIBRANK ------");
99 EXEC_XBIN("librank");
100 PRINT("------ BINDER FAILED TRANSACTION LOG ------");
101 DUMP("/proc/binder/failed_transaction_log");
102 PRINT("");
103 PRINT("------ BINDER TRANSACTION LOG ------");
104 DUMP("/proc/binder/transaction_log");
105 PRINT("");
106 PRINT("------ BINDER TRANSACTIONS ------");
107 DUMP("/proc/binder/transactions");
108 PRINT("");
109 PRINT("------ BINDER STATS ------");
110 DUMP("/proc/binder/stats");
111 PRINT("");
112 PRINT("------ BINDER PROCESS STATE: $i ------");
113 DUMP_FILES("/proc/binder/proc");
114 PRINT("------ FILESYSTEMS ------");
115 EXEC("df");
116 PRINT("------ PACKAGE SETTINGS ------");
117 DUMP("/data/system/packages.xml");
118 PRINT("------ PACKAGE UID ERRORS ------");
119 DUMP("/data/system/uiderrors.txt");
San Mehat30b9f572009-09-01 13:27:20 -0700120
Dima Zavinf8172182009-11-25 23:31:48 -0800121 dump_kernel_log("/proc/last_kmsg", "LAST KMSG");
Iliyan Malchev326e3e22009-11-15 18:28:06 -0800122
123 PRINT("------ LAST RADIO LOG ------");
124 EXEC1("parse_radio_log", "/proc/last_radio_log");
125
San Mehat30b9f572009-09-01 13:27:20 -0700126 dump_kernel_log("/data/dontpanic/apanic_console",
127 "PANIC CONSOLE");
128 dump_kernel_log("/data/dontpanic/apanic_threads",
129 "PANIC THREADS");
Mike Lockwood2ecf3f5e02009-10-04 17:21:05 -0400130
131 PRINT("------ BACKLIGHTS ------");
132 DUMP_PROMPT("LCD brightness=", "/sys/class/leds/lcd-backlight/brightness");
133 DUMP_PROMPT("Button brightness=", "/sys/class/leds/button-backlight/brightness");
134 DUMP_PROMPT("Keyboard brightness=", "/sys/class/leds/keyboard-backlight/brightness");
135 DUMP_PROMPT("ALS mode=", "/sys/class/leds/lcd-backlight/als");
136 DUMP_PROMPT("LCD driver registers:\n", "/sys/class/leds/lcd-backlight/registers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 }
138 PRINT("========================================================");
139 PRINT("== build.prop");
140 PRINT("========================================================");
141
142 /* the crash server parses key-value pairs between the VERSION INFO and
143 * END lines so we can aggregate crash reports based on this data.
144 */
145 PRINT("------ VERSION INFO ------");
146 print_date("currenttime=", &now);
147 DUMP_PROMPT("kernel.version=", "/proc/version");
148 DUMP_PROMPT("kernel.cmdline=", "/proc/cmdline");
149 DUMP("/system/build.prop");
150 PROPERTY("gsm.version.ril-impl");
151 PROPERTY("gsm.version.baseband");
152 PROPERTY("gsm.imei");
153 PROPERTY("gsm.sim.operator.numeric");
154 PROPERTY("gsm.operator.alpha");
155 PRINT("------ END ------");
156
157 if (full) {
158 PRINT("========================================================");
159 PRINT("== dumpsys");
160 PRINT("========================================================");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800161 /* the full dumpsys is starting to take a long time, so we need
162 to increase its timeout. we really need to do the timeouts in
163 dumpsys itself... */
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700164 EXEC_TIMEOUT("dumpsys", 60);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 }
166}
167
168/* used to check the file name passed via argv[0] */
169static int check_command_name(const char* name, const char* test) {
170 int name_length, test_length;
171
172 if (!strcmp(name, test))
173 return 1;
174
175 name_length = strlen(name);
176 test_length = strlen(test);
177
178 if (name_length > test_length + 2) {
179 name += (name_length - test_length);
180 if (name[-1] != '/')
181 return 0;
182 if (!strcmp(name, test))
183 return 1;
184 }
185
186 return 0;
187}
188
189int main(int argc, char *argv[]) {
190 int dumpcrash = check_command_name(argv[0], "dumpcrash");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 int add_date = 0;
192 char* outfile = 0;
193 int vibrate = 0;
194 int compress = 0;
Mike Lockwood8d533732009-09-02 18:01:05 -0400195 int socket = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 int c, fd, vibrate_fd, fds[2];
197 char path[PATH_MAX];
198 pid_t pid;
Mike Lockwood472be482009-05-22 13:31:42 -0400199 gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200
Mike Lockwoodbb6fa172009-10-05 23:23:40 -0400201 LOGI("begin\n");
202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 /* set as high priority, and protect from OOM killer */
204 setpriority(PRIO_PROCESS, 0, -20);
205 protect_from_oom_killer();
206
207 get_time(&now);
208
Mike Lockwood8d533732009-09-02 18:01:05 -0400209 do {
210 c = getopt(argc, argv, "do:svz");
211 if (c == EOF)
212 break;
213 switch (c) {
214 case 'd':
215 add_date = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 break;
Mike Lockwood8d533732009-09-02 18:01:05 -0400217 case 'o':
218 outfile = optarg;
219 break;
220 case 'v':
221 vibrate = 1;
222 break;
223 case 'z':
224 compress = 1;
225 break;
226 case 's':
227 socket = 1;
228 break;
229 case '?':
230 fprintf(stderr, "%s: invalid option -%c\n",
231 argv[0], optopt);
232 exit(1);
233 }
234 } while (1);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235
236 /* open vibrator before switching user */
237 if (vibrate) {
238 vibrate_fd = open("/sys/class/timed_output/vibrator/enable", O_WRONLY);
239 if (vibrate_fd > 0)
240 fcntl(vibrate_fd, F_SETFD, FD_CLOEXEC);
241 } else
242 vibrate_fd = -1;
243
244 /* switch to non-root user and group */
Mike Lockwood472be482009-05-22 13:31:42 -0400245 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 setuid(AID_SHELL);
247
248 /* make it safe to use both printf and STDOUT_FILENO */
249 setvbuf(stdout, 0, _IONBF, 0);
250
Mike Lockwood8d533732009-09-02 18:01:05 -0400251 if (socket) {
252 struct sockaddr addr;
253 socklen_t alen;
254
255 int s = android_get_control_socket("dumpstate");
256 if (s < 0) {
257 fprintf(stderr, "could not open dumpstate socket\n");
258 exit(1);
259 }
260 if (listen(s, 4) < 0) {
261 fprintf(stderr, "could not listen on dumpstate socket\n");
262 exit(1);
263 }
264
265 alen = sizeof(addr);
266 fd = accept(s, &addr, &alen);
267 if (fd < 0) {
268 fprintf(stderr, "could not accept dumpstate socket\n");
269 exit(1);
270 }
271
272 /* redirect stdout to the socket */
273 dup2(fd, STDOUT_FILENO);
274 close(fd);
275 } else if (outfile) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 if (strlen(outfile) > sizeof(path) - 100)
277 exit(1);
278
279 strcpy(path, outfile);
280 if (add_date) {
281 char date[260];
282 strftime(date, sizeof(date),
283 "-%Y-%m-%d-%H-%M-%S",
284 &now);
285 strcat(path, date);
286 }
287 if (compress)
288 strcat(path, ".gz");
289 else
290 strcat(path, ".txt");
291
292 /* ensure that all directories in the path exist */
293 create_directories(path);
294 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
295 if (fd < 0)
296 return fd;
297
298 if (compress) {
299 pipe(fds);
300
301 /* redirect our stdout to the pipe */
302 dup2(fds[1], STDOUT_FILENO);
303 close(fds[1]);
304
305 if ((pid = fork()) < 0)
306 {
307 fprintf(stderr, "fork error\n");
308 exit(1);
309 }
310
311 if (pid) {
312 /* parent case */
313
314 /* close our copy of the input to gzip */
315 close(fds[0]);
316 /* close our copy of the output file */
317 close(fd);
318 } else {
319 /* child case */
320
321 /* redirect our input pipe to stdin */
322 dup2(fds[0], STDIN_FILENO);
323 close(fds[0]);
324
325 /* redirect stdout to the output file */
326 dup2(fd, STDOUT_FILENO);
327 close(fd);
328
329 /* run gzip to postprocess our output */
330 execv("/system/bin/gzip", gzip_args);
331 fprintf(stderr, "execv returned\n");
332 }
333 } else {
334 /* redirect stdout to the output file */
335 dup2(fd, STDOUT_FILENO);
336 close(fd);
337 }
338 }
339 /* else everything will print to stdout */
340
341 if (vibrate) {
342 vibrate_pattern(vibrate_fd, start_pattern);
343 }
344 dumpstate(!dumpcrash);
345 if (vibrate) {
346 vibrate_pattern(vibrate_fd, end_pattern);
347 close(vibrate_fd);
348 }
349
350 /* so gzip will terminate */
351 close(STDOUT_FILENO);
352
Mike Lockwoodbb6fa172009-10-05 23:23:40 -0400353 LOGI("done\n");
354
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 return 0;
356}
357
San Mehat30b9f572009-09-01 13:27:20 -0700358static void dump_kernel_log(const char *path, const char *title)
359
360{
San Mehata4eb91d2009-09-05 15:20:20 -0700361 printf("------ KERNEL %s LOG ------\n", title);
362 if (access(path, R_OK) < 0)
363 printf("%s: %s\n", path, strerror(errno));
364 else {
365 struct stat sbuf;
366
367 if (stat(path, &sbuf) < 0)
368 printf("%s: stat failed (%s)\n", path, strerror(errno));
369 else
San Mehataf686342009-10-02 13:15:53 -0700370 printf("Harvested %s", ctime(&sbuf.st_mtime));
San Mehata4eb91d2009-09-05 15:20:20 -0700371
372 DUMP(path);
373 }
San Mehat30b9f572009-09-01 13:27:20 -0700374}