summaryrefslogblamecommitdiffstats
path: root/c/src/libmisc/monitor/mon-monitor.c
blob: ef86decda9db4329cdf0902511deabab58af7fc6 (plain) (tree)
1
2
3
4
  
                          

         











                                                                     
                                    


                                                         

        


                  



                   
                    

                   
                          





                                                          




                                                                
 
                                
 

                                                                          

  
                         

   

                                            
  





                                                        
                         

   
                                                          
               
                                       

                               
                                  
                                 

              
                                       

                               
                                     
                                 

            
                                                           

                               
                                
                                 

              


                                                                        


                              
                                 

                 

                                                                         


                                 
                                 

           
                             


                                 
                                 

             

                                                                  


                             
                                 

               


                                                        

                               


                                                                    
                                          
      
                                 

                  


                                                                              

                               
                                     
                                 

             


                                                                         

                               
                                
                                  

              


                                                                          

                               
                                 
                                  

               



                                                           

                               
                                   
                                  

               

                                                

                               
                                  
                                  

              
                                                    

                               
                                 
                                  

             


                                                          


                              
                                  

              

                                                                      


                                                                
                                  

             
                           


                                                                
                                  

             


                                                

                             


                                                                    
                                          
      
                                  


                          

                                                                   
        
                                 
        
                                  

                  
                                                  
  
 






                                             



                                                       










                                                                           











                           
 












                                                      
 






                           
 



                                                           


    





                           
 

                                            
 
    









                                                     
     


                                                                    
 


                                              
 


                                                        
     
 



                                                             

 
 










                                                                        

                                 


                                                          


                                                            











                                                                        


                                                          



                                                          
                               
    




















                                                                               
                                                                 




                          
                                                      




                      
           
 
 

















































                                                                             
















                                     
                        
 






























                                                                 









                                                       
                                                          
                                                                        


               





                                                                           


                                                         
                     
         




























                                                                             
                                                            































                                                               
/*
 * RTEMS monitor main body
 *	
 *  TODO:
 *      add stuff to RTEMS api
 *            rtems_get_name(id)
 *            rtems_get_type(id)
 *            rtems_build_id(node, type, num)
 *      Add a command to dump out info about an arbitrary id when
 *         types are added to id's
 *         rtems> id idnum
 *                idnum: node n, object: whatever, id: whatever
 *      allow id's to be specified as n:t:id, where 'n:t' is optional
 *      should have a separate monitor FILE stream (ala the debugger)
 *      remote request/response stuff should be cleaned up
 *         maybe we can use real rpc??
 *      'info' command to print out:
 *           interrupt stack location, direction and size
 *           floating point config stuff
 *           interrupt config stuff
 *
 *  $Id$
 */

#include <rtems.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>

#include <rtems/monitor.h>

/* set by trap handler */
extern rtems_tcb       *debugger_interrupted_task;
extern rtems_context   *debugger_interrupted_task_context;
extern rtems_unsigned32 debugger_trap;

/*
 * Various id's for the monitor
 * They need to be public variables for access by other agencies
 * such as debugger and remote servers'
 */

rtems_id  rtems_monitor_task_id;

unsigned32 rtems_monitor_node;		/* our node number */
unsigned32 rtems_monitor_default_node;  /* current default for commands */

/*
 * The rtems symbol table
 */

rtems_symbol_table_t *rtems_monitor_symbols;

/*
 * User registered commands.
 */

rtems_monitor_command_entry_t rtems_registered_commands;

/*
 * The top-level commands
 */

