summaryrefslogtreecommitdiff
path: root/linkers/rld-rap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linkers/rld-rap.cpp')
-rw-r--r--linkers/rld-rap.cpp1668
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;
- }
- }
-
- }
-}