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

5
Last change on this file since 6c9f017 was 6c9f017, checked in by Chris Johns <chrisj@…>, on 02/02/19 at 04:09:53

libdl: Add powerpc large memory and small data support.

  • Add support for architecure sections that can be handled by the architecture back end.
  • Add trampoline/fixup support for PowerPC. This means the PowerPC now supports large memory loading of applications.
  • Add a bit allocator to manage small block based regions of memory.
  • Add small data (sdata/sbss) support for the PowerPC. The support makes the linker allocated small data region of memory a global resource available to libdl loaded object files.

Updates #3687
Updates #3685

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