rtems_monitor_command_entry_t rtems_monitor_commands[] = {
    { "config",
      "Show the system configuration.",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_CONFIG,
      &rtems_monitor_commands[1],
    },
    { "itask",
      "List init tasks for the system",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_INIT_TASK,
      &rtems_monitor_commands[2],
    }, 
   { "mpci",
      "Show the MPCI system configuration, if configured.",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_MPCI,
      &rtems_monitor_commands[3],
    },
    { "pause",
      "Monitor goes to \"sleep\" for specified ticks (default is 1). "
      "Monitor will resume at end of period or if explicitly awakened\n"
      "  pause [ticks]",
      0,
      rtems_monitor_pause_cmd,
      0,
      &rtems_monitor_commands[4],
    },
    { "continue",
      "Put the monitor to sleep waiting for an explicit wakeup from the "
      "program running.\n",
      0,
      rtems_monitor_continue_cmd,
      0,
      &rtems_monitor_commands[5],
    },
    { "go",
      "Alias for 'continue'",
      0,
      rtems_monitor_continue_cmd,
      0,
      &rtems_monitor_commands[6],
    },
    { "node",
      "Specify default node number for commands that take id's.\n"
      "  node [ node number ]",
      0,
      rtems_monitor_node_cmd,
      0,
      &rtems_monitor_commands[7],
    },
    { "symbol",
      "Display value associated with specified symbol. "
      "Defaults to displaying all known symbols.\n"
      "  symbol [ symbolname [symbolname ... ] ]",
      0,
      rtems_monitor_symbol_cmd,
#if defined(RTEMS_CPU_HAS_16_BIT_ADDRESSES)
      0,    /* XXX find a way to fix the compile time error on h8 */
#else
      (unsigned32) &rtems_monitor_symbols,
#endif
      &rtems_monitor_commands[8],
    },
    { "extension",
      "Display information about specified extensions. "
      "Default is to display information about all extensions on this node.\n"
      "  extension [id [id ...] ]",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_EXTENSION,
      &rtems_monitor_commands[9],
    },
    { "task",
      "Display information about the specified tasks. "
      "Default is to display information about all tasks on this node.\n"
      "  task [id [id ...] ]",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_TASK,
      &rtems_monitor_commands[10],
    },
    { "queue",
      "Display information about the specified message queues. "
      "Default is to display information about all queues on this node.\n"
      "  queue [id [id ... ] ]",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_QUEUE,
      &rtems_monitor_commands[11],
    },
    { "object",
      "Display information about specified RTEMS objects. "
      "Object id's must include 'type' information. "
      "(which may normally be defaulted)\n"
      "  object [id [id ...] ]",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_INVALID,
      &rtems_monitor_commands[12],
    },
    { "driver",
      "Display the RTEMS device driver table.\n"
      "  driver [ major [ major ... ] ]",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_DRIVER,
      &rtems_monitor_commands[13],
    },
    { "dname",
      "Displays information about named drivers.\n",
      0,
      rtems_monitor_object_cmd,
      RTEMS_MONITOR_OBJECT_DNAME,
      &rtems_monitor_commands[14],
    },
    { "exit",
      "Invoke 'rtems_fatal_error_occurred' with 'status' "
      "(default is RTEMS_SUCCESSFUL)\n"
      "  exit [status]",
      0,
      rtems_monitor_fatal_cmd,
      RTEMS_SUCCESSFUL,
      &rtems_monitor_commands[15],
    },
    { "fatal",
      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
      "  fatal [status]",
      0,
      rtems_monitor_fatal_cmd,
      RTEMS_TASK_EXITTED,			/* exit value */
      &rtems_monitor_commands[16],
    },
    { "quit",
      "Alias for 'exit'\n",
      0,
      rtems_monitor_fatal_cmd,
      RTEMS_SUCCESSFUL,				/* exit value */
      &rtems_monitor_commands[17],
    },
    { "help",
      "Provide information about commands. "
      "Default is show basic command summary.\n"
      "help [ command [ command ] ]",
      0,
      rtems_monitor_help_cmd,
#if defined(RTEMS_CPU_HAS_16_BIT_ADDRESSES)
      0,    /* XXX find a way to fix the compile time error on h8 */
#else
      (unsigned32) rtems_monitor_commands,
#endif
      &rtems_monitor_commands[18],
    },
#ifdef CPU_INVOKE_DEBUGGER
    { "debugger",
      "Enter the debugger, if possible. "
      "A continue from the debugger will return to the monitor.\n",
      0,
      rtems_monitor_debugger_cmd,
      0,
      &rtems_monitor_commands[19],
    },
#endif            
    { 0, 0, 0, 0, 0, &rtems_registered_commands },
};


rtems_status_code
rtems_monitor_suspend(rtems_interval timeout)
{
    rtems_event_set event_set;
    rtems_status_code status;
    
    status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
                                 RTEMS_DEFAULT_OPTIONS,
                                 timeout,
                                 &event_set);
    return status;
}

