/* * Copyright (c) 2012, Chris Johns * * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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::path::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::path::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::path::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::path::paths& raps, bool warnings) { std::cout << "Overlay .... " << std::endl; for (rld::path::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::path::paths& raps, bool warnings) { std::cout << "Expanding .... " << std::endl; for (rld::path::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::path::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, "hvVnaHmlsSroxf", 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; }