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

4.104.114.84.95
Last change on this file since e420436 was e420436, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 6, 2007 at 3:45:45 PM

2007-09-06 Joel Sherrill <joel.sherrill@…>

  • libmisc/monitor/mon-monitor.c: Fix warnings and typo.
  • Property mode set to 100644
File size: 15.2 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#include <termios.h>
35#include <unistd.h>
36
37#include <rtems/monitor.h>
38
39#define STREQ(a,b)      (strcmp(a,b) == 0)
40
41/* set by trap handler */
42extern rtems_tcb       *debugger_interrupted_task;
43extern rtems_context   *debugger_interrupted_task_context;
44extern uint32_t   debugger_trap;
45
46/*
47 * Various id's for the monitor
48 * They need to be public variables for access by other agencies
49 * such as debugger and remote servers'
50 */
51
52rtems_id  rtems_monitor_task_id;
53
54uint32_t   rtems_monitor_node;          /* our node number */
55uint32_t   rtems_monitor_default_node;  /* current default for commands */
56
57/*
58 * The rtems symbol table
59 */
60
61rtems_symbol_table_t *rtems_monitor_symbols;
62
63/*
64 * User registered commands.
65 */
66
67rtems_monitor_command_entry_t rtems_registered_commands;
68
69/*
70 * The top-level commands
71 */
72
73rtems_monitor_command_entry_t rtems_monitor_commands[] = {
74    { "config",
75      "Show the system configuration.",
76      0,
77      rtems_monitor_object_cmd,
78      { RTEMS_MONITOR_OBJECT_CONFIG },
79      &rtems_monitor_commands[1],
80    },
81    { "itask",
82      "List init tasks for the system",
83      0,
84      rtems_monitor_object_cmd,
85      { RTEMS_MONITOR_OBJECT_INIT_TASK },
86      &rtems_monitor_commands[2],
87    },
88   { "mpci",
89      "Show the MPCI system configuration, if configured.",
90      0,
91      rtems_monitor_object_cmd,
92      { RTEMS_MONITOR_OBJECT_MPCI },
93      &rtems_monitor_commands[3],
94    },
95    { "pause",
96      "Monitor goes to \"sleep\" for specified ticks (default is 1). "
97      "Monitor will resume at end of period or if explicitly awakened\n"
98      "  pause [ticks]",
99      0,
100      rtems_monitor_pause_cmd,
101      { 0 },
102      &rtems_monitor_commands[4],
103    },
104    { "continue",
105      "Put the monitor to sleep waiting for an explicit wakeup from the "
106      "program running.\n",
107      0,
108      rtems_monitor_continue_cmd,
109      { 0 },
110      &rtems_monitor_commands[5],
111    },
112    { "go",
113      "Alias for 'continue'",
114      0,
115      rtems_monitor_continue_cmd,
116      { 0 },
117      &rtems_monitor_commands[6],
118    },
119    { "node",
120      "Specify default node number for commands that take id's.\n"
121      "  node [ node number ]",
122      0,
123      rtems_monitor_node_cmd,
124      { 0 },
125      &rtems_monitor_commands[7],
126    },
127    { "symbol",
128      "Display value associated with specified symbol. "
129      "Defaults to displaying all known symbols.\n"
130      "  symbol [ symbolname [symbolname ... ] ]",
131      0,
132      rtems_monitor_symbol_cmd,
133      { .symbol_table = &rtems_monitor_symbols },
134      &rtems_monitor_commands[8],
135    },
136    { "extension",
137      "Display information about specified extensions. "
138      "Default is to display information about all extensions on this node.\n"
139      "  extension [id [id ...] ]",
140      0,
141      rtems_monitor_object_cmd,
142      { RTEMS_MONITOR_OBJECT_EXTENSION },
143      &rtems_monitor_commands[9],
144    },
145    { "task",
146      "Display information about the specified tasks. "
147      "Default is to display information about all tasks on this node.\n"
148      "  task [id [id ...] ]",
149      0,
150      rtems_monitor_object_cmd,
151      { RTEMS_MONITOR_OBJECT_TASK },
152      &rtems_monitor_commands[10],
153    },
154    { "queue",
155      "Display information about the specified message queues. "
156      "Default is to display information about all queues on this node.\n"
157      "  queue [id [id ... ] ]",
158      0,
159      rtems_monitor_object_cmd,
160      { RTEMS_MONITOR_OBJECT_QUEUE },
161      &rtems_monitor_commands[11],
162    },
163    { "sema",
164      "sema [id [id ... ] ]\n"
165      "  display information about the specified semaphores\n"
166      "  Default is to display information about all semaphores on this node\n"
167      ,
168      0,
169      rtems_monitor_object_cmd,
170      { RTEMS_MONITOR_OBJECT_SEMAPHORE },
171    },
172    { "region",
173      "region [id [id ... ] ]\n"
174      "  display information about the specified regions\n"
175      "  Default is to display information about all regions on this node\n"
176      ,
177      0,
178      rtems_monitor_object_cmd,
179      { RTEMS_MONITOR_OBJECT_REGION },
180    },
181    { "part",
182      "part [id [id ... ] ]\n"
183      "  display information about the specified partitions\n"
184      "  Default is to display information about all partitions on this node\n"
185      ,
186      0,
187      rtems_monitor_object_cmd,
188      { RTEMS_MONITOR_OBJECT_PARTITION },
189    },
190    { "object",
191      "Display information about specified RTEMS objects. "
192      "Object id's must include 'type' information. "
193      "(which may normally be defaulted)\n"
194      "  object [id [id ...] ]",
195      0,
196      rtems_monitor_object_cmd,
197      { RTEMS_MONITOR_OBJECT_INVALID },
198      &rtems_monitor_commands[12],
199    },
200    { "driver",
201      "Display the RTEMS device driver table.\n"
202      "  driver [ major [ major ... ] ]",
203      0,
204      rtems_monitor_object_cmd,
205      { RTEMS_MONITOR_OBJECT_DRIVER },
206      &rtems_monitor_commands[13],
207    },
208    { "dname",
209      "Displays information about named drivers.\n",
210      0,
211      rtems_monitor_object_cmd,
212      { RTEMS_MONITOR_OBJECT_DNAME },
213      &rtems_monitor_commands[14],
214    },
215    { "exit",
216      "Invoke 'rtems_fatal_error_occurred' with 'status' "
217      "(default is RTEMS_SUCCESSFUL)\n"
218      "  exit [status]",
219      0,
220      rtems_monitor_fatal_cmd,
221      { .status_code = RTEMS_SUCCESSFUL },
222      &rtems_monitor_commands[15],
223    },
224    { "fatal",
225      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
226      "  fatal [status]",
227      0,
228      rtems_monitor_fatal_cmd,
229      { .status_code = RTEMS_TASK_EXITTED },            /* exit value */
230      &rtems_monitor_commands[16],
231    },
232    { "quit",
233      "Alias for 'exit'\n",
234      0,
235      rtems_monitor_fatal_cmd,
236      { .status_code = RTEMS_SUCCESSFUL },              /* exit value */
237      &rtems_monitor_commands[17],
238    },
239    { "help",
240      "Provide information about commands. "
241      "Default is show basic command summary.\n"
242      "help [ command [ command ] ]",
243      0,
244      rtems_monitor_help_cmd,
245      { .monitor_command_entry = rtems_monitor_commands },
246      &rtems_monitor_commands[18],
247    },
248#ifdef CPU_INVOKE_DEBUGGER
249    { "debugger",
250      "Enter the debugger, if possible. "
251      "A continue from the debugger will return to the monitor.\n",
252      0,
253      rtems_monitor_debugger_cmd,
254      { 0 },
255      &rtems_monitor_commands[19],
256    },
257#endif
258    { 0, 0, 0, 0, { 0 }, &rtems_registered_commands },
259};
260
261
262rtems_status_code
263rtems_monitor_suspend(rtems_interval timeout)
264{
265    rtems_event_set event_set;
266    rtems_status_code status;
267
268    status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
269                                 RTEMS_DEFAULT_OPTIONS,
270                                 timeout,
271                                 &event_set);
272    return status;
273}
274
275void
276rtems_monitor_wakeup(void)
277{
278    rtems_status_code status;
279
280    status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
281}
282
283void
284rtems_monitor_debugger_cmd(
285    int        argc,
286    char     **argv,
287    rtems_monitor_command_arg_t* command_arg,
288    boolean    verbose
289)
290{
291#ifdef CPU_INVOKE_DEBUGGER
292    CPU_INVOKE_DEBUGGER;
293#endif
294}
295
296void
297rtems_monitor_pause_cmd(
298    int        argc,
299    char     **argv,
300    rtems_monitor_command_arg_t* command_arg,
301    boolean    verbose
302)
303{
304    if (argc == 1)
305        rtems_monitor_suspend(1);
306    else
307        rtems_monitor_suspend(strtoul(argv[1], 0, 0));
308}
309
310void
311rtems_monitor_fatal_cmd(
312    int     argc,
313    char  **argv,
314    rtems_monitor_command_arg_t* command_arg,
315    boolean verbose
316)
317{
318    if (argc == 1)
319        rtems_fatal_error_occurred(command_arg->status_code);
320    else
321        rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
322}
323
324void
325rtems_monitor_continue_cmd(
326    int     argc,
327    char  **argv,
328    rtems_monitor_command_arg_t* command_arg,
329    boolean verbose
330)
331{
332    rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
333}
334
335void
336rtems_monitor_node_cmd(
337    int     argc,
338    char  **argv,
339    rtems_monitor_command_arg_t* command_arg,
340    boolean verbose
341)
342{
343    uint32_t   new_node = rtems_monitor_default_node;
344
345    switch (argc)
346    {
347        case 1:                 /* no node, just set back to ours */
348            new_node = rtems_monitor_node;
349            break;
350
351        case 2:
352            new_node = strtoul(argv[1], 0, 0);
353            break;
354
355        default:
356            fprintf(stdout,"invalid syntax, try 'help node'\n");
357            break;
358    }
359
360    #if defined(RTEMS_MULTIPROCESSING)
361      if ((new_node >= 1) &&
362        _Configuration_MP_table &&
363        (new_node <= _Configuration_MP_table->maximum_nodes))
364            rtems_monitor_default_node = new_node;
365    #endif
366}
367
368
369/*
370 *  Function:   rtems_monitor_symbols_loadup
371 *
372 *  Description:
373 *      Create and load the monitor's symbol table.
374 *      We are reading the output format of 'gnm' which looks like this:
375 *
376 *              400a7068 ? _Rate_monotonic_Information
377 *              400a708c ? _Thread_Dispatch_disable_level
378 *              400a7090 ? _Configuration_Table
379 *
380 *      We ignore the type field.
381 *
382 *  Side Effects:
383 *      Creates and fills in 'rtems_monitor_symbols' table
384 *
385 *  TODO
386 *      there should be a BSP #define or something like that
387 *         to do this;  Assuming stdio is crazy.
388 *      Someday this should know BFD
389 *              Maybe we could get objcopy to just copy the symbol areas
390 *              and copy that down.
391 *
392 */
393
394void
395rtems_monitor_symbols_loadup(void)
396{
397    FILE *fp;
398    char buffer[128];
399
400    if (rtems_monitor_symbols)
401        rtems_symbol_table_destroy(rtems_monitor_symbols);
402
403    rtems_monitor_symbols = rtems_symbol_table_create(10);
404    if (rtems_monitor_symbols == 0)
405        return;
406
407    fp = fopen("symbols", "r");
408
409    if (fp == 0)
410        return;
411
412    while (fgets(buffer, sizeof(buffer) - 1, fp))
413    {
414        char *symbol;
415        char *value;
416        char *ignored_type;
417
418        value = strtok(buffer, " \t\n");
419        ignored_type = strtok(0, " \t\n");
420        symbol = strtok(0, " \t\n");
421
422        if (symbol && ignored_type && value)
423        {
424            rtems_symbol_t *sp;
425            sp = rtems_symbol_create(rtems_monitor_symbols,
426                                     symbol,
427                                     (uint32_t  ) strtoul(value, 0, 16));
428            if (sp == 0)
429            {
430                fprintf(stdout,"could not define symbol '%s'\n", symbol);
431                goto done;
432            }
433        }
434        else
435        {
436            fprintf(stdout,"parsing error on '%s'\n", buffer);
437            goto done;
438        }
439    }
440
441done:
442    return;
443}
444
445/*
446 * User registered commands.
447 */
448
449int
450rtems_monitor_insert_cmd (
451    rtems_monitor_command_entry_t *command
452)
453{
454    rtems_monitor_command_entry_t **p =  &rtems_registered_commands.next;
455
456    command->next = 0;
457
458    while (*p) {
459        if ( STREQ(command->command, (*p)->command) )
460            return 0;
461        p = & (*p)->next;
462    }
463    *p = command;
464    return 1;
465}
466
467int
468rtems_monitor_erase_cmd (
469    rtems_monitor_command_entry_t *command
470)
471{
472    rtems_monitor_command_entry_t **p = & rtems_registered_commands.next;
473
474    while (*p) {
475        if ( STREQ(command->command, (*p)->command) ) {
476            *p = (*p)->next;
477            command->next = 0;
478            return 1;
479        }
480        p = & (*p)->next;
481    }
482    return 0;
483
484}
485
486/*
487 * Main monitor command loop
488 */
489
490void
491rtems_monitor_task(
492    rtems_task_argument monitor_flags
493)
494{
495    rtems_tcb *debugee = 0;
496    rtems_context *rp;
497    rtems_context_fp *fp;
498    char command_buffer[513];
499    int argc;
500    char *argv[64];
501    boolean verbose = FALSE;
502    struct termios term;
503
504    /*
505     * Make the stdin stream characte not line based.
506     */
507
508    if (tcgetattr (STDIN_FILENO, &term) < 0)
509    {
510      fprintf(stdout,"rtems-monitor: cannot get terminal attributes.\n");
511    }
512    else
513    {
514      /*
515       * No echo, no canonical processing.
516       */
517
518      term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
519
520      /*
521       * No sigint on BREAK, CR-to-NL off, input parity off,
522       * don't strip 8th bit on input, output flow control off
523       */
524
525      term.c_lflag    &= ~(INPCK | ISTRIP | IXON);
526      term.c_cc[VMIN]  = 1;
527      term.c_cc[VTIME] = 0;
528
529      if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
530      {
531        fprintf(stdout,"cannot set terminal attributes\n");
532      }
533    }
534
535    if (!(monitor_flags & RTEMS_MONITOR_NOSYMLOAD)) {
536      rtems_monitor_symbols_loadup();
537    }
538
539    if (monitor_flags & RTEMS_MONITOR_SUSPEND)
540        (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
541
542    for (;;)
543    {
544        extern rtems_tcb * _Thread_Executing;
545        rtems_monitor_command_entry_t *command;
546
547        debugee = _Thread_Executing;
548        rp = &debugee->Registers;
549#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
550        fp = debugee->fp_context;  /* possibly 0 */
551#else
552        fp = 0;
553#endif
554
555        if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
556            continue;
557        if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
558                                                    argc,
559                                                    argv)) == 0)
560        {
561            /* no command */
562            fprintf(stdout,"Unrecognised command; try 'help'\n");
563            continue;
564        }
565
566        command->command_function(argc, argv, &command->command_arg, verbose);
567
568        fflush(stdout);
569    }
570}
571
572
573void
574rtems_monitor_kill(void)
575{
576    if (rtems_monitor_task_id)
577        rtems_task_delete(rtems_monitor_task_id);
578    rtems_monitor_task_id = 0;
579
580    rtems_monitor_server_kill();
581}
582
583void
584rtems_monitor_init(
585    uint32_t   monitor_flags
586)
587{
588    rtems_status_code status;
589
590    rtems_monitor_kill();
591
592    status = rtems_task_create(RTEMS_MONITOR_NAME,
593                               1,
594                               RTEMS_MINIMUM_STACK_SIZE * 2,
595                               RTEMS_INTERRUPT_LEVEL(0),
596                               RTEMS_DEFAULT_ATTRIBUTES,
597                               &rtems_monitor_task_id);
598    if (status != RTEMS_SUCCESSFUL)
599    {
600        rtems_error(status, "could not create monitor task");
601        return;
602    }
603
604    rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
605    rtems_monitor_default_node = rtems_monitor_node;
606
607    rtems_monitor_server_init(monitor_flags);
608
609    if (!(monitor_flags & RTEMS_MONITOR_NOTASK)) {
610      /*
611       * Start the monitor task itself
612       */
613      status = rtems_task_start(
614        rtems_monitor_task_id, rtems_monitor_task, monitor_flags);
615      if (status != RTEMS_SUCCESSFUL) {
616        rtems_error(status, "could not start monitor");
617        return;
618      }
619   }
620}
Note: See TracBrowser for help on using the repository browser.