source: rtems-tools/linkers/rtems-exeinfo.cpp @ 3fab1f5

Last change on this file since 3fab1f5 was 3fab1f5, checked in by Chris Johns <chrisj@…>, on Jan 10, 2019 at 1:40:52 AM

linkers: Fix the -O option handling in rtems-execinfo

  • Property mode set to 100644
File size: 26.6 KB
Line 
1/*
2 * Copyright (c) 2016-2018, Chris Johns <chrisj@rtems.org>
3 *
4 * RTEMS Tools Project (http://www.rtems.org/)
5 * This file is part of the RTEMS Tools package in 'rtems-tools'.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19/**
20 * @file
21 *
22 * @ingroup rtems_rld
23 *
24 * @brief RTEMS Init dumps the initialisation section data in a format we can
25 *        read.
26 *
27 */
28
29#if HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <iostream>
34#include <iomanip>
35
36#include <cxxabi.h>
37#include <signal.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include <getopt.h>
43
44#include <rld.h>
45#include <rld-buffer.h>
46#include <rld-dwarf.h>
47#include <rld-files.h>
48#include <rld-process.h>
49#include <rld-rtems.h>
50
51#ifndef HAVE_KILL
52#define kill(p,s) raise(s)
53#endif
54
55namespace rld
56{
57  namespace exeinfo
58  {
59    /**
60     * Default section list.
61     */
62    const char* default_init[] =
63    {
64      ".rtemsroset",
65      ".ctors",
66      ".init",
67      0
68    };
69
70    const char* default_fini[] =
71    {
72      ".dtors",
73      ".fini",
74      0
75    };
76
77    /**
78     * ARM section list.
79     */
80    const char* arm_init[] =
81    {
82      ".rtemsroset",
83      ".init_array",
84      0
85    };
86
87    const char* arm_fini[] =
88    {
89      ".fini_array",
90      0
91    };
92
93    /**
94     * An executable section's address, offset, size and alignment.
95     */
96    struct section
97    {
98      const files::section& sec;        //< The executable's section.
99      buffer::buffer        data;       //< The section's data.
100      files::byteorder      byteorder;  //< The image's byteorder.
101
102      /**
103       * Construct the section.
104       */
105      section (const files::section& sec, files::byteorder byteorder);
106
107      /**
108       * Copy construct.
109       */
110      section (const section& orig);
111
112      /**
113       * Clean up the section's memory.
114       */
115      ~section ();
116
117    private:
118      /**
119       * Default constructor.
120       */
121      section ();
122    };
123
124    /**
125     * Container of sections. Order is the address in memory.
126     */
127    typedef std::list < section > sections;
128
129    /**
130     * The kernel image.
131     */
132    struct image
133    {
134      files::object    exe;         //< The object file that is the executable.
135      dwarf::file      debug;       //< The executable's DWARF details.
136      symbols::table   symbols;     //< The synbols for a map.
137      symbols::addrtab addresses;   //< The symbols keyed by address.
138      files::sections  secs;        //< The sections in the executable.
139      const char**     init;        //< The init section's list for the machinetype.
140      const char**     fini;        //< The fini section's list for the machinetype.
141
142
143      /**
144       * Load the executable file.
145       */
146      image (const std::string exe_name);
147
148      /**
149       * Clean up.
150       */
151      ~image ();
152
153      /*
154       * Check the compiler and flags match.
155       */
156      void output_compilation_unit (bool objects);
157
158      /*
159       * Output the sections.
160       */
161      void output_sections ();
162
163      /*
164       * Output the init sections.
165       */
166      void output_init ();
167
168      /*
169       * Output the fini sections.
170       */
171      void output_fini ();
172
173      /*
174       * Output init/fini worker.
175       */
176      void output_init_fini (const char* label, const char** names);
177
178      /*
179       * Output the inlined functions.
180       */
181      void output_inlined ();
182
183      /*
184       * Output the DWARF data.
185       */
186      void output_dwarf ();
187    };
188
189    section::section (const files::section& sec, files::byteorder byteorder)
190      : sec (sec),
191        data (sec.size, byteorder == rld::files::little_endian),
192        byteorder (byteorder)
193    {
194    }
195
196    section::section (const section& orig)
197      : sec (orig.sec),
198        data (orig.data)
199    {
200    }
201
202    section::~section ()
203    {
204    }
205
206    /**
207     * Helper for for_each to filter and load the sections we wish to
208     * dump.
209     */
210    class section_loader:
211      public std::unary_function < const files::section, void >
212    {
213    public:
214
215      section_loader (image& img, sections& secs, const char* names[]);
216
217      ~section_loader ();
218
219      void operator () (const files::section& fsec);
220
221    private:
222
223      image&       img;
224      sections&    secs;
225      const char** names;
226    };
227
228    section_loader::section_loader (image&      img,
229                                    sections&   secs,
230                                    const char* names[])
231      : img (img),
232        secs (secs),
233        names (names)
234    {
235    }
236
237    section_loader::~section_loader ()
238    {
239    }
240
241    void
242    section_loader::operator () (const files::section& fsec)
243    {
244      if (rld::verbose () >= RLD_VERBOSE_DETAILS)
245        std::cout << "init:section-loader: " << fsec.name
246                  << " address=" << std::hex << fsec.address << std::dec
247                  << " relocs=" << fsec.relocs.size ()
248                  << " fsec.size=" << fsec.size
249                  << " fsec.alignment=" << fsec.alignment
250                  << " fsec.rela=" << fsec.rela
251                  << std::endl;
252
253      for (int n = 0; names[n] != 0; ++n)
254      {
255        if (fsec.name == names[n])
256        {
257          if (rld::verbose () >= RLD_VERBOSE_DETAILS)
258            std::cout << "init:section-loader: " << fsec.name
259                      << " added" << std::endl;
260
261          section sec (fsec, img.exe.get_byteorder ());
262          img.exe.seek (fsec.offset);
263          sec.data.read (img.exe, fsec.size);
264          secs.push_back (sec);
265          break;
266        }
267      }
268    }
269
270    image::image (const std::string exe_name)
271      : exe (exe_name),
272        init (0),
273        fini (0)
274    {
275      /*
276       * Open the executable file and begin the session on it.
277       */
278      exe.open ();
279      exe.begin ();
280      debug.begin (exe.elf ());
281
282      if (!exe.valid ())
283        throw rld::error ("Not valid: " + exe.name ().full (),
284                          "init::image");
285
286      /*
287       * Set up the section lists for the machiner type.
288       */
289      switch (exe.elf ().machinetype ())
290      {
291        case EM_ARM:
292          init = arm_init;
293          fini = arm_fini;
294          break;
295        default:
296          init  = default_init;
297          fini  = default_fini;
298          break;
299      }
300
301      /*
302       * Load the symbols and sections.
303       */
304      exe.load_symbols (symbols, true);
305      debug.load_debug ();
306      debug.load_types ();
307      debug.load_functions ();
308      symbols.globals (addresses);
309      symbols.weaks (addresses);
310      symbols.locals (addresses);
311      exe.get_sections (secs);
312    }
313
314    image::~image ()
315    {
316    }
317
318    void
319    image::output_compilation_unit (bool objects)
320    {
321      dwarf::compilation_units& cus = debug.get_cus ();
322
323      std::cout << "Compilation: " << std::endl;
324
325      rld::strings flag_exceptions = { "-O",
326                                       "-g",
327                                       "-mtune=",
328                                       "-fno-builtin",
329                                       "-fno-inline",
330                                       "-fexceptions",
331                                       "-fnon-call-exceptions",
332                                       "-fvisibility=",
333                                       "-fno-stack-protector",
334                                       "-fbuilding-libgcc",
335                                       "-fno-implicit-templates",
336                                       "-fimplicit-templates",
337                                       "-ffunction-sections",
338                                       "-fdata-sections",
339                                       "-frandom-seed=",
340                                       "-fno-common",
341                                       "-fno-keep-inline-functions" };
342
343      dwarf::producer_sources producers;
344
345      debug.get_producer_sources (producers);
346
347      /*
348       * Find which flags are common to the building of all source. We are only
349       * interested in files that have any flags. This filters out things like
350       * the assembler which does not have flags.
351       */
352
353      rld::strings all_flags;
354
355      size_t source_max = 0;
356
357      for (auto& p : producers)
358      {
359        dwarf::source_flags_compare compare;
360        std::sort (p.sources.begin (), p.sources.end (), compare);
361
362        for (auto& s : p.sources)
363        {
364          size_t len = rld::path::basename (s.source).length ();
365          if (len > source_max)
366            source_max = len;
367
368          if (!s.flags.empty ())
369          {
370            for (auto& f : s.flags)
371            {
372              bool add = true;
373              for (auto& ef : flag_exceptions)
374              {
375                if (rld::starts_with (f, ef))
376                {
377                  add = false;
378                  break;
379                }
380              }
381              if (add)
382              {
383                for (auto& af : all_flags)
384                {
385                  if (f == af)
386                  {
387                    add = false;
388                    break;
389                  }
390                }
391                if (add)
392                  all_flags.push_back (f);
393              }
394            }
395          }
396        }
397      }
398
399      rld::strings common_flags;
400
401      for (auto& flag : all_flags)
402      {
403        bool found_in_all = true;
404        for (auto& p : producers)
405        {
406          for (auto& s : p.sources)
407          {
408            if (!s.flags.empty ())
409            {
410              bool flag_found = false;
411              for (auto& f : s.flags)
412              {
413                if (flag == f)
414                {
415                  flag_found = true;
416                  break;
417                }
418              }
419              if (!flag_found)
420              {
421                found_in_all = false;
422                break;
423              }
424            }
425            if (!found_in_all)
426              break;
427          }
428        }
429        if (found_in_all)
430          common_flags.push_back (flag);
431      }
432
433      std::cout << " Producers: " << producers.size () << std::endl;
434
435      for (auto& p : producers)
436      {
437        std::cout << "  | " << p.producer
438                  << ": " << p.sources.size () << " objects" << std::endl;
439      }
440
441      std::cout << " Common flags: " << common_flags.size () << std::endl
442                << "  |";
443
444      for (auto& f : common_flags)
445        std::cout << ' ' << f;
446      std::cout << std::endl;
447
448      if (objects)
449      {
450        std::cout << " Object files: " << cus.size () << std::endl;
451
452        rld::strings filter_flags = common_flags;
453        filter_flags.insert (filter_flags.end (),
454                             flag_exceptions.begin (),
455                             flag_exceptions.end());
456
457        for (auto& p : producers)
458        {
459          std::cout << ' ' << p.producer
460                    << ": " << p.sources.size () << " objects" << std::endl;
461          for (auto& s : p.sources)
462          {
463            std::cout << "   | "
464                      << std::setw (source_max + 1) << std::left
465                      << rld::path::basename (s.source);
466            if (!s.flags.empty ())
467            {
468              bool first = true;
469              for (auto& f : s.flags)
470              {
471                bool present = false;
472                for (auto& ff : filter_flags)
473                {
474                  if (rld::starts_with(f, ff))
475                  {
476                    present = true;
477                    break;
478                  }
479                }
480                if (!present)
481                {
482                  if (first)
483                  {
484                    std::cout << ':';
485                    first = false;
486                  }
487                  std::cout << ' ' << f;
488                }
489              }
490            }
491            std::cout << std::endl;
492          }
493        }
494      }
495
496      std::cout << std::endl;
497    }
498
499    void
500    image::output_sections ()
501    {
502      std::cout << "Sections: " << secs.size () << std::endl;
503
504      size_t max_section_name = 0;
505
506      for (files::sections::const_iterator si = secs.begin ();
507           si != secs.end ();
508           ++si)
509      {
510        const files::section& sec = *si;
511        if (sec.name.length() > max_section_name)
512          max_section_name = sec.name.length();
513      }
514
515      for (files::sections::const_iterator si = secs.begin ();
516           si != secs.end ();
517           ++si)
518      {
519        const files::section& sec = *si;
520
521        #define SF(f, i, c) if (sec.flags & (f)) flags[i] = c
522
523        std::string flags ("--------------");
524
525        SF (SHF_WRITE,            0, 'W');
526        SF (SHF_ALLOC,            1, 'A');
527        SF (SHF_EXECINSTR,        2, 'E');
528        SF (SHF_MERGE,            3, 'M');
529        SF (SHF_STRINGS,          4, 'S');
530        SF (SHF_INFO_LINK,        5, 'I');
531        SF (SHF_LINK_ORDER,       6, 'L');
532        SF (SHF_OS_NONCONFORMING, 7, 'N');
533        SF (SHF_GROUP,            8, 'G');
534        SF (SHF_TLS,              9, 'T');
535        SF (SHF_AMD64_LARGE,     10, 'a');
536        SF (SHF_ENTRYSECT,       11, 'e');
537        SF (SHF_COMDEF,          12, 'c');
538        SF (SHF_ORDERED,         13, 'O');
539
540        std::cout << "  " << std::left
541                  << std::setw (max_section_name) << sec.name
542                  << " " << flags
543                  << std::right << std::hex << std::setfill ('0')
544                  << " addr: 0x" << std::setw (8) << sec.address
545                  << " 0x" << std::setw (8) << sec.address + sec.size
546                  << std::dec << std::setfill (' ')
547                  << " size: " << std::setw (10) << sec.size
548                  << " align: " << std::setw (3) << sec.alignment
549                  << " relocs: " << std::setw (6) << sec.relocs.size ()
550                  << std::endl;
551      }
552
553      std::cout << std::endl;
554    }
555
556    void
557    image::output_init ()
558    {
559      output_init_fini ("Init", init);
560    }
561
562    void
563    image::output_fini ()
564    {
565      output_init_fini ("Fini", fini);
566    }
567
568    void
569    image::output_init_fini (const char* label, const char** names)
570    {
571      /*
572       * Load the sections.
573       */
574      sections ifsecs;
575      std::for_each (secs.begin (), secs.end (),
576                     section_loader (*this, ifsecs, names));
577
578      std::cout << label << " sections: " << ifsecs.size () << std::endl;
579
580      for (auto& sec : ifsecs)
581      {
582        const size_t machine_size = exe.elf ().machine_size ();
583        const int    count = sec.data.level () / machine_size;
584
585        std::cout << " " << sec.sec.name << std::endl;
586
587        for (int i = 0; i < count; ++i)
588        {
589          uint32_t         address;
590          symbols::symbol* sym;
591          sec.data >> address;
592          sym = addresses[address];
593          std::cout << "  "
594                    << std::hex << std::setfill ('0')
595                    << "0x" << std::setw (8) << address
596                    << std::dec << std::setfill ('0');
597          if (sym)
598          {
599            std::string label = sym->name ();
600            if (rld::symbols::is_cplusplus (label))
601              rld::symbols::demangle_name (label, label);
602            std::cout << " " << label;
603          }
604          else
605          {
606            std::cout << " no symbol";
607          }
608          std::cout << std::endl;
609        }
610      }
611
612      std::cout << std::endl;
613    }
614
615    struct func_count
616    {
617      std::string name;
618      int         count;
619      size_t      size;
620
621      func_count (std::string name, size_t size)
622        : name (name),
623          count (1),
624          size (size) {
625      }
626    };
627    typedef std::vector < func_count > func_counts;
628
629    void image::output_inlined ()
630    {
631      size_t           total = 0;
632      size_t           total_size = 0;
633      size_t           inlined_size = 0;
634      dwarf::functions funcs_inlined;
635      dwarf::functions funcs_not_inlined;
636      func_counts      counts;
637
638      for (auto& cu : debug.get_cus ())
639      {
640        for (auto& f : cu.get_functions ())
641        {
642          if (f.size () > 0 && f.has_machine_code ())
643          {
644            bool counted;
645            ++total;
646            total_size += f.size ();
647            switch (f.get_inlined ())
648            {
649              case dwarf::function::inl_inline:
650              case dwarf::function::inl_declared_inlined:
651                inlined_size += f.size ();
652                counted = false;
653                for (auto& c : counts)
654                {
655                  if (c.name == f.name ())
656                  {
657                    ++c.count;
658                    c.size += f.size ();
659                    counted = true;
660                    break;
661                  }
662                }
663                if (!counted)
664                  counts.push_back (func_count (f.name (), f.size ()));
665                funcs_inlined.push_back (f);
666                break;
667              case dwarf::function::inl_declared_not_inlined:
668                funcs_not_inlined.push_back (f);
669                break;
670              default:
671                break;
672            }
673          }
674        }
675      }
676
677      std::cout << "inlined funcs   : " << funcs_inlined.size () << std::endl
678                << "    total funcs : " << total << std::endl
679                << " % inline funcs : " << (funcs_inlined.size () * 100) / total << '%'
680                << std::endl
681                << "     total size : " << total_size << std::endl
682                << "    inline size : " << inlined_size << std::endl
683                << "  % inline size : " << (inlined_size * 100) / total_size << '%'
684                << std::endl;
685
686      auto count_compare = [](func_count const & a, func_count const & b) {
687        return a.size != b.size?  a.size < b.size : a.count > b.count;
688      };
689      std::sort (counts.begin (), counts.end (), count_compare);
690      std::reverse (counts.begin (), counts.end ());
691
692      std::cout  << std::endl << "inlined repeats : " << std::endl;
693      for (auto& c : counts)
694        if (c.count > 1)
695          std::cout << std::setw (6) << c.size << ' '
696                    << std::setw (4) << c.count << ' '
697                    << c.name << std::endl;
698
699      dwarf::function_compare compare (dwarf::function_compare::fc_by_size);
700
701      std::sort (funcs_inlined.begin (), funcs_inlined.end (), compare);
702      std::reverse (funcs_inlined.begin (), funcs_inlined.end ());
703
704      std::cout << std::endl << "inline funcs : " << std::endl;
705      for (auto& f : funcs_inlined)
706      {
707        std::string flags;
708
709        std::cout << std::setw (6) << f.size () << ' '
710                  << (char) (f.is_external () ? 'E' : ' ')
711                  << (char) (f.get_inlined () == dwarf::function::inl_inline ? 'C' : ' ')
712                  << std::hex << std::setfill ('0')
713                  << " 0x" << std::setw (8) << f.pc_low ()
714                  << std::dec << std::setfill (' ')
715                  << ' ' << f.name ()
716                  << std::endl;
717      }
718
719      if (funcs_not_inlined.size () > 0)
720      {
721        std::sort (funcs_not_inlined.begin (), funcs_not_inlined.end (), compare);
722        std::reverse (funcs_not_inlined.begin (), funcs_not_inlined.end ());
723
724        std::cout << std::endl << "inline funcs not inlined: " << std::endl;
725        for (auto& f : funcs_not_inlined)
726        {
727          std::cout << std::setw (6) << f.size () << ' '
728                    << (char) (f.is_external () ? 'E' : ' ')
729                    << (char) (f.get_inlined () == dwarf::function::inl_inline ? 'C' : ' ')
730                    << std::hex << std::setfill ('0')
731                    << " 0x" << std::setw (8) << f.pc_low ()
732                    << std::dec << std::setfill (' ')
733                    << ' ' << f.name ()
734                    << std::endl;
735        }
736      }
737    }
738
739    void image::output_dwarf ()
740    {
741      std::cout << "DWARF Data:" << std::endl;
742      debug.dump (std::cout);
743    }
744  }
745}
746
747/**
748 * RTEMS Exe Info options. This needs to be rewritten to be like cc where only
749 * a single '-' and long options is present.
750 */
751static struct option rld_opts[] = {
752  { "help",        no_argument,            NULL,           'h' },
753  { "version",     no_argument,            NULL,           'V' },
754  { "verbose",     no_argument,            NULL,           'v' },
755  { "map",         no_argument,            NULL,           'M' },
756  { "all",         no_argument,            NULL,           'a' },
757  { "sections",    no_argument,            NULL,           'S' },
758  { "init",        no_argument,            NULL,           'I' },
759  { "fini",        no_argument,            NULL,           'F' },
760  { "objects",     no_argument,            NULL,           'O' },
761  { "inlined",     no_argument,            NULL,           'i' },
762  { "dwarf",       no_argument,            NULL,           'D' },
763  { NULL,          0,                      NULL,            0 }
764};
765
766void
767usage (int exit_code)
768{
769  std::cout << "rtems-exeinfo [options] objects" << std::endl
770            << "Options and arguments:" << std::endl
771            << " -h        : help (also --help)" << std::endl
772            << " -V        : print linker version number and exit (also --version)" << std::endl
773            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
774            << "             to increase verbosity (also --verbose)" << std::endl
775            << " -M        : generate map output (also --map)" << std::endl
776            << " -a        : all output excluding the map and DAWRF (also --all)" << std::endl
777            << " -S        : show all section (also --sections)" << std::endl
778            << " -I        : show init section tables (also --init)" << std::endl
779            << " -F        : show fini section tables (also --fini)" << std::endl
780            << " -O        : show object files (also --objects)" << std::endl
781            << " -i        : show inlined code (also --inlined)" << std::endl
782            << " -D        : dump the DWARF data (also --dwarf)" << std::endl;
783  ::exit (exit_code);
784}
785
786static void
787fatal_signal (int signum)
788{
789  signal (signum, SIG_DFL);
790
791  rld::process::temporaries_clean_up ();
792
793  /*
794   * Get the same signal again, this time not handled, so its normal effect
795   * occurs.
796   */
797  kill (getpid (), signum);
798}
799
800static void
801setup_signals (void)
802{
803  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
804    signal (SIGINT, fatal_signal);
805#ifdef SIGHUP
806  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
807    signal (SIGHUP, fatal_signal);
808#endif
809  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
810    signal (SIGTERM, fatal_signal);
811#ifdef SIGPIPE
812  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
813    signal (SIGPIPE, fatal_signal);
814#endif
815#ifdef SIGCHLD
816  signal (SIGCHLD, SIG_DFL);
817#endif
818}
819
820void
821unhandled_exception (void)
822{
823  std::cerr << "error: exception handling error, please report" << std::endl;
824  exit (1);
825}
826
827int
828main (int argc, char* argv[])
829{
830  int ec = 0;
831
832  setup_signals ();
833
834  std::set_terminate(unhandled_exception);
835
836  try
837  {
838    std::string exe_name;
839    bool        map = false;
840    bool        all = false;
841    bool        sections = false;
842    bool        init = false;
843    bool        fini = false;
844    bool        objects = false;
845    bool        inlined = false;
846    bool        dwarf_data = false;
847
848    rld::set_cmdline (argc, argv);
849
850    while (true)
851    {
852      int opt = ::getopt_long (argc, argv, "hvVMaSIFOiD", rld_opts, NULL);
853      if (opt < 0)
854        break;
855
856      switch (opt)
857      {
858        case 'V':
859          std::cout << "rtems-exeinfo (RTEMS Executable Info) " << rld::version ()
860                    << ", RTEMS revision " << rld::rtems::version ()
861                    << std::endl;
862          ::exit (0);
863          break;
864
865        case 'v':
866          rld::verbose_inc ();
867          break;
868
869        case 'M':
870          map = true;
871          break;
872
873        case 'a':
874          all = true;
875          break;
876
877        case 'I':
878          init = true;
879          break;
880
881        case 'F':
882          fini = true;
883          break;
884
885        case 'S':
886          sections = true;
887          break;
888
889        case 'O':
890          objects = true;
891          break;
892
893        case 'i':
894          inlined = true;
895          break;
896
897        case 'D':
898          dwarf_data = true;
899          break;
900
901        case '?':
902          usage (3);
903          break;
904
905        case 'h':
906          usage (0);
907          break;
908      }
909    }
910
911    /*
912     * Set the program name.
913     */
914    rld::set_progname (argv[0]);
915
916    argc -= optind;
917    argv += optind;
918
919    std::cout << "RTEMS Executable Info " << rld::version () << std::endl;
920    std::cout << " " << rld::get_cmdline () << std::endl;
921
922    /*
923     * All means all types of output.
924     */
925    if (all)
926    {
927      sections = true;
928      init = true;
929      fini = true;
930      objects = true;
931      inlined = true;
932    }
933
934    /*
935     * If there is no executable there is nothing to convert.
936     */
937    if (argc == 0)
938      throw rld::error ("no executable", "options");
939    if (argc > 1)
940      throw rld::error ("only a single executable", "options");
941
942    /*
943     * The name of the executable.
944     */
945    exe_name = *argv;
946
947    if (rld::verbose ())
948      std::cout << "exe-image: " << exe_name << std::endl;
949
950    /*
951     * Open the executable and read the symbols.
952     */
953    rld::exeinfo::image exe (exe_name);
954
955    std::cout << "exe: " << exe.exe.name ().full () << std::endl
956              << std::endl;
957
958    /*
959     * Generate the output.
960     */
961    exe.output_compilation_unit (objects);
962    if (sections)
963      exe.output_sections ();
964    if (init)
965      exe.output_init ();
966    if (fini)
967      exe.output_fini ();
968    if (inlined)
969      exe.output_inlined ();
970    if (dwarf_data)
971      exe.output_dwarf ();
972
973    /*
974     * Map ?
975     */
976    if (map)
977      rld::symbols::output (std::cout, exe.symbols);
978  }
979  catch (rld::error re)
980  {
981    std::cerr << "error: "
982              << re.where << ": " << re.what
983              << std::endl;
984    ec = 10;
985  }
986  catch (std::exception& e)
987  {
988    int   status;
989    char* realname;
990    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
991    std::cerr << "error: exception: " << realname << " [";
992    ::free (realname);
993    const std::type_info &ti = typeid (e);
994    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
995    std::cerr << realname << "] " << e.what () << std::endl << std::flush;
996    ::free (realname);
997    ec = 11;
998  }
999  catch (...)
1000  {
1001    /*
1002     * Helps to know if this happens.
1003     */
1004    std::cerr << "error: unhandled exception" << std::endl;
1005    ec = 12;
1006  }
1007
1008  return ec;
1009}
Note: See TracBrowser for help on using the repository browser.