void
rtems_monitor_wakeup(void)
{
    rtems_status_code status;
    
    status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
}

void
rtems_monitor_debugger_cmd(
    int        argc,
    char     **argv,
    unsigned32 command_arg,
    boolean    verbose
)
{
#ifdef CPU_INVOKE_DEBUGGER
    CPU_INVOKE_DEBUGGER;
#endif
}

void
rtems_monitor_pause_cmd(
    int        argc,
    char     **argv,
    unsigned32 command_arg,
    boolean    verbose
)
{
    if (argc == 1)
        rtems_monitor_suspend(1);
    else
        rtems_monitor_suspend(strtoul(argv[1], 0, 0));
}

void
rtems_monitor_fatal_cmd(
    int     argc,
    char  **argv,
    unsigned32 command_arg,
    boolean verbose
)
{
    if (argc == 1)
        rtems_fatal_error_occurred(command_arg);
    else
        rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
}

void
rtems_monitor_continue_cmd(
    int     argc,
    char  **argv,
    unsigned32 command_arg,
    boolean verbose
)
{
    rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
}

void
rtems_monitor_node_cmd(
    int     argc,
    char  **argv,
    unsigned32 command_arg,
    boolean verbose
)
{
    unsigned32 new_node = rtems_monitor_default_node;
    
    switch (argc)
    {
        case 1: 		/* no node, just set back to ours */
            new_node = rtems_monitor_node;
            break;

        case 2:
            new_node = strtoul(argv[1], 0, 0);
            break;

        default:
            printf("invalid syntax, try 'help node'\n");
            break;
    }

    if ((new_node >= 1) &&
        _Configuration_MP_table &&
        (new_node <= _Configuration_MP_table->maximum_nodes))
            rtems_monitor_default_node = new_node;
}


/*
 *  Function:   rtems_monitor_symbols_loadup
 *
 *  Description:
 *      Create and load the monitor's symbol table.
 *      We are reading the output format of 'gnm' which looks like this:
 *
 *              400a7068 ? _Rate_monotonic_Information
 *              400a708c ? _Thread_Dispatch_disable_level
 *              400a7090 ? _Configuration_Table
 *
 *      We ignore the type field.
 *
 *  Side Effects:
 *      Creates and fills in 'rtems_monitor_symbols' table
 *
 *  TODO
 *      there should be a BSP #define or something like that
 *         to do this;  Assuming stdio is crazy.
 *      Someday this should know BFD
 *              Maybe we could get objcopy to just copy the symbol areas
 *              and copy that down.
 *
 */

void
rtems_monitor_symbols_loadup(void)
{
    FILE *fp;
    char buffer[128];

    if (rtems_monitor_symbols)
        rtems_symbol_table_destroy(rtems_monitor_symbols);
    
    rtems_monitor_symbols = rtems_symbol_table_create(10);
    if (rtems_monitor_symbols == 0)
        return;

    fp = fopen("symbols", "r");
    
    if (fp == 0)
        return;

    while (fgets(buffer, sizeof(buffer) - 1, fp))
    {
        char *symbol;
        char *value;
        char *ignored_type;

        value = strtok(buffer, " \t\n");
        ignored_type = strtok(0, " \t\n");
        symbol = strtok(0, " \t\n");

        if (symbol && ignored_type && value)
        {
            rtems_symbol_t *sp;
            sp = rtems_symbol_create(rtems_monitor_symbols,
                                     symbol,
                                     (rtems_unsigned32) strtoul(value, 0, 16));
            if (sp == 0)
            {
                printf("could not define symbol '%s'\n", symbol);
                goto done;
            }
        }
        else
        {
            printf("parsing error on '%s'\n", buffer);
            goto done;
        }
    }

done:
    return;
}

/*
 * User registered commands.
 */

int
rtems_monitor_insert_cmd (
    rtems_monitor_command_entry_t *command
)
{
    rtems_monitor_command_entry_t *p = rtems_registered_commands.next;

    command->next = 0;

    if (rtems_registered_commands.next)
    {
        for (; p->next; p = p->next)
        {
            if (STREQ(command->command, p->command))
                return 0;
        }
        p->next = command;
    }
    else
        rtems_registered_commands.next = command;
  
    return 1;
}

