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

4.115
Last change on this file since 0771936e was 0771936e, checked in by Joel Sherrill <joel.sherrill@…>, on 03/22/15 at 15:27:00

libdl/rtl-shell.c: Adjust printf() format for off_t based on target

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