summaryrefslogtreecommitdiff
path: root/linkers/rtems-rapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linkers/rtems-rapper.cpp')
-rw-r--r--linkers/rtems-rapper.cpp1311
1 files changed, 1311 insertions, 0 deletions
diff --git a/linkers/rtems-rapper.cpp b/linkers/rtems-rapper.cpp
new file mode 100644
index 0000000..2e3d2cf
--- /dev/null
+++ b/linkers/rtems-rapper.cpp
@@ -0,0 +1,1311 @@
+/*
+ * Copyright (c) 2012, Chris Johns <chrisj@rtems.org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rld
+ *
+ * @brief RTEMS RAP Manager lets you look at and play with RAP files.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <algorithm>
+#include <iomanip>
+#include <iostream>
+#include <vector>
+
+#include <cxxabi.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <getopt.h>
+
+#include <rld.h>
+#include <rld-compression.h>
+#include <rld-files.h>
+#include <rld-process.h>
+#include <rld-rap.h>
+
+#include <rtems-utils.h>
+
+#ifndef HAVE_KILL
+#define kill(p,s) raise(s)
+#endif
+
+/**
+ * RTEMS Application.
+ */
+namespace rap
+{
+ /**
+ * The names of the RAP sections.
+ */
+ static const char* section_names[6] =
+ {
+ ".text",
+ ".const",
+ ".ctor",
+ ".dtor",
+ ".data",
+ ".bss"
+ };
+
+ /**
+ * A relocation record.
+ */
+ struct relocation
+ {
+ uint32_t info;
+ uint32_t offset;
+ uint32_t addend;
+ std::string symname;
+ off_t rap_off;
+
+ relocation ();
+
+ void output ();
+ };
+
+ typedef std::vector < relocation > relocations;
+
+ /**
+ * Relocation offset sorter for the relocations container.
+ */
+ class reloc_offset_compare
+ {
+ public:
+ bool operator () (const relocation& lhs,
+ const relocation& rhs) const {
+ return lhs.offset < rhs.offset;
+ }
+ };
+
+ /**
+ * A RAP section.
+ */
+ struct section
+ {
+ std::string name;
+ uint32_t size;
+ uint32_t alignment;
+ uint8_t* data;
+ uint32_t relocs_size;
+ relocations relocs;
+ bool rela;
+ off_t rap_off;
+
+ section ();
+ ~section ();
+
+ void load_data (rld::compress::compressor& comp);
+ void load_relocs (rld::compress::compressor& comp);
+ };
+
+ /**
+ * Section detail
+ */
+ struct section_detail
+ {
+ uint32_t name; //< The offset in the strtable.
+ uint32_t offset; //< The offset in the rap section.
+ uint32_t id; //< The rap id.
+ uint32_t size; //< The size of the elf section.
+ uint32_t obj; //< The obj id.
+
+ /* Constructor */
+ section_detail (const section_detail& s);
+ section_detail ();
+ };
+
+ section_detail::section_detail (const section_detail& s)
+ : name (s.name),
+ offset (s.offset),
+ id (s.id),
+ size (s.size),
+ obj (s.obj)
+ {
+ }
+
+ section_detail::section_detail ()
+ : name (0),
+ offset (0),
+ id (0),
+ size (0),
+ obj (0)
+ {
+ }
+
+ /**
+ * A container of section_detail
+ */
+ typedef std::list < section_detail > section_details;
+
+ /**
+ * A RAP file.
+ */
+ struct file
+ {
+ enum {
+ rap_comp_buffer = 2 * 1024
+ };
+
+ std::string header;
+ size_t rhdr_len;
+ uint32_t rhdr_length;
+ uint32_t rhdr_version;
+ std::string rhdr_compression;
+ uint32_t rhdr_checksum;
+
+ off_t machine_rap_off;
+ uint32_t machinetype;
+ uint32_t datatype;
+ uint32_t class_;
+
+ off_t layout_rap_off;
+ std::string init;
+ uint32_t init_off;
+ std::string fini;
+ uint32_t fini_off;
+
+ off_t strtab_rap_off;
+ uint32_t strtab_size;
+ uint8_t* strtab;
+
+ off_t symtab_rap_off;
+ uint32_t symtab_size;
+ uint8_t* symtab;
+
+ off_t relocs_rap_off;
+ uint32_t relocs_size; /* not used */
+
+ off_t detail_rap_off;
+ uint32_t obj_num;
+ uint8_t** obj_name;
+ uint32_t* sec_num;
+ uint8_t* rpath;
+ uint32_t rpathlen;
+ uint8_t* str_detail;
+ section_details sec_details;
+
+ section secs[rld::rap::rap_secs];
+
+ /**
+ * Open a RAP file and read the header.
+ */
+ file (const std::string& name, bool warnings);
+
+ /**
+ * Close the RAP file.
+ */
+ ~file ();
+
+ /**
+ * Parse header.
+ */
+ void parse_header ();
+
+ /**
+ * Load the file.
+ */
+ void load ();
+
+ /**
+ * Expand the image.
+ */
+ void expand ();
+
+ /**
+ * Load details.
+ */
+ void load_details(rld::compress::compressor& comp);
+
+ /**
+ * The name.
+ */
+ const std::string name () const;
+
+ /**
+ * The number of symbols in the symbol table.
+ */
+ int symbols () const;
+
+ /**
+ * Return a symbol given an index.
+ */
+ void symbol (int index,
+ uint32_t& data,
+ uint32_t& name,
+ uint32_t& value) const;
+
+ /**
+ * Return the string from the string table.
+ */
+ const char* string (int index);
+
+ private:
+
+ bool warnings;
+ rld::files::image image;
+ };
+
+ template < typename T > T
+ get_value (const uint8_t* data)
+ {
+ T v = 0;
+ for (size_t b = 0; b < sizeof (T); ++b)
+ {
+ v <<= 8;
+ v |= (T) data[b];
+ }
+ return v;
+ }
+
+ relocation::relocation ()
+ : info (0),
+ offset (0),
+ addend (0),
+ rap_off (0)
+ {
+ }
+
+ void
+ relocation::output ()
+ {
+ std::cout << std::hex << std::setfill ('0')
+ << "0x" << std::setw (8) << info
+ << " 0x" << std::setw (8) << offset
+ << " 0x" << std::setw(8) << addend
+ << std::dec << std::setfill (' ')
+ << " " << symname;
+ }
+
+ section::section ()
+ : size (0),
+ alignment (0),
+ data (0),
+ relocs_size (0),
+ relocs (0),
+ rela (false),
+ rap_off (0)
+ {
+ }
+
+ section::~section ()
+ {
+ if (data)
+ delete [] data;
+ }
+
+ void
+ section::load_data (rld::compress::compressor& comp)
+ {
+ rap_off = comp.offset ();
+ if (size)
+ {
+ data = new uint8_t[size];
+ if (comp.read (data, size) != size)
+ throw rld::error ("Reading section data failed", "rapper");
+ }
+ }
+
+ void
+ section::load_relocs (rld::compress::compressor& comp)
+ {
+ uint32_t header;
+ comp >> header;
+
+ rela = header & RAP_RELOC_RELA ? true : false;
+ relocs_size = header & ~RAP_RELOC_RELA;
+
+ if (relocs_size)
+ {
+ for (uint32_t r = 0; r < relocs_size; ++r)
+ {
+ relocation reloc;
+
+ reloc.rap_off = comp.offset ();
+
+ comp >> reloc.info
+ >> reloc.offset;
+
+ if (((reloc.info & RAP_RELOC_STRING) == 0) || rela)
+ comp >> reloc.addend;
+
+ if ((reloc.info & RAP_RELOC_STRING) != 0)
+ {
+ if ((reloc.info & RAP_RELOC_STRING_EMBED) == 0)
+ {
+ size_t symname_size = (reloc.info & ~(3 << 30)) >> 8;
+ reloc.symname.resize (symname_size);
+ size_t symname_read = comp.read ((void*) reloc.symname.c_str (), symname_size);
+ if (symname_read != symname_size)
+ throw rld::error ("Reading reloc symbol name failed", "rapper");
+ }
+ }
+
+ relocs.push_back (reloc);
+ }
+
+ std::stable_sort (relocs.begin (), relocs.end (), reloc_offset_compare ());
+ }
+ }
+
+ file::file (const std::string& name, bool warnings)
+ : rhdr_len (0),
+ rhdr_length (0),
+ rhdr_version (0),
+ rhdr_checksum (0),
+ machine_rap_off (0),
+ machinetype (0),
+ datatype (0),
+ class_ (0),
+ layout_rap_off (0),
+ init_off (0),
+ fini_off (0),
+ strtab_rap_off (0),
+ strtab_size (0),
+ strtab (0),
+ symtab_rap_off (0),
+ symtab_size (0),
+ symtab (0),
+ relocs_rap_off (0),
+ relocs_size (0),
+ detail_rap_off (0),
+ obj_num (0),
+ obj_name (0),
+ sec_num (0),
+ rpath (0),
+ rpathlen (0),
+ str_detail (0),
+ warnings (warnings),
+ image (name)
+ {
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ secs[s].name = rld::rap::section_name (s);
+ image.open ();
+ parse_header ();
+ }
+
+ file::~file ()
+ {
+ image.close ();
+
+ if (symtab)
+ delete [] symtab;
+ if (strtab)
+ delete [] strtab;
+ if (obj_name)
+ delete [] obj_name;
+ if (sec_num)
+ delete [] sec_num;
+ if (str_detail)
+ delete [] str_detail;
+
+ }
+
+ void
+ file::parse_header ()
+ {
+ std::string name = image.name ().full ();
+
+ char rhdr[64];
+
+ image.seek_read (0, (uint8_t*) rhdr, 64);
+
+ if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
+ throw rld::error ("Invalid RAP file", "open: " + name);
+
+ char* sptr = rhdr + 4;
+ char* eptr;
+
+ rhdr_length = ::strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ throw rld::error ("Cannot parse RAP header", "open: " + name);
+
+ sptr = eptr + 1;
+
+ rhdr_version = ::strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ throw rld::error ("Cannot parse RAP header", "open: " + name);
+
+ sptr = eptr + 1;
+
+ if ((sptr[0] == 'N') &&
+ (sptr[1] == 'O') &&
+ (sptr[2] == 'N') &&
+ (sptr[3] == 'E'))
+ {
+ rhdr_compression = "NONE";
+ eptr = sptr + 4;
+ }
+ else if ((sptr[0] == 'L') &&
+ (sptr[1] == 'Z') &&
+ (sptr[2] == '7') &&
+ (sptr[3] == '7'))
+ {
+ rhdr_compression = "LZ77";
+ eptr = sptr + 4;
+ }
+ else
+ throw rld::error ("Cannot parse RAP header", "open: " + name);
+
+ if (*eptr != ',')
+ throw rld::error ("Cannot parse RAP header", "open: " + name);
+
+ sptr = eptr + 1;
+
+ rhdr_checksum = ::strtoul (sptr, &eptr, 16);
+
+ if (*eptr != '\n')
+ throw rld::error ("Cannot parse RAP header", "open: " + name);
+
+ rhdr_len = eptr - rhdr + 1;
+
+ if (warnings && (rhdr_length != image.size ()))
+ std::cout << " warning: header length does not match file size: header="
+ << rhdr_length
+ << " file-size=" << image.size ()
+ << std::endl;
+
+ header.insert (0, rhdr, rhdr_len);
+
+ image.seek (rhdr_len);
+ }
+
+ void
+ file::load_details (rld::compress::compressor& comp)
+ {
+ uint32_t tmp;
+
+ comp >> rpathlen;
+
+ obj_name = new uint8_t*[obj_num];
+
+ sec_num = new uint32_t[obj_num];
+
+ /* how many sections of each object file */
+ for (uint32_t i = 0; i < obj_num; i++)
+ {
+ comp >> tmp;
+ sec_num[i] = tmp;
+ }
+
+ /* strtable size */
+ comp >> tmp;
+ str_detail = new uint8_t[tmp];
+ if (comp.read (str_detail, tmp) != tmp)
+ throw rld::error ("Reading file str details error", "rapper");
+
+ if (rpathlen > 0)
+ rpath = (uint8_t*)str_detail;
+ else rpath = NULL;
+
+ section_detail sec;
+
+ for (uint32_t i = 0; i < obj_num; i++)
+ {
+ sec.obj = i;
+ for (uint32_t j = 0; j < sec_num[i]; j++)
+ {
+ comp >> sec.name;
+ comp >> tmp;
+ sec.offset = tmp & 0xfffffff;
+ sec.id = tmp >> 28;
+ comp >> sec.size;
+
+ sec_details.push_back (section_detail (sec));
+ }
+ }
+ }
+ void
+ file::load ()
+ {
+ image.seek (rhdr_len);
+
+ rld::compress::compressor comp (image, rap_comp_buffer, false);
+
+ /*
+ * uint32_t: machinetype
+ * uint32_t: datatype
+ * uint32_t: class
+ */
+ machine_rap_off = comp.offset ();
+ comp >> machinetype
+ >> datatype
+ >> class_;
+
+ /*
+ * uint32_t: init
+ * uint32_t: fini
+ * uint32_t: symtab_size
+ * uint32_t: strtab_size
+ * uint32_t: relocs_size
+ */
+ layout_rap_off = comp.offset ();
+ comp >> init_off
+ >> fini_off
+ >> symtab_size
+ >> strtab_size
+ >> relocs_size;
+
+ /*
+ * Load the file details.
+ */
+ detail_rap_off = comp.offset ();
+
+ comp >> obj_num;
+
+ if (obj_num > 0)
+ load_details(comp);
+
+ /*
+ * uint32_t: text_size
+ * uint32_t: text_alignment
+ * uint32_t: const_size
+ * uint32_t: const_alignment
+ * uint32_t: ctor_size
+ * uint32_t: ctor_alignment
+ * uint32_t: dtor_size
+ * uint32_t: dtor_alignment
+ * uint32_t: data_size
+ * uint32_t: data_alignment
+ * uint32_t: bss_size
+ * uint32_t: bss_alignment
+ */
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ comp >> secs[s].size
+ >> secs[s].alignment;
+
+ /*
+ * Load sections.
+ */
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ if (s != rld::rap::rap_bss)
+ secs[s].load_data (comp);
+
+ /*
+ * Load the string table.
+ */
+ strtab_rap_off = comp.offset ();
+ if (strtab_size)
+ {
+ strtab = new uint8_t[strtab_size];
+ if (comp.read (strtab, strtab_size) != strtab_size)
+ throw rld::error ("Reading string table failed", "rapper");
+ }
+
+ /*
+ * Load the symbol table.
+ */
+ symtab_rap_off = comp.offset ();
+ if (symtab_size)
+ {
+ symtab = new uint8_t[symtab_size];
+ if (comp.read (symtab, symtab_size) != symtab_size)
+ throw rld::error ("Reading symbol table failed", "rapper");
+ }
+
+ /*
+ * Load the relocation tables.
+ */
+ relocs_rap_off = comp.offset ();
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ secs[s].load_relocs (comp);
+ }
+
+ void
+ file::expand ()
+ {
+ std::string name = image.name ().full ();
+ std::string extension = rld::files::extension (image.name ().full ());
+
+ name = name.substr (0, name.size () - extension.size ()) + ".xrap";
+
+ image.seek (rhdr_len);
+
+ rld::compress::compressor comp (image, rap_comp_buffer, false);
+ rld::files::image out (name);
+
+ out.open (true);
+ out.seek (0);
+ while (true)
+ {
+ if (comp.read (out, rap_comp_buffer) != rap_comp_buffer)
+ break;
+ }
+ out.close ();
+ }
+
+ const std::string
+ file::name () const
+ {
+ return image.name ().full ();
+ }
+
+ int
+ file::symbols () const
+ {
+ return symtab_size / (3 * sizeof (uint32_t));
+ }
+
+ void
+ file::symbol (int index, uint32_t& data, uint32_t& name, uint32_t& value) const
+ {
+ if (index < symbols ())
+ {
+ uint8_t* sym = symtab + (index * 3 * sizeof (uint32_t));
+ data = get_value < uint32_t > (sym);
+ name = get_value < uint32_t > (sym + (1 * sizeof (uint32_t)));
+ value = get_value < uint32_t > (symtab + (2 * sizeof (uint32_t)));
+ }
+ }
+
+ const char*
+ file::string (int index)
+ {
+ std::string name = image.name ().full ();
+
+ if (strtab_size == 0)
+ throw rld::error ("No string table", "string: " + name);
+
+ uint32_t offset = 0;
+ int count = 0;
+ while (offset < strtab_size)
+ {
+ if (count++ == index)
+ return (const char*) &strtab[offset];
+ offset = ::strlen ((const char*) &strtab[offset]) + 1;
+ }
+
+ throw rld::error ("Invalid string index", "string: " + name);
+ }
+}
+
+void
+rap_show (rld::files::paths& raps,
+ bool warnings,
+ bool show_header,
+ bool show_machine,
+ bool show_layout,
+ bool show_strings,
+ bool show_symbols,
+ bool show_relocs,
+ bool show_details)
+{
+ for (rld::files::paths::iterator pi = raps.begin();
+ pi != raps.end();
+ ++pi)
+ {
+ std::cout << *pi << ':' << std::endl;
+
+ rap::file r (*pi, warnings);
+
+ try
+ {
+ r.load ();
+ }
+ catch (rld::error re)
+ {
+ std::cout << " error: "
+ << re.where << ": " << re.what
+ << std::endl
+ << " warning: file read failed, some data may be corrupt or not present."
+ << std::endl;
+ }
+
+ if (show_header)
+ {
+ std::cout << " Header:" << std::endl
+ << " string: " << r.header
+ << " length: " << r.rhdr_len << std::endl
+ << " version: " << r.rhdr_version << std::endl
+ << " compression: " << r.rhdr_compression << std::endl
+ << std::hex << std::setfill ('0')
+ << " checksum: " << std::setw (8) << r.rhdr_checksum << std::endl
+ << std::dec << std::setfill(' ');
+ }
+
+ if (show_machine)
+ {
+ std::cout << " Machine: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.machine_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.machine_rap_off << ')' << std::endl
+ << " machinetype: "<< r.machinetype << std::endl
+ << " datatype: "<< r.datatype << std::endl
+ << " class: "<< r.class_ << std::endl;
+ }
+
+ if (show_layout)
+ {
+ std::cout << " Layout: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.layout_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.layout_rap_off << ')' << std::endl
+ << std::setw (18) << " "
+ << " size align offset " << std::endl;
+ uint32_t relocs_size = 0;
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ {
+ relocs_size += r.secs[s].relocs.size ();
+ std::cout << std::setw (16) << rld::rap::section_name (s)
+ << ": " << std::setw (6) << r.secs[s].size
+ << std::setw (7) << r.secs[s].alignment;
+ if (s != rld::rap::rap_bss)
+ std::cout << std::hex << std::setfill ('0')
+ << " 0x" << std::setw (8) << r.secs[s].rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.secs[s].rap_off << ')';
+ else
+ std::cout << " -";
+ std::cout << std::endl;
+ }
+ std::cout << std::setw (16) << "strtab" << ": "
+ << std::setw (6) << r.strtab_size
+ << std::setw (7) << '-'
+ << std::hex << std::setfill ('0')
+ << " 0x" << std::setw (8) << r.strtab_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.strtab_rap_off << ')' << std::endl
+ << std::setw (16) << "symtab" << ": "
+ << std::setw (6) << r.symtab_size
+ << std::setw (7) << '-'
+ << std::hex << std::setfill ('0')
+ << " 0x" << std::setw (8) << r.symtab_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.symtab_rap_off << ')' << std::endl
+ << std::setw (16) << "relocs" << ": "
+ << std::setw (6) << (relocs_size * 3 * sizeof (uint32_t))
+ << std::setw (7) << '-'
+ << std::hex << std::setfill ('0')
+ << " 0x" << std::setw (8) << r.relocs_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.relocs_rap_off << ')' << std::endl;
+ }
+
+ if (show_details)
+ {
+ std::cout << " Details: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.detail_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.detail_rap_off << ')' << std::endl;
+
+ uint32_t pos = 0;
+ if (r.rpath != NULL)
+ {
+ std::cout << " rpath:" << std::endl;
+ while (pos < r.rpathlen)
+ {
+ std::cout << " " << r.rpath + pos << std::endl;
+ pos = std::string ((char*)(r.rpath + pos)).length () + pos + 1;
+ }
+ }
+
+ if (r.obj_num == 0)
+ std::cout << " No details" << std::endl;
+ else
+ std::cout << ' ' << r.obj_num <<" Files" << std::endl;
+
+ for (uint32_t i = 0; i < r.obj_num; ++i)
+ {
+ r.obj_name[i] = (uint8_t*) &r.str_detail[pos];
+ pos += ::strlen ((char*) &r.str_detail[pos]) + 1;
+ }
+
+ for (uint32_t i = 0; i < r.obj_num; ++i)
+ {
+ std::cout << " File: " << r.obj_name[i] << std::endl;
+
+ for (rap::section_details::const_iterator sd = r.sec_details.begin ();
+ sd != r.sec_details.end ();
+ ++sd)
+ {
+ rap::section_detail tmp = *sd;
+ if (tmp.obj == i)
+ {
+ std::cout << std::setw (12) << "name:"
+ << std::setw (16) << (char*)&r.str_detail[tmp.name]
+ << " rap_section:"<< std::setw (8)
+ << rap::section_names[tmp.id]
+ << std::hex << std::setfill ('0')
+ << " offset:0x" << std::setw (8) << tmp.offset
+ << " size:0x" << std::setw (8) << tmp.size << std::dec
+ << std::setfill (' ') << std::endl;
+
+ }
+ }
+ }
+ }
+
+ if (show_strings)
+ {
+ std::cout << " Strings: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.strtab_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.strtab_rap_off << ')'
+ << " size: " << r.strtab_size
+ << std::endl;
+ if (r.strtab_size)
+ {
+ uint32_t offset = 0;
+ int count = 0;
+ while (offset < r.strtab_size)
+ {
+ std::cout << std::setw (16) << count++
+ << std::hex << std::setfill ('0')
+ << " (0x" << std::setw (6) << offset << "): "
+ << std::dec << std::setfill (' ')
+ << (char*) &r.strtab[offset] << std::endl;
+ offset += ::strlen ((char*) &r.strtab[offset]) + 1;
+ }
+ }
+ else
+ {
+ std::cout << std::setw (16) << " "
+ << "No string table found." << std::endl;
+ }
+ }
+
+ if (show_symbols)
+ {
+ std::cout << " Symbols: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.symtab_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.symtab_rap_off << ')'
+ << " size: " << r.symtab_size
+ << std::endl;
+ if (r.symtab_size)
+ {
+ std::cout << std::setw (18) << " "
+ << " data section value name" << std::endl;
+ for (int s = 0; s < r.symbols (); ++s)
+ {
+ uint32_t data;
+ uint32_t name;
+ uint32_t value;
+ r.symbol (s, data, name, value);
+ std::cout << std::setw (16) << s << ": "
+ << std::hex << std::setfill ('0')
+ << "0x" << std::setw (4) << (data & 0xffff)
+ << std::dec << std::setfill (' ')
+ << " " << std::setw (8) << rld::rap::section_name (data >> 16)
+ << std::hex << std::setfill ('0')
+ << " 0x" << std::setw(8) << value
+ << " " << &r.strtab[name]
+ << std::dec << std::setfill (' ')
+ << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << std::setw (16) << " "
+ << "No symbol table found." << std::endl;
+ }
+ }
+
+ if (show_relocs)
+ {
+ std::cout << " Relocations: 0x"
+ << std::hex << std::setfill ('0')
+ << std::setw (8) << r.relocs_rap_off
+ << std::setfill (' ') << std::dec
+ << " (" << r.relocs_rap_off << ')' << std::endl;
+ int count = 0;
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ {
+ if (r.secs[s].relocs.size ())
+ {
+ const char* rela = r.secs[s].rela ? "(A)" : " ";
+ std::cout << std::setw (16) << r.secs[s].name
+ << ": info offset addend "
+ << rela
+ << " symbol name" << std::endl;
+ for (size_t f = 0; f < r.secs[s].relocs.size (); ++f)
+ {
+ rap::relocation& reloc = r.secs[s].relocs[f];
+ std::cout << std::setw (16) << count++ << ": ";
+ reloc.output ();
+ std::cout << std::endl;
+ }
+ }
+ }
+ }
+ }
+}
+
+void
+rap_overlay (rld::files::paths& raps, bool warnings)
+{
+ std::cout << "Overlay .... " << std::endl;
+ for (rld::files::paths::iterator pi = raps.begin();
+ pi != raps.end();
+ ++pi)
+ {
+ rap::file r (*pi, warnings);
+ std::cout << r.name () << std::endl;
+
+ r.load ();
+
+ for (int s = 0; s < rld::rap::rap_secs; ++s)
+ {
+ rap::section& sec = r.secs[s];
+
+ if (sec.size && sec.data)
+ {
+ std::cout << rld::rap::section_name (s) << ':' << std::endl;
+
+ size_t line_length = 16;
+ uint32_t offset = 0;
+ size_t reloc = 0;
+
+ while (offset < sec.size)
+ {
+ size_t length = sec.size - offset;
+
+ if (reloc < sec.relocs.size ())
+ length = sec.relocs[reloc].offset - offset;
+
+ if ((offset + length) < sec.size)
+ {
+ length += line_length;
+ length -= length % line_length;
+ }
+
+ rtems::utils::dump (sec.data + offset,
+ length,
+ sizeof (uint8_t),
+ false,
+ line_length,
+ offset);
+
+ const int indent = 8;
+ std::ostringstream line;
+
+ line << std::setw (indent) << ' ';
+
+ while ((reloc < sec.relocs.size ()) &&
+ (sec.relocs[reloc].offset >= offset) &&
+ (sec.relocs[reloc].offset < (offset + length)))
+ {
+ int spaces = ((((sec.relocs[reloc].offset + 1) % line_length) * 3) +
+ indent - 1);
+
+ spaces -= line.str ().size ();
+
+ line << std::setw (spaces) << " ^" << reloc
+ << ':' << std::hex
+ << sec.relocs[reloc].addend
+ << std::dec;
+
+ ++reloc;
+ }
+
+ std::cout << line.str () << std::endl;
+
+ offset += length;
+ }
+
+ if (sec.relocs.size ())
+ {
+ int count = 0;
+ std::cout << " info offset addend symbol name" << std::endl;
+ for (size_t f = 0; f < r.secs[s].relocs.size (); ++f)
+ {
+ rap::relocation& reloc = r.secs[s].relocs[f];
+ std::cout << std::setw (4) << count++ << ' ';
+ reloc.output ();
+ std::cout << std::endl;
+ }
+ }
+
+ }
+ }
+ }
+}
+
+void
+rap_expander (rld::files::paths& raps, bool warnings)
+{
+ std::cout << "Expanding .... " << std::endl;
+ for (rld::files::paths::iterator pi = raps.begin();
+ pi != raps.end();
+ ++pi)
+ {
+ rap::file r (*pi, warnings);
+ std::cout << ' ' << r.name () << std::endl;
+ r.expand ();
+ }
+}
+
+/**
+ * RTEMS RAP options.
+ */
+static struct option rld_opts[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'V' },
+ { "verbose", no_argument, NULL, 'v' },
+ { "no-warn", no_argument, NULL, 'n' },
+ { "all", no_argument, NULL, 'a' },
+ { "header", no_argument, NULL, 'H' },
+ { "machine", no_argument, NULL, 'm' },
+ { "layout", no_argument, NULL, 'l' },
+ { "strings", no_argument, NULL, 's' },
+ { "symbols", no_argument, NULL, 'S' },
+ { "relocs", no_argument, NULL, 'r' },
+ { "overlay", no_argument, NULL, 'o' },
+ { "expand", no_argument, NULL, 'x' },
+ { NULL, 0, NULL, 0 }
+};
+
+void
+usage (int exit_code)
+{
+ std::cout << "rtems-rap [options] objects" << std::endl
+ << "Options and arguments:" << std::endl
+ << " -h : help (also --help)" << std::endl
+ << " -V : print linker version number and exit (also --version)" << std::endl
+ << " -v : verbose (trace import parts), can supply multiple times" << std::endl
+ << " to increase verbosity (also --verbose)" << std::endl
+ << " -n : no warnings (also --no-warn)" << std::endl
+ << " -a : show all (also --all)" << std::endl
+ << " -H : show header (also --header)" << std::endl
+ << " -m : show machine details (also --machine)" << std::endl
+ << " -l : show layout (also --layout)" << std::endl
+ << " -s : show strings (also --strings)" << std::endl
+ << " -S : show symbols (also --symbols)" << std::endl
+ << " -r : show relocations (also --relocs)" << std::endl
+ << " -o : linkage overlay (also --overlay)" << std::endl
+ << " -x : expand (also --expand)" << std::endl
+ << " -f : show file details" << std::endl;
+ ::exit (exit_code);
+}
+
+static void
+fatal_signal (int signum)
+{
+ signal (signum, SIG_DFL);
+
+ rld::process::temporaries_clean_up ();
+
+ /*
+ * Get the same signal again, this time not handled, so its normal effect
+ * occurs.
+ */
+ kill (getpid (), signum);
+}
+
+static void
+setup_signals (void)
+{
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN)
+ signal (SIGINT, fatal_signal);
+#ifdef SIGHUP
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN)
+ signal (SIGHUP, fatal_signal);
+#endif
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN)
+ signal (SIGTERM, fatal_signal);
+#ifdef SIGPIPE
+ if (signal (SIGPIPE, SIG_IGN) != SIG_IGN)
+ signal (SIGPIPE, fatal_signal);
+#endif
+#ifdef SIGCHLD
+ signal (SIGCHLD, SIG_DFL);
+#endif
+}
+
+int
+main (int argc, char* argv[])
+{
+ int ec = 0;
+
+ setup_signals ();
+
+ try
+ {
+ rld::files::paths raps;
+ bool warnings = true;
+ bool show = false;
+ bool show_header = false;
+ bool show_machine = false;
+ bool show_layout = false;
+ bool show_strings = false;
+ bool show_symbols = false;
+ bool show_relocs = false;
+ bool show_details = false;
+ bool overlay = false;
+ bool expand = false;
+
+ while (true)
+ {
+ int opt = ::getopt_long (argc, argv, "hvVnaHlsSroxf", rld_opts, NULL);
+ if (opt < 0)
+ break;
+
+ switch (opt)
+ {
+ case 'V':
+ std::cout << "rtems-rap (RTEMS RAP Manager) " << rld::version ()
+ << std::endl;
+ ::exit (0);
+ break;
+
+ case 'v':
+ rld::verbose_inc ();
+ break;
+
+ case 'n':
+ warnings = false;
+ break;
+
+ case 'a':
+ show = true;
+ show_header = true;
+ show_machine = true;
+ show_layout = true;
+ show_strings = true;
+ show_symbols = true;
+ show_relocs = true;
+ show_details = true;
+ break;
+
+ case 'H':
+ show = true;
+ show_header = true;
+ break;
+
+ case 'm':
+ show = true;
+ show_machine = true;
+ break;
+
+ case 'l':
+ show = true;
+ show_layout = true;
+ break;
+
+ case 's':
+ show = true;
+ show_strings = true;
+ break;
+
+ case 'S':
+ show = true;
+ show_symbols = true;
+ break;
+
+ case 'r':
+ show = true;
+ show_relocs = true;
+ break;
+
+ case 'o':
+ overlay = true;
+ break;
+
+ case 'x':
+ expand = true;
+ break;
+
+ case 'f':
+ show_details = true;
+ break;
+
+ case '?':
+ case 'h':
+ usage (0);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ std::cout << "RTEMS RAP " << rld::version () << std::endl << std::endl;
+
+ /*
+ * If there are no RAP files so there is nothing to do.
+ */
+ if (argc == 0)
+ throw rld::error ("no RAP files", "options");
+
+ /*
+ * Load the remaining command line arguments into a container.
+ */
+ while (argc--)
+ raps.push_back (*argv++);
+
+ if (show)
+ rap_show (raps,
+ warnings,
+ show_header,
+ show_machine,
+ show_layout,
+ show_strings,
+ show_symbols,
+ show_relocs,
+ show_details);
+
+ if (overlay)
+ rap_overlay (raps, warnings);
+
+ if (expand)
+ rap_expander (raps, warnings);
+ }
+ catch (rld::error re)
+ {
+ std::cerr << "error: "
+ << re.where << ": " << re.what
+ << std::endl;
+ ec = 10;
+ }
+ catch (std::exception e)
+ {
+ int status;
+ char* realname;
+ realname = abi::__cxa_demangle (e.what(), 0, 0, &status);
+ std::cerr << "error: exception: " << realname << " [";
+ ::free (realname);
+ const std::type_info &ti = typeid (e);
+ realname = abi::__cxa_demangle (ti.name(), 0, 0, &status);
+ std::cerr << realname << "] " << e.what () << std::endl;
+ ::free (realname);
+ ec = 11;
+ }
+ catch (...)
+ {
+ /*
+ * Helps to know if this happens.
+ */
+ std::cout << "error: unhandled exception" << std::endl;
+ ec = 12;
+ }
+
+ return ec;
+}