summaryrefslogtreecommitdiff
path: root/rld-rap.cpp
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-11-29 19:05:19 +1100
committerChris Johns <chrisj@rtems.org>2012-11-29 19:05:19 +1100
commitc23f29ec5f5fa18e6b068317cd94a735fceba684 (patch)
tree28679b24bf2a03e49a48d95c88d417760e126bc9 /rld-rap.cpp
parent5c716ef1d1ed1962ffe2470a6d702759718f9875 (diff)
Add support for a custom RAP file format.
The file is a header and a searies of LZ77 blocks which hold the application. The format allows for easy streaming and loading on the target without needing the rewind or seek around the file.
Diffstat (limited to 'rld-rap.cpp')
-rw-r--r--rld-rap.cpp570
1 files changed, 403 insertions, 167 deletions
diff --git a/rld-rap.cpp b/rld-rap.cpp
index 017e8d7..a17bf80 100644
--- a/rld-rap.cpp
+++ b/rld-rap.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#endif
+#include <algorithm>
#include <list>
#include <iomanip>
@@ -38,38 +39,113 @@ namespace rld
namespace rap
{
/**
+ * The sections of interest in a RAP file.
+ */
+ enum sections
+ {
+ rap_text = 0,
+ rap_const = 1,
+ rap_ctor = 2,
+ rap_dtor = 3,
+ rap_data = 4,
+ rap_bss = 5,
+ rap_secs = 6
+ };
+
+ /**
+ * The names of the RAP sections.
+ */
+ static const char* section_names[rap_secs] =
+ {
+ ".text",
+ ".const",
+ ".ctor",
+ ".dtor",
+ ".data",
+ ".bss"
+ };
+
+ /**
+ * The RAP section data.
+ */
+ struct section
+ {
+ std::string name; //< The name of the section.
+ uint32_t size; //< The size of the section.
+ uint32_t offset; //< The offset of the section.
+ uint32_t align; //< The alignment of the section.
+
+ /**
+ * Operator to add up section data.
+ */
+ section& operator += (const section& sec);
+
+ /**
+ * Default constructor.
+ */
+ section ();
+ };
+
+ /**
+ * 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 default constructor.
+ */
+ external (const uint32_t name,
+ const sections sec,
+ const uint32_t value,
+ const uint32_t info);
+
+ /**
+ * 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 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 section file offset.
- uint32_t symtab_size; //< The symbols section size.
- uint32_t strtab_off; //< The strings section file offset.
- uint32_t strtab_size; //< The strings section size.
- uint32_t relocs_off; //< The reloc's section file offset.
- uint32_t relocs_size; //< The reloc's section size.
+
+ 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 relocs; //< All relocation records.
+ files::sections symtab; //< All exported symbols.
+ files::sections strtab; //< All exported strings.
+ section secs[rap_secs]; //< The sections of interest.
+ uint32_t symtab_off; //< The symbols section file offset.
+ uint32_t symtab_size; //< The symbols section size.
+ uint32_t strtab_off; //< The strings section file offset.
+ uint32_t strtab_size; //< The strings section size.
+ uint32_t relocs_off; //< The reloc's section file offset.
+ uint32_t relocs_size; //< The reloc's section size.
/**
* The constructor. Need to have an object file to create.
@@ -81,6 +157,11 @@ namespace rld
*/
object (const object& orig);
+ /**
+ * Find the section type that matches the section index.
+ */
+ sections find (const uint32_t index) const;
+
private:
/**
* No default constructor allowed.
@@ -100,11 +181,6 @@ namespace rld
{
public:
/**
- * The text section.
- */
- typedef std::vector < uint8_t > bytes;
-
- /**
* Construct the image.
*/
image ();
@@ -128,13 +204,12 @@ namespace rld
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.
+ objects objs; //< The RAP objects
+ section secs[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.
};
/**
@@ -190,19 +265,64 @@ namespace rld
}
}
+ section::section ()
+ : size (0),
+ offset (0),
+ align (0)
+ {
+ }
+
+ section&
+ section::operator += (const section& sec)
+ {
+ if (sec.size)
+ {
+ if (align == 0)
+ align = sec.align;
+ else if (align != sec.align)
+ throw rld::error ("Alignments do not match for section '" + name + "'",
+ "rap::section");
+
+ if (size && (align == 0))
+ throw rld::error ("Invalid alignment '" + name + "'",
+ "rap::section");
+
+ size += sec.size;
+ offset = sec.offset + sec.size;
+
+ uint32_t mask = (1 << (align - 1)) - 1;
+
+ if (offset & mask)
+ {
+ offset &= ~mask;
+ offset += (1 << align);
+ }
+ }
+
+ return *this;
+ }
+
+ 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),
- 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),
@@ -211,6 +331,12 @@ namespace rld
relocs_size (0)
{
/*
+ * Set up the names of the sections.
+ */
+ for (int s = 0; s < rap_secs; ++s)
+ secs[s].name = section_names[s];
+
+ /*
* Get from the object file the various sections we need to format a
* memory layout.
*/
@@ -236,11 +362,30 @@ namespace rld
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);
+ secs[rap_text].size = files::sum_sizes (text);
+ if (!text.empty ())
+ secs[rap_text].align = (*text.begin ()).alignment;
+
+ secs[rap_const].size = files::sum_sizes (const_);
+ if (!const_.empty ())
+ secs[rap_const].align = (*const_.begin ()).alignment;
+
+ secs[rap_ctor].size = files::sum_sizes (ctor);
+ if (!ctor.empty ())
+ secs[rap_ctor].align = (*ctor.begin ()).alignment;
+
+ secs[rap_dtor].size = files::sum_sizes (dtor);
+ if (!dtor.empty ())
+ secs[rap_dtor].align = (*dtor.begin ()).alignment;
+
+ secs[rap_data].size = files::sum_sizes (data);
+ if (!data.empty ())
+ secs[rap_data].align = (*data.begin ()).alignment;
+
+ secs[rap_bss].size = files::sum_sizes (bss);
+ if (!bss.empty ())
+ secs[rap_bss].align = (*bss.begin ()).alignment;
+
symtab_size = files::sum_sizes (symtab);
strtab_size = files::sum_sizes (strtab);
relocs_size = files::sum_sizes (relocs);
@@ -248,13 +393,13 @@ namespace rld
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 ("text", secs[rap_text].size, text);
+ output ("const", secs[rap_const].size, const_);
+ output ("ctor", secs[rap_ctor].size, ctor);
+ output ("dtor", secs[rap_dtor].size, dtor);
+ output ("data", secs[rap_data].size, data);
+ if (secs[rap_bss].size)
+ std::cout << " bss: size: " << secs[rap_bss].size << std::endl;
output ("relocs", relocs_size, relocs);
output ("symtab", symtab_size, symtab);
output ("strtab", strtab_size, strtab);
@@ -272,17 +417,6 @@ namespace rld
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),
@@ -290,16 +424,52 @@ namespace rld
relocs_off (orig.relocs_off),
relocs_size (orig.relocs_size)
{
+ 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 not found: " + obj.name ().full (),
+ "rap::object");
}
image::image ()
- : text_size (0),
- data_size (0),
- bss_size (0),
- symtab_size (0),
- strtab_size (0),
+ : symtab_size (0),
relocs_size (0)
{
+ /*
+ * Set up the names of the sections.
+ */
+ for (int s = 0; s < rap_secs; ++s)
+ secs[s].name = section_names[s];
}
void
@@ -321,23 +491,11 @@ namespace rld
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)
+ for (int s = 0; s < rap_secs; ++s)
{
- 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;
+ secs[s].size = 0;
+ secs[s].offset = 0;
+ secs[s].align = 0;
}
for (objects::iterator oi = objs.begin ();
@@ -345,43 +503,118 @@ namespace rld
++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;
- }
+ secs[rap_text] += obj.secs[rap_text];
+ secs[rap_const] += obj.secs[rap_const];
+ secs[rap_ctor] += obj.secs[rap_ctor];
+ secs[rap_dtor] += obj.secs[rap_dtor];
+ secs[rap_data] += obj.secs[rap_data];
+ secs[rap_bss] += obj.secs[rap_bss];
- for (objects::iterator oi = objs.begin ();
- oi != objs.end ();
- ++oi)
- {
- object& obj = *oi;
- obj.dtor_off = text_size;
- text_size += obj.dtor_size;
+ symtab_size = 0;
+ strtab.clear ();
+
+ uint32_t sym_count = 0;
+
+ symbols::pointers& esyms = obj.obj.external_symbols ();
+ for (symbols::pointers::const_iterator ei = esyms.begin ();
+ ei != esyms.end ();
+ ++ei, ++sym_count)
+ {
+ const symbols::symbol& sym = *(*ei);
+
+ if ((sym.type () == STT_OBJECT) || (sym.type () == STT_FUNC))
+ {
+ if ((sym.binding () == STB_GLOBAL) || (sym.binding () == STB_WEAK))
+ {
+ externs.push_back (external (sym_count,
+ obj.find (sym.index ()),
+ sym.value (),
+ sym.info ()));
+ symtab_size += external::rap_size;
+ strtab += sym.name ();
+ strtab += '\0';
+ }
+ }
+ }
+
+ relocs_size += obj.relocs_size;
}
if (rld::verbose () >= RLD_VERBOSE_INFO)
{
- uint32_t total = (text_size + data_size + data_size + bss_size +
- symtab_size + strtab_size + relocs_size);
+ uint32_t total = (secs[rap_text].size + secs[rap_data].size +
+ secs[rap_data].size + secs[rap_bss].size +
+ symtab_size + strtab.size() + relocs_size);
std::cout << "rap::layout: total:" << total
- << " text:" << text_size
- << " data:" << data_size
- << " bss:" << bss_size
- << " symbols:" << symtab_size
- << " strings:" << strtab_size
+ << " text:" << secs[rap_text].size
+ << " const:" << secs[rap_const].size
+ << " ctor:" << secs[rap_ctor].size
+ << " dtor:" << secs[rap_dtor].size
+ << " data:" << secs[rap_data].size
+ << " bss:" << secs[rap_bss].size
+ << " symbols:" << symtab_size << " (" << externs.size () << ')'
+ << " strings:" << strtab.size ()
<< " relocs:" << relocs_size
<< std::endl;
}
}
+ /**
+ * 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;
+ };
+
+ section_writer::section_writer (image& img,
+ compress::compressor& comp,
+ sections sec)
+ : img (img),
+ comp (comp),
+ sec (sec)
+ {
+ }
+
+ void
+ section_writer::operator () (object& obj)
+ {
+ switch (sec)
+ {
+ case rap_text:
+ img.write (comp, obj.obj, obj.text);
+ break;
+ case rap_const:
+ img.write (comp, obj.obj, obj.const_);
+ break;
+ case rap_ctor:
+ img.write (comp, obj.obj, obj.ctor);
+ break;
+ case rap_dtor:
+ img.write (comp, obj.obj, obj.dtor);
+ break;
+ case rap_data:
+ img.write (comp, obj.obj, obj.data);
+ break;
+ default:
+ break;
+ }
+ }
+
void
image::write (compress::compressor& comp, const std::string& metadata)
{
@@ -393,56 +626,44 @@ namespace rld
*/
comp << elf::object_machine_type ()
<< elf::object_datatype ()
- << elf::object_class ()
- << (uint32_t) objs.size ()
- << text_size
- << data_size
- << bss_size
+ << elf::object_class ();
+
+ for (int s = 0; s < rap_secs; ++s)
+ comp << secs[s].size
+ << secs[s].align
+ << secs[s].offset;
+
+ comp << symtab_size
+ << (uint32_t) strtab.size ()
<< (uint32_t) metadata.size ()
<< metadata;
/*
- * Add each object file in the list.
+ * Output the sections from each object file.
*/
- for (objects::iterator oi = objs.begin ();
- oi != objs.end ();
- ++oi)
+ std::for_each (objs.begin (), objs.end (),
+ section_writer (*this, comp, rap_text));
+ std::for_each (objs.begin (), objs.end (),
+ section_writer (*this, comp, rap_const));
+ std::for_each (objs.begin (), objs.end (),
+ section_writer (*this, comp, rap_ctor));
+ std::for_each (objs.begin (), objs.end (),
+ section_writer (*this, comp, rap_dtor));
+ std::for_each (objs.begin (), objs.end (),
+ section_writer (*this, comp, rap_data));
+
+ for (externals::const_iterator ei = externs.begin ();
+ ei != externs.end ();
+ ++ei)
{
- 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 ();
+ const external& ext = *ei;
+ comp << (uint32_t) ((ext.sec << 16) | ext.data)
+ << ext.name
+ << ext.value;
}
+
+ comp << strtab;
}
void
@@ -450,13 +671,28 @@ namespace rld
files::object& obj,
const files::sections& secs)
{
- for (files::sections::const_iterator si = secs.begin ();
- si != secs.end ();
- ++si)
+ obj.open ();
+
+ try
+ {
+ obj.begin ();
+ for (files::sections::const_iterator si = secs.begin ();
+ si != secs.end ();
+ ++si)
+ {
+ const files::section& sec = *si;
+ comp.write (obj, sec.offset, sec.size);
+ }
+
+ obj.end ();
+ }
+ catch (...)
{
- const files::section& sec = *si;
- comp.write (obj, sec.offset, sec.size);
+ obj.close ();
+ throw;
}
+
+ obj.close ();
}
void
@@ -466,7 +702,7 @@ namespace rld
const symbols::table& /* symbols */) /* Add back for incremental
* linking */
{
- compress::compressor compressor (app, 128 * 1024);
+ compress::compressor compressor (app, 2 * 1024);
image rap;
rap.layout (app_objects);