summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-02-02 15:09:53 +1100
committerChris Johns <chrisj@rtems.org>2019-02-09 10:06:34 +1100
commit6c9f0176a916cdbe88e04417e7aa1405d80c500f (patch)
tree1846dd800a123e682f15e49a893426a9a6a064c4 /cpukit
parentlibdl: Add support for large memory programs (diff)
downloadrtems-6c9f0176a916cdbe88e04417e7aa1405d80c500f.tar.bz2
libdl: Add powerpc large memory and small data support.
- Add support for architecure sections that can be handled by the architecture back end. - Add trampoline/fixup support for PowerPC. This means the PowerPC now supports large memory loading of applications. - Add a bit allocator to manage small block based regions of memory. - Add small data (sdata/sbss) support for the PowerPC. The support makes the linker allocated small data region of memory a global resource available to libdl loaded object files. Updates #3687 Updates #3685
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/Makefile.am1
-rw-r--r--cpukit/include/rtems/rtl/rtl-obj.h69
-rw-r--r--cpukit/include/rtems/rtl/rtl-trace.h1
-rw-r--r--cpukit/libdl/rtl-archive.c7
-rw-r--r--cpukit/libdl/rtl-bit-alloc.c197
-rw-r--r--cpukit/libdl/rtl-bit-alloc.h82
-rw-r--r--cpukit/libdl/rtl-elf.c59
-rw-r--r--cpukit/libdl/rtl-elf.h41
-rw-r--r--cpukit/libdl/rtl-error.c1
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c38
-rw-r--r--cpukit/libdl/rtl-mdreloc-bfin.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-h8300.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-i386.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-lm32.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-m68k.c36
-rw-r--r--cpukit/libdl/rtl-mdreloc-mips.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-moxie.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-powerpc.c359
-rw-r--r--cpukit/libdl/rtl-mdreloc-sparc.c32
-rw-r--r--cpukit/libdl/rtl-mdreloc-v850.c32
-rw-r--r--cpukit/libdl/rtl-obj.c77
-rw-r--r--cpukit/libdl/rtl-shell.c2
-rw-r--r--cpukit/libdl/rtl-unresolved.c2
23 files changed, 1099 insertions, 129 deletions
diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
index 8ea7cbbfb0..51ab18ca05 100644
--- a/cpukit/Makefile.am
+++ b/cpukit/Makefile.am
@@ -1141,6 +1141,7 @@ librtemscpu_a_SOURCES += libdl/rap-shell.c
librtemscpu_a_SOURCES += libdl/rtl-allocator.c
librtemscpu_a_SOURCES += libdl/rtl-alloc-heap.c
librtemscpu_a_SOURCES += libdl/rtl-archive.c
+librtemscpu_a_SOURCES += libdl/rtl-bit-alloc.c
librtemscpu_a_SOURCES += libdl/rtl.c
librtemscpu_a_SOURCES += libdl/rtl-chain-iterator.c
librtemscpu_a_SOURCES += libdl/rtl-debugger.c
diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index e01af20957..9c2b4f0300 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -87,25 +87,26 @@ typedef struct rtems_rtl_loader_table
/**
* Flags for the various section types.
*/
-#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */
-#define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */
-#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */
-#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
-#define RTEMS_RTL_OBJ_SECT_EH (1 << 4) /**< Section holds exception data. */
-#define RTEMS_RTL_OBJ_SECT_TLS (1 << 5) /**< Section holds TLS data. */
-#define RTEMS_RTL_OBJ_SECT_REL (1 << 6) /**< Section holds relocation recs. */
-#define RTEMS_RTL_OBJ_SECT_RELA (1 << 7) /**< Section holds reloc addend recs. */
-#define RTEMS_RTL_OBJ_SECT_SYM (1 << 8) /**< Section holds symbols. */
-#define RTEMS_RTL_OBJ_SECT_STR (1 << 9) /**< Section holds strings. */
-#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 10 /**< Section allocates runtime memory. */
-#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 11) /**< Section is loaded from object file. */
-#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 12) /**< Section is writable, ie data. */
-#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 13) /**< Section is executable. */
-#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 14) /**< Section is preset to zero. */
-#define RTEMS_RTL_OBJ_SECT_LINK (1 << 15) /**< Section is link-ordered. */
-#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 16) /**< Section contains constructors. */
-#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 17) /**< Section contains destructors. */
-#define RTEMS_RTL_OBJ_SECT_LOCD (1 << 18) /**< Section has been located. */
+#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */
+#define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */
+#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */
+#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
+#define RTEMS_RTL_OBJ_SECT_EH (1 << 4) /**< Section holds exception data. */
+#define RTEMS_RTL_OBJ_SECT_TLS (1 << 5) /**< Section holds TLS data. */
+#define RTEMS_RTL_OBJ_SECT_REL (1 << 6) /**< Section holds relocation recs. */
+#define RTEMS_RTL_OBJ_SECT_RELA (1 << 7) /**< Section holds reloc addend recs. */
+#define RTEMS_RTL_OBJ_SECT_SYM (1 << 8) /**< Section holds symbols. */
+#define RTEMS_RTL_OBJ_SECT_STR (1 << 9) /**< Section holds strings. */
+#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 10 /**< Section allocates runtime memory. */
+#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 11) /**< Section is loaded from object file. */
+#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 12) /**< Section is writable, ie data. */
+#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 13) /**< Section is executable. */
+#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 14) /**< Section is preset to zero. */
+#define RTEMS_RTL_OBJ_SECT_LINK (1 << 15) /**< Section is link-ordered. */
+#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 16) /**< Section contains constructors. */
+#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 17) /**< Section contains destructors. */
+#define RTEMS_RTL_OBJ_SECT_LOCD (1 << 18) /**< Section has been located. */
+#define RTEMS_RTL_OBJ_SECT_ARCH_ALLOC (1 << 19) /**< Section use arch allocator. */
/**
* Section types mask.
@@ -237,7 +238,7 @@ struct rtems_rtl_obj
/**
* A section handler is called once for each section that needs to be
- * processed by this handler.
+ * processed by this handler. The handler is specific to a task.
*
* @param obj The object file's descriptor the section belongs too.
* @param fd The file descriptor of the object file beling loaded.
@@ -377,6 +378,17 @@ static inline bool rtems_rtl_obj_has_ramp_space (const rtems_rtl_obj* obj,
}
/**
+ * Does the section require architecture specific allocations?
+ *
+ * @param sect The section.
+ * @retval bool Returns @true if the section requires arch allocation.
+ */
+static inline bool rtems_rtl_obj_sect_is_arch_alloc (rtems_rtl_obj_sect* sect)
+{
+ return (sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) != 0;
+}
+
+/**
* Allocate an object structure on the heap.
*
* @retval NULL No memory for the object.
@@ -729,6 +741,23 @@ bool rtems_rtl_obj_load_symbols (rtems_rtl_obj* obj,
void* data);
/**
+ * Allocate the sections. If a handler is provided (not NULL) it is called for
+ * all section.
+ *
+ * @param obj The object file's descriptor.
+ * @param fd The object file's file descriptor.
+ * @param handler The object file's format specific allocation handler.
+ * @param data User specific data handle.
+ * @retval true The object has been sucessfully loaded.
+ * @retval false The load failed. The RTL error has been set.
+ */
+bool
+rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler handler,
+ void* data);
+
+/**
* Load the sections that have been allocated memory in the target. The bss
* type section does not load any data, it is set to 0. The text and data
* sections read the detault data from the object file into the target memory.
diff --git a/cpukit/include/rtems/rtl/rtl-trace.h b/cpukit/include/rtems/rtl/rtl-trace.h
index 6905e02245..cd3921400c 100644
--- a/cpukit/include/rtems/rtl/rtl-trace.h
+++ b/cpukit/include/rtems/rtl/rtl-trace.h
@@ -51,6 +51,7 @@ typedef uint32_t rtems_rtl_trace_mask;
#define RTEMS_RTL_TRACE_ARCHIVES (1UL << 12)
#define RTEMS_RTL_TRACE_ARCHIVE_SYMS (1UL << 13)
#define RTEMS_RTL_TRACE_DEPENDENCY (1UL << 14)
+#define RTEMS_RTL_TRACE_BIT_ALLOC (1UL << 15)
#define RTEMS_RTL_TRACE_ALL (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE | \
RTEMS_RTL_TRACE_GLOBAL_SYM | \
RTEMS_RTL_TRACE_ARCHIVE_SYMS))
diff --git a/cpukit/libdl/rtl-archive.c b/cpukit/libdl/rtl-archive.c
index be1199f62f..07d40187e1 100644
--- a/cpukit/libdl/rtl-archive.c
+++ b/cpukit/libdl/rtl-archive.c
@@ -21,6 +21,7 @@
#include <dirent.h>
#include <errno.h>
#include <fnmatch.h>
+#include <inttypes.h>
#include <stdio.h>
#include <string.h>
@@ -572,7 +573,7 @@ rtems_rtl_archives_close (rtems_rtl_archives* archives)
{
rtems_chain_node* node;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
- printf ("rtl: archive: close: count=%ds\n",
+ printf ("rtl: archive: close: count=%zu\n",
rtems_chain_node_count_unprotected (&archives->archives));
node = rtems_chain_first (&archives->archives);
while (!rtems_chain_is_tail (&archives->archives, node))
@@ -591,7 +592,7 @@ rtems_rtl_archives_remove (rtems_rtl_archives* archives)
{
rtems_chain_node* node = rtems_chain_first (&archives->archives);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
- printf ("rtl: archive: refresh: remove: checking %d archive(s)\n",
+ printf ("rtl: archive: refresh: remove: checking %zu archive(s)\n",
rtems_chain_node_count_unprotected (&archives->archives));
while (!rtems_chain_is_tail (&archives->archives, node))
{
@@ -716,7 +717,7 @@ rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
archive->symbols.base,
archive->symbols.entries,
archive->symbols.names,
- (archive->symbols.entries + 1) * 4,
+ (unsigned int) (archive->symbols.entries + 1) * 4,
archive->symbols.symbols);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVE_SYMS) &&
diff --git a/cpukit/libdl/rtl-bit-alloc.c b/cpukit/libdl/rtl-bit-alloc.c
new file mode 100644
index 0000000000..b7871f227b
--- /dev/null
+++ b/cpukit/libdl/rtl-bit-alloc.c
@@ -0,0 +1,197 @@
+/*
+ * COPYRIGHT (c) 2019 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.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor Bit Allocator
+ *
+ * A configurable allocator for small peices of memory where embedding
+ * control blocks into the memory are not viable. The amount of memory
+ * should be small and the minimum allocator a 32bit work or higher.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rtems/rtl/rtl-allocator.h>
+#include "rtl-bit-alloc.h"
+#include "rtl-error.h"
+#include <rtems/rtl/rtl-trace.h>
+
+#define BITS_PER_WORD (sizeof (uint32_t) * 8)
+
+static size_t
+bit_blocks (rtems_rtl_bit_alloc* balloc, size_t size)
+{
+ if (size == 0)
+ return 0;
+ return ((size - 1) / balloc->block_size) + 1;
+}
+
+static size_t
+bit_word (size_t bit)
+{
+ return bit / BITS_PER_WORD;
+}
+
+static size_t
+bit_offset (size_t bit)
+{
+ return bit % (sizeof (uint32_t) * 8);
+}
+
+static uint32_t
+bit_mask (size_t bit)
+{
+ return 1 << bit_offset (bit);
+}
+
+static void
+bit_set (rtems_rtl_bit_alloc* balloc, size_t start, size_t bits)
+{
+ size_t b;
+ for (b = start; b < (start + bits); ++b)
+ balloc->bits[bit_word (b)] |= bit_mask (b);
+}
+
+static void
+bit_clear (rtems_rtl_bit_alloc* balloc, size_t start, size_t bits)
+{
+ size_t b;
+ for (b = start; b < (start + bits); ++b)
+ balloc->bits[bit_word (b)] &= ~bit_mask (b);
+}
+
+static ssize_t
+bit_find_clear (rtems_rtl_bit_alloc* balloc, size_t blocks)
+{
+ size_t base = 0;
+ size_t clear = 0;
+ size_t b;
+
+ for (b = 0; b < balloc->blocks; ++b)
+ {
+ if (balloc->bits[b] != 0xffffffff)
+ {
+ uint32_t word = balloc->bits[b];
+ size_t o;
+ for (o = 0; o < BITS_PER_WORD; ++o, word >>= 1)
+ {
+ if ((word & 1) == 0)
+ {
+ if (clear == 0)
+ base = (b * BITS_PER_WORD) + o;
+ ++clear;
+ if (clear == blocks)
+ return base;
+ }
+ else
+ {
+ clear = 0;
+ base = 0;
+ }
+ }
+ }
+ else
+ {
+ clear = 0;
+ base = 0;
+ }
+ }
+
+ return -1;
+}
+
+rtems_rtl_bit_alloc*
+rtems_rtl_bit_alloc_open (void* base, size_t size, size_t block_size, size_t used)
+{
+ rtems_rtl_bit_alloc* balloc;
+ const size_t base_size = base == NULL ? size : 0;;
+ const size_t blocks = (size / block_size) / BITS_PER_WORD;
+ const size_t bit_bytes = blocks * sizeof(uint32_t);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_BIT_ALLOC))
+ printf ("rtl: balloc: open: base=%p size=%zu" \
+ " block-size=%zu blocks=%zu used=%zu\n",
+ base, size, block_size, blocks, used);
+
+ if (size == 0)
+ {
+ rtems_rtl_set_error (ENOMEM, "bit allocator size is 0");
+ return false;
+ }
+
+ if (used > size)
+ {
+ rtems_rtl_set_error (ENOMEM, "bad bit allocator used value");
+ return false;
+ }
+
+ balloc = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ sizeof (rtems_rtl_bit_alloc) + bit_bytes + base_size,
+ true);
+ if (balloc == NULL)
+ {
+ rtems_rtl_set_error (ENOMEM, "not bit allocator memory");
+ return NULL;
+ }
+
+ balloc->base =
+ base == NULL ? ((void*) balloc) + sizeof (rtems_rtl_bit_alloc) + bit_bytes: base;
+ balloc->size = size;
+ balloc->bits = ((void*) balloc) + sizeof (rtems_rtl_bit_alloc);
+ balloc->block_size = block_size;
+ balloc->blocks = blocks;
+
+ bit_set (balloc, 0, bit_blocks (balloc, used));
+
+ return balloc;
+}
+
+void
+rtems_rtl_bit_alloc_close (rtems_rtl_bit_alloc* balloc)
+{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_BIT_ALLOC))
+ printf ("rtl: balloc: close: base=%p size=%zu\n",
+ balloc->base, balloc->size);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, balloc);
+}
+
+void*
+rtems_rtl_bit_alloc_balloc (rtems_rtl_bit_alloc* balloc, size_t size)
+{
+ size_t blocks = bit_blocks (balloc, size);
+ ssize_t block = bit_find_clear (balloc, blocks);
+ if (block < 0)
+ return NULL;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_BIT_ALLOC))
+ printf ("rtl: balloc: balloc: size=%zu blocks=%zu block=%zi\n",
+ size, blocks, block);
+ bit_set (balloc, block, blocks);
+ return (void*) (balloc->base + (block * balloc->block_size));
+}
+
+void
+rtems_rtl_bit_alloc_bfree (rtems_rtl_bit_alloc* balloc, void* addr, size_t size)
+{
+ const uint8_t* a = (const uint8_t*) addr;
+ if (addr != NULL && a >= balloc->base && a < balloc->base + balloc->size)
+ {
+ size_t block = bit_blocks (balloc, a - balloc->base);
+ size_t blocks = bit_blocks (balloc, size);
+ bit_clear (balloc, block, blocks);
+ }
+}
diff --git a/cpukit/libdl/rtl-bit-alloc.h b/cpukit/libdl/rtl-bit-alloc.h
new file mode 100644
index 0000000000..d977473a96
--- /dev/null
+++ b/cpukit/libdl/rtl-bit-alloc.h
@@ -0,0 +1,82 @@
+/*
+ * COPYRIGHT (c) 2019 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.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Bit Allocator Header
+ */
+
+#if !defined (_RTEMS_RTL_BIT_ALLOC_H_)
+#define _RTEMS_RTL_BIT_ALLOC_H_
+
+#include <rtems/rtl/rtl-fwd.h>
+#include <rtems/rtl/rtl-obj-fwd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Bit Allocator data
+ */
+typedef struct rtems_rtl_bit_alloc
+{
+ uint8_t* base; /**< The memory being allocated. */
+ size_t size; /**< The number of bytes of memory being managed. */
+ uint32_t* bits; /**< The bit map indicating which blocks are allocated. */
+ size_t block_size; /**< The size of a block, the minimum allocation unit. */
+ size_t blocks; /**< The number of blocks in the memory. */
+} rtems_rtl_bit_alloc;
+
+/**
+ * Open a bit allocator. The allocator allocates block_size pieces of the memory
+ * being managed.
+ *
+ * @param base The memory to managem NULL to allocate a piece of memory.
+ * @param size The size of the memory being managed in bytes.
+ * @param block_size The minimum allocation unit in bytes.
+ * @param used The amount of memory already in use in bytes.
+ * @retval rtems_rtl_bit_alloc The bit allocator structure.
+ */
+rtems_rtl_bit_alloc* rtems_rtl_bit_alloc_open (void* base,
+ size_t size,
+ size_t block_size,
+ size_t used);
+
+/**
+ * Close the bit allocator.
+ *
+ * @param balloc The allocator to close.
+ */
+
+void rtems_rtl_bit_alloc_close (rtems_rtl_bit_alloc* balloc);
+
+/**
+ * Allocate a piece of memory being managed. The size is in bytes are is rounded
+ * up the next block size.
+ *
+ * @param balloc The allocator.
+ * @param size Number of bytes to allocate.
+ * @return void* The memory if the allocation is successful else NULL if there
+ * is no more memory.
+ */
+void* rtems_rtl_bit_alloc_balloc (rtems_rtl_bit_alloc* balloc, size_t size);
+
+/**
+ * Free an allocated memory block. The size is required because the allocator does not
+ * contain any state information.
+ */
+void rtems_rtl_bit_alloc_bfree (rtems_rtl_bit_alloc* balloc, void* addr, size_t size);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index e65c70308d..54ea1464cc 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -474,7 +474,6 @@ rtems_rtl_elf_relocs_parser (rtems_rtl_obj* obj,
{
bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
rtems_rtl_elf_reloc_parser, data);
- rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
return r;
}
@@ -603,10 +602,11 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
(ELF_ST_TYPE (symbol.st_info) == STT_COMMON)))
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
- printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d\n",
+ printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d name:%d\n",
sym, (int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info),
- (int) symbol.st_size, (int) symbol.st_value);
+ (int) symbol.st_size, (int) symbol.st_value,
+ (int) symbol.st_name);
/*
* If the size is zero this is the first entry, it defines the common
* section's aligment. The symbol's value is the alignment.
@@ -953,6 +953,36 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
}
static bool
+rtems_rtl_elf_arch_alloc (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ void* data)
+{
+ if (rtems_rtl_obj_sect_is_arch_alloc (sect))
+ return rtems_rtl_elf_arch_section_alloc (obj, sect);
+ return true;
+}
+
+static bool
+rtems_rtl_elf_arch_free (rtems_rtl_obj* obj)
+{
+ int index = -1;
+ while (true)
+ {
+ rtems_rtl_obj_sect* sect;
+ sect = rtems_rtl_obj_find_section_by_mask (obj,
+ index,
+ RTEMS_RTL_OBJ_SECT_ARCH_ALLOC);
+ if (sect == NULL)
+ break;
+ if (!rtems_rtl_elf_arch_section_free (obj, sect))
+ return false;
+ index = sect->section;
+ }
+ return true;
+}
+
+static bool
rtems_rtl_elf_loader (rtems_rtl_obj* obj,
int fd,
rtems_rtl_obj_sect* sect,
@@ -1168,6 +1198,22 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
flags |= RTEMS_RTL_OBJ_SECT_EH;
}
+ /*
+ * Architecture specific parsing. Modified or extends the flags.
+ */
+ flags = rtems_rtl_elf_arch_parse_section (obj, section, name, &shdr, flags);
+ if (flags == 0)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
+ printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
+ section, (int) shdr.sh_type, (int) shdr.sh_flags);
+ rtems_rtl_set_error (ENOMEM, "invalid architecture section: %s", name);
+ return false;
+ }
+
+ /*
+ * Add the section.
+ */
if (!rtems_rtl_obj_add_section (obj, section, name,
shdr.sh_size, shdr.sh_offset,
shdr.sh_addralign, shdr.sh_link,
@@ -1411,6 +1457,12 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
obj->entry = (void*)(uintptr_t) ehdr.e_entry;
/*
+ * Allocate the sections.
+ */
+ if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
+ return false;
+
+ /*
* Load the sections and symbols and then relocation to the base address.
*/
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
@@ -1453,6 +1505,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
bool
rtems_rtl_elf_file_unload (rtems_rtl_obj* obj)
{
+ rtems_rtl_elf_arch_free (obj);
rtems_rtl_elf_unwind_deregister (obj);
return true;
}
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index d781bfb3a4..73d1e01bb1 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -70,7 +70,7 @@ typedef struct rtems_rtl_mdreloc_trmap
/**
* Architecture specific handler to translate unknown section flags to RTL
- * section flags.
+ * section flags. If this function returns 0 an error is raised.
*
* @param obj The object file being relocated.
* @param shdr The ELF section header.
@@ -81,6 +81,45 @@ uint32_t rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
const Elf_Shdr* shdr);
/**
+ * Architecture specific handler to parse the section and add any flags that
+ * may be need to handle the section.
+ *
+ * @param obj The object file being relocated.
+ * @param seciton The section index.
+ * @param name The name of the section
+ * @param shdr The ELF section header.
+ * @param flags The standard ELF parsed flags.
+ * @retval uint32_t Extra RTL object file flags.
+ */
+uint32_t rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags);
+
+/**
+ * Architecture specific handler to allocate a section. Some sections are
+ * specific to an architecture and need special allocators.
+ *
+ * @param obj The object file being relocated.
+ * @param sect The section data.
+ * @retval true The allocator was successful.
+ */
+bool rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect);
+
+/**
+ * Architecture specific handler to free a section. Some sections are
+ * specific to an architecture and need special allocators.
+ *
+ * @param obj The object file being relocated.
+ * @param sect The section data.
+ * @retval true The allocator was successful.
+ */
+bool rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect);
+
+/**
* Architecture specific handler to check is a relocation record's type is
* required to resolve a symbol.
*
diff --git a/cpukit/libdl/rtl-error.c b/cpukit/libdl/rtl-error.c
index 7b72c0a26d..acd89ac07d 100644
--- a/cpukit/libdl/rtl-error.c
+++ b/cpukit/libdl/rtl-error.c
@@ -44,6 +44,7 @@ rtems_rtl_get_error (char* message, size_t max_message)
if (rtl != NULL)
{
int last_errno = rtl->last_errno;
+ rtl->last_errno = 0;
strlcpy (message, rtl->last_error, max_message);
rtems_rtl_unlock ();
return last_errno;
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index 19a5904a25..b0c55c257a 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -109,6 +109,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return flags;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
@@ -152,7 +184,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
}
static bool
-rtems_rtl_elf_relor_rel (rtems_rtl_obj* obj,
+rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -493,7 +525,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Byte syminfo,
const Elf_Word symvalue)
{
- return rtems_rtl_elf_relor_rel (obj,
+ return rtems_rtl_elf_reloc_rel (obj,
rel,
sect,
symname,
@@ -510,7 +542,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Byte syminfo,
const Elf_Word symvalue)
{
- return rtems_rtl_elf_relor_rel (obj,
+ return rtems_rtl_elf_reloc_rel (obj,
rel,
sect,
symname,
diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c
index b4c20fac24..af130276a4 100644
--- a/cpukit/libdl/rtl-mdreloc-bfin.c
+++ b/cpukit/libdl/rtl-mdreloc-bfin.c
@@ -16,6 +16,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c
index e0cb826dc8..4a12f34f36 100644
--- a/cpukit/libdl/rtl-mdreloc-h8300.c
+++ b/cpukit/libdl/rtl-mdreloc-h8300.c
@@ -19,6 +19,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
index 016f99f379..576914cf04 100644
--- a/cpukit/libdl/rtl-mdreloc-i386.c
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -26,6 +26,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c
index cf64ea8fb3..9f4606ebad 100644
--- a/cpukit/libdl/rtl-mdreloc-lm32.c
+++ b/cpukit/libdl/rtl-mdreloc-lm32.c
@@ -19,6 +19,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c
index 1981e93d56..21a60ee62a 100644
--- a/cpukit/libdl/rtl-mdreloc-m68k.c
+++ b/cpukit/libdl/rtl-mdreloc-m68k.c
@@ -39,6 +39,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
@@ -156,12 +188,12 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
break;
default:
- printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
"contents = %p\n",
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)*where);
rtems_rtl_set_error (EINVAL,
- "%s: Unsupported relocation type %ld "
+ "%s: Unsupported relocation type %d "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
return false;
diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c
index 4860fdfe72..f01a6552a5 100644
--- a/cpukit/libdl/rtl-mdreloc-mips.c
+++ b/cpukit/libdl/rtl-mdreloc-mips.c
@@ -19,6 +19,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c
index cc0558eaa5..68fa2d2a16 100644
--- a/cpukit/libdl/rtl-mdreloc-moxie.c
+++ b/cpukit/libdl/rtl-mdreloc-moxie.c
@@ -20,6 +20,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
index b205ed5215..5c52823a0f 100644
--- a/cpukit/libdl/rtl-mdreloc-powerpc.c
+++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
@@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <rtems/rtl/rtl.h>
+#include "rtl-bit-alloc.h"
#include "rtl-elf.h"
#include "rtl-error.h"
#include <rtems/rtl/rtl-trace.h>
@@ -23,6 +24,57 @@
((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
#define l(x) ((u_int32_t)(x) & 0xffff)
+/*
+ * SDATA allocator.
+ */
+static rtems_rtl_bit_alloc* sdata;
+
+static Elf_Addr
+get_sda_base (void)
+{
+ uint32_t sda_base;
+ __asm__ volatile (" mr %0, 13\n" : "=r" (sda_base));
+ return sda_base;
+}
+
+/*
+ * Access the variables via asm statements to avoid any fix up issues
+ * generated by the C compiler which thinks they belong in the .sdata
+ * section.
+ */
+
+#define GET_ADDR(_l, _v) \
+ __asm__ volatile (" lis %0, " #_l "@h\n" \
+ " ori %0, %0, " #_l "@l\n" : "=r" (_v))
+
+static void*
+get_sdata_start (void)
+{
+ Elf_Addr addr;
+ GET_ADDR(__SDATA_START__, addr);
+ return (void*) addr;
+}
+
+static size_t
+get_sdata_sbss_size (void)
+{
+ Elf_Addr sdata_begin;
+ Elf_Addr sbss_end;
+ GET_ADDR(bsp_section_sdata_begin, sdata_begin);
+ GET_ADDR(bsp_section_sbss_end, sbss_end);
+ return sbss_end - sdata_begin;
+}
+
+static size_t
+get_sdata_libdl_size (void)
+{
+ Elf_Addr begin;
+ Elf_Addr end;
+ GET_ADDR(bsp_section_sdata_libdl_begin, begin);
+ GET_ADDR(bsp_section_sdata_libdl_end, end);
+ return end - begin;
+}
+
uint32_t
rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
const Elf_Shdr* shdr)
@@ -30,6 +82,75 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ struct {
+ const char* label;
+ size_t len;
+ } prefix[] = {
+ #define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 }
+ SEPARATED_PREFIX (".sdata"),
+ SEPARATED_PREFIX (".sbss"),
+ };
+ const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]);
+ size_t p;
+ for (p = 0; p < prefixes; ++p)
+ {
+ if (strncmp (name, prefix[p].label, prefix[p].len) == 0)
+ return flags | RTEMS_RTL_OBJ_SECT_ARCH_ALLOC;
+ }
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: section: arch: alloc: name=%s size=%zu flags=%08" PRIx32 \
+ " order=%i link=%d info=%d\n",
+ sect->name, sect->size, sect->flags, sect->load_order,
+ sect->link, sect->info);
+
+ if (sdata == NULL)
+ {
+ sdata = rtems_rtl_bit_alloc_open (get_sdata_start (),
+ get_sdata_libdl_size (),
+ sizeof (uint32_t),
+ get_sdata_sbss_size ());
+ if (sdata == NULL)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for sdata allocator");
+ return false;
+ }
+ }
+
+ sect->base = rtems_rtl_bit_alloc_balloc (sdata, sect->size);
+ if (sect->base == NULL)
+ {
+ rtems_rtl_set_error (ENOMEM, "no .sdata memory: %s", sect->name);
+ return false;
+ }
+
+ return true;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
+ printf ("rtl: section: arch: free: name=%s size=%zu\n", sect->name, sect->size);
+ if (sdata != NULL)
+ rtems_rtl_bit_alloc_bfree (sdata, sect->base, sect->size);
+ return true;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
@@ -40,35 +161,51 @@ size_t
rtems_rtl_elf_relocate_tramp_max_size (void)
{
/*
- * Disable by returning 0.
+ * We have 4 instructions and each instruction is 32bits.
*/
- return 0;
+ return 4 * 4;
}
-bool
-rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
- const Elf_Rela* rela,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue)
+static void*
+set_veneer (void* tramopline, Elf_Addr target)
{
- (void) obj;
- (void) rela;
- (void) sect;
- (void) symname;
- (void) syminfo;
- (void) symvalue;
- return true;
+ /*
+ * http://shell-storm.org/online/Online-Assembler-and-Disassembler/
+ *
+ * lis 12,0x1234
+ * ori 12,12,0x5678
+ * mtctr 12
+ * bctr
+ */
+#if COMPILE_ASM
+ asm volatile (" lis 12,0x1234\n" \
+ " ori 12,12,0x5678\n" \
+ " mtctr 12\n" \
+ " bctr\n");
+#endif
+ uint32_t* tramp = (uint32_t*) tramopline;
+ *tramp++ = 0x3d800000 | (target >> 16);
+ *tramp++ = 0x618c0000 | (target & 0xffff);
+ *tramp++ = 0x7d8903a6;
+ *tramp++ = 0x4e800420;
+ return tramp;
}
-bool
-rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
- const Elf_Rela* rela,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue)
+static size_t
+get_veneer_size (int type)
+{
+ (void) type;
+ return rtems_rtl_elf_relocate_tramp_max_size ();
+}
+
+static bool
+rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue,
+ const bool parsing)
{
Elf_Addr* where;
Elf_Word tmp;
@@ -84,10 +221,12 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
/*
* value:1; Field: word32; Expression: S + A
*/
- *where = symvalue + rela->r_addend;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: ADDR32 %p @ %p in %s\n",
- (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ *where = symvalue + rela->r_addend;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR32 %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(14):
@@ -107,47 +246,67 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
}
tmp = (symvalue + rela->r_addend) >> 2;
if (tmp > ((1<<bits) - 1 )) {
- printf("Overflow ADDR14/ADDR24\n");
- return false;
+ Elf_Word tramp_addr;
+ size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
+ if (parsing) {
+ obj->tramp_size += tramp_size;
+ return true;
+ }
+ tramp_addr = (Elf_Addr) obj->tramp_brk;
+ obj->tramp_brk = set_veneer(obj->tramp_brk,
+ symvalue + rela->r_addend);
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (tramp_addr + rela->r_addend) & mask;
+ }
+ else {
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (symvalue + rela->r_addend) & mask;
+ }
+
+ if (!parsing) {
+ *where = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
}
- tmp = *where;
- tmp &= ~mask;
- tmp |= (symvalue + rela->r_addend) & mask;
- *where = tmp;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
break;
case R_TYPE(16_HA):
/*
* value:6; Field:half16; Expression: #ha(S+A)
*/
-
- tmp = symvalue + rela->r_addend;
- *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: 16_HA %p @ %p in %s\n",
- (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ tmp = symvalue + rela->r_addend;
+ *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_HA %p @ %p in %s\n",
+ (void *)*(where), where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(16_HI):
/*
* value:5; Field:half16; Expression: #hi(S+A)
*/
- *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: 16_HI %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_HI %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(16_LO):
/*
* value:4; Field:half16; Expression: #lo(S+A)
*/
- *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: 16_LO %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: 16_LO %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(REL14):
@@ -170,27 +329,44 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
((Elf_Sword)tmp < -(1<<(bits-1)))) {
- printf("Overflow REL14/REL24\n");
- return false;
+ Elf_Word tramp_addr;
+ size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
+ if (parsing) {
+ obj->tramp_size += tramp_size;
+ return true;
+ }
+ tramp_addr = (Elf_Addr) obj->tramp_brk;
+ obj->tramp_brk = set_veneer(obj->tramp_brk,
+ symvalue + rela->r_addend);
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (tramp_addr + rela->r_addend - (Elf_Addr)where) & mask;
+ }
+ else
+ {
+ tmp = *where;
+ tmp &= ~mask;
+ tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
}
- tmp = *where;
- tmp &= ~mask;
- tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
- *where = tmp;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: REL24/REL14 %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ *where = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL24/REL14 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(REL32):
/*
* value:26; Field:word32*; Expression:S+A-P
*/
- *where = symvalue + rela->r_addend - (Elf_Addr)where;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: REL32 %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ *where = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL32 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(SDAREL16):
@@ -198,19 +374,22 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
* A sign-extended 16 bit value relative to _SDA_BASE_, for use with
* small data items.
*/
- mask = 0xffff;
- tmp = *((Elf32_Half*) where);
- tmp &= ~mask;
- tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask;
- *((Elf32_Half*) where) = tmp;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: SDAREL16 %p @ %p in %s\n",
- (void *) (uintptr_t) *((Elf32_Half*) where),
- where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ Elf_Addr sda_base = get_sda_base ();
+ mask = 0xffff;
+ tmp = *((Elf32_Half*) where);
+ tmp &= ~mask;
+ tmp |= (symvalue + rela->r_addend - sda_base) & mask;
+ *((Elf32_Half*) where) = tmp;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: SDAREL16 %p @ %p in %s\n",
+ (void *) (uintptr_t) *((Elf32_Half*) where),
+ where, rtems_rtl_obj_oname (obj));
+ }
break;
default:
- printf ("rtl: reloc unknown: sym = %lu, type = %" PRIu32 ", offset = %p, "
+ printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p, "
"contents = %p\n",
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)*where);
@@ -224,6 +403,40 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
}
bool
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ return rtems_rtl_elf_reloc_rela (obj,
+ rela,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ true);
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue)
+{
+ return rtems_rtl_elf_reloc_rela (obj,
+ rela,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ false);
+}
+
+bool
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
index bc05392659..f76da575e4 100644
--- a/cpukit/libdl/rtl-mdreloc-sparc.c
+++ b/cpukit/libdl/rtl-mdreloc-sparc.c
@@ -138,6 +138,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c
index 2aca5e0270..93e531b40e 100644
--- a/cpukit/libdl/rtl-mdreloc-v850.c
+++ b/cpukit/libdl/rtl-mdreloc-v850.c
@@ -20,6 +20,38 @@ rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
return 0;
}
+uint32_t
+rtems_rtl_elf_arch_parse_section (const rtems_rtl_obj* obj,
+ int section,
+ const char* name,
+ const Elf_Shdr* shdr,
+ const uint32_t flags)
+{
+ (void) obj;
+ (void) section;
+ (void) name;
+ (void) shdr;
+ return flags;
+}
+
+bool
+rtems_rtl_elf_arch_section_alloc (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
+bool
+rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
+ rtems_rtl_obj_sect* sect)
+{
+ (void) obj;
+ (void) sect;
+ return false;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 0a7763b3b2..15e5bf1137 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -300,11 +300,14 @@ typedef struct
static bool
rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data)
{
- rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
- rtems_rtl_obj_sect_summer_data* summer = data;
- if ((sect->flags & summer->mask) == summer->mask)
- summer->size =
- rtems_rtl_obj_align (summer->size, sect->alignment) + sect->size;
+ rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
+ if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
+ {
+ rtems_rtl_obj_sect_summer_data* summer = data;
+ if ((sect->flags & summer->mask) == summer->mask)
+ summer->size =
+ rtems_rtl_obj_align (summer->size, sect->alignment) + sect->size;
+ }
return true;
}
@@ -821,7 +824,9 @@ rtems_rtl_obj_relocate (rtems_rtl_obj* obj,
const uint32_t flags = (RTEMS_RTL_OBJ_SECT_LOAD |
RTEMS_RTL_OBJ_SECT_REL |
RTEMS_RTL_OBJ_SECT_RELA);
- return rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
+ bool r = rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
+ rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
+ return r;
}
/**
@@ -993,7 +998,7 @@ rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj)
}
}
-static size_t
+static bool
rtems_rtl_obj_sections_loader (uint32_t mask,
rtems_rtl_obj* obj,
int fd,
@@ -1004,26 +1009,27 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
rtems_chain_control* sections = &obj->sections;
rtems_chain_node* node = rtems_chain_first (sections);
size_t base_offset = 0;
- bool first = true;
int order = 0;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
+
while (!rtems_chain_is_tail (sections, node))
{
rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
- if ((sect->size != 0) && ((sect->flags & mask) != 0))
+ if ((sect->size != 0) && ((sect->flags & mask) == mask))
{
if (sect->load_order == order)
{
- if (!first)
+ if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
+ {
base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
-
- first = false;
-
- sect->base = base + base_offset;
+ sect->base = base + base_offset;
+ }
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
- printf ("rtl: loading:%2d: %s -> %8p (s:%zi f:%04" PRIx32
+ printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
" a:%" PRIu32 " l:%02d)\n",
order, sect->name, sect->base, sect->size,
sect->flags, sect->alignment, sect->link);
@@ -1038,7 +1044,7 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
}
else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
{
- memset (base + base_offset, 0, sect->size);
+ memset (sect->base, 0, sect->size);
}
else
{
@@ -1065,10 +1071,10 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
}
bool
-rtems_rtl_obj_load_sections (rtems_rtl_obj* obj,
- int fd,
- rtems_rtl_obj_sect_handler handler,
- void* data)
+rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler handler,
+ void* data)
{
size_t text_size;
size_t const_size;
@@ -1092,6 +1098,22 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj* obj,
obj->bss_size = bss_size;
/*
+ * Perform any specific allocations for sections.
+ */
+ if (handler != NULL)
+ {
+ if (!rtems_rtl_obj_section_handler (RTEMS_RTL_OBJ_SECT_TYPES,
+ obj,
+ fd,
+ handler,
+ data))
+ {
+ obj->exec_size = 0;
+ return false;
+ }
+ }
+
+ /*
* Let the allocator manage the actual allocation. The user can use the
* standard heap or provide a specific allocator with memory protection.
*/
@@ -1129,10 +1151,21 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj* obj,
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj);
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH, obj);
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA, obj);
+ rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, obj);
+ return true;
+}
+
+bool
+rtems_rtl_obj_load_sections (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect_handler handler,
+ void* data)
+{
/*
- * Load all text then data then bss sections in seperate operations so each
- * type of section is grouped together.
+ * Load all text, data and bsssections in seperate operations so each type of
+ * section is grouped together. Finish by loading any architecure specific
+ * sections.
*/
if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT,
obj, fd, obj->text_base, handler, data) ||
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index ab5553174b..7458fb5608 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -175,7 +175,7 @@ rtems_rtl_dependencies (rtems_rtl_obj* obj,
{
rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
if (!dd->first)
- printf ("\n%-*c: ", dd->indent, ' ');
+ printf ("\n%-*c: ", (int) dd->indent, ' ');
else
dd->first = false;
printf ("%s", dependent->oname);
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index 0e70c5dacf..7ee572c351 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -700,7 +700,7 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
break;
case rtems_rtl_unresolved_symbol:
++dd->names;
- printf (" %3zu: 1: name: %3d refs:%4d: flags:%04x %s (%d)\n",
+ printf (" %3zu: 1: name: %3zu refs:%4d: flags:%04x %s (%d)\n",
dd->rec, dd->names,
rec->rec.name.refs,
rec->rec.name.flags,