source: rtems/cpukit/libmisc/monitor/mon-monitor.c @ 3ff9156

4.115
Last change on this file since 3ff9156 was 3ff9156, checked in by Sebastian Huber <sebastian.huber@…>, on 11/19/10 at 09:44:21

2010-11-19 Sebastian Huber <sebastian.huber@…>

  • libmisc/monitor/mon-monitor.c: Fixed broken monitor command list.
  • Property mode set to 100644
File size: 13.9 KB
Line 
1/*
2 * RTEMS monitor main body
3 *
4 *  TODO:
5 *      add stuff to RTEMS api
6 *            rtems_get_name(id)
7 *            rtems_get_type(id)
8 *            rtems_build_id(node, type, num)
9 *      Add a command to dump out info about an arbitrary id when
10 *         types are added to id's
11 *         rtems> id idnum
12 *                idnum: node n, object: whatever, id: whatever
13 *      allow id's to be specified as n:t:id, where 'n:t' is optional
14 *      should have a separate monitor FILE stream (ala the debugger)
15 *      remote request/response stuff should be cleaned up
16 *         maybe we can use real rpc??
17 *      'info' command to print out:
18 *           interrupt stack location, direction and size
19 *           floating point config stuff
20 *           interrupt config stuff
21 *
22 *  $Id$
23 */
24
25#ifdef HAVE_CONFIG_H
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/* set by trap handler */
38extern rtems_tcb       *debugger_interrupted_task;
39extern rtems_context   *debugger_interrupted_task_context;
40extern uint32_t   debugger_trap;
41
42/*
43 * Various id's for the monitor
44 * They need to be public variables for access by other agencies
45 * such as debugger and remote servers'
46 */
47
48rtems_id  rtems_monitor_task_id;
49
50uint32_t   rtems_monitor_node;          /* our node number */
51uint32_t   rtems_monitor_default_node;  /* current default for commands */
52
53/*
54 * The rtems symbol table
55 */
56
57rtems_symbol_table_t *rtems_monitor_symbols;
58
59/*
60 * The top-level commands
61 */
62
63static 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    { "symbol",
110      "Display value associated with specified symbol. "
111      "Defaults to displaying all known symbols.\n"
112      "  symbol [ symbolname [symbolname ... ] ]",
113      0,
114      rtems_monitor_symbol_cmd,
115      { .symbol_table = &rtems_monitor_symbols },
116      &rtems_monitor_commands[7],
117    },
118    { "extension",
119      "Display information about specified extensions. "
120      "Default is to display information about all extensions on this node.\n"
121      "  extension [id [id ...] ]",
122      0,
123      rtems_monitor_object_cmd,
124      { RTEMS_MONITOR_OBJECT_EXTENSION },
125      &rtems_monitor_commands[8],
126    },
127    { "task",
128      "Display information about the specified tasks. "
129      "Default is to display information about all tasks on this node.\n"
130      "  task [id [id ...] ]",
131      0,
132      rtems_monitor_object_cmd,
133      { RTEMS_MONITOR_OBJECT_TASK },
134      &rtems_monitor_commands[9],
135    },
136    { "queue",
137      "Display information about the specified message queues. "
138      "Default is to display information about all queues on this node.\n"
139      "  queue [id [id ... ] ]",
140      0,
141      rtems_monitor_object_cmd,
142      { RTEMS_MONITOR_OBJECT_QUEUE },
143      &rtems_monitor_commands[10],
144    },
145    { "sema",
146      "sema [id [id ... ] ]\n"
147      "  display information about the specified semaphores\n"
148      "  Default is to display information about all semaphores on this node\n"
149      ,
150      0,
151      rtems_monitor_object_cmd,
152      { RTEMS_MONITOR_OBJECT_SEMAPHORE },
153      &rtems_monitor_commands[11],
154    },
155    { "region",
156      "region [id [id ... ] ]\n"
157      "  display information about the specified regions\n"
158      "  Default is to display information about all regions on this node\n"
159      ,
160      0,
161      rtems_monitor_object_cmd,
162      { RTEMS_MONITOR_OBJECT_REGION },
163      &rtems_monitor_commands[12],
164    },
165    { "part",
166      "part [id [id ... ] ]\n"
167      "  display information about the specified partitions\n"
168      "  Default is to display information about all partitions on this node\n"
169      ,
170      0,
171      rtems_monitor_object_cmd,
172      { RTEMS_MONITOR_OBJECT_PARTITION },
173      &rtems_monitor_commands[13],
174    },
175    { "object",
176      "Display information about specified RTEMS objects. "
177      "Object id's must include 'type' information. "
178      "(which may normally be defaulted)\n"
179      "  object [id [id ...] ]",
180      0,
181      rtems_monitor_object_cmd,
182      { RTEMS_MONITOR_OBJECT_INVALID },
183      &rtems_monitor_commands[14],
184    },
185    { "driver",
186      "Display the RTEMS device driver table.\n"
187      "  driver [ major [ major ... ] ]",
188      0,
189      rtems_monitor_object_cmd,
190      { RTEMS_MONITOR_OBJECT_DRIVER },
191      &rtems_monitor_commands[15],
192    },
193    { "dname",
194      "Displays information about named drivers.\n",
195      0,
196      rtems_monitor_object_cmd,
197      { RTEMS_MONITOR_OBJECT_DNAME },
198      &rtems_monitor_commands[16],
199    },
200    { "exit",
201      "Invoke 'rtems_fatal_error_occurred' with 'status' "
202      "(default is RTEMS_SUCCESSFUL)\n"
203      "  exit [status]",
204      0,
205      rtems_monitor_fatal_cmd,
206      { .status_code = RTEMS_SUCCESSFUL },
207      &rtems_monitor_commands[17],
208    },
209    { "fatal",
210      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
211      "  fatal [status]",
212      0,
213      rtems_monitor_fatal_cmd,
214      { .status_code = RTEMS_TASK_EXITTED },            /* exit value */
215      &rtems_monitor_commands[18],
216    },
217    { "quit",
218      "Alias for 'exit'\n",
219      0,
220      rtems_monitor_fatal_cmd,
221      { .status_code = RTEMS_SUCCESSFUL },              /* exit value */
222      &rtems_monitor_commands[19],
223    },
224    { "reset",
225      "(SW)Resets the System.",
226      0,
227      rtems_monitor_reset_cmd,
228      { 0 },
229      &rtems_monitor_commands[20],
230    },
231#if defined(RTEMS_MULTIPROCESSING)
232    { "node",
233      "Specify default node number for commands that take id's.\n"
234      "  node [ node number ]",
235      0,
236      rtems_monitor_node_cmd,
237      { 0 },
238      &rtems_monitor_commands[21],
239    },
240  #define RTEMS_MONITOR_POSIX_NEXT 22
241#else
242  #define RTEMS_MONITOR_POSIX_NEXT 21
243#endif
244#ifdef RTEMS_POSIX_API
245    { "pthread",
246      "Display information about the specified pthreads. "
247      "Default is to display information about all pthreads on this node.\n"
248      "  pthread [id [id ...] ]",
249      0,
250      rtems_monitor_object_cmd,
251      { RTEMS_MONITOR_OBJECT_PTHREAD },
252      &rtems_monitor_commands[RTEMS_MONITOR_POSIX_NEXT],
253    },
254  #define RTEMS_MONITOR_DEBUGGER_NEXT (RTEMS_MONITOR_POSIX_NEXT + 1)
255#else
256  #define RTEMS_MONITOR_DEBUGGER_NEXT RTEMS_MONITOR_POSIX_NEXT
257#endif
258#ifdef CPU_INVOKE_DEBUGGER
259    { "debugger",
260      "Enter the debugger, if possible. "
261      "A continue from the debugger will return to the monitor.\n",
262      0,
263      rtems_monitor_debugger_cmd,
264      { 0 },
265      &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT],
266    },
267#endif
268    { "help",
269      "Provide information about commands. "
270      "Default is show basic command summary.\n"
271      "help [ command [ command ] ]",
272      0,
273      rtems_monitor_help_cmd,
274      { .monitor_command_entry = rtems_monitor_commands },
275      NULL
276    }
277};
278
279/*
280 * All registered commands.
281 */
282
283static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
284  &rtems_monitor_commands [0];
285
286
287rtems_status_code
288rtems_monitor_suspend(rtems_interval timeout)
289{
290    rtems_event_set event_set;
291    rtems_status_code status;
292
293    status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
294                                 RTEMS_DEFAULT_OPTIONS,
295                                 timeout,
296                                 &event_set);
297    return status;
298}
299
300void __attribute__((weak))
301rtems_monitor_reset_cmd(
302  int argc,
303  char **argv,
304  const rtems_monitor_command_arg_t* command_arg,
305  bool verbose
306)
307{
308
309}
310
311void
312rtems_monitor_wakeup(void)
313{
314    rtems_status_code status;
315
316    status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
317}
318
319void rtems_monitor_debugger_cmd(
320  int                                argc __attribute__((unused)),
321  char                             **argv __attribute__((unused)),
322  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
323  bool                               verbose __attribute__((unused))
324)
325{
326#ifdef CPU_INVOKE_DEBUGGER
327    CPU_INVOKE_DEBUGGER;
328#endif
329}
330
331void rtems_monitor_pause_cmd(
332  int                                argc,
333  char                             **argv,
334  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
335  bool                               verbose __attribute__((unused))
336)
337{
338    if (argc == 1)
339        rtems_monitor_suspend(1);
340    else
341        rtems_monitor_suspend(strtoul(argv[1], 0, 0));
342}
343
344void rtems_monitor_fatal_cmd(
345  int                                argc,
346  char                             **argv,
347  const rtems_monitor_command_arg_t *command_arg,
348  bool                               verbose __attribute__((unused))
349)
350{
351    if (argc == 1)
352        rtems_fatal_error_occurred(command_arg->status_code);
353    else
354        rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
355}
356
357void rtems_monitor_continue_cmd(
358  int                                argc __attribute__((unused)),
359  char                             **argv __attribute__((unused)),
360  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
361  bool                               verbose __attribute__((unused))
362)
363{
364    rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
365}
366
367#if defined(RTEMS_MULTIPROCESSING)
368void rtems_monitor_node_cmd(
369  int                                argc,
370  char                             **argv,
371  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
372  bool                               verbose __attribute__((unused))
373)
374{
375  uint32_t   new_node = rtems_monitor_default_node;
376
377  switch (argc) {
378    case 1:             /* no node, just set back to ours */
379      new_node = rtems_monitor_node;
380      break;
381
382    case 2:
383      new_node = strtoul(argv[1], 0, 0);
384      break;
385
386    default:
387      fprintf(stdout,"invalid syntax, try 'help node'\n");
388      break;
389  }
390
391  if ((new_node >= 1) &&
392    _Configuration_MP_table &&
393    (new_node <= _Configuration_MP_table->maximum_nodes))
394        rtems_monitor_default_node = new_node;
395}
396#endif
397
398
399/*
400 *  Function:   rtems_monitor_symbols_loadup
401 *
402 *  Description:
403 *      Create and load the monitor's symbol table.
404 *      We are reading the output format of 'gnm' which looks like this:
405 *
406 *              400a7068 ? _Rate_monotonic_Information
407 *              400a708c ? _Thread_Dispatch_disable_level
408 *              400a7090 ? _Configuration_Table
409 *
410 *      We ignore the type field.
411 *
412 *  Side Effects:
413 *      Creates and fills in 'rtems_monitor_symbols' table
414 *
415 *  TODO
416 *      there should be a BSP #define or something like that
417 *         to do this;  Assuming stdio is crazy.
418 *      Someday this should know BFD
419 *              Maybe we could get objcopy to just copy the symbol areas
420 *              and copy that down.
421 *
422 */
423
424void
425rtems_monitor_symbols_loadup(void)
426{
427    FILE *fp;
428    char buffer[128];
429
430    if (rtems_monitor_symbols)
431        rtems_symbol_table_destroy(rtems_monitor_symbols);
432
433    rtems_monitor_symbols = rtems_symbol_table_create();
434    if (rtems_monitor_symbols == 0)
435        return;
436
437    fp = fopen("symbols", "r");
438
439    if (fp == 0)
440        return;
441
442    while (fgets(buffer, sizeof(buffer) - 1, fp))
443    {
444        char *symbol;
445        char *value;
446        char *ignored_type;
447
448        value = strtok(buffer, " \t\n");
449        ignored_type = strtok(0, " \t\n");
450        symbol = strtok(0, " \t\n");
451
452        if (symbol && ignored_type && value)
453        {
454            rtems_symbol_t *sp;
455            sp = rtems_symbol_create(rtems_monitor_symbols,
456                                     symbol,
457                                     (uint32_t) strtoul(value, 0, 16));
458            if (sp == 0)
459            {
460                fprintf(stdout,"could not define symbol '%s'\n", symbol);
461                goto done;
462            }
463        }
464        else
465        {
466            fprintf(stdout,"parsing error on '%s'\n", buffer);
467            goto done;
468        }
469    }
470
471done:
472    fclose(fp);
473    return;
474}
475
476/*
477 * User registered commands.
478 */
479
480int
481rtems_monitor_insert_cmd (
482  rtems_monitor_command_entry_t *command
483)
484{
485  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
486
487  /* Reject empty commands */
488  if (command->command == NULL) {
489    return 0;
490  }
491
492  /* Reject command if already present */
493  while (e->next != NULL) {
494      if (e->command != NULL && strcmp(command->command, e->command) == 0) {
495        return 0;
496      }
497      e = e->next;
498  }
499
500  /* Prepend new command */
501  command->next = rtems_monitor_registered_commands;
502  rtems_monitor_registered_commands = command;
503
504  return 1;
505}
506
507/**
508 * @brief Iterates through all registerd commands.
509 *
510 * For each command the interation routine @a routine is called with the
511 * command entry and the user provided argument @a arg.  It is guaranteed that
512 * the command name and function are not NULL.
513 */
514void rtems_monitor_command_iterate(
515  rtems_monitor_per_command_routine routine,
516  void *arg
517)
518{
519  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
520
521  while (e != NULL) {
522    if (e->command != NULL && e->command_function != NULL) {
523      if (!routine(e, arg)) {
524        break;
525      }
526    }
527    e = e->next;
528  }
529}
Note: See TracBrowser for help on using the repository browser.