int
rtems_monitor_erase_cmd (
    rtems_monitor_command_entry_t *command
)
{
    rtems_monitor_command_entry_t *p;
    rtems_monitor_command_entry_t **p_prev = &rtems_registered_commands.next;

    if (rtems_registered_commands.next)
    {
        for (p = rtems_registered_commands.next; p->next; p = p->next)
        {
            if (STREQ(command->command, p->command))
            {
                *p_prev = p->next;
                return 1;
            }
            p_prev = &p->next;
        }
    }
    return 0;
}

/*
 * Main monitor command loop
 */

void
rtems_monitor_task(
    rtems_task_argument monitor_flags
)
{
    rtems_tcb *debugee = 0;
    rtems_context *rp;
    rtems_context_fp *fp;
    char command_buffer[513];
    int argc;
    char *argv[64];        
    boolean verbose = FALSE;
    struct termios term;

    /*
     * Make the stdin stream characte not line based.
     */
    
    if (tcgetattr (STDIN_FILENO, &term) < 0)
    {
      printf("rtems-monitor: cannot get terminal attributes.\n");
    }
    else
    {
      /*
       * No echo, no canonical processing.
       */

      term.c_lflag &= ~(ECHO | ICANON | IEXTEN);
  
      /*
       * No sigint on BREAK, CR-to-NL off, input parity off,
       * don't strip 8th bit on input, output flow control off
       */

      term.c_lflag    &= ~(INPCK | ISTRIP | IXON);
      term.c_cc[VMIN]  = 1;
      term.c_cc[VTIME] = 0;

      if (tcsetattr (STDIN_FILENO, TCSANOW, &term) < 0)
      {
        printf("cannot set terminal attributes\n");
      }
    }
    
    if (monitor_flags & RTEMS_MONITOR_SUSPEND)
        (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT);

    for (;;)
    {
        extern rtems_tcb * _Thread_Executing;
        rtems_monitor_command_entry_t *command;

        debugee = _Thread_Executing;
        rp = &debugee->Registers;
#if (CPU_HARDWARE_FP == TRUE) || (CPU_SOFTWARE_FP == TRUE)
        fp = (rtems_context_fp *) debugee->fp_context;  /* possibly 0 */
#else
        fp = 0;
#endif

        if (0 == rtems_monitor_command_read(command_buffer, &argc, argv))
            continue;
        if ((command = rtems_monitor_command_lookup(rtems_monitor_commands,
                                                    argc,
                                                    argv)) == 0)
        {
            /* no command */
            printf("Unrecognised command; try 'help'\n");
            continue;
        }

        command->command_function(argc, argv, command->command_arg, verbose);

        fflush(stdout);
    }
}


void
rtems_monitor_kill(void)
{
    if (rtems_monitor_task_id)
        rtems_task_delete(rtems_monitor_task_id);
    rtems_monitor_task_id = 0;
    
    rtems_monitor_server_kill();
}

void
rtems_monitor_init(
    unsigned32 monitor_flags
)
{
    rtems_status_code status;
    
    rtems_monitor_kill();

    status = rtems_task_create(RTEMS_MONITOR_NAME,
                               1,
                               RTEMS_MINIMUM_STACK_SIZE * 2,
                               RTEMS_INTERRUPT_LEVEL(0),
                               RTEMS_DEFAULT_ATTRIBUTES,
                               &rtems_monitor_task_id);
    if (status != RTEMS_SUCCESSFUL)
    {
        rtems_error(status, "could not create monitor task");
        goto done;
    }

    rtems_monitor_node = rtems_get_node(rtems_monitor_task_id);
    rtems_monitor_default_node = rtems_monitor_node;

    rtems_monitor_symbols_loadup();

    if (monitor_flags & RTEMS_MONITOR_GLOBAL)
        rtems_monitor_server_init(monitor_flags);

    /*
     * Start the monitor task itself
     */
    
    status = rtems_task_start(rtems_monitor_task_id,
                              rtems_monitor_task,
                              monitor_flags);
    if (status != RTEMS_SUCCESSFUL)
    {
        rtems_error(status, "could not start monitor");
        goto done;
    }

done:
}