1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | #ifdef HAVE_CONFIG_H1 |
26 | #include "config.h" |
27 | #endif |
28 | |
29 | #include <rtems.h> |
30 | |
31 | #include <stdio.h> |
32 | #include <string.h> |
33 | #include <stdlib.h> |
34 | |
35 | #include <rtems/monitor.h> |
36 | |
37 | |
38 | extern rtems_tcb *debugger_interrupted_task; |
39 | extern rtems_context *debugger_interrupted_task_context; |
40 | extern uint32_t debugger_trap; |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | rtems_id rtems_monitor_task_id; |
49 | |
50 | uint32_t rtems_monitor_node; |
51 | uint32_t rtems_monitor_default_node; |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | rtems_symbol_table_t *rtems_monitor_symbols; |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | static const rtems_monitor_command_entry_t rtems_monitor_commands[] = { |
64 | { "config", |
65 | "Show the system configuration.", |
66 | 0, |
67 | rtems_monitor_object_cmd, |
68 | { RTEMS_MONITOR_OBJECT_CONFIG }, |
69 | &rtems_monitor_commands[1], |
70 | }, |
71 | { "itask", |
72 | "List init tasks for the system", |
73 | 0, |
74 | rtems_monitor_object_cmd, |
75 | { RTEMS_MONITOR_OBJECT_INIT_TASK }, |
76 | &rtems_monitor_commands[2], |
77 | }, |
78 | { "mpci", |
79 | "Show the MPCI system configuration, if configured.", |
80 | 0, |
81 | rtems_monitor_object_cmd, |
82 | { RTEMS_MONITOR_OBJECT_MPCI }, |
83 | &rtems_monitor_commands[3], |
84 | }, |
85 | { "pause", |
86 | "Monitor goes to \"sleep\" for specified ticks (default is 1). " |
87 | "Monitor will resume at end of period or if explicitly awakened\n" |
88 | " pause [ticks]", |
89 | 0, |
90 | rtems_monitor_pause_cmd, |
91 | { 0 }, |
92 | &rtems_monitor_commands[4], |
93 | }, |
94 | { "continue", |
95 | "Put the monitor to sleep waiting for an explicit wakeup from the " |
96 | "program running.\n", |
97 | 0, |
98 | rtems_monitor_continue_cmd, |
99 | { 0 }, |
100 | &rtems_monitor_commands[5], |
101 | }, |
102 | { "go", |
103 | "Alias for 'continue'", |
104 | 0, |
105 | rtems_monitor_continue_cmd, |
106 | { 0 }, |
107 | &rtems_monitor_commands[6], |
108 | }, |
109 | { "node", |
110 | "Specify default node number for commands that take id's.\n" |
111 | " node [ node number ]", |
112 | 0, |
113 | rtems_monitor_node_cmd, |
114 | { 0 }, |
115 | &rtems_monitor_commands[7], |
116 | }, |
117 | { "symbol", |
118 | "Display value associated with specified symbol. " |
119 | "Defaults to displaying all known symbols.\n" |
120 | " symbol [ symbolname [symbolname ... ] ]", |
121 | 0, |
122 | rtems_monitor_symbol_cmd, |
123 | { .symbol_table = &rtems_monitor_symbols }, |
124 | &rtems_monitor_commands[8], |
125 | }, |
126 | { "extension", |
127 | "Display information about specified extensions. " |
128 | "Default is to display information about all extensions on this node.\n" |
129 | " extension [id [id ...] ]", |
130 | 0, |
131 | rtems_monitor_object_cmd, |
132 | { RTEMS_MONITOR_OBJECT_EXTENSION }, |
133 | &rtems_monitor_commands[9], |
134 | }, |
135 | { "task", |
136 | "Display information about the specified tasks. " |
137 | "Default is to display information about all tasks on this node.\n" |
138 | " task [id [id ...] ]", |
139 | 0, |
140 | rtems_monitor_object_cmd, |
141 | { RTEMS_MONITOR_OBJECT_TASK }, |
142 | &rtems_monitor_commands[10], |
143 | }, |
144 | { "queue", |
145 | "Display information about the specified message queues. " |
146 | "Default is to display information about all queues on this node.\n" |
147 | " queue [id [id ... ] ]", |
148 | 0, |
149 | rtems_monitor_object_cmd, |
150 | { RTEMS_MONITOR_OBJECT_QUEUE }, |
151 | &rtems_monitor_commands[11], |
152 | }, |
153 | { "sema", |
154 | "sema [id [id ... ] ]\n" |
155 | " display information about the specified semaphores\n" |
156 | " Default is to display information about all semaphores on this node\n" |
157 | , |
158 | 0, |
159 | rtems_monitor_object_cmd, |
160 | { RTEMS_MONITOR_OBJECT_SEMAPHORE }, |
161 | &rtems_monitor_commands[12], |
162 | }, |
163 | { "region", |
164 | "region [id [id ... ] ]\n" |
165 | " display information about the specified regions\n" |
166 | " Default is to display information about all regions on this node\n" |
167 | , |
168 | 0, |
169 | rtems_monitor_object_cmd, |
170 | { RTEMS_MONITOR_OBJECT_REGION }, |
171 | &rtems_monitor_commands[13], |
172 | }, |
173 | { "part", |
174 | "part [id [id ... ] ]\n" |
175 | " display information about the specified partitions\n" |
176 | " Default is to display information about all partitions on this node\n" |
177 | , |
178 | 0, |
179 | rtems_monitor_object_cmd, |
180 | { RTEMS_MONITOR_OBJECT_PARTITION }, |
181 | &rtems_monitor_commands[14], |
182 | }, |
183 | { "object", |
184 | "Display information about specified RTEMS objects. " |
185 | "Object id's must include 'type' information. " |
186 | "(which may normally be defaulted)\n" |
187 | " object [id [id ...] ]", |
188 | 0, |
189 | rtems_monitor_object_cmd, |
190 | { RTEMS_MONITOR_OBJECT_INVALID }, |
191 | &rtems_monitor_commands[15], |
192 | }, |
193 | { "driver", |
194 | "Display the RTEMS device driver table.\n" |
195 | " driver [ major [ major ... ] ]", |
196 | 0, |
197 | rtems_monitor_object_cmd, |
198 | { RTEMS_MONITOR_OBJECT_DRIVER }, |
199 | &rtems_monitor_commands[16], |
200 | }, |
201 | { "dname", |
202 | "Displays information about named drivers.\n", |
203 | 0, |
204 | rtems_monitor_object_cmd, |
205 | { RTEMS_MONITOR_OBJECT_DNAME }, |
206 | &rtems_monitor_commands[17], |
207 | }, |
208 | { "exit", |
209 | "Invoke 'rtems_fatal_error_occurred' with 'status' " |
210 | "(default is RTEMS_SUCCESSFUL)\n" |
211 | " exit [status]", |
212 | 0, |
213 | rtems_monitor_fatal_cmd, |
214 | { .status_code = RTEMS_SUCCESSFUL }, |
215 | &rtems_monitor_commands[18], |
216 | }, |
217 | { "fatal", |
218 | "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n" |
219 | " fatal [status]", |
220 | 0, |
221 | rtems_monitor_fatal_cmd, |
222 | { .status_code = RTEMS_TASK_EXITTED }, |
223 | &rtems_monitor_commands[19], |
224 | }, |
225 | { "quit", |
226 | "Alias for 'exit'\n", |
227 | 0, |
228 | rtems_monitor_fatal_cmd, |
229 | { .status_code = RTEMS_SUCCESSFUL }, |
230 | &rtems_monitor_commands[20], |
231 | }, |
232 | { "reset", |
233 | "(SW)Resets the System.", |
234 | 0, |
235 | rtems_monitor_reset_cmd, |
236 | { 0 }, |
237 | &rtems_monitor_commands[21], |
238 | }, |
239 | #ifdef RTEMS_POSIX_API1 |
240 | { "pthread", |
241 | "Display information about the specified pthreads. " |
242 | "Default is to display information about all pthreads on this node.\n" |
243 | " pthread [id [id ...] ]", |
244 | 0, |
245 | rtems_monitor_object_cmd, |
246 | { RTEMS_MONITOR_OBJECT_PTHREAD }, |
247 | &rtems_monitor_commands[22], |
248 | }, |
249 | #define RTEMS_MONITOR_DEBUGGER_NEXT23 23 |
250 | #else |
251 | #define RTEMS_MONITOR_DEBUGGER_NEXT23 22 |
252 | #endif |
253 | #ifdef CPU_INVOKE_DEBUGGER |
254 | { "debugger", |
255 | "Enter the debugger, if possible. " |
256 | "A continue from the debugger will return to the monitor.\n", |
257 | 0, |
258 | rtems_monitor_debugger_cmd, |
259 | { 0 }, |
260 | &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT23], |
261 | }, |
262 | #endif |
263 | { "help", |
264 | "Provide information about commands. " |
265 | "Default is show basic command summary.\n" |
266 | "help [ command [ command ] ]", |
267 | 0, |
268 | rtems_monitor_help_cmd, |
269 | { .monitor_command_entry = rtems_monitor_commands }, |
270 | NULL((void*)0) |
271 | } |
272 | }; |
273 | |
274 | |
275 | |
276 | |
277 | |
278 | static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands = |
279 | &rtems_monitor_commands [0]; |
280 | |
281 | |
282 | rtems_status_code |
283 | rtems_monitor_suspend(rtems_interval timeout) |
284 | { |
285 | rtems_event_set event_set; |
286 | rtems_status_code status; |
287 | |
288 | status = rtems_event_receive(MONITOR_WAKEUP_EVENT0x00000001, |
289 | RTEMS_DEFAULT_OPTIONS0x00000000, |
290 | timeout, |
291 | &event_set); |
292 | return status; |
293 | } |
294 | |
295 | void __attribute__((weak)) |
296 | rtems_monitor_reset_cmd( |
297 | int argc, |
298 | char **argv, |
299 | const rtems_monitor_command_arg_t* command_arg, |
300 | bool_Bool verbose |
301 | ) |
302 | { |
303 | |
304 | } |
305 | |
306 | void |
307 | rtems_monitor_wakeup(void) |
308 | { |
309 | rtems_status_code status; |
310 | |
311 | status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT0x00000001); |
312 | } |
313 | |
314 | void rtems_monitor_debugger_cmd( |
315 | int argc __attribute__((unused)), |
316 | char **argv __attribute__((unused)), |
317 | const rtems_monitor_command_arg_t *command_arg __attribute__((unused)), |
318 | bool_Bool verbose __attribute__((unused)) |
319 | ) |
320 | { |
321 | #ifdef CPU_INVOKE_DEBUGGER |
322 | CPU_INVOKE_DEBUGGER; |
323 | #endif |
324 | } |
325 | |
326 | void rtems_monitor_pause_cmd( |
327 | int argc, |
328 | char **argv, |
329 | const rtems_monitor_command_arg_t *command_arg __attribute__((unused)), |
330 | bool_Bool verbose __attribute__((unused)) |
331 | ) |
332 | { |
333 | if (argc == 1) |
334 | rtems_monitor_suspend(1); |
335 | else |
336 | rtems_monitor_suspend(strtoul(argv[1], 0, 0)); |
337 | } |
338 | |
339 | void rtems_monitor_fatal_cmd( |
340 | int argc, |
341 | char **argv, |
342 | const rtems_monitor_command_arg_t *command_arg, |
343 | bool_Bool verbose __attribute__((unused)) |
344 | ) |
345 | { |
346 | if (argc == 1) |
347 | rtems_fatal_error_occurred(command_arg->status_code); |
348 | else |
349 | rtems_fatal_error_occurred(strtoul(argv[1], 0, 0)); |
350 | } |
351 | |
352 | void rtems_monitor_continue_cmd( |
353 | int argc __attribute__((unused)), |
354 | char **argv __attribute__((unused)), |
355 | const rtems_monitor_command_arg_t *command_arg __attribute__((unused)), |
356 | bool_Bool verbose __attribute__((unused)) |
357 | ) |
358 | { |
359 | rtems_monitor_suspend(RTEMS_NO_TIMEOUT0); |
360 | } |
361 | |
362 | void rtems_monitor_node_cmd( |
363 | int argc, |
364 | char **argv, |
365 | const rtems_monitor_command_arg_t *command_arg __attribute__((unused)), |
366 | bool_Bool verbose __attribute__((unused)) |
367 | ) |
368 | { |
369 | uint32_t new_node = rtems_monitor_default_node; |
| Value stored to 'new_node' during its initialization is never read |
370 | |
371 | switch (argc) |
372 | { |
373 | case 1: |
374 | new_node = rtems_monitor_node; |
375 | break; |
376 | |
377 | case 2: |
378 | new_node = strtoul(argv[1], 0, 0); |
379 | break; |
380 | |
381 | default: |
382 | fprintf(stdoutstdout,"invalid syntax, try 'help node'\n"); |
383 | break; |
384 | } |
385 | |
386 | #if defined(RTEMS_MULTIPROCESSING) |
387 | if ((new_node >= 1) && |
388 | _Configuration_MP_table && |
389 | (new_node <= _Configuration_MP_table->maximum_nodes)) |
390 | rtems_monitor_default_node = new_node; |
391 | #endif |
392 | } |
393 | |
394 | |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | |
401 | |
402 | |
403 | |
404 | |
405 | |
406 | |
407 | |
408 | |
409 | |
410 | |
411 | |
412 | |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | void |
421 | rtems_monitor_symbols_loadup(void) |
422 | { |
423 | FILE *fp; |
424 | char buffer[128]; |
425 | |
426 | if (rtems_monitor_symbols) |
427 | rtems_symbol_table_destroy(rtems_monitor_symbols); |
428 | |
429 | rtems_monitor_symbols = rtems_symbol_table_create(); |
430 | if (rtems_monitor_symbols == 0) |
431 | return; |
432 | |
433 | fp = fopen("symbols", "r"); |
434 | |
435 | if (fp == 0) |
436 | return; |
437 | |
438 | while (fgets(buffer, sizeof(buffer) - 1, fp)) |
439 | { |
440 | char *symbol; |
441 | char *value; |
442 | char *ignored_type; |
443 | |
444 | value = strtok(buffer, " \t\n"); |
445 | ignored_type = strtok(0, " \t\n"); |
446 | symbol = strtok(0, " \t\n"); |
447 | |
448 | if (symbol && ignored_type && value) |
449 | { |
450 | rtems_symbol_t *sp; |
451 | sp = rtems_symbol_create(rtems_monitor_symbols, |
452 | symbol, |
453 | (uint32_t) strtoul(value, 0, 16)); |
454 | if (sp == 0) |
455 | { |
456 | fprintf(stdoutstdout,"could not define symbol '%s'\n", symbol); |
457 | goto done; |
458 | } |
459 | } |
460 | else |
461 | { |
462 | fprintf(stdoutstdout,"parsing error on '%s'\n", buffer); |
463 | goto done; |
464 | } |
465 | } |
466 | |
467 | done: |
468 | fclose(fp); |
469 | return; |
470 | } |
471 | |
472 | |
473 | |
474 | |
475 | |
476 | int |
477 | rtems_monitor_insert_cmd ( |
478 | rtems_monitor_command_entry_t *command |
479 | ) |
480 | { |
481 | const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands; |
482 | |
483 | |
484 | if (command->command == NULL((void*)0)) { |
485 | return 0; |
486 | } |
487 | |
488 | |
489 | while (e->next != NULL((void*)0)) { |
490 | if (e->command != NULL((void*)0) && strcmp(command->command, e->command) == 0) { |
491 | return 0; |
492 | } |
493 | e = e->next; |
494 | } |
495 | |
496 | |
497 | command->next = rtems_monitor_registered_commands; |
498 | rtems_monitor_registered_commands = command; |
499 | |
500 | return 1; |
501 | } |
502 | |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | |
509 | |
510 | void rtems_monitor_command_iterate( |
511 | rtems_monitor_per_command_routine routine, |
512 | void *arg |
513 | ) |
514 | { |
515 | const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands; |
516 | |
517 | while (e != NULL((void*)0)) { |
518 | if (e->command != NULL((void*)0) && e->command_function != NULL((void*)0)) { |
519 | if (!routine(e, arg)) { |
520 | break; |
521 | } |
522 | } |
523 | e = e->next; |
524 | } |
525 | } |