diff options
Diffstat (limited to 'linkers/rld-rap.cpp')
-rw-r--r-- | linkers/rld-rap.cpp | 1668 |
1 files changed, 0 insertions, 1668 deletions
diff --git a/linkers/rld-rap.cpp b/linkers/rld-rap.cpp deleted file mode 100644 index 9b87279..0000000 --- a/linkers/rld-rap.cpp +++ /dev/null @@ -1,1668 +0,0 @@ -/* - * 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_ld - * - * @brief RTEMS Linker. - * - * @todo Set the RAP alignment as the max of all alignments. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include <string.h> - -#include <algorithm> -#include <list> -#include <iomanip> - -#include <rld.h> -#include <rld-compression.h> -#include <rld-rap.h> - -namespace rld -{ - namespace rap - { - - /** - * Output details or not. - */ - bool add_obj_details = true; - - /** - * Store the path of object files. - */ - std::string rpath; - - /** - * The names of the RAP sections. - */ - static const char* section_names[rap_secs] = - { - ".text", - ".const", - ".ctor", - ".dtor", - ".data", - ".bss" - }; - - /** - * RAP relocation record. This one does not have const fields. - */ - struct relocation - { - uint32_t offset; //< The offset in the section to apply the fixup. - uint32_t info; //< The ELF info record. - uint32_t addend; //< The ELF constant addend. - std::string symname; //< The symbol name if there is one. - uint32_t symtype; //< The type of symbol. - int symsect; //< The symbol's RAP section. - uint32_t symvalue; //< The symbol's default value. - uint32_t symbinding;//< The symbol's binding. - - /** - * Construct the relocation using the file relocation, the offset of the - * section in the target RAP section and the RAP section of the symbol. - */ - relocation (const files::relocation& reloc, const uint32_t offset); - }; - - /** - * Relocation records. - */ - typedef std::vector < relocation > relocations; - - /** - * Relocation symname sorter for the relocations container. - */ - class reloc_symname_compare - { - public: - bool operator () (const relocation& lhs, - const relocation& rhs) const { - return lhs.symname < rhs.symname; - } - }; - - /** - * Relocation offset sorter for the relocations container. - */ - class reloc_offset_compare - { - public: - bool operator () (const relocation& lhs, - const relocation& rhs) const { - if (lhs.symname == rhs.symname) - return lhs.offset < rhs.offset; - else return false; - } - }; - - /** - * An object section's offset, size and alignment. - */ - struct osection - { - std::string name; //< The name of the section. - uint32_t offset; //< The offset in the object file. - uint32_t size; //< The size of this section. - uint32_t align; //< The alignment. - uint32_t relocs; //< The number of relocations. - uint64_t flags; //< The flags. - - /** - * Construct the object section. - */ - osection (const std::string& name, - uint32_t offset, - uint32_t size, - uint32_t align, - uint32_t relocs, - uint64_t flags); - - /** - * Default constructor. - */ - osection (); - }; - - /** - * Map of object file section offsets keyed by the object file section - * index. This is used when adding the external symbols so the symbol's - * value can be adjusted by the offset of the section in the RAP section. - */ - typedef std::map < int, osection > osections; - - /** - * An ordered container of object section indexes. We need the same - * order so the alignments match up with the layout. - */ - typedef std::vector < int > osecindexes; - - /** - * Section detail will be written into RAP file - */ - 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 section. - - /* Constructor */ - section_detail (uint32_t name, uint32_t offset, uint32_t id, uint32_t size); - }; - - /* - * A container of section detail - */ - typedef std::list < section_detail > section_details; - - /** - * The RAP section data. - */ - struct section - { - std::string name; //< The name of the section. - uint32_t offset; //< The offset of the section. - bool rela; //< The relocation record has an addend field. - relocations relocs; //< The relocations for this section. - osections osecs; //< The object section index. - osecindexes osindexes; //< The object section indexes in order. - - /** - * Default constructor. - */ - section (); - - /** - * Clear the section. - */ - void clear (); - - /** - * The size of the section given the offset. - */ - uint32_t size (uint32_t offset = 0) const; - - /** - * The alignment of the first section. - */ - uint32_t alignment () const; - - /** - * The alignment of the object section given its index. - */ - uint32_t alignment (int index) const; - - /** - * Set the offset of this section based on the previous section. - */ - void set_offset (const section& sec); - - /** - * Return the object section given the index. - */ - const osection& get_osection (int index) const; - - /** - * Output helper function to report the sections in an object file. This - * is useful when seeing the flags in the sections. - */ - void output (); - }; - - /** - * A symbol. This matches the symbol structure 'rtems_rtl_obj_sym_t' in the - * target code. - */ - struct external - { - /** - * Size of an external in the RAP file. - */ - static const uint32_t rap_size = sizeof (uint32_t) * 3; - - const uint32_t name; //< The string table's name index. - const sections sec; //< The section the symbols belongs to. - const uint32_t value; //< The offset from the section base. - const uint32_t data; //< The ELF st.info field. - - /** - * The constructor. - */ - external (const uint32_t name, - const sections sec, - const uint32_t value, - const uint32_t data); - - /** - * Copy constructor. - */ - external (const external& orig); - - }; - - /** - * A container of externals. - */ - typedef std::list < external > externals; - - /** - * The specific data for each object we need to collect to create the RAP - * format file. - */ - struct object - { - files::object& obj; //< The object file. - files::sections text; //< All executable code. - files::sections const_; //< All read only data. - files::sections ctor; //< The static constructor table. - files::sections dtor; //< The static destructor table. - files::sections data; //< All initialised read/write data. - files::sections bss; //< All uninitialised read/write data - files::sections symtab; //< All exported symbols. - files::sections strtab; //< All exported strings. - section secs[rap_secs]; //< The sections of interest. - - /** - * The constructor. Need to have an object file to create. - */ - object (files::object& obj); - - /** - * The copy constructor. - */ - object (const object& orig); - - /** - * Find the section type that matches the section index. - */ - sections find (const uint32_t index) const; - - /** - * The total number of relocations in the object file. - */ - uint32_t get_relocations () const; - - /** - * The total number of relocations for a specific RAP section in the - * object file. - */ - uint32_t get_relocations (int sec) const; - - /** - * Output the object file details.. - */ - void output (); - - private: - /** - * No default constructor allowed. - */ - object (); - }; - - /** - * A container of objects. - */ - typedef std::list < object > objects; - - /** - * The RAP image. - */ - class image - { - public: - /** - * Construct the image. - */ - image (); - - /** - * Load the layout data from the object files. - * - * @param app_objects The object files in the application. - * @param init The initialisation entry point label. - * @param fini The finish entry point label. - */ - void layout (const files::object_list& app_objects, - const std::string& init, - const std::string& fini); - - /** - * Collection the symbols from the object file. - * - * @param obj The object file to collection the symbol from. - */ - void collect_symbols (object& obj); - - /** - * Write the compressed output file. This is the top level write - * interface. - * - * @param comp The compressor. - */ - void write (compress::compressor& comp); - - /** - * Write the RAP section to the compressed output file given the object files. - * Check to make sure the size in the layout and the size written match. - * - * @param comp The compressor. - * @param sec The RAP setion to write. - */ - void write (compress::compressor& comp, sections sec); - - /** - * Write the sections to the compressed output file. The file sections - * are used to ensure the alignment. The offset is used to ensure the - * alignment of the first section of the object when it is written. - * - * @param comp The compressor. - * @param obj The object file the sections are part of. - * @param secs The container of file sections to write. - * @param offset The current offset in the RAP section. - */ - void write (compress::compressor& comp, - files::object& obj, - const files::sections& secs, - uint32_t& offset); - - /** - * Write the external symbols. - */ - void write_externals (compress::compressor& comp); - - /** - * Write the relocation records for all the object files. - */ - void write_relocations (compress::compressor& comp); - - /** - * Write the details of the files. - */ - void write_details (compress::compressor& comp); - - /** - * The total number of relocations for a specific RAP section in the - * image. - */ - uint32_t get_relocations (int sec) const; - - /** - * Clear the image values. - */ - void clear (); - - /** - * Report the RAP section's size. - */ - uint32_t section_size (sections sec) const; - - /** - * Find a symbol name in the string table. - */ - std::size_t find_in_strtab (const std::string& symname); - - private: - - objects objs; //< The RAP objects - uint32_t sec_size[rap_secs]; //< The sections of interest. - uint32_t sec_align[rap_secs]; //< The sections of interest. - bool sec_rela[rap_secs]; //< The sections of interest. - externals externs; //< The symbols in the image - uint32_t symtab_size; //< The size of the symbols. - std::string strtab; //< The strings table. - uint32_t relocs_size; //< The relocations size. - uint32_t init_off; //< The strtab offset to the init label. - uint32_t fini_off; //< The strtab offset to the fini label. - }; - - const char* - section_name (int sec) - { - if (sec < rap_secs) - return section_names[sec]; - throw rld::error ("Invalid section '" + rld::to_string (sec) + "'", - "rap::section-name"); - } - - /** - * Update the offset taking into account the alignment. - * - * @param offset The current offset. - * @param size The size to move the offset by. - * @param alignment The alignment of the offset. - * @return uint32_t The new aligned offset. - */ - uint32_t align_offset (uint32_t offset, uint32_t size, uint32_t alignment) - { - offset += size; - - if (alignment > 1) - { - uint32_t mask = alignment - 1; - if (offset & mask) - { - offset &= ~mask; - offset += alignment; - } - } - - return offset; - } - - relocation::relocation (const files::relocation& reloc, - const uint32_t offset) - : offset (reloc.offset + offset), - info (reloc.info), - addend (reloc.addend), - symname (reloc.symname), - symtype (reloc.symtype), - symsect (reloc.symsect), - symvalue (reloc.symvalue), - symbinding (reloc.symbinding) - { - } - - section_detail::section_detail (uint32_t name, - uint32_t offset, - uint32_t id, - uint32_t size) - : name (name), - offset (offset), - id (id), - size (size) - { - } - - osection::osection (const std::string& name, - uint32_t offset, - uint32_t size, - uint32_t align, - uint32_t relocs, - uint64_t flags) - : name (name), - offset (offset), - size (size), - align (align), - relocs (relocs), - flags (flags) - { - } - - osection::osection () - : offset (0), - size (0), - align (0), - relocs (0), - flags (0) - { - } - - section::section () - : offset (0), - rela (false) - { - } - - void - section::clear () - { - offset = 0; - rela = false; - } - - uint32_t - section::size (uint32_t offset_) const - { - uint32_t end = offset_; - if (end == 0) - end = offset; - for (size_t si = 0; si < osindexes.size (); ++si) - { - const osection& osec = get_osection (osindexes[si]); - end = align_offset (end, 0, osec.align); - end += osec.size; - } - return end - offset; - } - - uint32_t - section::alignment () const - { - if (!osindexes.empty ()) - { - const osection& osec = get_osection (osindexes[0]); - return osec.align; - } - return 0; - } - - uint32_t - section::alignment (int index) const - { - const osection& osec = get_osection (index); - return osec.align; - } - - void - section::set_offset (const section& sec) - { - uint32_t align = alignment (); - offset = align_offset (sec.offset, sec.size (), align); - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "rap:section::set-offset: " << name - << " offset=" << offset - << " size=" << size () - << " align=" << align - << " sec.offset=" << sec.offset - << " sec.size=" << sec.size (sec.offset) - << std::endl; - } - - const osection& - section::get_osection (int index) const - { - osections::const_iterator osi = osecs.find (index); - if (osi == osecs.end ()) - throw rld::error ("Invalid object seciton index in '" + name +"': index=" + - rld::to_string (index), - "rap::section"); - return (*osi).second; - } - - /** - * Output helper function to report the sections in an object file. This is - * useful when seeing the flags in the sections. - */ - void - section::output () - { - if (!osindexes.empty ()) - { - std::cout << ' ' << name - << ": size: " << size (offset) - << " offset: " << offset - << " rela: " << (rela ? "yes" : "no") - << std::endl; - - for (osecindexes::const_iterator osi = osindexes.begin (); - osi != osindexes.end (); - ++osi) - { - const osection& osec = get_osection (*osi); - - if (osec.size) - { - #define SF(f, i, c) if (osec.flags & (f)) flags[i] = c - - std::string flags ("--------------"); - - SF (SHF_WRITE, 0, 'W'); - SF (SHF_ALLOC, 1, 'A'); - SF (SHF_EXECINSTR, 2, 'E'); - SF (SHF_MERGE, 3, 'M'); - SF (SHF_STRINGS, 4, 'S'); - SF (SHF_INFO_LINK, 5, 'I'); - SF (SHF_LINK_ORDER, 6, 'L'); - SF (SHF_OS_NONCONFORMING, 7, 'N'); - SF (SHF_GROUP, 8, 'G'); - SF (SHF_TLS, 9, 'T'); - SF (SHF_AMD64_LARGE, 10, 'a'); - SF (SHF_ENTRYSECT, 11, 'e'); - SF (SHF_COMDEF, 12, 'c'); - SF (SHF_ORDERED, 13, 'O'); - - std::cout << " " << std::left - << std::setw (15) << osec.name - << " " << flags - << " size: " << std::setw (5) << osec.size - << " align: " << std::setw (3) << osec.align - << " relocs: " << std::setw (4) << osec.relocs - << " offset: " << std::setw (5) << osec.offset - << std::hex - << " image: 0x" << offset + osec.offset - << std::dec << std::right << std::endl; - } - } - } - } - - /** - * Helper for for_each to merge the related object sections into the RAP - * section. - */ - class section_merge: - public std::unary_function < const files::section, void > - { - public: - - section_merge (object& obj, section& sec); - - ~section_merge (); - - void operator () (const files::section& fsec); - - private: - - object& obj; - section& sec; - }; - - section_merge::section_merge (object& obj, section& sec) - : obj (obj), - sec (sec) - { - sec.offset = 0; - sec.rela = false; - } - - section_merge::~section_merge () - { - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "rap:section-merge: " << sec.name - << " size=" << sec.size () - << " offset=" << sec.offset - << " " << obj.obj.name ().full () << std::endl; - } - - void - section_merge::operator () (const files::section& fsec) - { - /* - * Align the size up to the next alignment boundary and use that as the - * offset for this object file section. - */ - uint32_t offset = align_offset (sec.size (), 0, fsec.alignment); - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "rap:section-merge: " << fsec.name - << " sec-size=" << sec.size () - << " relocs=" << fsec.relocs.size () - << " offset=" << offset - << " fsec.size=" << fsec.size - << " fsec.alignment=" << fsec.alignment - << " fsec.rela=" << fsec.rela - << " " << obj.obj.name ().full () << std::endl; - - /* - * Add the object file's section offset to the map. This is needed - * to adjust the external symbol offsets. - */ - osection osec (fsec.name, - offset, - fsec.size, - fsec.alignment, - fsec.relocs.size (), - fsec.flags); - sec.osecs[fsec.index] = osec; - sec.osindexes.push_back (fsec.index); - - uint32_t rc = 0; - - for (files::relocations::const_iterator fri = fsec.relocs.begin (); - fri != fsec.relocs.end (); - ++fri, ++rc) - { - const files::relocation& freloc = *fri; - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << " " << std::setw (2) << sec.relocs.size () - << '/' << std::setw (2) << rc - << std::hex << ": reloc.info=0x" << freloc.info << std::dec - << " reloc.offset=" << freloc.offset - << " reloc.addend=" << freloc.addend - << " reloc.symtype=" << freloc.symtype - << " reloc.symsect=" << freloc.symsect - << " reloc.symbinding=" << freloc.symbinding - << std::endl; - - sec.relocs.push_back (relocation (freloc, offset)); - } - - std::stable_sort (sec.relocs.begin (), - sec.relocs.end (), - reloc_symname_compare ()); - std::stable_sort (sec.relocs.begin (), - sec.relocs.end (), - reloc_offset_compare ()); - - if (fsec.rela == true) - sec.rela = fsec.rela; - } - - external::external (const uint32_t name, - const sections sec, - const uint32_t value, - const uint32_t data) - : name (name), - sec (sec), - value (value), - data (data) - { - } - - external::external (const external& orig) - : name (orig.name), - sec (orig.sec), - value (orig.value), - data (orig.data) - { - } - - object::object (files::object& obj) - : obj (obj) - { - /* - * Set up the names of the sections. - */ - for (int s = 0; s < rap_secs; ++s) - secs[s].name = section_names[s]; - - /* - * Get the relocation records. Collect the various section types from the - * object file into the RAP sections. Merge those sections into the RAP - * sections. - */ - - obj.open (); - try - { - obj.begin (); - obj.load_relocations (); - obj.end (); - } - catch (...) - { - obj.close (); - throw; - } - obj.close (); - - obj.get_sections (text, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); - obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC, SHF_WRITE | SHF_EXECINSTR); - obj.get_sections (ctor, ".ctors"); - obj.get_sections (dtor, ".dtors"); - obj.get_sections (data, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); - obj.get_sections (bss, SHT_NOBITS, SHF_ALLOC | SHF_WRITE); - obj.get_sections (symtab, SHT_SYMTAB); - obj.get_sections (strtab, ".strtab"); - - std::for_each (text.begin (), text.end (), - section_merge (*this, secs[rap_text])); - std::for_each (const_.begin (), const_.end (), - section_merge (*this, secs[rap_const])); - std::for_each (ctor.begin (), ctor.end (), - section_merge (*this, secs[rap_ctor])); - std::for_each (dtor.begin (), dtor.end (), - section_merge (*this, secs[rap_dtor])); - std::for_each (data.begin (), data.end (), - section_merge (*this, secs[rap_data])); - std::for_each (bss.begin (), bss.end (), - section_merge (*this, secs[rap_bss])); - } - - object::object (const object& orig) - : obj (orig.obj), - text (orig.text), - const_ (orig.const_), - ctor (orig.ctor), - dtor (orig.dtor), - data (orig.data), - bss (orig.bss), - symtab (orig.symtab), - strtab (orig.strtab) - { - for (int s = 0; s < rap_secs; ++s) - secs[s] = orig.secs[s]; - } - - sections - object::find (const uint32_t index) const - { - const files::section* sec; - - sec = files::find (text, index); - if (sec) - return rap_text; - - sec = files::find (const_, index); - if (sec) - return rap_const; - - sec = files::find (ctor, index); - if (sec) - return rap_ctor; - - sec = files::find (dtor, index); - if (sec) - return rap_dtor; - - sec = files::find (data, index); - if (sec) - return rap_data; - - sec = files::find (bss, index); - if (sec) - return rap_bss; - - throw rld::error ("Section index '" + rld::to_string (index) + - "' not found: " + obj.name ().full (), "rap::object"); - } - - uint32_t - object::get_relocations () const - { - uint32_t relocs = 0; - for (int s = 0; s < rap_secs; ++s) - relocs += secs[s].relocs.size (); - return relocs; - } - - uint32_t - object::get_relocations (int sec) const - { - if ((sec < 0) || (sec >= rap_secs)) - throw rld::error ("Invalid section index '" + rld::to_string (sec), - "rap::relocations"); - return secs[sec].relocs.size (); - } - - void - object::output () - { - std::cout << "rap:object: " << obj.name ().full () << std::endl; - secs[rap_text].output (); - secs[rap_const].output (); - secs[rap_ctor].output (); - secs[rap_dtor].output (); - secs[rap_data].output (); - if (secs[rap_bss].size ()) - std::cout << " bss: size: " << secs[rap_bss].size () << std::endl; - } - - image::image () - { - clear (); - } - - void - image::layout (const files::object_list& app_objects, - const std::string& init, - const std::string& fini) - { - clear (); - - /* - * Create the local objects which contain the layout information. - */ - for (files::object_list::const_iterator aoi = app_objects.begin (); - aoi != app_objects.end (); - ++aoi) - { - files::object& app_obj = *(*aoi); - - if (!app_obj.valid ()) - throw rld::error ("Not valid: " + app_obj.name ().full (), - "rap::layout"); - - objs.push_back (object (app_obj)); - } - - for (objects::iterator oi = objs.begin (), poi = objs.begin (); - oi != objs.end (); - ++oi) - { - object& obj = *oi; - - /* - * Update the offsets in the object file. We need the object's offset - * to set the relocation offset's correctly as they are relative to the - * object file. - */ - if (oi != objs.begin ()) - { - object& pobj = *poi; - for (int s = 0; s < rap_secs; ++s) - { - obj.secs[s].set_offset (pobj.secs[s]); - sec_size[s] = obj.secs[s].offset + obj.secs[s].size (); - sec_align[s] = obj.secs[s].alignment (); - if (obj.secs[s].rela == true) - sec_rela[s] = obj.secs[s].rela; - } - ++poi; - } - else - { - for (int s = 0; s < rap_secs; ++s) - { - sec_size[s] = obj.secs[s].size (); - sec_align[s] = obj.secs[s].alignment (); - if (obj.secs[s].rela == true) - sec_rela[s] = true; - } - } - - collect_symbols (obj); - - relocs_size += obj.get_relocations (); - - if (rld::verbose () >= RLD_VERBOSE_DETAILS) - obj.output (); - } - - init_off = strtab.size () + 1; - strtab += '\0'; - strtab += init; - - fini_off = strtab.size () + 1; - strtab += '\0'; - strtab += fini; - - if (rld::verbose () >= RLD_VERBOSE_INFO) - { - uint32_t total = (sec_size[rap_text] + sec_size[rap_const] + - sec_size[rap_data] + sec_size[rap_bss] + - symtab_size + strtab.size() + relocs_size); - std::cout << "rap::layout: total:" << total - << " text:" << sec_size[rap_text] - << " const:" << sec_size[rap_const] - << " ctor:" << sec_size[rap_ctor] - << " dtor:" << sec_size[rap_dtor] - << " data:" << sec_size[rap_data] - << " bss:" << sec_size[rap_bss] - << " symbols:" << symtab_size << " (" << externs.size () << ')' - << " strings:" << strtab.size () + 1 - << " relocs:" << relocs_size - << std::endl; - } - } - - void - image::collect_symbols (object& obj) - { - symbols::pointers& esyms = obj.obj.external_symbols (); - for (symbols::pointers::const_iterator ei = esyms.begin (); - ei != esyms.end (); - ++ei) - { - const symbols::symbol& sym = *(*ei); - - if ((sym.type () == STT_OBJECT) || (sym.type () == STT_FUNC) || (sym.type () == STT_NOTYPE)) - { - if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK)) - { - int symsec = sym.section_index (); - - /* Ignore section index 0 */ - if (symsec == 0) - continue; - /* Ignore sparc common section */ - if ((elf::object_machine_type () == EM_SPARC) && (symsec == 65522)) - continue; - - sections rap_sec = obj.find (symsec); - section& sec = obj.secs[rap_sec]; - std::size_t name; - - /* - * See if the name is already in the string table. - */ - name = find_in_strtab (sym.name ()); - - if (name == std::string::npos) - { - name = strtab.size () + 1; - strtab += '\0'; - strtab += sym.name (); - } - - /* - * The symbol's value is the symbols value plus the offset of the - * object file's section offset in the RAP section. - */ - externs.push_back (external (name, - rap_sec, - sec.offset + sec.osecs[symsec].offset + - sym.value (), - sym.info ())); - - symtab_size += external::rap_size; - } - } - } - } - - void - image::write (compress::compressor& comp) - { - /* - * Start with the machine type so the target can check the applicatiion - * is ok and can be loaded. Add the init and fini labels to the string - * table and add the references to the string table next. Follow this - * with the section details then the string table and symbol table then - * finally the relocation records. - */ - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: machine=" << comp.transferred () << std::endl; - - comp << elf::object_machine_type () - << elf::object_datatype () - << elf::object_class (); - - /* - * The init and fini label offsets. Then the symbol table and string - * table sizes. - */ - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: header=" << comp.transferred () << std::endl; - - comp << init_off - << fini_off - << symtab_size - << (uint32_t) strtab.size () + 1 - << (uint32_t) 0; - - /* - * Output file details - */ - if (add_obj_details) - { - write_details (comp); - } - else - { - comp << (uint32_t)0; /* No file details */ - } - - /* - * The sections. - */ - for (int s = 0; s < rap_secs; ++s) - comp << sec_size[s] - << sec_align[s]; - - /* - * Output the sections from each object file. - */ - write (comp, rap_text); - write (comp, rap_const); - write (comp, rap_ctor); - write (comp, rap_dtor); - write (comp, rap_data); - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: strtab=" << comp.transferred () << std::endl; - - strtab += '\0'; - comp << strtab; - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: symbols=" << comp.transferred () << std::endl; - - write_externals (comp); - - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: relocs=" << comp.transferred () << std::endl; - - write_relocations (comp); - } - - /** - * Helper for for_each to write out the various sections. - */ - class section_writer: - public std::unary_function < object, void > - { - public: - - section_writer (image& img, - compress::compressor& comp, - sections sec); - - void operator () (object& obj); - - private: - - image& img; - compress::compressor& comp; - sections sec; - uint32_t offset; - }; - - section_writer::section_writer (image& img, - compress::compressor& comp, - sections sec) - : img (img), - comp (comp), - sec (sec), - offset (0) - { - if (rld::verbose () >= RLD_VERBOSE_INFO) - std::cout << "rap:output: " << section_names[sec] - << ": offset=" << comp.transferred () - << " size=" << img.section_size (sec) << std::endl; - } - - void - section_writer::operator () (object& obj) - { - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "rap:writing: " << section_names[sec] << std::endl; - - switch (sec) - { - case rap_text: - img.write (comp, obj.obj, obj.text, offset); - break; - case rap_const: - img.write (comp, obj.obj, obj.const_, offset); - break; - case rap_ctor: - img.write (comp, obj.obj, obj.ctor, offset); - break; - case rap_dtor: - img.write (comp, obj.obj, obj.dtor, offset); - break; - case rap_data: - img.write (comp, obj.obj, obj.data, offset); - break; - default: - break; - } - } - - void - image::write (compress::compressor& comp, sections sec) - { - uint32_t image_offset = comp.transferred (); - - std::for_each (objs.begin (), objs.end (), - section_writer (*this, comp, sec)); - - uint32_t written = comp.transferred () - image_offset; - - if (written != sec_size[sec]) - { - std::string msg = "Image output size does not match layout size: "; - msg += section_names[sec]; - msg += ": layout-size=" + rld::to_string (sec_size[sec]); - msg += " image-size=" + rld::to_string (written); - throw rld::error (msg, "rap::write"); - } - } - - void - image::write (compress::compressor& comp, - files::object& obj, - const files::sections& secs, - uint32_t& offset) - { - uint32_t size = 0; - - obj.open (); - - try - { - obj.begin (); - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << "rap:write sections: " << obj.name ().full () << std::endl; - - for (files::sections::const_iterator si = secs.begin (); - si != secs.end (); - ++si) - { - const files::section& sec = *si; - uint32_t unaligned_offset = offset + size; - - offset = align_offset (offset, size, sec.alignment); - - if (offset != unaligned_offset) - { - char ee = '\xee'; - for (uint32_t p = 0; p < (offset - unaligned_offset); ++p) - comp.write (&ee, 1); - } - - comp.write (obj, sec.offset, sec.size); - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << " sec: " << sec.index << ' ' << sec.name - << " offset=" << offset - << " size=" << sec.size - << " align=" << sec.alignment - << " padding=" << (offset - unaligned_offset) << std::endl; - - size = sec.size; - } - - offset += size; - - if (rld::verbose () >= RLD_VERBOSE_FULL_DEBUG) - std::cout << " total size=" << offset << std::endl; - - obj.end (); - } - catch (...) - { - obj.close (); - throw; - } - - obj.close (); - } - - void - image::write_externals (compress::compressor& comp) - { - int count = 0; - for (externals::const_iterator ei = externs.begin (); - ei != externs.end (); - ++ei, ++count) - { - const external& ext = *ei; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "rap:externs: " << count - << " name=" << &strtab[ext.name] << " (" << ext.name << ')' - << " section=" << section_names[ext.sec] - << " data=" << ext.data - << " value=0x" << std::hex << ext.value << std::dec - << std::endl; - - if ((ext.data & 0xffff0000) != 0) - throw rld::error ("Data value has data in bits higher than 15", - "rap::write-externs"); - - comp << (uint32_t) ((ext.sec << 16) | ext.data) - << ext.name - << ext.value; - } - } - - void - image::write_relocations (compress::compressor& comp) - { - for (int s = 0; s < rap_secs; ++s) - { - uint32_t count = get_relocations (s); - uint32_t sr = 0; - uint32_t header; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "rap:relocation: section:" << section_names[s] - << " relocs=" << count - << " rela=" << (char*) (sec_rela[s] ? "yes" : "no") - << std::endl; - - header = count; - header |= sec_rela[s] ? RAP_RELOC_RELA : 0; - - comp << header; - - for (objects::iterator oi = objs.begin (); - oi != objs.end (); - ++oi) - { - object& obj = *oi; - section& sec = obj.secs[s]; - relocations& relocs = sec.relocs; - uint32_t rc = 0; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << " relocs=" << sec.relocs.size () - << " sec.offset=" << sec.offset - << " sec.size=" << sec.size () - << " sec.align=" << sec.alignment () - << " " << obj.obj.name ().full () << std::endl; - - for (relocations::const_iterator ri = relocs.begin (); - ri != relocs.end (); - ++ri, ++sr, ++rc) - { - const relocation& reloc = *ri; - uint32_t info = GELF_R_TYPE (reloc.info); - uint32_t offset; - uint32_t addend = reloc.addend; - bool write_addend = sec.rela; - bool write_symname = false; - - offset = sec.offset + reloc.offset; - - if ((reloc.symtype == STT_SECTION) || (reloc.symbinding == STB_LOCAL)) - { - int rap_symsect = obj.find (reloc.symsect); - - /* - * Bit 31 clear, bits 30:8 RAP section index. - */ - info |= rap_symsect << 8; - - addend += (obj.secs[rap_symsect].offset + - obj.secs[rap_symsect].osecs[reloc.symsect].offset + - reloc.symvalue); - - write_addend = true; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << " " << std::setw (2) << sr - << '/' << std::setw (2) << rc - <<": rsym: sect=" << section_names[rap_symsect] - << " rap_symsect=" << rap_symsect - << " sec.offset=" << obj.secs[rap_symsect].offset - << " sec.osecs=" << obj.secs[rap_symsect].osecs[reloc.symsect].offset - << " (" << obj.obj.get_section (reloc.symsect).name << ')' - << " reloc.symsect=" << reloc.symsect - << " reloc.symvalue=" << reloc.symvalue - << " reloc.addend=" << reloc.addend - << " addend=" << addend - << std::endl; - } - else - { - /* - * Bit 31 must be set. Bit 30 determines the type of string and - * bits 29:8 the strtab offset or the size of the appended - * string. - */ - - info |= RAP_RELOC_STRING; - - std::size_t size = find_in_strtab (reloc.symname); - - if (size == std::string::npos) - { - /* - * Bit 30 clear, the size of the symbol name. - */ - info |= reloc.symname.size () << 8; - write_symname = true; - } - else - { - /* - * Bit 30 set, the offset in the strtab. - */ - info |= RAP_RELOC_STRING_EMBED | (size << 8); - } - } - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - { - std::cout << " " << std::setw (2) << sr << '/' - << std::setw (2) << rc - << std::hex << ": reloc: info=0x" << info << std::dec - << " offset=" << offset; - if (write_addend) - std::cout << " addend=" << addend; - if ((info & RAP_RELOC_STRING) != 0) - { - std::cout << " symname=" << reloc.symname; - if (write_symname) - std::cout << " (appended)"; - } - std::cout << std::hex - << " reloc.info=0x" << reloc.info << std::dec - << " reloc.offset=" << reloc.offset - << " reloc.symtype=" << reloc.symtype - << std::endl; - } - - comp << info << offset; - - if (write_addend) - comp << addend; - - if (write_symname) - comp << reloc.symname; - } - } - } - } - - void image::write_details (compress::compressor& comp) - { - - std::string strtable; - uint32_t pos = 0; - - section_details s_details; - - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - { - std::cout << "rap:file details" << std::endl - << " total " << objs.size () <<" files" << std::endl; - } - - comp << (uint32_t)(objs.size ()); - - /* rpath for rap file */ - if (rld::verbose () >= RLD_VERBOSE_TRACE) - { - std::cout << "rap:file rpath=" << rld::rap::rpath << std::endl; - } - - comp << (uint32_t)rld::rap::rpath.length (); - - if (rld::rap::rpath.length () > 0) - { - strtable += rld::rap::rpath; - } - - for (objects::iterator oi = objs.begin (); - oi != objs.end (); - ++oi) - { - object& obj = *oi; - - /* obj full name */ - strtable += obj.obj.name ().full (); - strtable += '\0'; - } - - pos = strtable.length (); - - uint32_t sec_num = 0; - for (objects::iterator oi = objs.begin (); - oi != objs.end (); - ++oi) - { - object& obj = *oi; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "file:" << obj.obj.name ().full () << std::endl; - - for (int s = 0; s < rap_secs; ++s) - { - section& sec = obj.secs[s]; - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - { - std::cout << "rap:section: " << sec.name << " " - "offset= " << sec.offset << std::endl; - } - - for (size_t si = 0; si < sec.osindexes.size (); ++si) - { - const osection& osec = sec.get_osection (sec.osindexes[si]); - - strtable += osec.name; - strtable += '\0'; - - /* sec.offset + osec.offset is the offset in the rap section */ - s_details.push_back (section_detail (pos, - sec.offset + osec.offset, - s, - osec.size)); - - pos = strtable.length (); - - if (rld::verbose () >= RLD_VERBOSE_TRACE) - { - std::cout << "osec.name=" << osec.name << " " - << "osec.offset=" << osec.offset << " " - << "osec.size=" << osec.size << std::endl; - } - } - } - - /* Output section numbers*/ - comp << (uint32_t)((s_details.size () - sec_num)); - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "sec_num:" << s_details.size () - sec_num << std::endl; - sec_num = s_details.size (); - } - - comp << (uint32_t)(strtable.size ()); - if (rld::verbose () >= RLD_VERBOSE_TRACE) - std::cout << "total detail size:" << strtable.size () << std::endl; - - comp << strtable; - - for (section_details::const_iterator si = s_details.begin (); - si != s_details.end (); - ++si) - { - const section_detail& sec_detail = *si; - comp << (uint32_t)(sec_detail.name); - - if (sec_detail.id > 0xf) - std::cout << "Out max rap section id 15\n" << std::endl; - - comp << (uint32_t)((sec_detail.id << 28) | sec_detail.offset); - comp << (uint32_t)(sec_detail.size); - } - } - - uint32_t - image::get_relocations (int sec) const - { - if ((sec < 0) || (sec >= rap_secs)) - throw rld::error ("Invalid section index '" + rld::to_string (sec), - "rap::image::relocations"); - - uint32_t relocs = 0; - - for (objects::const_iterator oi = objs.begin (); - oi != objs.end (); - ++oi) - { - const object& obj = *oi; - relocs += obj.get_relocations (sec); - } - - return relocs; - } - - void - image::clear () - { - for (int s = 0; s < rap_secs; ++s) - { - sec_size[s] = 0; - sec_align[s] = 0; - sec_rela[s] = false; - } - symtab_size = 0; - strtab.clear (); - relocs_size = 0; - init_off = 0; - fini_off = 0; - } - - uint32_t - image::section_size (sections sec) const - { - if ((sec < 0) || (sec >= rap_secs)) - throw rld::error ("Invalid section index '" + rld::to_string (sec), - "rap::image::section_size"); - return sec_size[sec]; - } - - std::size_t - image::find_in_strtab (const std::string& symname) - { - std::size_t pos = 0; - while (pos < strtab.size ()) - { - std::size_t off = strtab.find (symname, pos); - if (off == std::string::npos) - break; - if (::strlen (strtab.c_str () + off) == symname.size ()) - return off; - pos = off + 1; - } - return std::string::npos; - } - - void - write (files::image& app, - const std::string& init, - const std::string& fini, - const files::object_list& app_objects, - const symbols::table& /* symbols */) /* Add back for incremental - * linking */ - { - std::string header; - - header = "RAP,00000000,0002,LZ77,00000000\n"; - app.write (header.c_str (), header.size ()); - - compress::compressor compressor (app, 2 * 1024); - image rap; - - rap.layout (app_objects, init, fini); - rap.write (compressor); - - compressor.flush (); - - std::ostringstream length; - - length << std::setfill ('0') << std::setw (8) - << header.size () + compressor.compressed (); - - header.replace (4, 8, length.str ()); - - app.seek (0); - app.write (header.c_str (), header.size ()); - - if (rld::verbose () >= RLD_VERBOSE_INFO) - { - int pcent = (compressor.compressed () * 100) / compressor.transferred (); - int premand = (((compressor.compressed () * 1000) + 500) / - compressor.transferred ()) % 10; - std::cout << "rap: objects: " << app_objects.size () - << ", size: " << compressor.compressed () - << ", compression: " << pcent << '.' << premand << '%' - << std::endl; - } - } - - } -} |