diff options
Diffstat (limited to 'linkers/rtems-rapper.cpp')
-rw-r--r-- | linkers/rtems-rapper.cpp | 1311 |
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; +} |