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

Last change on this file since dad6fd4 was dad6fd4, checked in by Chris Johns <chrisj@…>, on Mar 9, 2019 at 6:04:42 PM

libdl: Add an archive command

  • The archive command lists archives, symbols and any duplicate symbols.
  • Change the RTL shell commands to the rtems_printer to allow the output to be captured.
  • Property mode set to 100644
File size: 30.7 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 <sys/stat.h>
26#include <regex.h>
27#include <string.h>
28
29#include <dlfcn.h>
30
31#include <rtems/printer.h>
32#include <rtems/rtl/rtl.h>
33#include <rtems/rtl/rtl-archive.h>
34#include <rtems/rtl/rtl-shell.h>
35#include <rtems/rtl/rtl-trace.h>
36#include "rtl-chain-iterator.h"
37
38/**
39 * The type of the shell handlers we have.
40 */
41typedef int (*rtems_rtl_shell_handler) (const rtems_printer* printer, int argc, char *argv[]);
42
43/**
44 * Table of handlers we parse to invoke the command.
45 */
46typedef struct
47{
48  const char*             name;    /**< The sub-command's name. */
49  rtems_rtl_shell_handler handler; /**< The sub-command's handler. */
50  const char*             help;    /**< The sub-command's help. */
51} rtems_rtl_shell_cmd;
52
53/**
54 * Object summary data.
55 */
56typedef struct
57{
58  int    count;   /**< The number of object files. */
59  size_t exec;    /**< The amount of executable memory allocated. */
60  size_t symbols; /**< The amount of symbol memory allocated. */
61} rtems_rtl_obj_summary;
62
63/**
64 * Object summary iterator.
65 */
66static bool
67rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data)
68{
69  rtems_rtl_obj_summary* summary = data;
70  rtems_rtl_obj*         obj = (rtems_rtl_obj*) node;
71  ++summary->count;
72  summary->exec += obj->exec_size;
73  summary->symbols += obj->global_size;
74  return true;
75}
76
77/**
78 * Count the number of symbols.
79 */
80static int
81rtems_rtl_count_symbols (rtems_rtl_data* rtl)
82{
83  int count;
84  int bucket;
85  for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket)
86    count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]);
87  return count;
88}
89
90static int
91rtems_rtl_shell_status (const rtems_printer* printer,
92                        int                  argc,
93                        char*                argv[])
94{
95  rtems_rtl_obj_summary summary;
96  size_t                total_memory;
97  rtems_rtl_data*       rtl;
98
99  rtl = rtems_rtl_lock ();
100  if (rtl == NULL)
101  {
102    rtems_printf (printer, "error: cannot lock the linker\n");
103    return 1;
104  }
105
106  summary.count   = 0;
107  summary.exec    = 0;
108  summary.symbols = 0;
109  rtems_rtl_chain_iterate (&rtl->objects,
110                           rtems_rtl_obj_summary_iterator,
111                           &summary);
112  /*
113   * Currently does not include the name strings in the obj struct.
114   */
115  total_memory =
116    sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj)) +
117    summary.exec + summary.symbols;
118
119  rtems_printf (printer, "Runtime Linker Status:\n");
120  rtems_printf (printer, "        paths: %s\n", rtl->paths);
121  rtems_printf (printer, "      objects: %d\n", summary.count);
122  rtems_printf (printer, " total memory: %zi\n", total_memory);
123  rtems_printf (printer, "  exec memory: %zi\n", summary.exec);
124  rtems_printf (printer, "   sym memory: %zi\n", summary.symbols);
125  rtems_printf (printer, "      symbols: %d\n", rtems_rtl_count_symbols (rtl));
126
127  rtems_rtl_unlock ();
128
129  return 0;
130}
131
132/**
133 * Object print data.
134 */
135typedef struct
136{
137  const rtems_printer* printer;      /**< The RTEMS printer. */
138  rtems_rtl_data*      rtl;          /**< The RTL data. */
139  int                  indent;       /**< Spaces to indent. */
140  bool                 oname;        /**< Print object names. */
141  bool                 names;        /**< Print details of all names. */
142  bool                 stats;        /**< Print stats. */
143  bool                 memory_map;   /**< Print the memory map. */
144  bool                 symbols;      /**< Print the global symbols. */
145  bool                 dependencies; /**< Print any dependencies. */
146  bool                 base;         /**< Include the base object file. */
147  const char*          re_name;      /**< Name regx to filter on. */
148  const char*          re_symbol;    /**< Symbol regx to filter on. */
149} rtems_rtl_obj_print;
150
151/**
152 * Parse an argument.
153 */
154static bool
155rtems_rtl_parse_opt (const char opt, int argc, char *argv[])
156{
157  size_t arg;
158  for (arg = 1; arg < argc; ++arg)
159  {
160    if (argv[arg][0] == '-')
161    {
162      size_t len = strlen (argv[arg]);
163      size_t i;
164      for (i = 1; i < len; ++i)
165        if (argv[arg][i] == opt)
166          return true;
167    }
168  }
169  return false;
170}
171
172static bool
173rtems_rtl_check_opts (const rtems_printer* printer,
174                      const char*          opts,
175                      int                  argc,
176                      char*                argv[])
177{
178  size_t olen = strlen (opts);
179  size_t arg;
180  for (arg = 1; arg < argc; ++arg)
181  {
182    if (argv[arg][0] == '-')
183    {
184      size_t len = strlen (argv[arg]);
185      size_t i;
186      for (i = 1; i < len; ++i)
187      {
188        bool found = false;
189        size_t       o;
190        for (o = 0; o < olen; ++o)
191        {
192          if (argv[arg][i] == opts[o])
193          {
194            found = true;
195            break;
196          }
197        }
198        if (!found)
199        {
200          rtems_printf (printer, "error: invalid option: %c (%s)\n",
201                        argv[arg][i], argv[arg]);
202          return false;
203        }
204      }
205    }
206  }
207  return true;
208}
209
210static ssize_t
211rtems_rtl_parse_arg_index (const char  opt,
212                           const char* skip_opts,
213                           int         argc,
214                           char*       argv[])
215{
216  ssize_t arg;
217  for (arg = 1; arg < argc; ++arg)
218  {
219    if (argv[arg][0] == '-')
220    {
221      /*
222       * We can check the next char because there has to be a valid char or a
223       * nul.
224       */
225      if (argv[arg][1] != '\0')
226      {
227        size_t len = skip_opts != NULL ? strlen (skip_opts) : 0;
228        size_t i;
229        for (i = 0; i < len; ++i)
230        {
231          if (skip_opts[i] == argv[arg][1])
232          {
233            ++arg;
234            break;
235          }
236        }
237      }
238    }
239    else
240    {
241      if (opt == ' ')
242        return arg;
243    }
244    /*
245     * Is this an option and does it match what we are looking for?
246     */
247    if (argv[arg][0] == '-' && argv[arg][1] == opt && arg < argc)
248      return arg + 1;
249  }
250  return -1;
251}
252
253static const char*
254rtems_rtl_parse_arg (const char  opt,
255                     const char* skip_opts,
256                     int         argc,
257                     char*       argv[])
258{
259  ssize_t arg = rtems_rtl_parse_arg_index (opt, skip_opts, argc, argv);
260  if (arg < 0)
261    return NULL;
262  return argv[arg];
263}
264
265/**
266 * Regx matching.
267 */
268static bool
269rtems_rtl_regx_compile (const rtems_printer* printer,
270                        const char*          label,
271                        regex_t*             rege,
272                        const char*          expression)
273{
274  int r = regcomp (rege, expression, REG_EXTENDED | REG_NOSUB);
275  if (r != 0)
276  {
277    char rerror[128];
278    regerror (r, rege, rerror, sizeof(rerror));
279    rtems_printf (printer, "error: %s: %s\n", label, rerror);
280    return false;
281  }
282  return true;
283}
284
285static int
286rtems_rtl_regx_match (const rtems_printer* printer,
287                      const char*          label,
288                      regex_t*             rege,
289                      const char*          string)
290{
291  int r = regexec (rege, string, 0, NULL, 0);
292  if (r != 0 && r != REG_NOMATCH)
293  {
294    char rerror[128];
295    regerror (r, rege, rerror, sizeof(rerror));
296    rtems_printf (printer, "error: %s: %s\n", label, rerror);
297    regfree (rege);
298    return -1;
299  }
300  return r == 0 ? 1 : 0;
301}
302
303/**
304 * Print the obj name.
305 */
306static void
307rtems_rtl_print_obj_name (const rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
308{
309  rtems_printf (print->printer, "%-*c", print->indent, ' ');
310  if (rtems_rtl_obj_aname (obj) != NULL)
311    rtems_printf (print->printer, "%s:", rtems_rtl_obj_aname (obj));
312  rtems_printf (print->printer, "%s\n", rtems_rtl_obj_oname (obj));
313}
314
315/**
316 * Print symbols.
317 */
318static bool
319rtems_rtl_print_symbols (rtems_rtl_obj_print* print,
320                         rtems_rtl_obj*       obj,
321                         int                  indent,
322                         bool                 show_name)
323{
324  regex_t rege;
325  int     max_len = 0;
326  int     s;
327
328  if (print->re_symbol != NULL &&
329      !rtems_rtl_regx_compile (print->printer,
330                               "symbol filter",
331                               &rege, print->re_symbol))
332  {
333    return false;
334  }
335
336  for (s = 0; s < obj->global_syms; ++s)
337  {
338    const char* sym = obj->global_table[s].name;
339    int         len;
340
341    if (print->re_symbol != NULL)
342    {
343      int r = rtems_rtl_regx_match (print->printer, "symbol match", &rege, sym);
344      if (r < 0)
345        return false;
346      if (!r)
347        continue;
348    }
349
350    len = strlen (obj->global_table[s].name);
351    if (len > max_len)
352      max_len = len;
353  }
354
355  for (s = 0; s < obj->global_syms; ++s)
356  {
357    const char* sym = obj->global_table[s].name;
358    if (print->re_symbol != NULL)
359    {
360      int r = rtems_rtl_regx_match (print->printer, "symbol match", &rege, sym);
361      if (r < 0)
362        return false;
363      if (r == 0)
364        continue;
365    }
366    if (show_name)
367    {
368      show_name = false;
369      rtems_rtl_print_obj_name (print, obj);
370    }
371    rtems_printf (print->printer, "%-*c%-*s = %p\n", indent + 2, ' ',
372                  max_len, sym, obj->global_table[s].value);
373  }
374
375  regfree (&rege);
376
377  return true;
378}
379
380/**
381 * Dependencies printer.
382 */
383typedef struct
384{
385  const rtems_rtl_obj_print* print;     /**< The print data. */
386  bool                       first;     /**< Is this the first line printed. */
387  bool                       show_name; /**< Show the object name. */
388  size_t                     indent;    /**< The indent. */
389} rtems_rtl_dep_data;
390
391static bool
392rtems_rtl_dependencies (rtems_rtl_obj* obj, rtems_rtl_obj* dependent, void* data)
393{
394  rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
395  if (dd->first)
396  {
397    dd->first = false;
398    if (dd->show_name)
399    {
400      dd->show_name = false;
401      rtems_rtl_print_obj_name (dd->print, obj);
402    }
403    rtems_printf (dd->print->printer, "%-*cdependencies  : ", dd->indent, ' ');
404    dd->indent += strlen ("dependencies :");
405  }
406  else
407  {
408    rtems_printf (dd->print->printer, "\n%-*c: ", (int) dd->indent, ' ');
409  }
410  rtems_printf (dd->print->printer, "%s", dependent->oname);
411  return false;
412}
413
414/**
415 * Object printer.
416 */
417static bool
418rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
419{
420  char flags_str[33];
421  int  indent = print->indent + 1;
422  bool show_name = true;
423
424  /*
425   * Skip the base module unless asked to show it.
426   */
427  if (!print->base && (obj == print->rtl->base))
428      return true;
429
430  if (print->re_name != NULL)
431  {
432    regex_t rege;
433    int     r = 0;
434
435    if (!rtems_rtl_regx_compile (print->printer,
436                                 "name filter",
437                                 &rege, print->re_name))
438    {
439      return false;
440    }
441
442    if (rtems_rtl_obj_aname (obj) != NULL)
443    {
444      r = rtems_rtl_regx_match (print->printer,
445                                "aname match",
446                                &rege,
447                                rtems_rtl_obj_aname (obj));
448      if (r < 0)
449        return false;
450    }
451
452    if (r == 0)
453    {
454      r = rtems_rtl_regx_match (print->printer,
455                                "oname match",
456                                &rege,
457                                rtems_rtl_obj_oname (obj));
458      if (r < 0)
459        return false;
460    }
461
462    regfree (&rege);
463
464    if (r == 0)
465      return true;
466  }
467
468  if (print->names || print->memory_map || print->stats ||
469      (!print->names && !print->memory_map && !print->stats &&
470       !print->symbols && !print->dependencies))
471  {
472    show_name = false;
473    rtems_rtl_print_obj_name (print, obj);
474  }
475
476  if (print->names)
477  {
478    rtems_printf (print->printer,
479                  "%-*cfile name     : %s\n",
480                  indent, ' ', rtems_rtl_obj_fname (obj));
481    rtems_printf (print->printer,
482                  "%-*carchive name  : %s\n",
483                  indent, ' ', rtems_rtl_obj_aname (obj));
484    strcpy (flags_str, "--");
485    if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
486      flags_str[0] = 'L';
487    if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
488      flags_str[1] = 'U';
489    rtems_printf (print->printer,
490                  "%-*cflags         : %s\n", indent, ' ', flags_str);
491    rtems_printf (print->printer,
492                  "%-*cfile offset   : %" PRIdoff_t "\n", indent, ' ', obj->ooffset);
493    rtems_printf (print->printer,
494                  "%-*cfile size     : %zi\n", indent, ' ', obj->fsize);
495  }
496  if (print->memory_map)
497  {
498    rtems_printf (print->printer,
499                  "%-*cexec size     : %zi\n", indent, ' ', obj->exec_size);
500    rtems_printf (print->printer,
501                  "%-*ctext base     : %p (%zi)\n", indent, ' ',
502                  obj->text_base, obj->text_size);
503    rtems_printf (print->printer,
504                  "%-*cconst base    : %p (%zi)\n", indent, ' ',
505                  obj->const_base, obj->const_size);
506    rtems_printf (print->printer,
507                  "%-*cdata base     : %p (%zi)\n", indent, ' ',
508                  obj->data_base, obj->data_size);
509    rtems_printf (print->printer,
510                  "%-*cbss base      : %p (%zi)\n", indent, ' ',
511                  obj->bss_base, obj->bss_size);
512  }
513  if (print->stats)
514  {
515    rtems_printf (print->printer, "%-*cunresolved    : %zu\n", indent, ' ', obj->unresolved);
516    rtems_printf (print->printer, "%-*cusers         : %zu\n", indent, ' ', obj->users);
517    rtems_printf (print->printer, "%-*creferences    : %zu\n", indent, ' ', obj->refs);
518    rtems_printf (print->printer, "%-*csymbols       : %zi\n", indent, ' ', obj->global_syms);
519    rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
520  }
521  if (print->symbols)
522  {
523    if (!rtems_rtl_print_symbols (print, obj, indent, show_name))
524      return false;
525  }
526  if (print->dependencies)
527  {
528    rtems_rtl_dep_data dd = {
529      .print = print,
530      .first = true,
531      .show_name = show_name,
532      .indent = indent
533    };
534    rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
535    if (!dd.first)
536      rtems_printf (print->printer, "\n");
537  }
538  return true;
539}
540
541/**
542 * Object unresolved symbols printer.
543 */
544static bool
545rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec* rec,
546                              void*                   data)
547{
548  rtems_rtl_obj_print* print = (rtems_rtl_obj_print*) data;
549  if (rec->type == rtems_rtl_unresolved_symbol)
550    rtems_printf (print->printer,
551                  "%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
552  return false;
553}
554
555/**
556 * Object print iterator.
557 */
558static bool
559rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
560{
561  rtems_rtl_obj_print* print = data;
562  rtems_rtl_obj*       obj = (rtems_rtl_obj*) node;
563  return rtems_rtl_obj_printer (print, obj);
564}
565
566int
567rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
568{
569  rtems_rtl_obj_print print = { 0 };
570  if (!rtems_rtl_check_opts (printer, "nlmsdb", argc, argv))
571    return 1;
572  print.printer = printer;
573  print.indent = 1;
574  print.oname = true;
575  print.names = rtems_rtl_parse_opt ('n', argc, argv);
576  print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
577  print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
578  print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
579  print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
580  print.base = rtems_rtl_parse_opt ('b', argc, argv);;
581  print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
582  print.re_symbol = NULL;
583  print.rtl = rtems_rtl_lock ();
584  if (print.rtl == NULL)
585  {
586    rtems_printf (print.printer, "error: cannot lock the linker\n");
587    return 1;
588  }
589  rtems_rtl_chain_iterate (&print.rtl->objects,
590                           rtems_rtl_obj_print_iterator,
591                           &print);
592  rtems_rtl_unlock ();
593  return 0;
594}
595
596int
597rtems_rtl_shell_sym (const rtems_printer* printer, int argc, char* argv[])
598{
599  rtems_rtl_obj_print print = { 0 };
600  if (!rtems_rtl_check_opts (printer, "buo", argc, argv))
601    return 1;
602  print.printer = printer;
603  print.indent = 1;
604  print.oname = true;
605  print.names = false;
606  print.stats = false;
607  print.memory_map = false;
608  print.symbols = !rtems_rtl_parse_opt ('u', argc, argv);;
609  print.dependencies = false;
610  print.base = rtems_rtl_parse_opt ('b', argc, argv);
611  print.re_name = rtems_rtl_parse_arg ('o', NULL, argc, argv);;
612  print.re_symbol = rtems_rtl_parse_arg (' ', "ou", argc, argv);
613  print.rtl = rtems_rtl_lock ();
614  if (print.rtl == NULL)
615  {
616    rtems_printf (print.printer, "error: cannot lock the linker\n");
617    return 1;
618  }
619  if (print.symbols)
620  {
621    rtems_rtl_chain_iterate (&print.rtl->objects,
622                             rtems_rtl_obj_print_iterator,
623                             &print);
624  }
625  if (rtems_rtl_parse_opt ('u', argc, argv))
626  {
627    rtems_printf (printer, "Unresolved:\n");
628    rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_printer, &print);
629  }
630  rtems_rtl_unlock ();
631  return 0;
632}
633
634int
635rtems_rtl_shell_object (const rtems_printer* printer, int argc, char* argv[])
636{
637  size_t arg;
638
639  --argc;
640  ++argv;
641
642  for (arg = 0; arg < argc; ++arg)
643  {
644    if (argv[arg][0] == '-')
645    {
646      switch (argv[arg][1])
647      {
648        case 'h':
649        case '?':
650          rtems_printf (printer, "obj commands:\n");
651          rtems_printf (printer, " load <file>\n");
652          rtems_printf (printer, " unload <file>\n");
653          break;
654        default:
655          rtems_printf (printer, "error: invalid option: %s\n", argv[arg]);
656          return 1;
657      }
658    }
659    else
660    {
661      break;
662    }
663  }
664
665  if (arg >= argc)
666  {
667    rtems_printf (printer, "error: no obj command\n");
668    return 1;
669  }
670
671  if (strcmp (argv[arg], "load") == 0)
672  {
673    void* handle;
674    int   unresolved;
675
676    ++arg;
677    if (arg >= argc)
678    {
679      rtems_printf (printer, "error: no object file to load\n");
680      return 1;
681    }
682
683    handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL);
684    if (handle == NULL)
685    {
686      rtems_printf (printer, "error: load: %s: %s\n", argv[arg], dlerror ());
687      return 1;
688    }
689
690    if (dlinfo (RTLD_SELF, RTLD_DI_UNRESOLVED, &unresolved) < 0)
691    {
692      rtems_printf (printer, "error: %s: %s\n", argv[arg], dlerror ());
693      return 1;
694    }
695
696    if (unresolved != 0)
697    {
698      rtems_printf (printer, "warning: unresolved symbols present\n");
699      return 1;
700    }
701  }
702  else if (strcmp (argv[arg], "unload") == 0)
703  {
704    rtems_rtl_data* rtl;
705    rtems_rtl_obj*  obj;
706
707    ++arg;
708    if (arg >= argc)
709    {
710      rtems_printf (printer, "error: no object file to load\n");
711      return 1;
712    }
713
714    rtl = rtems_rtl_lock ();
715    if (rtl == NULL)
716    {
717      rtems_printf (printer, "error: cannot lock RTL\n");
718      return 1;
719    }
720
721    obj = rtems_rtl_find_obj (argv[arg]);
722    if (obj == NULL)
723    {
724      rtems_rtl_unlock ();
725      rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
726      return 1;
727    }
728
729    if (!rtems_rtl_unload (obj))
730    {
731      rtems_rtl_unlock ();
732      rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
733      return 1;
734    }
735
736    rtems_rtl_unlock ();
737  }
738  else
739  {
740    rtems_printf (printer, "error: unknown obj command: %s\n", argv[arg]);
741    return 1;
742  }
743
744  return 0;
745}
746
747int
748rtems_rtl_shell_archive (const rtems_printer* printer, int argc, char* argv[])
749{
750  rtems_rtl_data*   rtl;
751  rtems_chain_node* node;
752  const char*       re_name;
753  bool              details;
754  bool              symbols;
755  bool              duplicates;
756  regex_t           rege;
757
758  if (!rtems_rtl_check_opts (printer, "dsl", argc, argv))
759    return 1;
760
761  details = rtems_rtl_parse_opt ('l', argc, argv);
762  symbols = rtems_rtl_parse_opt ('s', argc, argv);
763  duplicates = rtems_rtl_parse_opt ('d', argc, argv);
764
765  re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
766
767  if (re_name != NULL)
768  {
769    if (!rtems_rtl_regx_compile (printer,
770                                 "name filter",
771                                 &rege,
772                                 re_name))
773    {
774      return false;
775    }
776  }
777
778  rtl = rtems_rtl_lock ();
779  if (rtl == NULL)
780  {
781    rtems_printf (printer, "error: cannot lock the linker\n");
782    return 1;
783  }
784
785  node = rtems_chain_first (&rtl->archives.archives);
786
787  while (!rtems_chain_is_tail (&rtl->archives.archives, node))
788  {
789    #define SYM_DUPLICATE (1 << ((8 * sizeof (size_t)) - 1))
790
791    rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
792
793    if (re_name != NULL)
794    {
795      int r = rtems_rtl_regx_match (printer,
796                                    "name match",
797                                    &rege,
798                                    archive->name);
799      if (r < 0)
800      {
801        rtems_rtl_unlock ();
802        return false;
803      }
804
805      if (r == 0)
806      {
807        node = rtems_chain_next (node);
808        continue;
809      }
810    }
811
812    rtems_printf (printer, "%s%c\n",
813                  archive->name,
814                  details | symbols | duplicates ? ':' : ' ');
815
816    if (details)
817    {
818      rtems_printf (printer, "  size    : %zu\n", archive->size);
819      rtems_printf (printer, "  symbols : %zu\n", archive->symbols.entries);
820      rtems_printf (printer, "  refs    : %zu\n", archive->refs);
821      rtems_printf (printer, "  flags   : %" PRIx32 "\n", archive->flags);
822    }
823
824    if (symbols)
825    {
826      const char* symbol = archive->symbols.names;
827      int         indent = 0;
828      size_t      s;
829
830      rtems_printf (printer, "  symbols :");
831
832      for (s = 0; s < archive->symbols.entries; ++s)
833      {
834        if (archive->symbols.symbols != NULL)
835          symbol = archive->symbols.symbols[s].label;
836
837        rtems_printf (printer, "%-*c%s\n", indent, ' ', symbol);
838        indent = 12;
839
840        if (archive->symbols.symbols == NULL)
841          symbol += strlen (symbol) + 1;
842      }
843
844      if (indent == 0)
845        rtems_printf (printer, "\n");
846    }
847
848    if (duplicates)
849    {
850      rtems_chain_node* match_node;
851      int               indent = 0;
852      bool              show_dups = true;
853
854      match_node = rtems_chain_first (&rtl->archives.archives);
855
856      while (!rtems_chain_is_tail (&rtl->archives.archives, match_node))
857      {
858        rtems_rtl_archive* match_archive = (rtems_rtl_archive*) match_node;
859        const char*        symbol = archive->symbols.names;
860        size_t             s;
861
862        for (s = 0; s < archive->symbols.entries; ++s)
863        {
864          if (archive->symbols.symbols == NULL ||
865              (archive->symbols.symbols[s].entry & SYM_DUPLICATE) == 0)
866          {
867            const char* match_symbol = match_archive->symbols.names;
868            size_t      ms;
869
870            if (archive->symbols.symbols != NULL)
871              symbol = archive->symbols.symbols[s].label;
872
873            for (ms = 0; ms < match_archive->symbols.entries; ++ms)
874            {
875              if (match_archive->symbols.symbols != NULL)
876                match_symbol = match_archive->symbols.symbols[ms].label;
877
878              if (symbol != match_symbol && strcmp (symbol, match_symbol) == 0)
879              {
880                if (show_dups)
881                {
882                  show_dups = false;
883                  rtems_printf (printer, "  dups    :");
884                }
885                rtems_printf (printer, "%-*c%s (%s)\n",
886                              indent, ' ', symbol, archive->name);
887                indent = 12;
888
889                if (match_archive->symbols.symbols != NULL)
890                  match_archive->symbols.symbols[ms].entry |= SYM_DUPLICATE;
891              }
892
893              if (match_archive->symbols.symbols == NULL)
894                match_symbol += strlen (match_symbol) + 1;
895            }
896          }
897
898          if (archive->symbols.symbols == NULL)
899            symbol += strlen (symbol) + 1;
900        }
901
902        match_node = rtems_chain_next (match_node);
903      }
904
905      if (indent == 0)
906        rtems_printf (printer, "\n");
907    }
908
909    node = rtems_chain_next (node);
910  }
911
912  regfree (&rege);
913
914  node = rtems_chain_first (&rtl->archives.archives);
915
916  while (!rtems_chain_is_tail (&rtl->archives.archives, node))
917  {
918    rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
919    if (archive->symbols.symbols != NULL)
920    {
921      size_t s;
922      for (s = 0; s < archive->symbols.entries; ++s)
923        archive->symbols.symbols[s].entry &= ~SYM_DUPLICATE;
924    }
925    node = rtems_chain_next (node);
926  }
927
928  rtems_rtl_unlock ();
929
930  return 0;
931}
932
933int
934rtems_rtl_shell_call (const rtems_printer* printer, int argc, char* argv[])
935{
936  #define CALL_ARG_COUNT (4)
937
938  typedef void (*csig_none)(void);
939  typedef void (*csig_argv)(int argc, const char* argv[]);
940  typedef void (*csig_s)(const char* str);
941  typedef void (*csig_u)(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4);
942  typedef void (*csig_i)(int i1, int i2, int i3, int i4);
943
944  union {
945    char         s[64 + 1];
946    unsigned int u[CALL_ARG_COUNT];
947    int          i[CALL_ARG_COUNT];
948  } values = { 0 };
949  bool               keep_locked = false;
950  bool               args_s = false;
951  bool               args_i = false;
952  bool               args_u = false;
953  ssize_t            label;
954  rtems_rtl_data*    rtl;
955  rtems_rtl_obj_sym* sym;
956  rtems_rtl_obj*     obj;
957
958
959  if (!rtems_rtl_check_opts (printer, "lsui", argc, argv))
960    return 1;
961
962  keep_locked = rtems_rtl_parse_opt ('l', argc, argv);
963  args_s = rtems_rtl_parse_opt ('s', argc, argv);
964  args_u = rtems_rtl_parse_opt ('u', argc, argv);
965  args_i = rtems_rtl_parse_opt ('i', argc, argv);
966
967  if (args_s || args_u || args_i)
968  {
969    int c = 0;
970    c += args_s ? 1 : 0;
971    c += args_u ? 1 : 0;
972    c += args_i ? 1 : 0;
973    if (c > 1)
974    {
975      rtems_printf (printer,
976                    "error: too many options, only one -sul at a time\n");
977      return 1;
978    }
979  }
980
981  label = rtems_rtl_parse_arg_index (' ', NULL, argc, argv);
982  if (label < 0)
983  {
984    rtems_printf (printer, "error: no symbol found on command line\n");
985    return 1;
986  }
987
988  if ((label + 1) < argc)
989  {
990    if (args_s)
991    {
992      size_t arg;
993      for (arg = label + 1; arg < argc; ++arg)
994      {
995        size_t o = strlen (values.s);
996        if (strlen (argv[arg]) + 1 >= (sizeof (values.s) - o))
997        {
998          rtems_printf (printer, "error: string args too big\n");
999          return 1;
1000        }
1001        if (o > 0)
1002          values.s[o++] = ' ';
1003        strcat (values.s, argv[arg]);
1004      }
1005    }
1006    else if (args_u || args_i)
1007    {
1008      size_t arg;
1009      size_t i;
1010      if (argc > (label + 1 + CALL_ARG_COUNT))
1011      {
1012        rtems_printf (printer, "error: too many args\n");
1013        return 1;
1014      }
1015      for (i = 0, arg = label + 1; arg < argc; ++arg)
1016      {
1017        if (args_u)
1018          values.u[i] = strtoul (argv[arg], 0, 0);
1019        else
1020          values.i[i] = strtol (argv[arg], 0, 0);
1021        ++i;
1022      }
1023    }
1024  }
1025
1026  rtl = rtems_rtl_lock ();
1027  if (rtl == NULL)
1028  {
1029    rtems_printf (printer, "error: cannot lock the linker\n");
1030    return 1;
1031  }
1032
1033  sym = rtems_rtl_symbol_global_find (argv[label]);
1034  if (sym == NULL)
1035  {
1036    rtems_rtl_unlock ();
1037    rtems_printf (printer, "error: symbol not found: %s\n", argv[label]);
1038    return 1;
1039  }
1040
1041  obj = rtems_rtl_find_obj_with_symbol (sym);
1042  if (obj == NULL)
1043  {
1044    rtems_rtl_unlock ();
1045    rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
1046    return 1;
1047  }
1048
1049  if (!rtems_rtl_obj_text_inside (obj, (const void*) sym->value))
1050  {
1051    rtems_rtl_unlock ();
1052    rtems_printf (printer, "error: symbol not in obj text: %s\n", argv[label]);
1053    return 1;
1054  }
1055
1056  /*
1057   * Lock the object file while it is being called.
1058   */
1059  rtems_rtl_obj_inc_reference (obj);
1060
1061  rtems_rtl_unlock ();
1062
1063  if (args_s)
1064  {
1065    csig_s call = (csig_s) sym->value;
1066    call (values.s);
1067  }
1068  else if (args_u)
1069  {
1070    csig_u call = (csig_u) sym->value;
1071    call (values.u[0], values.u[1], values.u[2], values.u[3]);
1072  }
1073  else if (args_i)
1074  {
1075    csig_i call = (csig_i) sym->value;
1076    call (values.i[0], values.i[1], values.i[2], values.i[3]);
1077  }
1078  else
1079  {
1080    int cargc = argc - (label + 1);
1081    if (cargc == 0)
1082    {
1083      csig_none call = (csig_none) sym->value;
1084      call ();
1085    }
1086    else
1087    {
1088      csig_argv   call = (csig_argv) sym->value;
1089      const char* cargv = argv[label + 1];
1090      call (cargc, &cargv);
1091    }
1092  }
1093
1094  if (!keep_locked)
1095  {
1096    rtl = rtems_rtl_lock ();
1097    if (rtl == NULL)
1098    {
1099      rtems_printf (printer, "error: cannot lock the linker\n");
1100      return 1;
1101    }
1102
1103    obj = rtems_rtl_find_obj_with_symbol (sym);
1104    if (obj == NULL)
1105    {
1106      rtems_rtl_unlock ();
1107      rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
1108      return 1;
1109    }
1110
1111    rtems_rtl_obj_dec_reference (obj);
1112
1113    rtems_rtl_unlock ();
1114  }
1115
1116  return 0;
1117}
1118
1119static void
1120rtems_rtl_shell_usage (const rtems_printer* printer, const char* arg)
1121{
1122  rtems_printf (printer, "%s: Runtime Linker\n", arg);
1123  rtems_printf (printer, "  %s [-hl] <command>\n", arg);
1124  rtems_printf (printer, "   where:\n");
1125  rtems_printf (printer, "     command: A n RTL command. See -l for a list plus help.\n");
1126  rtems_printf (printer, "     -h:      This help\n");
1127  rtems_printf (printer, "     -l:      The command list.\n");
1128}
1129
1130int
1131rtems_rtl_shell_command (int argc, char* argv[])
1132{
1133  const rtems_rtl_shell_cmd table[] =
1134  {
1135    { "status", rtems_rtl_shell_status,
1136      "Display the status of the RTL" },
1137    { "list", rtems_rtl_shell_list,
1138      "\tList the object files currently loaded" },
1139    { "sym", rtems_rtl_shell_sym,
1140      "\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
1141    { "obj", rtems_rtl_shell_object,
1142      "\tDisplay the object details, obj <name>" },
1143    { "call", rtems_rtl_shell_call,
1144      "\tCall a symbol" },
1145    { "ar", rtems_rtl_shell_archive,
1146      "\tDisplay the archive details, ar [-ls] <name>" },
1147    { "trace", rtems_rtl_trace_shell_command,
1148      "\tControl the RTL trace flags, trace [-h]" }
1149  };
1150
1151  rtems_printer printer;
1152  int           arg;
1153  int           t;
1154
1155  rtems_print_printer_printf (&printer);
1156
1157  for (arg = 1; arg < argc; arg++)
1158  {
1159    if (argv[arg][0] != '-')
1160      break;
1161
1162    switch (argv[arg][1])
1163    {
1164      case 'h':
1165        rtems_rtl_shell_usage (&printer, argv[0]);
1166        return 0;
1167      case 'l':
1168        rtems_printf (&printer, "%s: commands are:\n", argv[0]);
1169        for (t = 0;
1170             t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd));
1171             ++t)
1172          rtems_printf (&printer, "  %s\t%s\n", table[t].name, table[t].help);
1173        return 0;
1174      default:
1175        rtems_printf (&printer, "error: unknown option: %s\n", argv[arg]);
1176        return 1;
1177    }
1178  }
1179
1180  if ((argc - arg) < 1)
1181    rtems_printf (&printer, "error: you need to provide a command, try %s -h\n",
1182                  argv[0]);
1183  else
1184  {
1185    for (t = 0;
1186         t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd));
1187         ++t)
1188    {
1189      if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
1190        return table[t].handler (&printer, argc - 1, argv + 1);
1191    }
1192    rtems_printf (&printer, "error: command not found: %s (try -h)\n", argv[arg]);
1193  }
1194
1195  return 1;
1196}
Note: See TracBrowser for help on using the repository browser.