summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-11-29 19:08:57 +1100
committerChris Johns <chrisj@rtems.org>2012-11-29 19:08:57 +1100
commitfc313fda72db4b7aa774e191244bf83427b0fec1 (patch)
tree159e98d0ffaa489a4f4b3deb7ca49178df8bfa2a
parent62b19fe866226b8fa0ce54351162dab367daa06a (diff)
RAP file support.
This is the initial addition of support for LZ77 RTEMS applications in the RAP format. The change add support for different formats to the loader. Each format type is asked to check the file being loading and if it matches the format's loader is called to load the file. Support has been added to stream LZ77 files via the object file cache.
-rw-r--r--rtl-elf.c33
-rw-r--r--rtl-elf.h16
-rw-r--r--rtl-obj-cache.h6
-rw-r--r--rtl-obj-comp.c171
-rw-r--r--rtl-obj-comp.h113
-rw-r--r--rtl-obj.c43
-rw-r--r--rtl-obj.h21
-rw-r--r--rtl-rap.c453
-rw-r--r--rtl-rap.h47
-rw-r--r--rtl.c37
-rw-r--r--rtl.h17
-rw-r--r--wscript7
12 files changed, 960 insertions, 4 deletions
diff --git a/rtl-elf.c b/rtl-elf.c
index 3b7d231..ec73907 100644
--- a/rtl-elf.c
+++ b/rtl-elf.c
@@ -622,7 +622,38 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr)
}
bool
-rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd)
+rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_obj_cache_t* header;
+ Elf_Ehdr ehdr;
+
+ rtems_rtl_obj_caches (&header, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
+ &ehdr, sizeof (ehdr)))
+ return false;
+
+ /*
+ * Check we have a valid ELF file.
+ */
+ if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
+ || ehdr.e_ident[EI_CLASS] != ELFCLASS)
+ {
+ return false;
+ }
+
+ if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+ || (ehdr.e_version != EV_CURRENT)
+ || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd)
{
rtems_rtl_obj_cache_t* header;
Elf_Ehdr ehdr;
diff --git a/rtl-elf.h b/rtl-elf.h
index cafc4ce..470187b 100644
--- a/rtl-elf.h
+++ b/rtl-elf.h
@@ -128,6 +128,22 @@ bool rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj,
const char* symname,
Elf_Word* value);
+/**
+ * The ELF format check handler.
+ *
+ * @param obj The object being checked.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The ELF format load handler.
+ *
+ * @param obj The object to load.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/rtl-obj-cache.h b/rtl-obj-cache.h
index 01f9e96..65031c2 100644
--- a/rtl-obj-cache.h
+++ b/rtl-obj-cache.h
@@ -93,8 +93,9 @@ void rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache);
* and size is past the end of the file.
*
* @param cache The cache to reference data from.
- * @param fs The file descriptor. Must be an open file.
+ * @param fd The file descriptor. Must be an open file.
* @param offset The offset in the file to reference the data to.
+ * @param buffer The location to reference the data from.
* @param length The length of data to reference. Can be modified to a
* lesser value and true is still returned so check it.
* @retval true The data referenced is in the cache.
@@ -110,8 +111,9 @@ bool rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache,
* Read data by value. The data is copied to the user supplied buffer.
*
* @param cache The cache to read the data from.
- * @param fs The file descriptor. Must be an open file.
+ * @param fd The file descriptor. Must be an open file.
* @param offset The offset in the file to read the data from.
+ * @param buffer The location the data is written into.
* @param length The length of data to read.
* @retval true The data has been read from the cache.
* @retval false The read failed and the RTL error has been set.
diff --git a/rtl-obj-comp.c b/rtl-obj-comp.c
new file mode 100644
index 0000000..451d1cb
--- /dev/null
+++ b/rtl-obj-comp.c
@@ -0,0 +1,171 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object Compression manages a compress
+ * stream of data.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtl-allocator.h>
+#include <rtl-obj-comp.h>
+#include <rtl-error.h>
+
+#include "fastlz.h"
+
+#include <stdio.h>
+
+bool
+rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
+ size_t size)
+{
+ comp->cache = NULL;
+ comp->fd = -1;
+ comp->compression = RTEMS_RTL_COMP_LZ77;
+ comp->offset = 0;
+ comp->size = size;
+ comp->level = 0;
+ comp->buffer = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, false);
+ if (!comp->buffer)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for compressor buffer");
+ return false;
+ }
+ return true;
+}
+
+void
+rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, comp->buffer);
+ comp->cache = NULL;
+ comp->fd = -1;
+ comp->compression = RTEMS_RTL_COMP_LZ77;
+ comp->level = 0;
+ comp->size = 0;
+ comp->offset = 0;
+}
+
+void
+rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset)
+{
+ comp->cache = cache;
+ comp->fd = fd;
+ comp->compression = compression;
+ comp->offset = offset;
+ comp->level = 0;
+}
+
+bool
+rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
+ void* buffer,
+ size_t length)
+{
+ if (!comp->cache)
+ {
+ rtems_rtl_set_error (EINVAL, "not open");
+ return false;
+ }
+
+ if (comp->fd != comp->cache->fd)
+ {
+ comp->level = 0;
+ }
+
+ while (length)
+ {
+ size_t buffer_level;
+
+ buffer_level = length > comp->level ? comp->level : length;
+
+ if (buffer_level)
+ {
+ memcpy (buffer, comp->buffer, buffer_level);
+
+ length -= buffer_level;
+
+ if ((comp->level - buffer_level) != 0)
+ {
+ memmove (comp->buffer,
+ comp->buffer + buffer_level,
+ comp->level - buffer_level);
+ }
+
+ comp->level -= buffer_level;
+ }
+
+ if (length)
+ {
+ uint8_t* input = NULL;
+ size_t in_length;
+ uint16_t block_size;
+ int decompressed;
+
+ if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
+ (void**) &input, &in_length))
+ return false;
+
+ block_size = (input[0] << 8) | input[1];
+
+ comp->offset += sizeof (block_size);
+
+ in_length = block_size;
+
+ if (!rtems_rtl_obj_cache_read (comp->cache, comp->fd, comp->offset,
+ (void**) &input, &in_length))
+ return false;
+
+ if (in_length != block_size)
+ {
+ rtems_rtl_set_error (EIO, "compressed read failed");
+ return false;
+ }
+
+ switch (comp->compression)
+ {
+ case RTEMS_RTL_COMP_NONE:
+ memcpy (comp->buffer, input, in_length);
+ decompressed = in_length;
+ break;
+
+ case RTEMS_RTL_COMP_LZ77:
+ decompressed = fastlz_decompress (input, in_length,
+ comp->buffer, comp->size);
+ if (decompressed == 0)
+ {
+ rtems_rtl_set_error (EBADF, "decompression failed");
+ return false;
+ }
+ break;
+ default:
+ rtems_rtl_set_error (EINVAL, "bad compression type");
+ return false;
+ }
+
+ comp->offset += block_size;
+
+ comp->level = decompressed;
+ }
+ }
+
+ return true;
+}
diff --git a/rtl-obj-comp.h b/rtl-obj-comp.h
new file mode 100644
index 0000000..eb4ba55
--- /dev/null
+++ b/rtl-obj-comp.h
@@ -0,0 +1,113 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Compression manages a
+ * compressed stream of data.
+ *
+ * This is a simple interface to the object file cache to stream data from
+ * from a compressed object file. There is no ability to seek with the
+ * data from a compressed file. The module exists to allocate the output
+ * buffer when the loader starts and use the cache buffers will have been
+ * allocated.
+ */
+
+#if !defined (_RTEMS_RTL_OBJ_COMP_H_)
+#define _RTEMS_RTL_OBJ_COMP_H_
+
+#include <rtl-obj-cache.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The amount of input data read at a time from the file.
+ */
+#define RTEMS_RTL_DECOMP_INPUT_SIZE (256)
+
+/**
+ * The types of supported compression.
+ */
+#define RTEMS_RTL_COMP_NONE (0)
+#define RTEMS_RTL_COMP_LZ77 (1)
+
+/**
+ * The compressed file.
+ */
+typedef struct rtems_rtl_obj_cpmp_s
+{
+ rtems_rtl_obj_cache_t* cache; /**< The cache provides the input
+ * buffer. */
+ int fd; /**< The file descriptor. */
+ int compression; /**< The type of compression. */
+ off_t offset; /**< The base offset of the buffer. */
+ size_t size; /**< The size of the output buffer. */
+ size_t level; /**< The amount of data in the buffer. */
+ uint8_t* buffer; /**< The buffer */
+} rtems_rtl_obj_comp_t;
+
+/**
+ * Open a compressor allocating the output buffer.
+ *
+ * @param comp The compressor to initialise.
+ * @param size The size of the compressor's output buffer.
+ * @retval true The compressor is open.
+ * @retval false The compressor is not open. The RTL error is set.
+ */
+bool rtems_rtl_obj_comp_open (rtems_rtl_obj_comp_t* comp,
+ size_t size);
+
+/**
+ * Close a compressor.
+ *
+ * @param comp The compressor to close.
+ */
+void rtems_rtl_obj_comp_close (rtems_rtl_obj_comp_t* comp);
+
+/**
+ * Set the cache and offset in the file the compressed stream starts.
+ *
+ * @param comp The compressor to set the offset in.
+ * @param cache The cache to read the file in by.
+ * @param fd The file descriptor. Must be an open file.
+ * @param compression The type of compression being streamed.
+ * @param offset The offset in the file the compressed stream starts.
+ */
+void rtems_rtl_obj_comp_set (rtems_rtl_obj_comp_t* comp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset);
+
+/**
+ * Read decompressed data. The length contains the amount of data that should
+ * be available in the cache and referenced by the buffer handle. It must be
+ * less than or equal to the size of the cache. This call will return the
+ * amount of data that is available. It can be less than you ask if the offset
+ * and size is past the end of the file.
+ *
+ * @param comp The compressor to read data from.
+ * @param buffer The buffer the output is written too.
+ * @param length The length of data to read. Can be modified to a
+ * lesser value and true is still returned so check it.
+ * @retval true The data referenced is in the cache.
+ * @retval false The read failed and the RTL error has been set.
+ */
+bool rtems_rtl_obj_comp_read (rtems_rtl_obj_comp_t* comp,
+ void* buffer,
+ size_t length);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/rtl-obj.c b/rtl-obj.c
index 3234c08..8f839e2 100644
--- a/rtl-obj.c
+++ b/rtl-obj.c
@@ -37,6 +37,34 @@
#define rtems_filesystem_is_delimiter rtems_filesystem_is_separator
#endif
+#if RTEMS_RTL_RAP_LOADER
+#include "rtl-rap.h"
+#define RTEMS_RTL_RAP_LOADER_COUNT 1
+#else
+#define RTEMS_RTL_RAP_LOADER_COUNT 0
+#endif
+
+#if RTEMS_RTL_ELF_LOADER
+#include "rtl-elf.h"
+#define RTEMS_RTL_ELF_LOADER_COUNT 1
+#else
+#define RTEMS_RTL_ELF_LOADER_COUNT 0
+#endif
+
+/**
+ * The table of supported loader formats.
+ */
+static rtems_rtl_loader_table_t loaders[RTEMS_RTL_ELF_LOADER_COUNT +
+ RTEMS_RTL_RAP_LOADER_COUNT] =
+{
+#if RTEMS_RTL_RAP_LOADER
+ { rtems_rtl_rap_file_check, rtems_rtl_rap_file_load },
+#endif
+#if RTEMS_RTL_ELF_LOADER
+ { rtems_rtl_elf_file_check, rtems_rtl_elf_file_load },
+#endif
+};
+
rtems_rtl_obj_t*
rtems_rtl_obj_alloc (void)
{
@@ -983,6 +1011,21 @@ rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd)
}
bool
+rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd)
+{
+ int l;
+
+ for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table_t)); ++l)
+ {
+ if (loaders[l].check (obj, fd))
+ return loaders[l].load (obj, fd);
+ }
+
+ rtems_rtl_set_error (ENOENT, "no format loader found");
+ return false;
+}
+
+bool
rtems_rtl_obj_load (rtems_rtl_obj_t* obj)
{
int fd;
diff --git a/rtl-obj.h b/rtl-obj.h
index d1c9387..943abb5 100644
--- a/rtl-obj.h
+++ b/rtl-obj.h
@@ -26,6 +26,27 @@ extern "C" {
#endif /* __cplusplus */
/**
+ * The type of the format loader check handler. This handler checks the format
+ * and if it is detected as suitable it returns true.
+ */
+typedef bool (*rtems_rtl_loader_check)(rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The type of the format loader handler. This handler loads the specific
+ * format.
+ */
+typedef bool (*rtems_rtl_loader_load)(rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * Table for supported loadable formats.
+ */
+typedef struct rtems_rtl_loader_table_s
+{
+ rtems_rtl_loader_check check; /**< The check handler. */
+ rtems_rtl_loader_load load; /**< The loader. */
+} rtems_rtl_loader_table_t;
+
+/**
* Flags for the various section types.
*/
#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */
diff --git a/rtl-rap.c b/rtl-rap.c
new file mode 100644
index 0000000..b54e38a
--- /dev/null
+++ b/rtl-rap.c
@@ -0,0 +1,453 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor
+ *
+ * This is the RAP format loader support..
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rtl.h>
+#include "rtl-elf.h"
+#include "rtl-error.h"
+#include "rtl-obj-comp.h"
+#include "rtl-rap.h"
+#include "rtl-trace.h"
+#include "rtl-unresolved.h"
+
+/**
+ * The offsets in the unresolved array.
+ */
+#define REL_R_OFFSET (0)
+#define REL_R_INFO (1)
+#define REL_R_ADDEND (2)
+
+/**
+ * The section definitions found in a RAP file.
+ */
+typedef struct rtems_rtl_rap_sectdef_s
+{
+ const char* name; /**< Name of the section. */
+ const uint32_t flags; /**< Section flags. */
+} rtems_rtl_rap_sectdef_t;
+
+/**
+ * The sections as loaded from a RAP file.
+ */
+static const rtems_rtl_rap_sectdef_t rap_sections[6] =
+{
+ { ".text", RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".ctor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR },
+ { ".dtor", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR },
+ { ".data", RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD },
+ { ".bss", RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO }
+};
+
+/**
+ * The section indexes. These are fixed.
+ */
+#define RTEMS_RTL_RAP_TEXT_SEC (0)
+#define RTEMS_RTL_RAP_CONST_SEC (1)
+#define RTEMS_RTL_RAP_CTOR_SEC (2)
+#define RTEMS_RTL_RAP_DTOR_SEC (3)
+#define RTEMS_RTL_RAP_DATA_SEC (4)
+#define RTEMS_RTL_RAP_BSS_SEC (5)
+#define RTEMS_RTL_RAP_SECS (6)
+
+/**
+ * The number of RAP sections to load.
+ */
+#define RAP_SECTIONS (sizeof (rap_sections) / sizeof (rtems_rtl_rap_section_t))
+
+/**
+ * The section definitions found in a RAP file.
+ */
+typedef struct rtems_rtl_rap_section_s
+{
+ uint32_t size; /**< The size of the section. */
+ uint32_t alignment; /**< The alignment of the section. */
+ uint32_t offset; /**< The offset of the section. */
+} rtems_rtl_rap_section_t;
+
+/**
+ * The RAP loader.
+ */
+typedef struct rtems_rtl_rap_s
+{
+ rtems_rtl_obj_cache_t* file; /**< The file cache for the RAP file. */
+ rtems_rtl_obj_comp_t* decomp; /**< The decompression streamer. */
+ uint32_t length; /**< The file length. */
+ uint32_t version; /**< The RAP file version. */
+ uint32_t compression; /**< The type of compression. */
+ uint32_t checksum; /**< The checksum. */
+ uint32_t machinetype; /**< The ELF machine type. */
+ uint32_t datatype; /**< The ELF data type. */
+ uint32_t class; /**< The ELF class. */
+ rtems_rtl_rap_section_t secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */
+} rtems_rtl_rap_t;
+
+/**
+ * Check the machine type.
+ */
+static bool
+rtems_rtl_rap_machine_check (uint32_t machinetype)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ switch (machinetype)
+ {
+ ELFDEFNNAME (MACHDEP_ID_CASES)
+ default:
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Check the data type.
+ */
+static bool
+rtems_rtl_rap_datatype_check (uint32_t datatype)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS))
+ return false;
+ return true;
+}
+
+/**
+ * Check the class of executable.
+ */
+static bool
+rtems_rtl_rap_class_check (uint32_t class)
+{
+ /*
+ * This code is determined by the machine headers.
+ */
+ switch (class)
+ {
+ case ELFCLASS32:
+ if (ARCH_ELFSIZE == 32)
+ return true;
+ break;
+ case ELFCLASS64:
+ if (ARCH_ELFSIZE == 64)
+ return true;
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+static uint32_t
+rtems_rtl_rap_get_uint32 (const uint8_t* buffer)
+{
+ return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
+}
+
+static bool
+rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp_t* comp, uint32_t* value)
+{
+ uint8_t buffer[sizeof (uint32_t)];
+
+ if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t)))
+ return false;
+
+ *value = rtems_rtl_rap_get_uint32 (buffer);
+
+ return true;
+}
+
+static bool
+rtems_rtl_rap_symbols (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ return true;
+}
+
+static bool
+rtems_rtl_rap_relocator (rtems_rtl_obj_t* obj,
+ int fd,
+ rtems_rtl_obj_sect_t* sect,
+ void* data)
+{
+ return true;
+}
+
+static bool
+rtems_rtl_rap_parse_header (uint8_t* rhdr,
+ size_t* rhdr_len,
+ uint32_t* length,
+ uint32_t* version,
+ uint32_t* compression,
+ uint32_t* checksum)
+{
+ char* sptr = (char*) rhdr;
+ char* eptr;
+
+ *rhdr_len = 0;
+
+ /*
+ * "RAP," = 4 bytes, total 4
+ */
+
+ if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
+ return false;
+
+ sptr = sptr + 4;
+
+ /*
+ * "00000000," = 9 bytes, total 13
+ */
+
+ *length = strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "0000," = 5 bytes, total 18
+ */
+
+ *version = strtoul (sptr, &eptr, 10);
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "NONE," and "LZ77," = 5 bytes, total 23
+ */
+
+ if ((sptr[0] == 'N') &&
+ (sptr[1] == 'O') &&
+ (sptr[2] == 'N') &&
+ (sptr[3] == 'E'))
+ {
+ *compression = RTEMS_RTL_COMP_NONE;
+ eptr = sptr + 4;
+ }
+ else if ((sptr[0] == 'L') &&
+ (sptr[1] == 'Z') &&
+ (sptr[2] == '7') &&
+ (sptr[3] == '7'))
+ {
+ *compression = RTEMS_RTL_COMP_LZ77;
+ eptr = sptr + 4;
+ }
+ else
+ return false;
+
+ if (*eptr != ',')
+ return false;
+
+ sptr = eptr + 1;
+
+ /*
+ * "00000000," = 9 bytes, total 32
+ */
+ *checksum = strtoul (sptr, &eptr, 16);
+
+ /*
+ * "\n" = 1 byte, total 33
+ */
+ if (*eptr != '\n')
+ return false;
+
+ *rhdr_len = ((uint8_t*) eptr) - rhdr + 1;
+
+ return true;
+}
+
+bool
+rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_obj_cache_t* header;
+ uint8_t* rhdr = NULL;
+ size_t rlen = 64;
+ uint32_t length = 0;
+ uint32_t version = 0;
+ uint32_t compression = 0;
+ uint32_t checksum = 0;
+
+ rtems_rtl_obj_caches (&header, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
+ (void**) &rhdr, &rlen))
+ return false;
+
+ if (!rtems_rtl_rap_parse_header (rhdr,
+ &rlen,
+ &length,
+ &version,
+ &compression,
+ &checksum))
+ return false;
+
+ return true;
+}
+
+bool
+rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
+{
+ rtems_rtl_rap_t rap = { 0 };
+ uint8_t* rhdr = NULL;
+ size_t rlen = 64;
+ int section;
+
+ rtems_rtl_obj_caches (&rap.file, NULL, NULL);
+
+ if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset,
+ (void**) &rhdr, &rlen))
+ return false;
+
+ if (!rtems_rtl_rap_parse_header (rhdr,
+ &rlen,
+ &rap.length,
+ &rap.version,
+ &rap.compression,
+ &rap.checksum))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid RAP file format");
+ return false;
+ }
+
+ /*
+ * Set up the decompressor.
+ */
+ rtems_rtl_obj_comp (&rap.decomp, rap.file, fd, rap.compression, rlen);
+
+ /*
+ * uint32_t: machinetype
+ * uint32_t: datatype
+ * uint32_t: class
+ */
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: machinetype=%lu\n", rap.machinetype);
+
+ if (!rtems_rtl_rap_machine_check (rap.machinetype))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid machinetype");
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: datatype=%lu\n", rap.datatype);
+
+ if (!rtems_rtl_rap_datatype_check (rap.datatype))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid datatype");
+ return false;
+ }
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: class=%lu\n", rap.class);
+
+ if (!rtems_rtl_rap_class_check (rap.class))
+ {
+ rtems_rtl_set_error (EINVAL, "invalid class");
+ return false;
+ }
+
+ /*
+ * uint32_t: text_size
+ * uint32_t: text_alignment
+ * uint32_t: text_offset
+ * uint32_t: const_size
+ * uint32_t: const_alignment
+ * uint32_t: const_offset
+ * uint32_t: ctor_size
+ * uint32_t: ctor_alignment
+ * uint32_t: ctor_offset
+ * uint32_t: dtor_size
+ * uint32_t: dtor_alignment
+ * uint32_t: dtor_offset
+ * uint32_t: data_size
+ * uint32_t: data_alignment
+ * uint32_t: data_offset
+ * uint32_t: bss_size
+ * uint32_t: bss_alignment
+ * uint32_t: bss_offset
+ */
+
+ for (section = 0; section < RAP_SECTIONS; ++section)
+ {
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment))
+ return false;
+
+ if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].offset))
+ return false;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
+ printf ("rtl: rap: %s: size=%lu align=%lu off=%lu\n",
+ rap_sections[section].name,
+ rap.secs[section].size,
+ rap.secs[section].alignment,
+ rap.secs[section].offset);
+
+ if (!rtems_rtl_obj_add_section (obj,
+ section,
+ rap_sections[section].name,
+ rap.secs[section].size,
+ rap.secs[section].offset,
+ rap.secs[section].alignment,
+ 0, 0,
+ rap_sections[section].flags))
+ return false;
+ }
+
+ /** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
+
+ if (!rtems_rtl_obj_load_sections (obj, fd))
+ return false;
+
+ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_rap_symbols, &rap))
+ return false;
+
+ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_rap_relocator, &rap))
+ return false;
+
+ return true;
+}
diff --git a/rtl-rap.h b/rtl-rap.h
new file mode 100644
index 0000000..d937018
--- /dev/null
+++ b/rtl-rap.h
@@ -0,0 +1,47 @@
+/*
+ * COPYRIGHT (c) 2012 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.com/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker ELF Headers
+ */
+
+#if !defined (_RTEMS_RTL_RAP_H_)
+#define _RTEMS_RTL_RAP_H_
+
+#include <rtl-fwd.h>
+#include <rtl-obj-fwd.h>
+#include <rtl-sym.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * The RAP format check handler.
+ *
+ * @param obj The object being checked.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd);
+
+/**
+ * The RAP format load handler.
+ *
+ * @param obj The object to load.
+ * @param fd The file descriptor.
+ */
+bool rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/rtl.c b/rtl.c
index 52e8c85..59cd869 100644
--- a/rtl.c
+++ b/rtl.c
@@ -54,6 +54,11 @@
#define RTEMS_RTL_ELF_RELOC_CACHE (2048)
/**
+ * Decompression output buffer.
+ */
+#define RTEMS_RTL_COMP_OUTPUT (2048)
+
+/**
* Static RTL data is returned to the user when the linker is locked.
*/
static rtems_rtl_data_t* rtl;
@@ -183,9 +188,23 @@ rtems_rtl_data_init (void)
return false;
}
+ if (!rtems_rtl_obj_comp_open (&rtl->decomp,
+ RTEMS_RTL_COMP_OUTPUT))
+ {
+ rtems_rtl_obj_cache_close (&rtl->relocs);
+ rtems_rtl_obj_cache_close (&rtl->strings);
+ rtems_rtl_obj_cache_close (&rtl->symbols);
+ rtems_rtl_unresolved_table_close (&rtl->unresolved);
+ rtems_rtl_symbol_table_close (&rtl->globals);
+ rtems_semaphore_delete (lock);
+ free (rtl);
+ return false;
+ }
+
rtl->base = rtems_rtl_obj_alloc ();
if (!rtl->base)
{
+ rtems_rtl_obj_comp_close (&rtl->decomp);
rtems_rtl_obj_cache_close (&rtl->relocs);
rtems_rtl_obj_cache_close (&rtl->strings);
rtems_rtl_obj_cache_close (&rtl->symbols);
@@ -279,6 +298,24 @@ rtems_rtl_obj_caches_flush ()
}
}
+void
+rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset)
+{
+ if (!rtl)
+ {
+ *decomp = NULL;
+ }
+ else
+ {
+ *decomp = &rtl->decomp;
+ rtems_rtl_obj_comp_set (*decomp, cache, fd, compression, offset);
+ }
+}
+
rtems_rtl_data_t*
rtems_rtl_lock (void)
{
diff --git a/rtl.h b/rtl.h
index c02b4dd..52149d5 100644
--- a/rtl.h
+++ b/rtl.h
@@ -26,6 +26,7 @@
#include <rtl-fwd.h>
#include <rtl-obj.h>
#include <rtl-obj-cache.h>
+#include <rtl-obj-comp.h>
#include <rtl-unresolved.h>
#ifdef __cplusplus
@@ -93,6 +94,7 @@ struct rtems_rtl_data_s
rtems_rtl_obj_cache_t symbols; /**< Symbols object file cache. */
rtems_rtl_obj_cache_t strings; /**< Strings object file cache. */
rtems_rtl_obj_cache_t relocs; /**< Relocations object file cache. */
+ rtems_rtl_obj_comp_t decomp; /**< The decompression compressor. */
int last_errno; /**< Last error number. */
char last_error[64]; /**< Last error string. */
};
@@ -144,6 +146,21 @@ void rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols,
void rtems_rtl_obj_caches_flush (void);
/**
+ * Get the RTL decompressor setting the cache and the offset in the file the
+ * compressed stream starts. This call assmes the RTL is locked.
+ *
+ * @param decomp Pointer to the location to set the compressor into. Returns
+ * NULL is rtl is not initialised.
+ * @param cache The cache to read the file with. Saves needing an extrs buffer.
+ * @param offset The offset in the file the compressed stream starts.
+ */
+void rtems_rtl_obj_comp (rtems_rtl_obj_comp_t** decomp,
+ rtems_rtl_obj_cache_t* cache,
+ int fd,
+ int compression,
+ off_t offset);
+
+/**
* Lock the Run-time Linker.
*
* @return rtems_rtl_data_t* The RTL data after being locked.
diff --git a/wscript b/wscript
index d493e8c..f178bc9 100644
--- a/wscript
+++ b/wscript
@@ -47,7 +47,9 @@ def build(bld):
bld.includes = ['.',
'libbsd/include',
'libbsd/include/arch/' + arch]
- bld.defines = ['PACKAGE_VERSION="' + version + '"']
+ bld.defines = ['PACKAGE_VERSION="' + version + '"',
+ 'RTEMS_RTL_ELF_LOADER=1',
+ 'RTEMS_RTL_RAP_LOADER=1']
bld.cflags = ['-g']
#
@@ -74,6 +76,7 @@ def build(bld):
target = 'rtl',
includes = bld.includes,
cflags = bld.cflags,
+ defines = bld.defines,
source = ['dlfcn.c',
'dlfcn-shell.c',
'fastlz.c',
@@ -86,6 +89,8 @@ def build(bld):
'rtl-error.c',
'rtl-obj.c',
'rtl-obj-cache.c',
+ 'rtl-obj-comp.c',
+ 'rtl-rap.c',
'rtl-shell.c',
'rtl-string.c',
'rtl-sym.c',