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

Last change on this file since 4408603 was 89c59be, checked in by Chris Johns <chrisj@…>, on Dec 17, 2018 at 5:36:48 AM

libdl: Add symbol searching and loading from archives.

  • Load archive symbol tables to support searching of archives for symbols.
  • Search archive symbols and load the object file that contains the symbol.
  • Search the global and archives until all remaining unresolved symbols are not found. Group the loaded object files in the pending queue.
  • Run the object file and loaded dependents as a group before adding to the main object list.
  • Remove orphaned object files after references are removed.

Updates #3686

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