summaryrefslogtreecommitdiff
path: root/rld-outputter.cpp
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-11-21 11:05:04 +1100
committerChris Johns <chrisj@rtems.org>2012-11-21 11:05:04 +1100
commit9c0114a2161ce1fcc096ba05fbe07fe17182bf61 (patch)
treef247557bdd362c4fe44036b20cda5e48cf9d4edc /rld-outputter.cpp
parent4cbee029b186d321bbf3dc468ac606e3788469a5 (diff)
Set the correct header size field.
Diffstat (limited to 'rld-outputter.cpp')
-rw-r--r--rld-outputter.cpp269
1 files changed, 224 insertions, 45 deletions
diff --git a/rld-outputter.cpp b/rld-outputter.cpp
index 518bbec..3618371 100644
--- a/rld-outputter.cpp
+++ b/rld-outputter.cpp
@@ -32,43 +32,48 @@
#include <errno.h>
#include <rld.h>
-#include <rld.h>
+
+#include "fastlz.h"
namespace rld
{
namespace outputter
{
const std::string
- script_text (rld::files::object_list& dependents,
- rld::files::cache& cache)
+ script_text (files::object_list& dependents,
+ files::cache& cache)
{
- std::ostringstream out;
- rld::files::object_list objects;
+ std::ostringstream out;
+ files::object_list objects;
- cache.get_objects (objects);
+ /*
+ * The merge removes them from the dependent list.
+ */
+ files::object_list dep_copy (dependents);
- objects.merge (dependents);
+ cache.get_objects (objects);
+ objects.merge (dep_copy);
objects.unique ();
- for (rld::files::object_list::iterator oi = objects.begin ();
+ for (files::object_list::iterator oi = objects.begin ();
oi != objects.end ();
++oi)
{
- rld::files::object& obj = *(*oi);
+ files::object& obj = *(*oi);
if (rld::verbose () >= RLD_VERBOSE_INFO)
std::cout << " o: " << obj.name ().full () << std::endl;
out << "o:" << obj.name ().basename () << std::endl;
- rld::symbols::table& unresolved = obj.unresolved_symbols ();
+ symbols::table& unresolved = obj.unresolved_symbols ();
int count = 0;
- for (rld::symbols::table::iterator ursi = unresolved.begin ();
+ for (symbols::table::iterator ursi = unresolved.begin ();
ursi != unresolved.begin ();
++ursi)
{
- rld::symbols::symbol& urs = *((*ursi).second);
+ symbols::symbol& urs = *((*ursi).second);
++count;
@@ -82,29 +87,21 @@ namespace rld
return out.str ();
}
- const std::string
- metadata_object (const std::string& name,
- rld::files::object_list& dependents,
- rld::files::cache& cache)
+ void
+ metadata_object (files::object& metadata,
+ files::object_list& dependents,
+ files::cache& cache)
{
- const std::string script = script_text (dependents, cache);
-
- std::string ext = files::extension (name);
- std::string mdname =
- name.substr (0, name.length () - ext.length ()) + "-metadata.o";
-
if (rld::verbose () >= RLD_VERBOSE_INFO)
- std::cout << "metadata: " << mdname << std::endl;
+ std::cout << "metadata: " << metadata.name ().full () << std::endl;
- files::object metadata (mdname);
+ const std::string script = script_text (dependents, cache);
metadata.open (true);
metadata.begin ();
elf::file& elf = metadata.elf ();
- std::cout << "class: " << elf::object_class () << std::endl;
-
elf.set_header (ET_EXEC,
elf::object_class (),
elf::object_datatype (),
@@ -130,40 +127,44 @@ namespace rld
metadata.end ();
metadata.close ();
-
- return mdname;
}
void
- archive (const std::string& name,
- rld::files::object_list& dependents,
- rld::files::cache& cache)
+ archive (const std::string& name,
+ files::object_list& dependents,
+ files::cache& cache)
{
if (rld::verbose () >= RLD_VERBOSE_INFO)
- std::cout << "outputter:archive: " << name << std::endl;
+ std::cout << "outputter:archive: " << name
+ << ", dependents: " << dependents.size () << std::endl;
- std::string metadata = metadata_object (name,
- dependents,
- cache);
+ std::string ext = files::extension (name);
+ std::string mdname =
+ name.substr (0, name.length () - ext.length ()) + "-metadata.o";
- files::object_list objects;
- cache.get_objects (objects);
+ files::object metadata (mdname);
- for (rld::files::object_list::iterator oi = dependents.begin ();
- oi != dependents.end ();
- ++oi)
- objects.push_back (*oi);
+ metadata_object (metadata, dependents, cache);
+
+ /*
+ * The merge removes them from the dependent list.
+ */
+ files::object_list dep_copy (dependents);
+ files::object_list objects;
+ cache.get_objects (objects);
+ objects.merge (dep_copy);
+ objects.push_front (&metadata);
objects.unique ();
- rld::files::archive arch (name);
+ files::archive arch (name);
arch.create (objects);
}
void
- script (const std::string& name,
- rld::files::object_list& dependents,
- rld::files::cache& cache)
+ script (const std::string& name,
+ files::object_list& dependents,
+ files::cache& cache)
{
if (rld::verbose () >= RLD_VERBOSE_INFO)
std::cout << "outputter:script: " << name << std::endl;
@@ -183,9 +184,187 @@ namespace rld
catch (...)
{
out.close ();
+ throw;
}
out.close ();
}
+
+ /**
+ * Append the output data to the output buffer and if full compress and
+ * write to the output file. If the output buffer is 0 flush the output
+ * buffer.
+ */
+ static void
+ app_write_output (files::image& out,
+ const uint8_t* out_buffer,
+ const size_t out_buffer_size,
+ size_t& out_buffer_level,
+ const void* output_,
+ size_t outputting,
+ uint8_t* compress_buffer,
+ size_t& out_total)
+ {
+ const uint8_t* output = static_cast <const uint8_t*> (output_);
+
+ while (outputting)
+ {
+ if (output)
+ {
+ size_t appending;
+
+ if (outputting > (out_buffer_size - out_buffer_level))
+ appending = out_buffer_size - out_buffer_level;
+ else
+ appending = outputting;
+
+ ::memcpy ((void*) (out_buffer + out_buffer_level),
+ output,
+ appending);
+
+ out_buffer_level += appending;
+ outputting -= appending;
+ }
+ else
+ {
+ outputting = 0;
+ }
+
+ if (!output || (out_buffer_level >= out_buffer_size))
+ {
+ int writing =
+ ::fastlz_compress (out_buffer, out_buffer_level, compress_buffer);
+
+ out.write (compress_buffer, writing);
+
+ out_total += writing;
+
+ out_buffer_level = 0;
+ }
+ }
+ }
+
+ void
+ application (const std::string& name,
+ files::object_list& dependents,
+ files::cache& cache)
+ {
+ if (rld::verbose () >= RLD_VERBOSE_INFO)
+ std::cout << "outputter:application: " << name << std::endl;
+
+ files::object_list dep_copy (dependents);
+ files::object_list objects;
+ std::string header;
+ std::string script;
+ files::image app (name);
+
+ header = "RTEMS-APP,00000000,01.00.00,LZ77,00000000\n";
+ header += '\0';
+
+ script = script_text (dependents, cache);
+
+ cache.get_objects (objects);
+ objects.merge (dep_copy);
+ objects.unique ();
+
+ app.open (true);
+ app.write (header.c_str (), header.size ());
+
+ #define INPUT_BUFFER_SIZE (64 * 1024)
+ #define OUTPUT_BUFFER_SIZE (128 * 1024)
+ #define FASTLZ_BUFFER_SIZE (OUTPUT_BUFFER_SIZE + ((int) (OUTPUT_BUFFER_SIZE * 0.10)))
+
+ uint8_t* in_buffer = 0;
+ uint8_t* out_buffer = 0;
+ uint8_t* compress_buffer = 0;
+ size_t out_level = 0;
+ size_t in_total = 0;
+ size_t out_total = 0;
+
+ try
+ {
+ in_buffer = new uint8_t[INPUT_BUFFER_SIZE];
+ out_buffer = new uint8_t[OUTPUT_BUFFER_SIZE];
+ compress_buffer = new uint8_t[FASTLZ_BUFFER_SIZE];
+
+ app_write_output (app,
+ out_buffer, OUTPUT_BUFFER_SIZE, out_level,
+ script.c_str (), script.size (),
+ compress_buffer,
+ out_total);
+
+ in_total += script.size ();
+
+ for (files::object_list::iterator oi = objects.begin ();
+ oi != objects.end ();
+ ++oi)
+ {
+ files::object& obj = *(*oi);
+
+ obj.open ();
+
+ try
+ {
+ obj.seek (0);
+
+ size_t in_size = obj.name ().size ();
+
+ while (in_size)
+ {
+ size_t reading =
+ in_size < INPUT_BUFFER_SIZE ? in_size : INPUT_BUFFER_SIZE;
+
+ obj.read (in_buffer, reading);
+
+ app_write_output (app,
+ out_buffer, OUTPUT_BUFFER_SIZE, out_level,
+ in_buffer, reading,
+ compress_buffer,
+ out_total);
+
+ in_size -= reading;
+ in_total += reading;
+ }
+ }
+ catch (...)
+ {
+ obj.close ();
+ throw;
+ }
+
+ obj.close ();
+ }
+ }
+ catch (...)
+ {
+ delete [] in_buffer;
+ delete [] out_buffer;
+ delete [] compress_buffer;
+ throw;
+ }
+
+ app_write_output (app,
+ out_buffer, OUTPUT_BUFFER_SIZE, out_level,
+ 0, out_level,
+ compress_buffer,
+ out_total);
+
+ app.close ();
+
+ delete [] in_buffer;
+ delete [] out_buffer;
+ delete [] compress_buffer;
+
+ if (rld::verbose () >= RLD_VERBOSE_INFO)
+ {
+ int pcent = (out_total * 100) / in_total;
+ int premand = (((out_total * 1000) + 500) / in_total) % 10;
+ std::cout << "outputter:application: objects: " << objects.size ()
+ << ", size: " << out_total
+ << ", compression: " << pcent << '.' << premand << '%'
+ << std::endl;
+ }
+ }
+
}
}