Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief RTEMS monitor main body
0007  *
0008  *  TODO:
0009  *      add stuff to RTEMS api
0010  *            rtems_get_name(id)
0011  *            rtems_get_type(id)
0012  *            rtems_build_id(node, type, num)
0013  *      Add a command to dump out info about an arbitrary id when
0014  *         types are added to id's
0015  *         rtems> id idnum
0016  *                idnum: node n, object: whatever, id: whatever
0017  *      allow id's to be specified as n:t:id, where 'n:t' is optional
0018  *      should have a separate monitor FILE stream (ala the debugger)
0019  *      remote request/response stuff should be cleaned up
0020  *         maybe we can use real rpc??
0021  *      'info' command to print out:
0022  *           interrupt stack location, direction and size
0023  *           floating point config stuff
0024  *           interrupt config stuff
0025  */
0026 
0027 /*
0028  * COPYRIGHT (c) 1989-2022. On-Line Applications Research Corporation (OAR).
0029  *
0030  * Redistribution and use in source and binary forms, with or without
0031  * modification, are permitted provided that the following conditions
0032  * are met:
0033  * 1. Redistributions of source code must retain the above copyright
0034  *    notice, this list of conditions and the following disclaimer.
0035  * 2. Redistributions in binary form must reproduce the above copyright
0036  *    notice, this list of conditions and the following disclaimer in the
0037  *    documentation and/or other materials provided with the distribution.
0038  *
0039  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0040  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0041  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0042  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0043  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0044  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0045  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0046  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0047  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0048  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0049  * POSSIBILITY OF SUCH DAMAGE.
0050  */
0051 #ifdef HAVE_CONFIG_H
0052 #include "config.h"
0053 #endif
0054 
0055 #include <rtems.h>
0056 
0057 #include <stdio.h>
0058 #include <string.h>
0059 #include <stdlib.h>
0060 
0061 #include <rtems/monitor.h>
0062 
0063 /*
0064  * Various id's for the monitor
0065  * They need to be public variables for access by other agencies
0066  * such as debugger and remote servers'
0067  */
0068 
0069 rtems_id  rtems_monitor_task_id;
0070 
0071 uint32_t   rtems_monitor_node;      /* our node number */
0072 uint32_t   rtems_monitor_default_node;  /* current default for commands */
0073 
0074 /*
0075  * The rtems symbol table
0076  */
0077 
0078 rtems_symbol_table_t *rtems_monitor_symbols;
0079 
0080 /*
0081  * The top-level commands
0082  */
0083 
0084 static const rtems_monitor_command_entry_t rtems_monitor_commands[] = {
0085     { "config",
0086       "Show the system configuration.",
0087       0,
0088       rtems_monitor_object_cmd,
0089       { RTEMS_MONITOR_OBJECT_CONFIG },
0090       &rtems_monitor_commands[1],
0091     },
0092     { "itask",
0093       "List init tasks for the system",
0094       0,
0095       rtems_monitor_object_cmd,
0096       { RTEMS_MONITOR_OBJECT_INIT_TASK },
0097       &rtems_monitor_commands[2],
0098     },
0099    { "mpci",
0100       "Show the MPCI system configuration, if configured.",
0101       0,
0102       rtems_monitor_object_cmd,
0103       { RTEMS_MONITOR_OBJECT_MPCI },
0104       &rtems_monitor_commands[3],
0105     },
0106     { "pause",
0107       "Monitor goes to \"sleep\" for specified ticks (default is 1). "
0108       "Monitor will resume at end of period or if explicitly awakened\n"
0109       "  pause [ticks]",
0110       0,
0111       rtems_monitor_pause_cmd,
0112       { 0 },
0113       &rtems_monitor_commands[4],
0114     },
0115     { "continue",
0116       "Put the monitor to sleep waiting for an explicit wakeup from the "
0117       "program running.\n",
0118       0,
0119       rtems_monitor_continue_cmd,
0120       { 0 },
0121       &rtems_monitor_commands[5],
0122     },
0123     { "go",
0124       "Alias for 'continue'",
0125       0,
0126       rtems_monitor_continue_cmd,
0127       { 0 },
0128       &rtems_monitor_commands[6],
0129     },
0130     { "symbol",
0131       "Display value associated with specified symbol. "
0132       "Defaults to displaying all known symbols.\n"
0133       "  symbol [ symbolname [symbolname ... ] ]",
0134       0,
0135       rtems_monitor_symbol_cmd,
0136       { .symbol_table = &rtems_monitor_symbols },
0137       &rtems_monitor_commands[7],
0138     },
0139     { "extension",
0140       "Display information about specified extensions. "
0141       "Default is to display information about all extensions on this node.\n"
0142       "  extension [id [id ...] ]",
0143       0,
0144       rtems_monitor_object_cmd,
0145       { RTEMS_MONITOR_OBJECT_EXTENSION },
0146       &rtems_monitor_commands[8],
0147     },
0148     { "task",
0149       "Display information about the specified tasks. "
0150       "Default is to display information about all tasks on this node.\n"
0151       "  task [id [id ...] ]",
0152       0,
0153       rtems_monitor_object_cmd,
0154       { RTEMS_MONITOR_OBJECT_TASK },
0155       &rtems_monitor_commands[9],
0156     },
0157     { "queue",
0158       "Display information about the specified message queues. "
0159       "Default is to display information about all queues on this node.\n"
0160       "  queue [id [id ... ] ]",
0161       0,
0162       rtems_monitor_object_cmd,
0163       { RTEMS_MONITOR_OBJECT_QUEUE },
0164       &rtems_monitor_commands[10],
0165     },
0166     { "sema",
0167       "sema [id [id ... ] ]\n"
0168       "  display information about the specified semaphores\n"
0169       "  Default is to display information about all semaphores on this node\n"
0170       ,
0171       0,
0172       rtems_monitor_object_cmd,
0173       { RTEMS_MONITOR_OBJECT_SEMAPHORE },
0174       &rtems_monitor_commands[11],
0175     },
0176     { "region",
0177       "region [id [id ... ] ]\n"
0178       "  display information about the specified regions\n"
0179       "  Default is to display information about all regions on this node\n"
0180       ,
0181       0,
0182       rtems_monitor_object_cmd,
0183       { RTEMS_MONITOR_OBJECT_REGION },
0184       &rtems_monitor_commands[12],
0185     },
0186     { "part",
0187       "part [id [id ... ] ]\n"
0188       "  display information about the specified partitions\n"
0189       "  Default is to display information about all partitions on this node\n"
0190       ,
0191       0,
0192       rtems_monitor_object_cmd,
0193       { RTEMS_MONITOR_OBJECT_PARTITION },
0194       &rtems_monitor_commands[13],
0195     },
0196     { "object",
0197       "Display information about specified RTEMS objects. "
0198       "Object id's must include 'type' information. "
0199       "(which may normally be defaulted)\n"
0200       "  object [id [id ...] ]",
0201       0,
0202       rtems_monitor_object_cmd,
0203       { RTEMS_MONITOR_OBJECT_INVALID },
0204       &rtems_monitor_commands[14],
0205     },
0206     { "driver",
0207       "Display the RTEMS device driver table.\n"
0208       "  driver [ major [ major ... ] ]",
0209       0,
0210       rtems_monitor_object_cmd,
0211       { RTEMS_MONITOR_OBJECT_DRIVER },
0212       &rtems_monitor_commands[15],
0213     },
0214     { "dname",
0215       "Displays information about named drivers.\n",
0216       0,
0217       rtems_monitor_object_cmd,
0218       { RTEMS_MONITOR_OBJECT_DNAME },
0219       &rtems_monitor_commands[16],
0220     },
0221     { "fatal",
0222       "'exit' with fatal error; default error is RTEMS_TASK_EXITTED\n"
0223       "  fatal [status]",
0224       0,
0225       rtems_monitor_fatal_cmd,
0226       { .status_code = RTEMS_TASK_EXITTED },        /* exit value */
0227       &rtems_monitor_commands[17],
0228     },
0229     { "reset",
0230       "(SW)Resets the System.",
0231       0,
0232       rtems_monitor_reset_cmd,
0233       { 0 },
0234       &rtems_monitor_commands[18],
0235     },
0236 #if defined(RTEMS_MULTIPROCESSING)
0237     { "node",
0238       "Specify default node number for commands that take id's.\n"
0239       "  node [ node number ]",
0240       0,
0241       rtems_monitor_node_cmd,
0242       { 0 },
0243       &rtems_monitor_commands[19],
0244     },
0245   #define RTEMS_MONITOR_POSIX_NEXT 20
0246 #else
0247   #define RTEMS_MONITOR_POSIX_NEXT 19
0248 #endif
0249     { "pthread",
0250       "Display information about the specified pthreads. "
0251       "Default is to display information about all pthreads on this node.\n"
0252       "  pthread [id [id ...] ]",
0253       0,
0254       rtems_monitor_object_cmd,
0255       { RTEMS_MONITOR_OBJECT_PTHREAD },
0256       &rtems_monitor_commands[RTEMS_MONITOR_POSIX_NEXT],
0257     },
0258   #define RTEMS_MONITOR_DEBUGGER_NEXT (RTEMS_MONITOR_POSIX_NEXT + 1)
0259 #ifdef CPU_INVOKE_DEBUGGER
0260     { "debugger",
0261       "Enter the debugger, if possible. "
0262       "A continue from the debugger will return to the monitor.\n",
0263       0,
0264       rtems_monitor_debugger_cmd,
0265       { 0 },
0266       &rtems_monitor_commands[RTEMS_MONITOR_DEBUGGER_NEXT],
0267     },
0268 #endif
0269     { "help",
0270       "Provide information about commands. "
0271       "Default is show basic command summary.\n"
0272       "help [ command [ command ] ]",
0273       0,
0274       rtems_monitor_help_cmd,
0275       { .monitor_command_entry = rtems_monitor_commands },
0276       NULL
0277     }
0278 };
0279 
0280 /*
0281  * All registered commands.
0282  */
0283 
0284 static const rtems_monitor_command_entry_t *rtems_monitor_registered_commands =
0285   &rtems_monitor_commands [0];
0286 
0287 
0288 rtems_status_code
0289 rtems_monitor_suspend(rtems_interval timeout)
0290 {
0291     rtems_event_set event_set;
0292     rtems_status_code status;
0293 
0294     status = rtems_event_receive(MONITOR_WAKEUP_EVENT,
0295                                  RTEMS_DEFAULT_OPTIONS,
0296                                  timeout,
0297                                  &event_set);
0298     return status;
0299 }
0300 
0301 void __attribute__((weak))
0302 rtems_monitor_reset_cmd(
0303   int argc,
0304   char **argv,
0305   const rtems_monitor_command_arg_t* command_arg,
0306   bool verbose
0307 )
0308 {
0309 
0310 }
0311 
0312 void
0313 rtems_monitor_wakeup(void)
0314 {
0315     rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT);
0316 }
0317 
0318 void rtems_monitor_debugger_cmd(
0319   int                                argc RTEMS_UNUSED,
0320   char                             **argv RTEMS_UNUSED,
0321   const rtems_monitor_command_arg_t *command_arg RTEMS_UNUSED,
0322   bool                               verbose RTEMS_UNUSED
0323 )
0324 {
0325 #ifdef CPU_INVOKE_DEBUGGER
0326     CPU_INVOKE_DEBUGGER;
0327 #endif
0328 }
0329 
0330 void rtems_monitor_pause_cmd(
0331   int                                argc,
0332   char                             **argv,
0333   const rtems_monitor_command_arg_t *command_arg RTEMS_UNUSED,
0334   bool                               verbose RTEMS_UNUSED
0335 )
0336 {
0337     if (argc == 1)
0338         rtems_monitor_suspend(1);
0339     else
0340         rtems_monitor_suspend(strtoul(argv[1], 0, 0));
0341 }
0342 
0343 void rtems_monitor_fatal_cmd(
0344   int                                argc,
0345   char                             **argv,
0346   const rtems_monitor_command_arg_t *command_arg,
0347   bool                               verbose RTEMS_UNUSED
0348 )
0349 {
0350     if (argc == 1)
0351         rtems_fatal_error_occurred(command_arg->status_code);
0352     else
0353         rtems_fatal_error_occurred(strtoul(argv[1], 0, 0));
0354 }
0355 
0356 void rtems_monitor_continue_cmd(
0357   int                                argc RTEMS_UNUSED,
0358   char                             **argv RTEMS_UNUSED,
0359   const rtems_monitor_command_arg_t *command_arg RTEMS_UNUSED,
0360   bool                               verbose RTEMS_UNUSED
0361 )
0362 {
0363     rtems_monitor_suspend(RTEMS_NO_TIMEOUT);
0364 }
0365 
0366 #if defined(RTEMS_MULTIPROCESSING)
0367 void rtems_monitor_node_cmd(
0368   int                                argc,
0369   char                             **argv,
0370   const rtems_monitor_command_arg_t *command_arg RTEMS_UNUSED,
0371   bool                               verbose RTEMS_UNUSED
0372 )
0373 {
0374   uint32_t   new_node = rtems_monitor_default_node;
0375 
0376   switch (argc) {
0377     case 1:         /* no node, just set back to ours */
0378       new_node = rtems_monitor_node;
0379       break;
0380 
0381     case 2:
0382       new_node = strtoul(argv[1], 0, 0);
0383       break;
0384 
0385     default:
0386       fprintf(stdout,"invalid syntax, try 'help node'\n");
0387       break;
0388   }
0389 
0390   if ((new_node >= 1) &&
0391     (new_node <= _MPCI_Configuration.maximum_nodes))
0392     rtems_monitor_default_node = new_node;
0393 }
0394 #endif
0395 
0396 
0397 /*
0398  *  Function:   rtems_monitor_symbols_loadup
0399  *
0400  *  Description:
0401  *      Create and load the monitor's symbol table.
0402  *      We are reading the output format of 'gnm' which looks like this:
0403  *
0404  *              400a7068 ? _Rate_monotonic_Information
0405  *              400a708c ? _Thread_Dispatch_disable_level
0406  *              400a7090 ? _Configuration_Table
0407  *
0408  *      We ignore the type field.
0409  *
0410  *  Side Effects:
0411  *      Creates and fills in 'rtems_monitor_symbols' table
0412  *
0413  *  TODO
0414  *      there should be a BSP #define or something like that
0415  *         to do this;  Assuming stdio is crazy.
0416  *      Someday this should know BFD
0417  *              Maybe we could get objcopy to just copy the symbol areas
0418  *              and copy that down.
0419  *
0420  */
0421 
0422 void
0423 rtems_monitor_symbols_loadup(void)
0424 {
0425     FILE *fp;
0426     char buffer[128];
0427 
0428     if (rtems_monitor_symbols)
0429         rtems_symbol_table_destroy(rtems_monitor_symbols);
0430 
0431     rtems_monitor_symbols = rtems_symbol_table_create();
0432     if (rtems_monitor_symbols == 0)
0433         return;
0434 
0435     fp = fopen("symbols", "r");
0436 
0437     if (fp == 0)
0438         return;
0439 
0440     while (fgets(buffer, sizeof(buffer) - 1, fp))
0441     {
0442         char *symbol;
0443         char *value;
0444         char *ignored_type;
0445 
0446         value = strtok(buffer, " \t\n");
0447         ignored_type = strtok(0, " \t\n");
0448         symbol = strtok(0, " \t\n");
0449 
0450         if (symbol && ignored_type && value)
0451         {
0452             rtems_symbol_t *sp;
0453             sp = rtems_symbol_create(rtems_monitor_symbols,
0454                                      symbol,
0455                                      (uint32_t) strtoul(value, 0, 16));
0456             if (sp == 0)
0457             {
0458                 fprintf(stdout,"could not define symbol '%s'\n", symbol);
0459                 goto done;
0460             }
0461         }
0462         else
0463         {
0464             fprintf(stdout,"parsing error on '%s'\n", buffer);
0465             goto done;
0466         }
0467     }
0468 
0469 done:
0470     fclose(fp);
0471     return;
0472 }
0473 
0474 /*
0475  * User registered commands.
0476  */
0477 
0478 int
0479 rtems_monitor_insert_cmd (
0480   rtems_monitor_command_entry_t *command
0481 )
0482 {
0483   const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
0484 
0485   /* Reject empty commands */
0486   if (command->command == NULL) {
0487     return 0;
0488   }
0489 
0490   /* Reject command if already present */
0491   while (e->next != NULL) {
0492       if (e->command != NULL && strcmp(command->command, e->command) == 0) {
0493         return 0;
0494       }
0495       e = e->next;
0496   }
0497 
0498   /* Prepend new command */
0499   command->next = rtems_monitor_registered_commands;
0500   rtems_monitor_registered_commands = command;
0501 
0502   return 1;
0503 }
0504 
0505 /**
0506  * @brief Iterates through all registerd commands.
0507  *
0508  * For each command the interation routine @a routine is called with the
0509  * command entry and the user provided argument @a arg.  It is guaranteed that
0510  * the command name and function are not NULL.
0511  */
0512 void rtems_monitor_command_iterate(
0513   rtems_monitor_per_command_routine routine,
0514   void *arg
0515 )
0516 {
0517   const rtems_monitor_command_entry_t *e = rtems_monitor_registered_commands;
0518 
0519   while (e != NULL) {
0520     if (e->command != NULL && e->command_function != NULL) {
0521       if (!routine(e, arg)) {
0522         break;
0523       }
0524     }
0525     e = e->next;
0526   }
0527 }