source: rtems/cpukit/libdl/rtl-shell.c @ ae5fe7e6

4.115
Last change on this file since ae5fe7e6 was ae5fe7e6, checked in by Chris Johns <chrisj@…>, on 10/27/14 at 01:09:41

cpukit: Add libdl with the Runtime Loader (RTL) code.

This is a merge of the RTL project.

  • Property mode set to 100644
File size: 10.1 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.com/license/LICENSE.
7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtld
12 *
13 * @brief RTEMS Run-Time Link Editor Shell Commands
14 *
15 * A simple RTL command to aid using the RTL.
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <inttypes.h>
23
24//#if SIZEOF_OFF_T == 8
25#define PRIdoff_t PRIo64
26//#elif SIZEOF_OFF_T == 4
27//#define PRIdoff_t PRIo32
28//#else
29//#error "unsupported size of off_t"
30//#endif
31
32#include <stdio.h>
33#include <string.h>
34
35#include <rtems/rtl/rtl.h>
36#include "rtl-chain-iterator.h"
37#include "rtl-shell.h"
38#include "rtl-trace.h"
39
40/**
41 * The type of the shell handlers we have.
42 */
43typedef int (*rtems_rtl_shell_handler_t) (rtems_rtl_data_t* rtl, int argc, char *argv[]);
44
45/**
46 * Table of handlers we parse to invoke the command.
47 */
48typedef struct
49{
50  const char*               name;    /**< The sub-command's name. */
51  rtems_rtl_shell_handler_t handler; /**< The sub-command's handler. */
52  const char*               help;    /**< The sub-command's help. */
53} rtems_rtl_shell_cmd_t;
54
55/**
56 * Object summary data.
57 */
58typedef struct
59{
60  int    count;   /**< The number of object files. */
61  size_t exec;    /**< The amount of executable memory allocated. */
62  size_t symbols; /**< The amount of symbol memory allocated. */
63} rtems_rtl_obj_summary_t;
64
65/**
66 * Object summary iterator.
67 */
68static bool
69rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data)
70{
71  rtems_rtl_obj_summary_t* summary = data;
72  rtems_rtl_obj_t*         obj = (rtems_rtl_obj_t*) node;
73  ++summary->count;
74  summary->exec += obj->exec_size;
75  summary->symbols += obj->global_size;
76  return true;
77}
78
79/**
80 * Count the number of symbols.
81 */
82static int
83rtems_rtl_count_symbols (rtems_rtl_data_t* rtl)
84{
85  int count;
86  int bucket;
87  for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket)
88    count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]);
89  return count;
90}
91
92static int
93rtems_rtl_shell_status (rtems_rtl_data_t* rtl, int argc, char *argv[])
94{
95  rtems_rtl_obj_summary_t summary;
96  size_t                  total_memory;
97
98  summary.count   = 0;
99  summary.exec    = 0;
100  summary.symbols = 0;
101  rtems_rtl_chain_iterate (&rtl->objects,
102                           rtems_rtl_obj_summary_iterator,
103                           &summary);
104  /*
105   * Currently does not include the name strings in the obj struct.
106   */
107  total_memory =
108    sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj_t)) +
109    summary.exec + summary.symbols;
110
111  printf ("Runtime Linker Status:\n");
112  printf ("        paths: %s\n", rtl->paths);
113  printf ("      objects: %d\n", summary.count);
114  printf (" total memory: %zi\n", total_memory);
115  printf ("  exec memory: %zi\n", summary.exec);
116  printf ("   sym memory: %zi\n", summary.symbols);
117  printf ("      symbols: %d\n", rtems_rtl_count_symbols (rtl));
118
119  return 0;
120}
121
122/**
123 * Object print data.
124 */
125typedef struct
126{
127  rtems_rtl_data_t* rtl; /**< The RTL data. */
128  int  indent;           /**< Spaces to indent. */
129  bool oname;            /**< Print object names. */
130  bool names;            /**< Print details of all names. */
131  bool memory_map;       /**< Print the memory map. */
132  bool symbols;          /**< Print the global symbols. */
133  bool base;             /**< Include the base object file. */
134} rtems_rtl_obj_print_t;
135
136/**
137 * Return the different between 2 void*.
138 */
139static size_t
140rtems_rtl_delta_voids (void* higher, void* lower)
141{
142  char* ch = higher;
143  char* cl = lower;
144  return ch - cl;
145}
146
147/**
148 * Parse an argument.
149 */
150static bool
151rtems_rtl_parse_arg (const char* opt, int argc, char *argv[])
152{
153  int arg;
154  for (arg = 0; arg < argc; ++arg)
155    if (strncmp (opt, argv[arg], 2) == 0)
156      return true;
157  return false;
158}
159
160/**
161 * See if -b for base is set.
162 */
163static bool
164rtems_rtl_base_arg (int argc, char *argv[])
165{
166  return rtems_rtl_parse_arg ("-b", argc, argv);
167}
168
169/**
170 * See if -s for base is set.
171 */
172static bool
173rtems_rtl_symbols_arg (int argc, char *argv[])
174{
175  return rtems_rtl_parse_arg ("-s", argc, argv);
176}
177
178/**
179 * Object printer.
180 */
181static bool
182rtems_rtl_obj_printer (rtems_rtl_obj_print_t* print, rtems_rtl_obj_t* obj)
183{
184  char flags_str[33];
185
186  /*
187   * Skip the base module unless asked to show it.
188   */
189  if (!print->base && (obj == print->rtl->base))
190      return true;
191
192  if (print->oname)
193  {
194    printf ("%-*cobject name   : %s\n",
195            print->indent, ' ', rtems_rtl_obj_oname (obj));
196  }
197  if (print->names)
198  {
199    printf ("%-*cfile name     : %s\n",
200            print->indent, ' ', rtems_rtl_obj_fname (obj));
201    printf ("%-*carchive name  : %s\n",
202            print->indent, ' ', rtems_rtl_obj_aname (obj));
203    strcpy (flags_str, "--");
204    if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
205      flags_str[0] = 'L';
206    if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
207      flags_str[1] = 'U';
208    printf ("%-*cflags         : %s\n", print->indent, ' ', flags_str);
209    printf ("%-*cfile offset   : %" PRIdoff_t "\n", print->indent, ' ', obj->ooffset);
210    printf ("%-*cfile size     : %zi\n", print->indent, ' ', obj->fsize);
211  }
212  if (print->memory_map)
213  {
214    printf ("%-*cexec size     : %zi\n", print->indent, ' ', obj->exec_size);
215    printf ("%-*ctext base     : %p (%zi)\n", print->indent, ' ',
216            obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base));
217    printf ("%-*cconst base    : %p (%zi)\n", print->indent, ' ',
218            obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base));
219    printf ("%-*cdata base     : %p (%zi)\n", print->indent, ' ',
220            obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base));
221    printf ("%-*cbss base      : %p (%zi)\n", print->indent, ' ',
222            obj->bss_base, obj->bss_size);
223  }
224  printf ("%-*cunresolved    : %lu\n", print->indent, ' ', obj->unresolved);
225  printf ("%-*csymbols       : %zi\n", print->indent, ' ', obj->global_syms);
226  printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
227  if (print->symbols)
228  {
229    int max_len = 0;
230    int s;
231    for (s = 0; s < obj->global_syms; ++s)
232    {
233      int len = strlen (obj->global_table[s].name);
234      if (len > max_len)
235        max_len = len;
236    }
237    for (s = 0; s < obj->global_syms; ++s)
238      printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
239              max_len, obj->global_table[s].name, obj->global_table[s].value);
240  }
241  printf ("\n");
242  return true;
243}
244
245/**
246 * Object unresolved symbols printer.
247 */
248static bool
249rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec_t* rec,
250                              void*                     data)
251{
252  rtems_rtl_obj_print_t* print = (rtems_rtl_obj_print_t*) data;
253  if (rec->type == rtems_rtl_unresolved_name)
254    printf ("%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
255  return false;
256}
257
258/**
259 * Object print iterator.
260 */
261static bool
262rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
263{
264  rtems_rtl_obj_print_t* print = data;
265  rtems_rtl_obj_t*       obj = (rtems_rtl_obj_t*) node;
266  return rtems_rtl_obj_printer (print, obj);
267}
268
269static int
270rtems_rtl_shell_list (rtems_rtl_data_t* rtl, int argc, char *argv[])
271{
272  rtems_rtl_obj_print_t print;
273  print.rtl = rtl;
274  print.indent = 1;
275  print.oname = true;
276  print.names = true;
277  print.memory_map = true;
278  print.symbols = rtems_rtl_symbols_arg (argc, argv);
279  print.base = false;
280  rtems_rtl_chain_iterate (&rtl->objects,
281                           rtems_rtl_obj_print_iterator,
282                           &print);
283  return 0;
284}
285
286static int
287rtems_rtl_shell_sym (rtems_rtl_data_t* rtl, int argc, char *argv[])
288{
289  rtems_rtl_obj_print_t print;
290  print.rtl = rtl;
291  print.indent = 1;
292  print.oname = true;
293  print.names = false;
294  print.memory_map = false;
295  print.symbols = true;
296  print.base = rtems_rtl_base_arg (argc, argv);
297  rtems_rtl_chain_iterate (&rtl->objects,
298                           rtems_rtl_obj_print_iterator,
299                           &print);
300  printf ("Unresolved:\n");
301  rtems_rtl_unresolved_interate (rtems_rtl_unresolved_printer, &print);
302  return 0;
303}
304
305static int
306rtems_rtl_shell_object (rtems_rtl_data_t* rtl, int argc, char *argv[])
307{
308  return 0;
309}
310
311static void
312rtems_rtl_shell_usage (const char* arg)
313{
314  printf ("%s: Runtime Linker\n", arg);
315  printf ("  %s [-hl] <command>\n", arg);
316  printf ("   where:\n");
317  printf ("     command: A n RTL command. See -l for a list plus help.\n");
318  printf ("     -h:      This help\n");
319  printf ("     -l:      The command list.\n");
320}
321
322int
323rtems_rtl_shell_command (int argc, char* argv[])
324{
325  const rtems_rtl_shell_cmd_t table[] =
326  {
327    { "status", rtems_rtl_shell_status,
328      "Display the status of the RTL" },
329    { "list", rtems_rtl_shell_list,
330      "\tList the object files currently loaded" },
331    { "sym", rtems_rtl_shell_sym,
332      "\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
333    { "obj", rtems_rtl_shell_object,
334      "\tDisplay the object details, obj <name>" }
335  };
336
337  int arg;
338  int t;
339
340  for (arg = 1; arg < argc; arg++)
341  {
342    if (argv[arg][0] != '-')
343      break;
344
345    switch (argv[arg][1])
346    {
347      case 'h':
348        rtems_rtl_shell_usage (argv[0]);
349        return 0;
350      case 'l':
351        printf ("%s: commands are:\n", argv[0]);
352        for (t = 0;
353             t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
354             ++t)
355          printf ("  %s\t%s\n", table[t].name, table[t].help);
356        return 0;
357      default:
358        printf ("error: unknown option: %s\n", argv[arg]);
359        return 1;
360    }
361  }
362
363  if ((argc - arg) < 1)
364    printf ("error: you need to provide a command, try %s -h\n", argv[0]);
365  else
366  {
367    for (t = 0;
368         t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t));
369         ++t)
370    {
371      if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
372      {
373        rtems_rtl_data_t* rtl = rtems_rtl_data ();
374        int               r;
375        if (!rtl)
376        {
377          printf ("error: cannot lock the linker\n");
378          return 1;
379        }
380        r = table[t].handler (rtl, argc - 1, argv + 1);
381        rtems_rtl_unlock ();
382        return r;
383      }
384    }
385    printf ("error: command not found: %s (try -h)\n", argv[arg]);
386  }
387
388  return 1;
389}
Note: See TracBrowser for help on using the repository browser.