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

Last change on this file since 77c4089 was 10ec9ae, checked in by Jennifer Averett <Jennifer.Averett@…>, on 08/05/03 at 19:06:56

2003-08-05 Till Strauman <strauman@…>

PR 436/rtems_misc

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