summaryrefslogtreecommitdiff
path: root/rld-rap.cpp
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-11-26 11:09:35 +1100
committerChris Johns <chrisj@rtems.org>2012-11-26 11:09:35 +1100
commitf2d80ad90c9f363cf1951d79219d8bad1a51c35d (patch)
treeaaeaa107e99fcd90f465b0d02ab3cb88f127c8d3 /rld-rap.cpp
parent8fee2181fca611b4f50fc464227d3656f0b99a39 (diff)
Add RAP format support.
Diffstat (limited to 'rld-rap.cpp')
-rw-r--r--rld-rap.cpp471
1 files changed, 471 insertions, 0 deletions
diff --git a/rld-rap.cpp b/rld-rap.cpp
new file mode 100644
index 0000000..7a313b6
--- /dev/null
+++ b/rld-rap.cpp
@@ -0,0 +1,471 @@
+/*
+ * 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.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <list>
+#include <iomanip>
+
+#include <rld.h>
+#include <rld-compression.h>
+#include <rld-rap.h>
+
+namespace rld
+{
+ namespace rap
+ {
+ /**
+ * 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 execitable 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 relocs; //< All relocation records.
+ files::sections symtab; //< All exported symbols.
+ files::sections strtab; //< All exported strings.
+ uint32_t text_off; //< The text section file offset.
+ uint32_t text_size; //< The text section size.
+ uint32_t const_off; //< The const section file offset.
+ uint32_t const_size; //< The const section size.
+ uint32_t ctor_off; //< The ctor section file offset.
+ uint32_t ctor_size; //< The ctor section size.
+ uint32_t dtor_off; //< The dtor section file offset.
+ uint32_t dtor_size; //< The dtor section size.
+ uint32_t data_off; //< The data section file offset.
+ uint32_t data_size; //< The data section size.
+ uint32_t bss_size; //< The bss section size.
+ uint32_t symtab_off; //< The symbols sectuint32 fioffset.
+ uint32_t symtab_size; //< The symbol section size.
+ uint32_t strtab_off; //< The string section file offset.
+ uint32_t strtab_size; //< The string section size.
+ uint32_t relocs_off; //< The reloc section file offset.
+ uint32_t relocs_size; //< The reloc section size.
+
+ /**
+ * The constructor. Need to have an object file.
+ */
+ object (files::object& obj);
+
+ /**
+ * The copy constructor.
+ */
+ object (const object& orig);
+
+ private:
+ /**
+ * No default constructor allowed.
+ */
+ object ();
+ };
+
+ /**
+ * A container of objects.
+ */
+ typedef std::list < object > objects;
+
+ /**
+ * The RAP image.
+ */
+ class image
+ {
+ public:
+ /**
+ * The text section.
+ */
+ typedef std::vector < uint8_t > bytes;
+
+ /**
+ * Construct the image.
+ */
+ image ();
+
+ /**
+ * Load the layout data from the object files.
+ */
+ void layout (const files::object_list& app_objects);
+
+ /**
+ * Write the compressed output file.
+ */
+ void write (compress::compressor& comp, const std::string& metadata);
+
+ /**
+ * Write the sections to the compressed output file.
+ */
+ void write (compress::compressor& comp,
+ files::object& obj,
+ const files::sections& secs);
+
+ private:
+
+ objects objs; //< The RAP objects
+ uint32_t text_size; //< The text size.
+ uint32_t data_size; //< The data size.
+ uint32_t bss_size; //< The size of the .bss region of the image.
+ uint32_t symtab_size; //< The symbols size.
+ uint32_t strtab_size; //< The strings size.
+ uint32_t relocs_size; //< The relocations size.
+ };
+
+ void
+ output (const char* name, size_t size, const files::sections& secs)
+ {
+ if (size)
+ {
+ std::cout << ' ' << name << ": size: " << size << std::endl;
+
+ for (files::sections::const_iterator si = secs.begin ();
+ si != secs.end ();
+ ++si)
+ {
+ files::section sec = *si;
+
+ if (sec.size)
+ {
+ #define SF(f, i, c) if (sec.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) << sec.name
+ << " " << flags
+ << " size: " << std::setw (5) << sec.size
+ << " align: " << sec.alignment
+ << std::right << std::endl;
+ }
+ }
+ }
+ }
+
+ object::object (files::object& obj)
+ : obj (obj),
+ text_off (0),
+ text_size (0),
+ const_off (0),
+ const_size (0),
+ ctor_off (0),
+ ctor_size (0),
+ dtor_off (0),
+ dtor_size (0),
+ data_off (0),
+ data_size (0),
+ bss_size (0),
+ symtab_off (0),
+ symtab_size (0),
+ strtab_off (0),
+ strtab_size (0),
+ relocs_off (0),
+ relocs_size (0)
+ {
+ /*
+ * Get from the object file the various sections we need to format a
+ * memory layout.
+ */
+
+ obj.get_sections (text, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
+ obj.get_sections (const_, SHT_PROGBITS, SHF_ALLOC | SHF_MERGE, 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");
+
+ /*
+ * Only interested in the relocation records for the text sections.
+ */
+ for (files::sections::const_iterator ti = text.begin ();
+ ti != text.end ();
+ ++ti)
+ {
+ files::section sec = *ti;
+ obj.get_sections (relocs, ".rel" + sec.name);
+ obj.get_sections (relocs, ".rela" + sec.name);
+ }
+
+ text_size = files::sum_sizes (text);
+ const_size = files::sum_sizes (const_);
+ ctor_size = files::sum_sizes (ctor);
+ dtor_size = files::sum_sizes (dtor);
+ data_size = files::sum_sizes (data);
+ symtab_size = files::sum_sizes (symtab);
+ strtab_size = files::sum_sizes (strtab);
+ relocs_size = files::sum_sizes (relocs);
+
+ if (rld::verbose () >= RLD_VERBOSE_TRACE)
+ {
+ std::cout << "rap:object: " << obj.name ().full () << std::endl;
+ output ("text", text_size, text);
+ output ("const", const_size, const_);
+ output ("ctor", ctor_size, ctor);
+ output ("dtor", dtor_size, dtor);
+ output ("data", data_size, data);
+ if (bss_size)
+ std::cout << bss_size << std::endl;
+ output ("relocs", relocs_size, relocs);
+ output ("symtab", symtab_size, symtab);
+ output ("strtab", strtab_size, strtab);
+ }
+ }
+
+ 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),
+ relocs (orig.relocs),
+ symtab (orig.symtab),
+ strtab (orig.strtab),
+ text_off (orig.text_off),
+ text_size (orig.text_size),
+ const_off (orig.const_off),
+ const_size (orig.const_size),
+ ctor_off (orig.ctor_off),
+ ctor_size (orig.ctor_size),
+ dtor_off (orig.dtor_off),
+ dtor_size (orig.dtor_size),
+ data_off (orig.data_off),
+ data_size (orig.data_size),
+ bss_size (orig.bss_size),
+ symtab_off (orig.symtab_off),
+ symtab_size (orig.symtab_size),
+ strtab_off (orig.strtab_off),
+ strtab_size (orig.strtab_size),
+ relocs_off (orig.relocs_off),
+ relocs_size (orig.relocs_size)
+ {
+ }
+
+ image::image ()
+ : text_size (0),
+ data_size (0),
+ bss_size (0),
+ symtab_size (0),
+ strtab_size (0),
+ relocs_size (0)
+ {
+ }
+
+ void
+ image::layout (const files::object_list& app_objects)
+ {
+ /*
+ * 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::load-sections");
+
+ objs.push_back (object (app_obj));
+ }
+
+ text_size = 0;
+ data_size = 0;
+ bss_size = 0;
+
+ for (objects::iterator oi = objs.begin ();
+ oi != objs.end ();
+ ++oi)
+ {
+ object& obj = *oi;
+ obj.text_off = text_size;
+ text_size += obj.text_size;
+ obj.data_off = data_size;
+ data_size += obj.data_size;
+ bss_size += obj.bss_size;
+ symtab_size += obj.symtab_size;
+ strtab_size += obj.strtab_size;
+ relocs_size += obj.relocs_size;
+ }
+
+ for (objects::iterator oi = objs.begin ();
+ oi != objs.end ();
+ ++oi)
+ {
+ object& obj = *oi;
+ obj.const_off = text_size;
+ text_size += obj.const_size;
+ }
+
+ for (objects::iterator oi = objs.begin ();
+ oi != objs.end ();
+ ++oi)
+ {
+ object& obj = *oi;
+ obj.ctor_off = text_size;
+ text_size += obj.ctor_size;
+ }
+
+ for (objects::iterator oi = objs.begin ();
+ oi != objs.end ();
+ ++oi)
+ {
+ object& obj = *oi;
+ obj.dtor_off = text_size;
+ text_size += obj.dtor_size;
+ }
+
+ if (rld::verbose () >= RLD_VERBOSE_INFO)
+ {
+ uint32_t total = (text_size + data_size + data_size + bss_size +
+ symtab_size + strtab_size + relocs_size);
+ std::cout << "rap:image:layout: total:" << total
+ << " text:" << text_size
+ << " data:" << data_size
+ << " bss:" << bss_size
+ << " symbols:" << symtab_size
+ << " strings:" << strtab_size
+ << " relocs:" << relocs_size
+ << std::endl;
+ }
+ }
+
+ void
+ image::write (compress::compressor& comp, const std::string& metadata)
+ {
+ /*
+ * Start with the number of object files to load.
+ */
+ comp << metadata.size ()
+ << objs.size ()
+ << text_size
+ << data_size
+ << bss_size;
+
+ for (objects::iterator oi = objs.begin ();
+ oi != objs.end ();
+ ++oi)
+ {
+ object& obj = *oi;
+
+ comp << obj.text_size
+ << obj.ctor_size
+ << obj.dtor_size
+ << obj.data_size
+ << obj.symtab_size
+ << obj.strtab_size
+ << obj.relocs_size;
+
+ obj.obj.open ();
+
+ try
+ {
+ obj.obj.begin ();
+
+ write (comp, obj.obj, obj.text);
+ write (comp, obj.obj, obj.const_);
+ write (comp, obj.obj, obj.ctor);
+ write (comp, obj.obj, obj.dtor);
+ write (comp, obj.obj, obj.data);
+ write (comp, obj.obj, obj.symtab);
+ write (comp, obj.obj, obj.strtab);
+
+ obj.obj.end ();
+ }
+ catch (...)
+ {
+ obj.obj.close ();
+ throw;
+ }
+
+ obj.obj.close ();
+ }
+ }
+
+ void
+ image::write (compress::compressor& comp,
+ files::object& obj,
+ const files::sections& secs)
+ {
+ for (files::sections::const_iterator si = secs.begin ();
+ si != secs.end ();
+ ++si)
+ {
+ const files::section& sec = *si;
+ comp.write (obj, sec.offset, sec.size);
+ }
+ }
+
+ void
+ write (files::image& app,
+ const std::string& metadata,
+ const files::object_list& app_objects,
+ const symbols::table& /* symbols */) /* Add back for incremental
+ * linking */
+ {
+ compress::compressor compressor (app, 128 * 1024);
+ image rap;
+
+ rap.layout (app_objects);
+ rap.write (compressor, metadata);
+
+ compressor.flush ();
+
+ 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;
+ }
+ }
+
+ }
+}