summaryrefslogblamecommitdiffstats
path: root/cpukit/libmisc/monitor/mon-monitor.c
blob: 2e12c9c8fef5386b18bc0f96de9e4691df46de8e (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$
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <rtems.h>

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

#include <rtems/monitor.h>

/* set by trap handler */
extern rtems_tcb       *debugger_interrupted_task;
extern rtems_context   *debugger_interrupted_task_context;
extern uint32_t   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;

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

/*
 * The rtems symbol table
 */

rtems_symbol_table_t *rtems_monitor_symbols;

/*
 * The top-level commands
 */

static const 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],
    },
    { "symbol",
      "Display value associated with specified symbol. "
      "Defaults to displaying all known symbols.\n"
      "  symbol [ symbolname [symbolname ... ] ]",
      0,
      rtems_monitor_symbol_cmd,
      { .symbol_table = &rtems_monitor_symbols },
      &rtems_monitor_commands[7],
    },
    { "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[8],
    },
    { "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[9],
    },
    { "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[10],
    },
    { "sema",
      "sema [id [id ... ] ]\n"
      "  display information about the specified semaphores\n"
      "  Default is to display information about all semaphores on this node\n"
      ,
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_SEMAPHORE },
      &rtems_monitor_commands[11],
    },
    { "region",
      "region [id [id ... ] ]\n"
      "  display information about the specified regions\n"
      "  Default is to display information about all regions on this node\n"
      ,
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_REGION },
      &rtems_monitor_commands[12],
    },
    { "part",
      "part [id [id ... ] ]\n"
      "  display information about the specified partitions\n"
      "  Default is to display information about all partitions on this node\n"
      ,
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_PARTITION },
      &rtems_monitor_commands[13],
    },
    { "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[14],
    },
    { "driver",
      "Display the RTEMS device driver table.\n"
      "  driver [ major [ major ... ] ]",
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_DRIVER },
      &rtems_monitor_commands[15],
    },
    { "dname",
      "Displays information about named drivers.\n",
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_DNAME },
      &rtems_monitor_commands[16],
    },
    { "fatal",
      "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
      "  fatal [status]",
      0,
      rtems_monitor_fatal_cmd,
      { .status_code = RTEMS_TASK_EXITTED },		/* exit value */
      &rtems_monitor_commands[17],
    },
    { "reset",
      "(SW)Resets the System.",
      0,
      rtems_monitor_reset_cmd,
      { 0 },
      &rtems_monitor_commands[18],
    },
#if defined(RTEMS_MULTIPROCESSING)
    { "node",
      "Specify default node number for commands that take id's.\n"
      "  node [ node number ]",
      0,
      rtems_monitor_node_cmd,
      { 0 },
      &rtems_monitor_commands[19],
    },
  #define RTEMS_MONITOR_POSIX_NEXT 20
#else
  #define RTEMS_MONITOR_POSIX_NEXT 19
#endif
#ifdef RTEMS_POSIX_API
    { "pthread",
      "Display information about the specified pthreads. "
      "Default is to display information about all pthreads on this node.\n"
      "  pthread [id [id ...] ]",
      0,
      rtems_monitor_object_cmd,
      { RTEMS_MONITOR_OBJECT_PTHREAD },
      &rtems_monitor_commands[RTEMS_MONITOR_POSIX_NEXT],
    },
  #define RTEMS_MONITOR_DEBUGGER_NEXT (RTEMS_MONITOR_POSIX_NEXT + 1)
#else
  #define RTEMS_MONITOR_DEBUGGER_NEXT RTEMS_MONITOR_POSIX_NEXT
#endif
#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[RTEMS_MONITOR_DEBUGGER_NEXT],
    },
#endif
    { "help",
      "Provide information about commands. "
      "Default is show basic command summary.\n"
      "help [ command [ command ] ]",
      0,
      rtems_monitor_help_cmd,
      { .monitor_command_entry = rtems_monitor_commands },
      NULL
    }
};

/*
 * All registered commands.
 */

static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
  &rtems_monitor_commands [0];


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 __attribute__((weak))
rtems_monitor_reset_cmd(
  int argc,
  char **argv,
  const rtems_monitor_command_arg_t* command_arg,
  bool verbose
)
{

}

void
rtems_monitor_wakeup(void)
{
    rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
}

void rtems_monitor_debugger_cmd(
  int                                argc __attribute__((unused)),
  char                             **argv __attribute__((unused)),
  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
  bool                               verbose __attribute__((unused))
)
{
#ifdef CPU_INVOKE_DEBUGGER
    CPU_INVOKE_DEBUGGER;
#endif
}

void rtems_monitor_pause_cmd(
  int                                argc,
  char                             **argv,
  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
  bool                               verbose __attribute__((unused))
)
{
    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,
  const rtems_monitor_command_arg_t *command_arg,
  bool                               verbose __attribute__((unused))
)
{
    if (argc == 1)
        rtems_fatal_error_occurred(command_arg->status_code);
    else
        rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
}

void rtems_monitor_continue_cmd(
  int                                argc __attribute__((unused)),
  char                             **argv __attribute__((unused)),
  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
  bool                               verbose __attribute__((unused))
)
{
    rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
}

#if defined(RTEMS_MULTIPROCESSING)
void rtems_monitor_node_cmd(
  int                                argc,
  char                             **argv,
  const rtems_monitor_command_arg_t *command_arg __attribute__((unused)),
  bool                               verbose __attribute__((unused))
)
{
  uint32_t   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:
      fprintf(stdout,"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;
}
#endif


/*
 *  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();
    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,
                                     (uint32_t) strtoul(value, 0, 16));
            if (sp == 0)
            {
                fprintf(stdout,"could not define symbol '%s'\n", symbol);
                goto done;
            }
        }
        else
        {
            fprintf(stdout,"parsing error on '%s'\n", buffer);
            goto done;
        }
    }

done:
    fclose(fp);
    return;
}

/*
 * User registered commands.
 */

int
rtems_monitor_insert_cmd (
  rtems_monitor_command_entry_t *command
)
{
  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;

  /* Reject empty commands */
  if (command->command == NULL) {
    return 0;
  }

  /* Reject command if already present */
  while (e->next != NULL) {
      if (e->command != NULL && strcmp(command->command, e->command) == 0) {
        return 0;
      }
      e = e->next;
  }

  /* Prepend new command */
  command->next = rtems_monitor_registered_commands;
  rtems_monitor_registered_commands = command;

  return 1;
}

/**
 * @brief Iterates through all registerd commands.
 *
 * For each command the interation routine @a routine is called with the
 * command entry and the user provided argument @a arg.  It is guaranteed that
 * the command name and function are not NULL.
 */
void rtems_monitor_command_iterate(
  rtems_monitor_per_command_routine routine,
  void *arg
)
{
  const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;

  while (e != NULL) {
    if (e->command != NULL && e->command_function != NULL) {
      if (!routine(e, arg)) {
        break;
      }
    }
    e = e->next;
  }
}