blob: 3ddc9228b4d7cd6442aa376e6fe0d0610df05c8d [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
28#include "private/android_filesystem_config.h"
29
30#include "dumpstate.h"
31
32static char* const gzip_args[] = { "gzip", "-6", 0 };
33static int start_pattern[] = { 150, 0 };
34static int end_pattern[] = { 75, 50, 75, 50, 75, 0 };
35
36static struct tm now;
37
San Mehat30b9f572009-09-01 13:27:20 -070038static void dump_kernel_log(const char *path, const char *title) ;
39
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040/* dumps the current system state to stdout */
41static void dumpstate(int full) {
42 if (full) {
43 PRINT("========================================================");
44 PRINT("== dumpstate");
45 PRINT("========================================================");
46 PRINT("------ MEMORY INFO ------");
47 DUMP("/proc/meminfo");
48 PRINT("------ CPU INFO ------");
49 EXEC7("top", "-n", "1", "-d", "1", "-m", "30", "-t");
50 PRINT("------ PROCRANK ------");
51 EXEC_XBIN("procrank");
52 PRINT("------ VIRTUAL MEMORY STATS ------");
53 DUMP("/proc/vmstat");
54 PRINT("------ SLAB INFO ------");
55 DUMP("/proc/slabinfo");
56 PRINT("------ ZONEINFO ------");
57 DUMP("/proc/zoneinfo");
58 PRINT("------ SYSTEM LOG ------");
59 EXEC4("logcat", "-v", "time", "-d", "*:v");
60 PRINT("------ VM TRACES ------");
61 DUMP("/data/anr/traces.txt");
62 PRINT("------ EVENT LOG TAGS ------");
63 DUMP("/etc/event-log-tags");
64 PRINT("------ EVENT LOG ------");
65 EXEC6("logcat", "-b", "events", "-v", "time", "-d", "*:v");
66 PRINT("------ RADIO LOG ------");
67 EXEC6("logcat", "-b", "radio", "-v", "time", "-d", "*:v");
68 PRINT("------ NETWORK STATE ------");
69 PRINT("Interfaces:");
70 EXEC("netcfg");
71 PRINT("");
72 PRINT("Routes:");
73 DUMP("/proc/net/route");
74 PRINT("------ SYSTEM PROPERTIES ------");
75 print_properties();
76 PRINT("------ KERNEL LOG ------");
77 EXEC("dmesg");
78 PRINT("------ KERNEL WAKELOCKS ------");
79 DUMP("/proc/wakelocks");
80 PRINT("");
81 PRINT("------ PROCESSES ------");
82 EXEC("ps");
83 PRINT("------ PROCESSES AND THREADS ------");
84 EXEC2("ps", "-t", "-p");
85 PRINT("------ LIBRANK ------");
86 EXEC_XBIN("librank");
87 PRINT("------ BINDER FAILED TRANSACTION LOG ------");
88 DUMP("/proc/binder/failed_transaction_log");
89 PRINT("");
90 PRINT("------ BINDER TRANSACTION LOG ------");
91 DUMP("/proc/binder/transaction_log");
92 PRINT("");
93 PRINT("------ BINDER TRANSACTIONS ------");
94 DUMP("/proc/binder/transactions");
95 PRINT("");
96 PRINT("------ BINDER STATS ------");
97 DUMP("/proc/binder/stats");
98 PRINT("");
99 PRINT("------ BINDER PROCESS STATE: $i ------");
100 DUMP_FILES("/proc/binder/proc");
101 PRINT("------ FILESYSTEMS ------");
102 EXEC("df");
103 PRINT("------ PACKAGE SETTINGS ------");
104 DUMP("/data/system/packages.xml");
105 PRINT("------ PACKAGE UID ERRORS ------");
106 DUMP("/data/system/uiderrors.txt");
San Mehat30b9f572009-09-01 13:27:20 -0700107
108 dump_kernel_log("/data/dontpanic/last_kmsg", "RAMCONSOLE");
109 dump_kernel_log("/data/dontpanic/apanic_console",
110 "PANIC CONSOLE");
111 dump_kernel_log("/data/dontpanic/apanic_threads",
112 "PANIC THREADS");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 }
114 PRINT("========================================================");
115 PRINT("== build.prop");
116 PRINT("========================================================");
117
118 /* the crash server parses key-value pairs between the VERSION INFO and
119 * END lines so we can aggregate crash reports based on this data.
120 */
121 PRINT("------ VERSION INFO ------");
122 print_date("currenttime=", &now);
123 DUMP_PROMPT("kernel.version=", "/proc/version");
124 DUMP_PROMPT("kernel.cmdline=", "/proc/cmdline");
125 DUMP("/system/build.prop");
126 PROPERTY("gsm.version.ril-impl");
127 PROPERTY("gsm.version.baseband");
128 PROPERTY("gsm.imei");
129 PROPERTY("gsm.sim.operator.numeric");
130 PROPERTY("gsm.operator.alpha");
131 PRINT("------ END ------");
132
133 if (full) {
134 PRINT("========================================================");
135 PRINT("== dumpsys");
136 PRINT("========================================================");
The Android Open Source Project4df24232009-03-05 14:34:35 -0800137 /* the full dumpsys is starting to take a long time, so we need
138 to increase its timeout. we really need to do the timeouts in
139 dumpsys itself... */
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700140 EXEC_TIMEOUT("dumpsys", 60);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 }
142}
143
144/* used to check the file name passed via argv[0] */
145static int check_command_name(const char* name, const char* test) {
146 int name_length, test_length;
147
148 if (!strcmp(name, test))
149 return 1;
150
151 name_length = strlen(name);
152 test_length = strlen(test);
153
154 if (name_length > test_length + 2) {
155 name += (name_length - test_length);
156 if (name[-1] != '/')
157 return 0;
158 if (!strcmp(name, test))
159 return 1;
160 }
161
162 return 0;
163}
164
165int main(int argc, char *argv[]) {
166 int dumpcrash = check_command_name(argv[0], "dumpcrash");
167 int bugreport = check_command_name(argv[0], "bugreport");
168 int add_date = 0;
169 char* outfile = 0;
170 int vibrate = 0;
171 int compress = 0;
172 int c, fd, vibrate_fd, fds[2];
173 char path[PATH_MAX];
174 pid_t pid;
Mike Lockwood472be482009-05-22 13:31:42 -0400175 gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176
177 /* set as high priority, and protect from OOM killer */
178 setpriority(PRIO_PROCESS, 0, -20);
179 protect_from_oom_killer();
180
181 get_time(&now);
182
183 if (bugreport) {
184 do {
185 c = getopt(argc, argv, "do:vz");
186 if (c == EOF)
187 break;
188 switch (c) {
189 case 'd':
190 add_date = 1;
191 break;
192 case 'o':
193 outfile = optarg;
194 break;
195 case 'v':
196 vibrate = 1;
197 break;
198 case 'z':
199 compress = 1;
200 break;
201 case '?':
202 fprintf(stderr, "%s: invalid option -%c\n",
203 argv[0], optopt);
204 exit(1);
205 }
206 } while (1);
207 }
208
209 /* open vibrator before switching user */
210 if (vibrate) {
211 vibrate_fd = open("/sys/class/timed_output/vibrator/enable", O_WRONLY);
212 if (vibrate_fd > 0)
213 fcntl(vibrate_fd, F_SETFD, FD_CLOEXEC);
214 } else
215 vibrate_fd = -1;
216
217 /* switch to non-root user and group */
Mike Lockwood472be482009-05-22 13:31:42 -0400218 setgroups(sizeof(groups)/sizeof(groups[0]), groups);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 setuid(AID_SHELL);
220
221 /* make it safe to use both printf and STDOUT_FILENO */
222 setvbuf(stdout, 0, _IONBF, 0);
223
224 if (outfile) {
225 if (strlen(outfile) > sizeof(path) - 100)
226 exit(1);
227
228 strcpy(path, outfile);
229 if (add_date) {
230 char date[260];
231 strftime(date, sizeof(date),
232 "-%Y-%m-%d-%H-%M-%S",
233 &now);
234 strcat(path, date);
235 }
236 if (compress)
237 strcat(path, ".gz");
238 else
239 strcat(path, ".txt");
240
241 /* ensure that all directories in the path exist */
242 create_directories(path);
243 fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
244 if (fd < 0)
245 return fd;
246
247 if (compress) {
248 pipe(fds);
249
250 /* redirect our stdout to the pipe */
251 dup2(fds[1], STDOUT_FILENO);
252 close(fds[1]);
253
254 if ((pid = fork()) < 0)
255 {
256 fprintf(stderr, "fork error\n");
257 exit(1);
258 }
259
260 if (pid) {
261 /* parent case */
262
263 /* close our copy of the input to gzip */
264 close(fds[0]);
265 /* close our copy of the output file */
266 close(fd);
267 } else {
268 /* child case */
269
270 /* redirect our input pipe to stdin */
271 dup2(fds[0], STDIN_FILENO);
272 close(fds[0]);
273
274 /* redirect stdout to the output file */
275 dup2(fd, STDOUT_FILENO);
276 close(fd);
277
278 /* run gzip to postprocess our output */
279 execv("/system/bin/gzip", gzip_args);
280 fprintf(stderr, "execv returned\n");
281 }
282 } else {
283 /* redirect stdout to the output file */
284 dup2(fd, STDOUT_FILENO);
285 close(fd);
286 }
287 }
288 /* else everything will print to stdout */
289
290 if (vibrate) {
291 vibrate_pattern(vibrate_fd, start_pattern);
292 }
293 dumpstate(!dumpcrash);
294 if (vibrate) {
295 vibrate_pattern(vibrate_fd, end_pattern);
296 close(vibrate_fd);
297 }
298
299 /* so gzip will terminate */
300 close(STDOUT_FILENO);
301
302 return 0;
303}
304
San Mehat30b9f572009-09-01 13:27:20 -0700305static void dump_kernel_log(const char *path, const char *title)
306
307{
308 printf("------ KERNEL %s LOG ------\n", title);
309 if (access(path, R_OK) < 0)
310 printf("%s: %s\n", path, strerror(errno));
311 else
312 DUMP(path);
313}
314