source: rtems/c/src/libmisc/monitor/mon-monitor.c @ 32e2554

4.104.114.84.95
Last change on this file since 32e2554 was 32e2554, checked in by Joel Sherrill <joel.sherrill@…>, on 06/14/00 at 17:22:59

Patch rtems-4.5-beta3-mon.diff from Chris Johns <cjohns@…>
to:

I have also added the ability to register and unregister commands. This
allows me to create a set of monitor commands for the network stack plus
basic memory dump/patch commands (needs a working probe interface). I
will also look at a basic ls/cd/rm/mv/cp command set at some stage.

I have been thinking about changing the monitor in the future to more
like a light weight RTEMS shell, `eshell' for embedded shell. This is a
story for another day but is a process or getting the commands to map to
the filesystem (eg, major=commands, minor=command) and supporting an
environment. The filesystem provide a structure for the commands.

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