source: rtems/cpukit/libmisc/monitor/mon-monitor.c @ 0690fb28

4.115
Last change on this file since 0690fb28 was 0690fb28, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 2, 2011 at 1:17:35 PM

2011-09-02 Sebastian Huber <sebastian.huber@…>

  • libmisc/monitor/mon-monitor.c: Removed "exit" and "quit" commands to avoid confusion. They were an alias to the "fatal" command.
  • Property mode set to 100644
File size: 13.5 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    { "fatal",
201      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
202      "  fatal [status]",
203      0,
204      rtems_monitor_fatal_cmd,
205      { .status_code = RTEMS_TASK_EXITTED },            /* exit value */
206      &rtems_monitor_commands[17],
207    },
208    { "reset",
209      "(SW)Resets the System.",
210      0,
211      rtems_monitor_reset_cmd,
212      { 0 },
213      &rtems_monitor_commands[18],
214    },
215#if defined(RTEMS_MULTIPROCESSING)
216    { "node",
217      "Specify default node number for commands that take id's.\n"
218      "  node [ node number ]",
219      0,
220      rtems_monitor_node_cmd,
221      { 0 },
222      &rtems_monitor_commands[19],
223    },
224  #define RTEMS_MONITOR_POSIX_NEXT 20
225#else
226  #define RTEMS_MONITOR_POSIX_NEXT 19
227#endif
228#ifdef RTEMS_POSIX_API
229    { "pthread",
230      "Display information about the specified pthreads. "
231      "Default is to display information about all pthreads on this node.\n"
232      "  pthread [id [id ...] ]",
233      0,
234      rtems_monitor_object_cmd,
235      { RTEMS_MONITOR_OBJECT_PTHREAD },
236      &rtems_monitor_commands[RTEMS_MONITOR_POSIX_NEXT],
237    },
238  #define RTEMS_MONITOR_DEBUGGER_NEXT (RTEMS_MONITOR_POSIX_NEXT + 1)
239#else
240  #define RTEMS_MONITOR_DEBUGGER_NEXT RTEMS_MONITOR_POSIX_NEXT
241#endif
242#ifdef CPU_INVOKE_DEBUGGER
243    { "debugger",
244      "Enter the debugger, if possible. "
245      "A continue from the debugger will return to the monitor.\n",
246      0,
247      rtems_monitor_debugger_cmd,
248      { 0 },
249      &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT],
250    },
251#endif
252    { "help",
253      "Provide information about commands. "
254      "Default is show basic command summary.\n"
255      "help [ command [ command ] ]",
256      0,
257      rtems_monitor_help_cmd,
258      { .monitor_command_entry = rtems_monitor_commands },
259      NULL
260    }
261};
262
263/*
264 * All registered commands.
265 */
266
267static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
268  &rtems_monitor_commands [0];
269
270
271rtems_status_code
272rtems_monitor_suspend(rtems_interval timeout)
273{
274    rtems_event_set event_set;
275    rtems_status_code status;
276
277    status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
278                                 RTEMS_DEFAULT_OPTIONS,
279                                 timeout,
280                                 &event_set);
281    return status;
282}
283
284void __attribute__((weak))
285rtems_monitor_reset_cmd(
286  int argc,
287  char **argv,
288  const rtems_monitor_command_arg_t* command_arg,
289  bool verbose
290)
291{
292
293}
294
295void
296rtems_monitor_wakeup(void)
297{
298    rtems_status_code status;
299
300    status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
301}
302
303void rtems_monitor_debugger_cmd(
304  int                                argc __attribute__((unused)),
305  char                             **argv __attribute__((unused)),
306  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
307  bool                               verbose __attribute__((unused))
308)
309{
310#ifdef CPU_INVOKE_DEBUGGER
311    CPU_INVOKE_DEBUGGER;
312#endif
313}
314
315void rtems_monitor_pause_cmd(
316  int                                argc,
317  char                             **argv,
318  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
319  bool                               verbose __attribute__((unused))
320)
321{
322    if (argc == 1)
323        rtems_monitor_suspend(1);
324    else
325        rtems_monitor_suspend(strtoul(argv[1], 0, 0));
326}
327
328void rtems_monitor_fatal_cmd(
329  int                                argc,
330  char                             **argv,
331  const rtems_monitor_command_arg_t *command_arg,
332  bool                               verbose __attribute__((unused))
333)
334{
335    if (argc == 1)
336        rtems_fatal_error_occurred(command_arg->status_code);
337    else
338        rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
339}
340
341void rtems_monitor_continue_cmd(
342  int                                argc __attribute__((unused)),
343  char                             **argv __attribute__((unused)),
344  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
345  bool                               verbose __attribute__((unused))
346)
347{
348    rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
349}
350
351#if defined(RTEMS_MULTIPROCESSING)
352void rtems_monitor_node_cmd(
353  int                                argc,
354  char                             **argv,
355  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
356  bool                               verbose __attribute__((unused))
357)
358{
359  uint32_t   new_node = rtems_monitor_default_node;
360
361  switch (argc) {
362    case 1:             /* no node, just set back to ours */
363      new_node = rtems_monitor_node;
364      break;
365
366    case 2:
367      new_node = strtoul(argv[1], 0, 0);
368      break;
369
370    default:
371      fprintf(stdout,"invalid syntax, try 'help node'\n");
372      break;
373  }
374
375  if ((new_node >= 1) &&
376    _Configuration_MP_table &&
377    (new_node <= _Configuration_MP_table->maximum_nodes))
378        rtems_monitor_default_node = new_node;
379}
380#endif
381
382
383/*
384 *  Function:   rtems_monitor_symbols_loadup
385 *
386 *  Description:
387 *      Create and load the monitor's symbol table.
388 *      We are reading the output format of 'gnm' which looks like this:
389 *
390 *              400a7068 ? _Rate_monotonic_Information
391 *              400a708c ? _Thread_Dispatch_disable_level
392 *              400a7090 ? _Configuration_Table
393 *
394 *      We ignore the type field.
395 *
396 *  Side Effects:
397 *      Creates and fills in 'rtems_monitor_symbols' table
398 *
399 *  TODO
400 *      there should be a BSP #define or something like that
401 *         to do this;  Assuming stdio is crazy.
402 *      Someday this should know BFD
403 *              Maybe we could get objcopy to just copy the symbol areas
404 *              and copy that down.
405 *
406 */
407
408void
409rtems_monitor_symbols_loadup(void)
410{
411    FILE *fp;
412    char buffer[128];
413
414    if (rtems_monitor_symbols)
415        rtems_symbol_table_destroy(rtems_monitor_symbols);
416
417    rtems_monitor_symbols = rtems_symbol_table_create();
418    if (rtems_monitor_symbols == 0)
419        return;
420
421    fp = fopen("symbols", "r");
422
423    if (fp == 0)
424        return;
425
426    while (fgets(buffer, sizeof(buffer) - 1, fp))
427    {
428        char *symbol;
429        char *value;
430        char *ignored_type;
431
432        value = strtok(buffer, " \t\n");
433        ignored_type = strtok(0, " \t\n");
434        symbol = strtok(0, " \t\n");
435
436        if (symbol && ignored_type && value)
437        {
438            rtems_symbol_t *sp;
439            sp = rtems_symbol_create(rtems_monitor_symbols,
440                                     symbol,
441                                     (uint32_t) strtoul(value, 0, 16));
442            if (sp == 0)
443            {
444                fprintf(stdout,"could not define symbol '%s'\n", symbol);
445                goto done;
446            }
447        }
448        else
449        {
450            fprintf(stdout,"parsing error on '%s'\n", buffer);
451            goto done;
452        }
453    }
454
455done:
456    fclose(fp);
457    return;
458}
459
460/*
461 * User registered commands.
462 */
463
464int
465rtems_monitor_insert_cmd (
466  rtems_monitor_command_entry_t *command
467)
468{
469  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
470
471  /* Reject empty commands */
472  if (command->command == NULL) {
473    return 0;
474  }
475
476  /* Reject command if already present */
477  while (e->next != NULL) {
478      if (e->command != NULL && strcmp(command->command, e->command) == 0) {
479        return 0;
480      }
481      e = e->next;
482  }
483
484  /* Prepend new command */
485  command->next = rtems_monitor_registered_commands;
486  rtems_monitor_registered_commands = command;
487
488  return 1;
489}
490
491/**
492 * @brief Iterates through all registerd commands.
493 *
494 * For each command the interation routine @a routine is called with the
495 * command entry and the user provided argument @a arg.  It is guaranteed that
496 * the command name and function are not NULL.
497 */
498void rtems_monitor_command_iterate(
499  rtems_monitor_per_command_routine routine,
500  void *arg
501)
502{
503  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
504
505  while (e != NULL) {
506    if (e->command != NULL && e->command_function != NULL) {
507      if (!routine(e, arg)) {
508        break;
509      }
510    }
511    e = e->next;
512  }
513}
Note: See TracBrowser for help on using the repository browser.