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

4.104.115
Last change on this file since c917d31 was c917d31, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 19, 2010 at 11:49:40 PM

2010-01-19 Joel Sherrill <joel.sherrill@…>

Coverity Id 23

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