source: rtems-tools/linkers/rtems-rapper.cpp @ 4585798

4.104.115
Last change on this file since 4585798 was 40fd7a0, checked in by Chris Johns <chrisj@…>, on 09/01/14 at 03:26:47

rld: Split the file into a path module for path specific functions.

This allows resued for other parts of the system not dependent on
objcet files or archives.

  • Property mode set to 100644
File size: 32.7 KB
Line 
1/*
2 * Copyright (c) 2012, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems_rld
20 *
21 * @brief RTEMS RAP Manager lets you look at and play with RAP files.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <algorithm>
30#include <iomanip>
31#include <iostream>
32#include <vector>
33
34#include <cxxabi.h>
35#include <signal.h>
36#include <stdlib.h>
37#include <string.h>
38#include <unistd.h>
39
40#include <getopt.h>
41
42#include <rld.h>
43#include <rld-compression.h>
44#include <rld-files.h>
45#include <rld-process.h>
46#include <rld-rap.h>
47
48#include <rtems-utils.h>
49
50#ifndef HAVE_KILL
51#define kill(p,s) raise(s)
52#endif
53
54/**
55 * RTEMS Application.
56 */
57namespace rap
58{
59  /**
60   * The names of the RAP sections.
61   */
62  static const char* section_names[6] =
63  {
64    ".text",
65    ".const",
66    ".ctor",
67    ".dtor",
68    ".data",
69    ".bss"
70  };
71
72  /**
73   * A relocation record.
74   */
75  struct relocation
76  {
77    uint32_t    info;
78    uint32_t    offset;
79    uint32_t    addend;
80    std::string symname;
81    off_t       rap_off;
82
83    relocation ();
84
85    void output ();
86  };
87
88  typedef std::vector < relocation > relocations;
89
90  /**
91   * Relocation offset sorter for the relocations container.
92   */
93  class reloc_offset_compare
94  {
95  public:
96    bool operator () (const relocation& lhs,
97                      const relocation& rhs) const {
98      return lhs.offset < rhs.offset;
99    }
100  };
101
102  /**
103   * A RAP section.
104   */
105  struct section
106  {
107    std::string name;
108    uint32_t    size;
109    uint32_t    alignment;
110    uint8_t*    data;
111    uint32_t    relocs_size;
112    relocations relocs;
113    bool        rela;
114    off_t       rap_off;
115
116    section ();
117    ~section ();
118
119    void load_data (rld::compress::compressor& comp);
120    void load_relocs (rld::compress::compressor& comp);
121  };
122
123  /**
124   * Section detail
125   */
126  struct section_detail
127  {
128    uint32_t name;   //< The offset in the strtable.
129    uint32_t offset; //< The offset in the rap section.
130    uint32_t id;     //< The rap id.
131    uint32_t size;   //< The size of the elf section.
132    uint32_t obj;    //< The obj id.
133
134    /* Constructor */
135    section_detail (const section_detail& s);
136    section_detail ();
137  };
138
139  section_detail::section_detail (const section_detail& s)
140    : name (s.name),
141      offset (s.offset),
142      id (s.id),
143      size (s.size),
144      obj (s.obj)
145  {
146  }
147
148  section_detail::section_detail ()
149    : name (0),
150      offset (0),
151      id (0),
152      size (0),
153      obj (0)
154  {
155  }
156
157  /**
158   * A container of section_detail
159   */
160  typedef std::list < section_detail > section_details;
161
162  /**
163   * A RAP file.
164   */
165  struct file
166  {
167    enum {
168      rap_comp_buffer = 2 * 1024
169    };
170
171    std::string header;
172    size_t      rhdr_len;
173    uint32_t    rhdr_length;
174    uint32_t    rhdr_version;
175    std::string rhdr_compression;
176    uint32_t    rhdr_checksum;
177
178    off_t       machine_rap_off;
179    uint32_t    machinetype;
180    uint32_t    datatype;
181    uint32_t    class_;
182
183    off_t       layout_rap_off;
184    std::string init;
185    uint32_t    init_off;
186    std::string fini;
187    uint32_t    fini_off;
188
189    off_t       strtab_rap_off;
190    uint32_t    strtab_size;
191    uint8_t*    strtab;
192
193    off_t       symtab_rap_off;
194    uint32_t    symtab_size;
195    uint8_t*    symtab;
196
197    off_t       relocs_rap_off;
198    uint32_t    relocs_size; /* not used */
199
200    off_t       detail_rap_off;
201    uint32_t    obj_num;
202    uint8_t**   obj_name;
203    uint32_t*   sec_num;
204    uint8_t*    rpath;
205    uint32_t    rpathlen;
206    uint8_t*    str_detail;
207    section_details sec_details;
208
209    section     secs[rld::rap::rap_secs];
210
211    /**
212     * Open a RAP file and read the header.
213     */
214    file (const std::string& name, bool warnings);
215
216    /**
217     * Close the RAP file.
218     */
219    ~file ();
220
221    /**
222     * Parse header.
223     */
224    void parse_header ();
225
226    /**
227     * Load the file.
228     */
229    void load ();
230
231    /**
232     * Expand the image.
233     */
234    void expand ();
235
236    /**
237     * Load details.
238     */
239    void load_details(rld::compress::compressor& comp);
240
241    /**
242     * The name.
243     */
244    const std::string name () const;
245
246    /**
247     * The number of symbols in the symbol table.
248     */
249    int symbols () const;
250
251    /**
252     * Return a symbol given an index.
253     */
254    void symbol (int       index,
255                 uint32_t& data,
256                 uint32_t& name,
257                 uint32_t& value) const;
258
259    /**
260     * Return the string from the string table.
261     */
262    const char* string (int index);
263
264  private:
265
266    bool              warnings;
267    rld::files::image image;
268  };
269
270  template < typename T > T
271  get_value (const uint8_t* data)
272  {
273    T v = 0;
274    for (size_t b = 0; b < sizeof (T); ++b)
275    {
276      v <<= 8;
277      v |= (T) data[b];
278    }
279    return v;
280  }
281
282  relocation::relocation ()
283    : info (0),
284      offset (0),
285      addend (0),
286      rap_off (0)
287  {
288  }
289
290  void
291  relocation::output ()
292  {
293    std::cout << std::hex << std::setfill ('0')
294              << "0x" << std::setw (8) << info
295              << " 0x" << std::setw (8) << offset
296              << " 0x" << std::setw(8) << addend
297              << std::dec << std::setfill (' ')
298              << " " << symname;
299  }
300
301  section::section ()
302    : size (0),
303      alignment (0),
304      data (0),
305      relocs_size (0),
306      relocs (0),
307      rela (false),
308      rap_off (0)
309  {
310  }
311
312  section::~section ()
313  {
314    if (data)
315      delete [] data;
316  }
317
318  void
319  section::load_data (rld::compress::compressor& comp)
320  {
321    rap_off = comp.offset ();
322    if (size)
323    {
324      data = new uint8_t[size];
325      if (comp.read (data, size) != size)
326        throw rld::error ("Reading section data failed", "rapper");
327    }
328  }
329
330  void
331  section::load_relocs (rld::compress::compressor& comp)
332  {
333    uint32_t header;
334    comp >> header;
335
336    rela = header & RAP_RELOC_RELA ? true : false;
337    relocs_size = header & ~RAP_RELOC_RELA;
338
339    if (relocs_size)
340    {
341      for (uint32_t r = 0; r < relocs_size; ++r)
342      {
343        relocation reloc;
344
345        reloc.rap_off = comp.offset ();
346
347        comp >> reloc.info
348             >> reloc.offset;
349
350        if (((reloc.info & RAP_RELOC_STRING) == 0) || rela)
351          comp >> reloc.addend;
352
353        if ((reloc.info & RAP_RELOC_STRING) != 0)
354        {
355          if ((reloc.info & RAP_RELOC_STRING_EMBED) == 0)
356          {
357            size_t symname_size = (reloc.info & ~(3 << 30)) >> 8;
358            reloc.symname.resize (symname_size);
359            size_t symname_read = comp.read ((void*) reloc.symname.c_str (), symname_size);
360            if (symname_read != symname_size)
361              throw rld::error ("Reading reloc symbol name failed", "rapper");
362          }
363        }
364
365        relocs.push_back (reloc);
366      }
367
368      std::stable_sort (relocs.begin (), relocs.end (), reloc_offset_compare ());
369    }
370  }
371
372  file::file (const std::string& name, bool warnings)
373    : rhdr_len (0),
374      rhdr_length (0),
375      rhdr_version (0),
376      rhdr_checksum (0),
377      machine_rap_off (0),
378      machinetype (0),
379      datatype (0),
380      class_ (0),
381      layout_rap_off (0),
382      init_off (0),
383      fini_off (0),
384      strtab_rap_off (0),
385      strtab_size (0),
386      strtab (0),
387      symtab_rap_off (0),
388      symtab_size (0),
389      symtab (0),
390      relocs_rap_off (0),
391      relocs_size (0),
392      detail_rap_off (0),
393      obj_num (0),
394      obj_name (0),
395      sec_num (0),
396      rpath (0),
397      rpathlen (0),
398      str_detail (0),
399      warnings (warnings),
400      image (name)
401  {
402    for (int s = 0; s < rld::rap::rap_secs; ++s)
403      secs[s].name = rld::rap::section_name (s);
404    image.open ();
405    parse_header ();
406  }
407
408  file::~file ()
409  {
410    image.close ();
411
412    if (symtab)
413      delete [] symtab;
414    if (strtab)
415      delete [] strtab;
416    if (obj_name)
417      delete [] obj_name;
418    if (sec_num)
419      delete [] sec_num;
420    if (str_detail)
421      delete [] str_detail;
422
423  }
424
425  void
426  file::parse_header ()
427  {
428    std::string name = image.name ().full ();
429
430    char rhdr[64];
431
432    image.seek_read (0, (uint8_t*) rhdr, 64);
433
434    if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
435      throw rld::error ("Invalid RAP file", "open: " + name);
436
437    char* sptr = rhdr + 4;
438    char* eptr;
439
440    rhdr_length = ::strtoul (sptr, &eptr, 10);
441
442    if (*eptr != ',')
443      throw rld::error ("Cannot parse RAP header", "open: " + name);
444
445    sptr = eptr + 1;
446
447    rhdr_version = ::strtoul (sptr, &eptr, 10);
448
449    if (*eptr != ',')
450      throw rld::error ("Cannot parse RAP header", "open: " + name);
451
452    sptr = eptr + 1;
453
454    if ((sptr[0] == 'N') &&
455        (sptr[1] == 'O') &&
456        (sptr[2] == 'N') &&
457        (sptr[3] == 'E'))
458    {
459      rhdr_compression = "NONE";
460      eptr = sptr + 4;
461    }
462    else if ((sptr[0] == 'L') &&
463             (sptr[1] == 'Z') &&
464             (sptr[2] == '7') &&
465             (sptr[3] == '7'))
466    {
467      rhdr_compression = "LZ77";
468      eptr = sptr + 4;
469    }
470    else
471      throw rld::error ("Cannot parse RAP header", "open: " + name);
472
473    if (*eptr != ',')
474      throw rld::error ("Cannot parse RAP header", "open: " + name);
475
476    sptr = eptr + 1;
477
478    rhdr_checksum = ::strtoul (sptr, &eptr, 16);
479
480    if (*eptr != '\n')
481      throw rld::error ("Cannot parse RAP header", "open: " + name);
482
483    rhdr_len = eptr - rhdr + 1;
484
485    if (warnings && (rhdr_length != image.size ()))
486      std::cout << " warning: header length does not match file size: header="
487                << rhdr_length
488                << " file-size=" << image.size ()
489                << std::endl;
490
491    header.insert (0, rhdr, rhdr_len);
492
493    image.seek (rhdr_len);
494  }
495
496  void
497  file::load_details (rld::compress::compressor& comp)
498  {
499    uint32_t tmp;
500
501    comp >> rpathlen;
502
503    obj_name = new uint8_t*[obj_num];
504
505    sec_num = new uint32_t[obj_num];
506
507    /* how many sections of each object file */
508    for (uint32_t i = 0; i < obj_num; i++)
509    {
510      comp >> tmp;
511      sec_num[i] = tmp;
512    }
513
514    /* strtable size */
515    comp >> tmp;
516    str_detail = new uint8_t[tmp];
517    if (comp.read (str_detail, tmp) != tmp)
518      throw rld::error ("Reading file str details error", "rapper");
519
520    if (rpathlen > 0)
521      rpath = (uint8_t*)str_detail;
522    else rpath = NULL;
523
524    section_detail sec;
525
526    for (uint32_t i = 0; i < obj_num; i++)
527    {
528      sec.obj = i;
529      for (uint32_t j = 0; j < sec_num[i]; j++)
530      {
531        comp >> sec.name;
532        comp >> tmp;
533        sec.offset = tmp & 0xfffffff;
534        sec.id = tmp >> 28;
535        comp >> sec.size;
536
537        sec_details.push_back (section_detail (sec));
538      }
539    }
540  }
541  void
542  file::load ()
543  {
544    image.seek (rhdr_len);
545
546    rld::compress::compressor comp (image, rap_comp_buffer, false);
547
548    /*
549     * uint32_t: machinetype
550     * uint32_t: datatype
551     * uint32_t: class
552     */
553    machine_rap_off = comp.offset ();
554    comp >> machinetype
555         >> datatype
556         >> class_;
557
558    /*
559     * uint32_t: init
560     * uint32_t: fini
561     * uint32_t: symtab_size
562     * uint32_t: strtab_size
563     * uint32_t: relocs_size
564     */
565    layout_rap_off = comp.offset ();
566    comp >> init_off
567         >> fini_off
568         >> symtab_size
569         >> strtab_size
570         >> relocs_size;
571
572    /*
573     * Load the file details.
574     */
575    detail_rap_off = comp.offset ();
576
577    comp >> obj_num;
578
579    if (obj_num > 0)
580      load_details(comp);
581
582    /*
583     * uint32_t: text_size
584     * uint32_t: text_alignment
585     * uint32_t: const_size
586     * uint32_t: const_alignment
587     * uint32_t: ctor_size
588     * uint32_t: ctor_alignment
589     * uint32_t: dtor_size
590     * uint32_t: dtor_alignment
591     * uint32_t: data_size
592     * uint32_t: data_alignment
593     * uint32_t: bss_size
594     * uint32_t: bss_alignment
595     */
596    for (int s = 0; s < rld::rap::rap_secs; ++s)
597      comp >> secs[s].size
598           >> secs[s].alignment;
599
600    /*
601     * Load sections.
602     */
603    for (int s = 0; s < rld::rap::rap_secs; ++s)
604      if (s != rld::rap::rap_bss)
605        secs[s].load_data (comp);
606
607    /*
608     * Load the string table.
609     */
610    strtab_rap_off = comp.offset ();
611    if (strtab_size)
612    {
613      strtab = new uint8_t[strtab_size];
614      if (comp.read (strtab, strtab_size) != strtab_size)
615        throw rld::error ("Reading string table failed", "rapper");
616    }
617
618    /*
619     * Load the symbol table.
620     */
621    symtab_rap_off = comp.offset ();
622    if (symtab_size)
623    {
624      symtab = new uint8_t[symtab_size];
625      if (comp.read (symtab, symtab_size) != symtab_size)
626        throw rld::error ("Reading symbol table failed", "rapper");
627    }
628
629    /*
630     * Load the relocation tables.
631     */
632    relocs_rap_off = comp.offset ();
633    for (int s = 0; s < rld::rap::rap_secs; ++s)
634      secs[s].load_relocs (comp);
635  }
636
637  void
638  file::expand ()
639  {
640    std::string name = image.name ().full ();
641    std::string extension = rld::path::extension (image.name ().full ());
642
643    name = name.substr (0, name.size () - extension.size ()) + ".xrap";
644
645    image.seek (rhdr_len);
646
647    rld::compress::compressor comp (image, rap_comp_buffer, false);
648    rld::files::image         out (name);
649
650    out.open (true);
651    out.seek (0);
652    while (true)
653    {
654      if (comp.read (out, rap_comp_buffer) != rap_comp_buffer)
655        break;
656    }
657    out.close ();
658  }
659
660  const std::string
661  file::name () const
662  {
663    return image.name ().full ();
664  }
665
666  int
667  file::symbols () const
668  {
669    return symtab_size / (3 * sizeof (uint32_t));
670  }
671
672  void
673  file::symbol (int index, uint32_t& data, uint32_t& name, uint32_t& value) const
674  {
675    if (index < symbols ())
676    {
677      uint8_t* sym = symtab + (index * 3 * sizeof (uint32_t));
678      data  = get_value < uint32_t > (sym);
679      name  = get_value < uint32_t > (sym + (1 * sizeof (uint32_t)));
680      value = get_value < uint32_t > (symtab + (2 * sizeof (uint32_t)));
681    }
682  }
683
684  const char*
685  file::string (int index)
686  {
687    std::string name = image.name ().full ();
688
689    if (strtab_size == 0)
690      throw rld::error ("No string table", "string: " + name);
691
692    uint32_t offset = 0;
693    int count = 0;
694    while (offset < strtab_size)
695    {
696      if (count++ == index)
697        return (const char*) &strtab[offset];
698      offset = ::strlen ((const char*) &strtab[offset]) + 1;
699    }
700
701    throw rld::error ("Invalid string index", "string: " + name);
702  }
703}
704
705void
706rap_show (rld::path::paths& raps,
707          bool              warnings,
708          bool              show_header,
709          bool              show_machine,
710          bool              show_layout,
711          bool              show_strings,
712          bool              show_symbols,
713          bool              show_relocs,
714          bool              show_details)
715{
716  for (rld::path::paths::iterator pi = raps.begin();
717       pi != raps.end();
718       ++pi)
719  {
720    std::cout  << *pi << ':' << std::endl;
721
722    rap::file r (*pi, warnings);
723
724    try
725    {
726      r.load ();
727    }
728    catch (rld::error re)
729    {
730      std::cout << " error: "
731                << re.where << ": " << re.what
732                << std::endl
733                << " warning: file read failed, some data may be corrupt or not present."
734                << std::endl;
735    }
736
737    if (show_header)
738    {
739      std::cout << "  Header:" << std::endl
740                << "          string: " << r.header
741                << "          length: " << r.rhdr_len << std::endl
742                << "         version: " << r.rhdr_version << std::endl
743                << "     compression: " << r.rhdr_compression << std::endl
744                << std::hex << std::setfill ('0')
745                << "        checksum: " << std::setw (8) << r.rhdr_checksum << std::endl
746                << std::dec << std::setfill(' ');
747    }
748
749    if (show_machine)
750    {
751      std::cout << "  Machine: 0x"
752                << std::hex << std::setfill ('0')
753                << std::setw (8) << r.machine_rap_off
754                << std::setfill (' ') << std::dec
755                << " (" << r.machine_rap_off << ')' << std::endl
756                << "     machinetype: "<< r.machinetype << std::endl
757                << "        datatype: "<< r.datatype << std::endl
758                << "           class: "<< r.class_ << std::endl;
759    }
760
761    if (show_layout)
762    {
763      std::cout << "  Layout: 0x"
764                << std::hex << std::setfill ('0')
765                << std::setw (8) << r.layout_rap_off
766                << std::setfill (' ') << std::dec
767                << " (" << r.layout_rap_off << ')' << std::endl
768                << std::setw (18) << "  "
769                << "  size  align offset    " << std::endl;
770      uint32_t relocs_size = 0;
771      for (int s = 0; s < rld::rap::rap_secs; ++s)
772      {
773        relocs_size += r.secs[s].relocs.size ();
774        std::cout << std::setw (16) << rld::rap::section_name (s)
775                  << ": " << std::setw (6) << r.secs[s].size
776                  << std::setw (7)  << r.secs[s].alignment;
777        if (s != rld::rap::rap_bss)
778          std::cout << std::hex << std::setfill ('0')
779                    << " 0x" << std::setw (8) << r.secs[s].rap_off
780                    << std::setfill (' ') << std::dec
781                    << " (" << r.secs[s].rap_off << ')';
782        else
783          std::cout << " -";
784        std::cout << std::endl;
785      }
786      std::cout << std::setw (16) << "strtab" << ": "
787                << std::setw (6) << r.strtab_size
788                << std::setw (7) << '-'
789                << std::hex << std::setfill ('0')
790                << " 0x" << std::setw (8) << r.strtab_rap_off
791                << std::setfill (' ') << std::dec
792                << " (" << r.strtab_rap_off << ')' << std::endl
793                << std::setw (16) << "symtab" << ": "
794                << std::setw (6) << r.symtab_size
795                << std::setw (7) << '-'
796                << std::hex << std::setfill ('0')
797                << " 0x" << std::setw (8) << r.symtab_rap_off
798                << std::setfill (' ') << std::dec
799                << " (" << r.symtab_rap_off << ')' << std::endl
800                << std::setw (16) << "relocs" << ": "
801                << std::setw (6) << (relocs_size * 3 * sizeof (uint32_t))
802                << std::setw (7) << '-'
803                << std::hex << std::setfill ('0')
804                << " 0x" << std::setw (8) << r.relocs_rap_off
805                << std::setfill (' ') << std::dec
806                << " (" << r.relocs_rap_off << ')' << std::endl;
807    }
808
809    if (show_details)
810    {
811      std::cout << " Details: 0x"
812                << std::hex << std::setfill ('0')
813                << std::setw (8) << r.detail_rap_off
814                << std::setfill (' ') << std::dec
815                << " (" << r.detail_rap_off << ')' << std::endl;
816
817      uint32_t pos = 0;
818      if (r.rpath != NULL)
819      {
820        std::cout << " rpath:" << std::endl;
821        while (pos < r.rpathlen)
822        {
823          std::cout << " " << r.rpath + pos << std::endl;
824          pos = std::string ((char*)(r.rpath + pos)).length () + pos + 1;
825        }
826      }
827
828      if (r.obj_num == 0)
829        std::cout << " No details" << std::endl;
830      else
831        std::cout << ' ' << r.obj_num <<" Files" << std::endl;
832
833      for (uint32_t i = 0; i < r.obj_num; ++i)
834      {
835        r.obj_name[i] = (uint8_t*) &r.str_detail[pos];
836        pos += ::strlen ((char*) &r.str_detail[pos]) + 1;
837      }
838
839      for (uint32_t i = 0; i < r.obj_num; ++i)
840      {
841        std::cout << " File: " << r.obj_name[i] << std::endl;
842
843        for (rap::section_details::const_iterator sd = r.sec_details.begin ();
844             sd != r.sec_details.end ();
845             ++sd)
846        {
847          rap::section_detail tmp = *sd;
848          if (tmp.obj == i)
849          {
850            std::cout << std::setw (12) << "name:"
851                      << std::setw (16) << (char*)&r.str_detail[tmp.name]
852                      << " rap_section:"<< std::setw (8)
853                      << rap::section_names[tmp.id]
854                      << std::hex << std::setfill ('0')
855                      << " offset:0x" << std::setw (8) << tmp.offset
856                      << " size:0x" << std::setw (8) << tmp.size << std::dec
857                      << std::setfill (' ') << std::endl;
858
859          }
860        }
861      }
862    }
863
864    if (show_strings)
865    {
866      std::cout << "  Strings: 0x"
867                << std::hex << std::setfill ('0')
868                << std::setw (8) << r.strtab_rap_off
869                << std::setfill (' ') << std::dec
870                << " (" << r.strtab_rap_off << ')'
871                << " size: " << r.strtab_size
872                << std::endl;
873      if (r.strtab_size)
874      {
875        uint32_t offset = 0;
876        int count = 0;
877        while (offset < r.strtab_size)
878        {
879          std::cout << std::setw (16) << count++
880                    << std::hex << std::setfill ('0')
881                    << " (0x" << std::setw (6) << offset << "): "
882                    << std::dec << std::setfill (' ')
883                    << (char*) &r.strtab[offset] << std::endl;
884          offset += ::strlen ((char*) &r.strtab[offset]) + 1;
885        }
886      }
887      else
888      {
889        std::cout << std::setw (16) << " "
890                  << "No string table found." << std::endl;
891      }
892    }
893
894    if (show_symbols)
895    {
896      std::cout << "  Symbols: 0x"
897                << std::hex << std::setfill ('0')
898                << std::setw (8) << r.symtab_rap_off
899                << std::setfill (' ') << std::dec
900                << " (" << r.symtab_rap_off << ')'
901                << " size: " << r.symtab_size
902                << std::endl;
903      if (r.symtab_size)
904      {
905        std::cout << std::setw (18) << "  "
906                  << "  data section  value      name" << std::endl;
907        for (int s = 0; s < r.symbols (); ++s)
908        {
909          uint32_t data;
910          uint32_t name;
911          uint32_t value;
912          r.symbol (s, data, name, value);
913          std::cout << std::setw (16) << s << ": "
914                    << std::hex << std::setfill ('0')
915                    << "0x" << std::setw (4) << (data & 0xffff)
916                    << std::dec << std::setfill (' ')
917                    << " " << std::setw (8) << rld::rap::section_name (data >> 16)
918                    << std::hex << std::setfill ('0')
919                    << " 0x" << std::setw(8) << value
920                    << " " << &r.strtab[name]
921                    << std::dec << std::setfill (' ')
922                    << std::endl;
923        }
924      }
925      else
926      {
927        std::cout << std::setw (16) << " "
928                  << "No symbol table found." << std::endl;
929      }
930    }
931
932    if (show_relocs)
933    {
934      std::cout << "  Relocations: 0x"
935                << std::hex << std::setfill ('0')
936                << std::setw (8) << r.relocs_rap_off
937                << std::setfill (' ') << std::dec
938                << " (" << r.relocs_rap_off << ')' << std::endl;
939      int count = 0;
940      for (int s = 0; s < rld::rap::rap_secs; ++s)
941      {
942        if (r.secs[s].relocs.size ())
943        {
944          const char* rela = r.secs[s].rela ? "(A)" : "   ";
945          std::cout << std::setw (16) << r.secs[s].name
946                    << ": info       offset     addend "
947                    << rela
948                    << " symbol name" << std::endl;
949          for (size_t f = 0; f < r.secs[s].relocs.size (); ++f)
950          {
951            rap::relocation& reloc = r.secs[s].relocs[f];
952            std::cout << std::setw (16) << count++ << ": ";
953            reloc.output ();
954            std::cout << std::endl;
955          }
956        }
957      }
958    }
959  }
960}
961
962void
963rap_overlay (rld::path::paths& raps, bool warnings)
964{
965  std::cout << "Overlay .... " << std::endl;
966  for (rld::path::paths::iterator pi = raps.begin();
967       pi != raps.end();
968       ++pi)
969  {
970    rap::file r (*pi, warnings);
971    std::cout << r.name () << std::endl;
972
973    r.load ();
974
975    for (int s = 0; s < rld::rap::rap_secs; ++s)
976    {
977      rap::section& sec = r.secs[s];
978
979      if (sec.size && sec.data)
980      {
981        std::cout << rld::rap::section_name (s) << ':' << std::endl;
982
983        size_t   line_length = 16;
984        uint32_t offset = 0;
985        size_t   reloc = 0;
986
987        while (offset < sec.size)
988        {
989          size_t length = sec.size - offset;
990
991          if (reloc < sec.relocs.size ())
992            length = sec.relocs[reloc].offset - offset;
993
994          if ((offset + length) < sec.size)
995          {
996            length += line_length;
997            length -= length % line_length;
998          }
999
1000          rtems::utils::dump (sec.data + offset,
1001                              length,
1002                              sizeof (uint8_t),
1003                              false,
1004                              line_length,
1005                              offset);
1006
1007          const int          indent = 8;
1008          std::ostringstream line;
1009
1010          line << std::setw (indent) << ' ';
1011
1012          while ((reloc < sec.relocs.size ()) &&
1013                 (sec.relocs[reloc].offset >= offset) &&
1014                 (sec.relocs[reloc].offset < (offset + length)))
1015          {
1016            int spaces = ((((sec.relocs[reloc].offset + 1) % line_length) * 3) +
1017                          indent - 1);
1018
1019            spaces -= line.str ().size ();
1020
1021            line << std::setw (spaces) << " ^" << reloc
1022                 << ':' << std::hex
1023                 << sec.relocs[reloc].addend
1024                 << std::dec;
1025
1026            ++reloc;
1027          }
1028
1029          std::cout << line.str () << std::endl;
1030
1031          offset += length;
1032        }
1033
1034        if (sec.relocs.size ())
1035        {
1036          int count = 0;
1037          std::cout << "     info       offset     addend     symbol name" << std::endl;
1038          for (size_t f = 0; f < r.secs[s].relocs.size (); ++f)
1039          {
1040            rap::relocation& reloc = r.secs[s].relocs[f];
1041            std::cout << std::setw (4) << count++ << ' ';
1042            reloc.output ();
1043            std::cout << std::endl;
1044          }
1045        }
1046
1047      }
1048    }
1049  }
1050}
1051
1052void
1053rap_expander (rld::path::paths& raps, bool warnings)
1054{
1055  std::cout << "Expanding .... " << std::endl;
1056  for (rld::path::paths::iterator pi = raps.begin();
1057       pi != raps.end();
1058       ++pi)
1059  {
1060    rap::file r (*pi, warnings);
1061    std::cout << ' ' << r.name () << std::endl;
1062    r.expand ();
1063  }
1064}
1065
1066/**
1067 * RTEMS RAP options.
1068 */
1069static struct option rld_opts[] = {
1070  { "help",        no_argument,            NULL,           'h' },
1071  { "version",     no_argument,            NULL,           'V' },
1072  { "verbose",     no_argument,            NULL,           'v' },
1073  { "no-warn",     no_argument,            NULL,           'n' },
1074  { "all",         no_argument,            NULL,           'a' },
1075  { "header",      no_argument,            NULL,           'H' },
1076  { "machine",     no_argument,            NULL,           'm' },
1077  { "layout",      no_argument,            NULL,           'l' },
1078  { "strings",     no_argument,            NULL,           's' },
1079  { "symbols",     no_argument,            NULL,           'S' },
1080  { "relocs",      no_argument,            NULL,           'r' },
1081  { "overlay",     no_argument,            NULL,           'o' },
1082  { "expand",      no_argument,            NULL,           'x' },
1083  { NULL,          0,                      NULL,            0 }
1084};
1085
1086void
1087usage (int exit_code)
1088{
1089  std::cout << "rtems-rap [options] objects" << std::endl
1090            << "Options and arguments:" << std::endl
1091            << " -h        : help (also --help)" << std::endl
1092            << " -V        : print linker version number and exit (also --version)" << std::endl
1093            << " -v        : verbose (trace import parts), can supply multiple times" << std::endl
1094            << "             to increase verbosity (also --verbose)" << std::endl
1095            << " -n        : no warnings (also --no-warn)" << std::endl
1096            << " -a        : show all (also --all)" << std::endl
1097            << " -H        : show header (also --header)" << std::endl
1098            << " -m        : show machine details (also --machine)" << std::endl
1099            << " -l        : show layout (also --layout)" << std::endl
1100            << " -s        : show strings (also --strings)" << std::endl
1101            << " -S        : show symbols (also --symbols)" << std::endl
1102            << " -r        : show relocations (also --relocs)" << std::endl
1103            << " -o        : linkage overlay (also --overlay)" << std::endl
1104            << " -x        : expand (also --expand)" << std::endl
1105            << " -f        : show file details" << std::endl;
1106  ::exit (exit_code);
1107}
1108
1109static void
1110fatal_signal (int signum)
1111{
1112  signal (signum, SIG_DFL);
1113
1114  rld::process::temporaries_clean_up ();
1115
1116  /*
1117   * Get the same signal again, this time not handled, so its normal effect
1118   * occurs.
1119   */
1120  kill (getpid (), signum);
1121}
1122
1123static void
1124setup_signals (void)
1125{
1126  if (signal (SIGINT, SIG_IGN) != SIG_IGN)
1127    signal (SIGINT, fatal_signal);
1128#ifdef SIGHUP
1129  if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
1130    signal (SIGHUP, fatal_signal);
1131#endif
1132  if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
1133    signal (SIGTERM, fatal_signal);
1134#ifdef SIGPIPE
1135  if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
1136    signal (SIGPIPE, fatal_signal);
1137#endif
1138#ifdef SIGCHLD
1139  signal (SIGCHLD, SIG_DFL);
1140#endif
1141}
1142
1143int
1144main (int argc, char* argv[])
1145{
1146  int ec = 0;
1147
1148  setup_signals ();
1149
1150  try
1151  {
1152    rld::path::paths raps;
1153    bool             warnings = true;
1154    bool             show = false;
1155    bool             show_header = false;
1156    bool             show_machine = false;
1157    bool             show_layout = false;
1158    bool             show_strings = false;
1159    bool             show_symbols = false;
1160    bool             show_relocs = false;
1161    bool             show_details = false;
1162    bool             overlay = false;
1163    bool             expand = false;
1164
1165    while (true)
1166    {
1167      int opt = ::getopt_long (argc, argv, "hvVnaHmlsSroxf", rld_opts, NULL);
1168      if (opt < 0)
1169        break;
1170
1171      switch (opt)
1172      {
1173        case 'V':
1174          std::cout << "rtems-rap (RTEMS RAP Manager) " << rld::version ()
1175                    << std::endl;
1176          ::exit (0);
1177          break;
1178
1179        case 'v':
1180          rld::verbose_inc ();
1181          break;
1182
1183        case 'n':
1184          warnings = false;
1185          break;
1186
1187        case 'a':
1188          show = true;
1189          show_header = true;
1190          show_machine = true;
1191          show_layout = true;
1192          show_strings = true;
1193          show_symbols = true;
1194          show_relocs = true;
1195          show_details = true;
1196          break;
1197
1198        case 'H':
1199          show = true;
1200          show_header = true;
1201          break;
1202
1203        case 'm':
1204          show = true;
1205          show_machine = true;
1206          break;
1207
1208        case 'l':
1209          show = true;
1210          show_layout = true;
1211          break;
1212
1213        case 's':
1214          show = true;
1215          show_strings = true;
1216          break;
1217
1218        case 'S':
1219          show = true;
1220          show_symbols = true;
1221          break;
1222
1223        case 'r':
1224          show = true;
1225          show_relocs = true;
1226          break;
1227
1228        case 'o':
1229          overlay = true;
1230          break;
1231
1232        case 'x':
1233          expand = true;
1234          break;
1235
1236        case 'f':
1237          show_details = true;
1238          break;
1239
1240        case '?':
1241        case 'h':
1242          usage (0);
1243          break;
1244      }
1245    }
1246
1247    argc -= optind;
1248    argv += optind;
1249
1250    std::cout << "RTEMS RAP " << rld::version () << std::endl << std::endl;
1251
1252    /*
1253     * If there are no RAP files so there is nothing to do.
1254     */
1255    if (argc == 0)
1256      throw rld::error ("no RAP files", "options");
1257
1258    /*
1259     * Load the remaining command line arguments into a container.
1260     */
1261    while (argc--)
1262      raps.push_back (*argv++);
1263
1264    if (show)
1265      rap_show (raps,
1266                warnings,
1267                show_header,
1268                show_machine,
1269                show_layout,
1270                show_strings,
1271                show_symbols,
1272                show_relocs,
1273                show_details);
1274
1275    if (overlay)
1276      rap_overlay (raps, warnings);
1277
1278    if (expand)
1279      rap_expander (raps, warnings);
1280  }
1281  catch (rld::error re)
1282  {
1283    std::cerr << "error: "
1284              << re.where << ": " << re.what
1285              << std::endl;
1286    ec = 10;
1287  }
1288  catch (std::exception e)
1289  {
1290    int   status;
1291    char* realname;
1292    realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
1293    std::cerr << "error: exception: " << realname << " [";
1294    ::free (realname);
1295    const std::type_info &ti = typeid (e);
1296    realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
1297    std::cerr << realname << "] " << e.what () << std::endl;
1298    ::free (realname);
1299    ec = 11;
1300  }
1301  catch (...)
1302  {
1303    /*
1304     * Helps to know if this happens.
1305     */
1306    std::cout << "error: unhandled exception" << std::endl;
1307    ec = 12;
1308  }
1309
1310  return ec;
1311}
Note: See TracBrowser for help on using the repository browser.