source: mainline/uspace/app/taskdump/taskdump.c@ 03333bc

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 03333bc was a074b4f, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Implement fault notifications and task monitoring service.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Copyright (c) 2010 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup taskdump
30 * @{
31 */
32/** @file
33 */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <ipc/ipc.h>
39#include <errno.h>
40#include <udebug.h>
41#include <task.h>
42#include <kernel/mm/as.h>
43#include <macros.h>
44#include <assert.h>
45#include <bool.h>
46
47#define LINE_BYTES 16
48
49#define DBUF_SIZE 4096
50static uint8_t data_buf[DBUF_SIZE];
51
52static int phoneid;
53static task_id_t task_id;
54static bool dump_memory;
55
56static int connect_task(task_id_t task_id);
57static int parse_args(int argc, char *argv[]);
58static void print_syntax();
59static int threads_dump(void);
60static int areas_dump(void);
61static int area_dump(as_area_info_t *area);
62static void hex_dump(uintptr_t addr, void *buffer, size_t size);
63
64int main(int argc, char *argv[])
65{
66 int rc;
67
68 printf("Task Dump Utility\n");
69 dump_memory = false;
70
71 if (parse_args(argc, argv) < 0)
72 return 1;
73
74 rc = connect_task(task_id);
75 if (rc < 0) {
76 printf("Failed connecting to task %lld.\n", task_id);
77 return 1;
78 }
79
80 printf("Dumping task %lld.\n\n", task_id);
81
82 rc = threads_dump();
83 if (rc < 0)
84 printf("Failed dumping threads.\n");
85
86 rc = areas_dump();
87 if (rc < 0)
88 printf("Failed dumping address space areas.\n");
89
90 udebug_end(phoneid);
91 ipc_hangup(phoneid);
92
93 return 0;
94}
95
96static int connect_task(task_id_t task_id)
97{
98 int rc;
99
100 rc = ipc_connect_kbox(task_id);
101
102 if (rc == ENOTSUP) {
103 printf("You do not have userspace debugging support "
104 "compiled in the kernel.\n");
105 printf("Compile kernel with 'Support for userspace debuggers' "
106 "(CONFIG_UDEBUG) enabled.\n");
107 return rc;
108 }
109
110 if (rc < 0) {
111 printf("Error connecting\n");
112 printf("ipc_connect_task(%lld) -> %d ", task_id, rc);
113 return rc;
114 }
115
116 phoneid = rc;
117
118 rc = udebug_begin(phoneid);
119 if (rc < 0) {
120 printf("udebug_begin() -> %d\n", rc);
121 return rc;
122 }
123
124 return 0;
125}
126
127static int parse_args(int argc, char *argv[])
128{
129 char *arg;
130 char *err_p;
131
132 task_id = 0;
133
134 --argc; ++argv;
135
136 while (argc > 0) {
137 arg = *argv;
138 if (arg[0] == '-') {
139 if (arg[1] == 't' && arg[2] == '\0') {
140 /* Task ID */
141 --argc; ++argv;
142 task_id = strtol(*argv, &err_p, 10);
143 if (*err_p) {
144 printf("Task ID syntax error\n");
145 print_syntax();
146 return -1;
147 }
148 } else if (arg[1] == 'm' && arg[2] == '\0') {
149 dump_memory = true;
150 } else {
151 printf("Uknown option '%s'\n", arg[0]);
152 print_syntax();
153 return -1;
154 }
155 } else {
156 break;
157 }
158
159 --argc; ++argv;
160 }
161
162 if (task_id == 0) {
163 printf("Missing task ID argument\n");
164 print_syntax();
165 return -1;
166 }
167
168 if (argc != 0) {
169 printf("Extra arguments\n");
170 print_syntax();
171 return -1;
172 }
173
174 return 0;
175}
176
177static void print_syntax()
178{
179 printf("Syntax: taskdump [-m] -t <task_id>\n");
180 printf("\t-m\tDump memory area contents.\n");
181 printf("\t-t <task_id>\tWhich task to dump.\n");
182}
183
184static int threads_dump(void)
185{
186 uintptr_t *thash_buf;
187 uintptr_t dummy_buf;
188 size_t buf_size, n_threads;
189
190 size_t copied;
191 size_t needed;
192 size_t i;
193 int rc;
194
195 /* TODO: See why NULL does not work. */
196 rc = udebug_thread_read(phoneid, &dummy_buf, 0, &copied, &needed);
197 if (rc < 0) {
198 printf("udebug_thread_read() -> %d\n", rc);
199 return rc;
200 }
201
202 if (needed == 0) {
203 printf("No threads.\n\n");
204 return 0;
205 }
206
207 buf_size = needed;
208 thash_buf = malloc(buf_size);
209
210 rc = udebug_thread_read(phoneid, thash_buf, buf_size, &copied, &needed);
211 if (rc < 0) {
212 printf("udebug_thread_read() -> %d\n", rc);
213 return rc;
214 }
215
216 assert(copied == buf_size);
217 assert(needed == buf_size);
218
219 n_threads = copied / sizeof(uintptr_t);
220
221 printf("Threads:\n");
222 for (i = 0; i < n_threads; i++) {
223 printf(" [%d] hash: 0x%lx\n", 1+i, thash_buf[i]);
224 }
225 putchar('\n');
226
227 free(thash_buf);
228
229 return 0;
230}
231
232static int areas_dump(void)
233{
234 as_area_info_t *ainfo_buf;
235 as_area_info_t dummy_buf;
236 size_t buf_size, n_areas;
237
238 size_t copied;
239 size_t needed;
240 size_t i;
241 int rc;
242
243 rc = udebug_areas_read(phoneid, &dummy_buf, 0, &copied, &needed);
244 if (rc < 0) {
245 printf("udebug_areas_read() -> %d\n", rc);
246 return rc;
247 }
248
249 buf_size = needed;
250 ainfo_buf = malloc(buf_size);
251
252 rc = udebug_areas_read(phoneid, ainfo_buf, buf_size, &copied, &needed);
253 if (rc < 0) {
254 printf("udebug_areas_read() -> %d\n", rc);
255 return rc;
256 }
257
258 assert(copied == buf_size);
259 assert(needed == buf_size);
260
261 n_areas = copied / sizeof(as_area_info_t);
262
263 printf("Address space areas:\n");
264 for (i = 0; i < n_areas; i++) {
265 printf(" [%d] flags: %c%c%c%c base: 0x%lx size: 0x%lx\n", 1+i,
266 (ainfo_buf[i].flags & AS_AREA_READ) ? 'R' : '-',
267 (ainfo_buf[i].flags & AS_AREA_WRITE) ? 'W' : '-',
268 (ainfo_buf[i].flags & AS_AREA_EXEC) ? 'X' : '-',
269 (ainfo_buf[i].flags & AS_AREA_CACHEABLE) ? 'C' : '-',
270 ainfo_buf[i].start_addr, ainfo_buf[i].size);
271
272 if (dump_memory) {
273 putchar('\n');
274 area_dump(&ainfo_buf[i]);
275 putchar('\n');
276 }
277 }
278
279 putchar('\n');
280
281 free(ainfo_buf);
282
283 return 0;
284}
285
286static int area_dump(as_area_info_t *area)
287{
288 size_t to_copy;
289 size_t total;
290 uintptr_t addr;
291 int rc;
292
293 addr = area->start_addr;
294 total = 0;
295
296 while (total < area->size) {
297 to_copy = min(area->size - total, DBUF_SIZE);
298 rc = udebug_mem_read(phoneid, data_buf, addr, to_copy);
299 if (rc < 0) {
300 printf("udebug_mem_read() failed.\n");
301 return rc;
302 }
303
304 hex_dump(addr, data_buf, to_copy);
305
306 addr += to_copy;
307 total += to_copy;
308 }
309
310 return EOK;
311}
312
313static void hex_dump(uintptr_t addr, void *buffer, size_t size)
314{
315 uint8_t *data = (uint8_t *) buffer;
316 uint8_t b;
317 size_t pos, i;
318
319 assert(addr % LINE_BYTES == 0);
320 assert(size % LINE_BYTES == 0);
321
322 pos = 0;
323
324 while (pos < size) {
325 printf("%08x:", addr + pos);
326 for (i = 0; i < LINE_BYTES; ++i) {
327 if (i % 4 == 0) putchar(' ');
328 printf(" %02x", data[pos + i]);
329 }
330 putchar('\t');
331
332 for (i = 0; i < LINE_BYTES; ++i) {
333 b = data[pos + i];
334 if (b >= 32 && b < 127) {
335 putchar(b);
336 } else {
337 putchar(' ');
338 }
339 }
340 putchar('\n');
341 pos += LINE_BYTES;
342 }
343}
344
345/** @}
346 */
Note: See TracBrowser for help on using the repository browser.