summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/include/rtems/rtl/rtl-obj-fwd.h6
-rw-r--r--cpukit/include/rtems/rtl/rtl-obj.h109
-rw-r--r--cpukit/include/rtems/rtl/rtl-sym.h4
-rw-r--r--cpukit/include/rtems/rtl/rtl.h25
-rw-r--r--cpukit/libdl/rtl-elf.c346
-rw-r--r--cpukit/libdl/rtl-elf.h22
-rw-r--r--cpukit/libdl/rtl-obj.c141
-rw-r--r--cpukit/libdl/rtl-shell.c54
-rw-r--r--cpukit/libdl/rtl-unresolved.c4
-rw-r--r--cpukit/libdl/rtl.c48
-rw-r--r--testsuites/libtests/Makefile.am40
-rw-r--r--testsuites/libtests/configure.ac1
-rw-r--r--testsuites/libtests/dl02/dl-load.c11
-rw-r--r--testsuites/libtests/dl07/dl-load.c165
-rw-r--r--testsuites/libtests/dl07/dl-load.h21
-rw-r--r--testsuites/libtests/dl07/dl-o1.c56
-rw-r--r--testsuites/libtests/dl07/dl-o1.h22
-rw-r--r--testsuites/libtests/dl07/dl-o2.c51
-rw-r--r--testsuites/libtests/dl07/dl-o2.h23
-rw-r--r--testsuites/libtests/dl07/dl-o3.c59
-rw-r--r--testsuites/libtests/dl07/dl-o4.c53
-rw-r--r--testsuites/libtests/dl07/dl-o4.h27
-rw-r--r--testsuites/libtests/dl07/dl-o5.c52
-rw-r--r--testsuites/libtests/dl07/dl-o5.h28
-rw-r--r--testsuites/libtests/dl07/dl07.doc27
-rw-r--r--testsuites/libtests/dl07/dl07.scn510
-rw-r--r--testsuites/libtests/dl07/init.c90
27 files changed, 1853 insertions, 142 deletions
diff --git a/cpukit/include/rtems/rtl/rtl-obj-fwd.h b/cpukit/include/rtems/rtl/rtl-obj-fwd.h
index 39e28c58e1..6d41483aa2 100644
--- a/cpukit/include/rtems/rtl/rtl-obj-fwd.h
+++ b/cpukit/include/rtems/rtl/rtl-obj-fwd.h
@@ -27,6 +27,12 @@ struct rtems_rtl_obj_sect;
typedef struct rtems_rtl_obj_sect rtems_rtl_obj_sect;
/**
+ * The forward declaration of the obj depends structure.
+ */
+struct rtems_rtl_obj_depends;
+typedef struct rtems_rtl_obj_depends rtems_rtl_obj_depends;
+
+/**
* The forward declaration of the obj structure.
*/
struct rtems_rtl_obj;
diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index be77a81c9d..976d6c293f 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -139,12 +139,35 @@ struct rtems_rtl_obj_sect
};
/**
+ * Object file dependents. This is a list of tables of pointers to the object
+ * modules the object file depends on. The table is a list of tables because
+ * unresolved externals can exist when an object file is loaded and resolved
+ * later when the dependent object file is loaded.
+ */
+struct rtems_rtl_obj_depends
+{
+ rtems_chain_node node; /**< The node's link in the chain. */
+ size_t dependents; /**< The number of dependent object pointers. */
+ rtems_rtl_obj* depends[]; /**< Dependtent objects. More follow. */
+};
+
+/**
+ * Dependency iterator.
+ */
+typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj,
+ rtems_rtl_obj* dependent,
+ void* data);
+
+/**
* Object file descriptor flags.
*/
-#define RTEMS_RTL_OBJ_LOCKED (1 << 0) /**< Lock the object file so it cannot
- * be unloaded. */
-#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
- * external symbols. */
+#define RTEMS_RTL_OBJ_LOCKED (1 << 0) /**< Lock the object file so it cannot
+ * be unloaded. */
+#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
+ * external symbols. */
+#define RTEMS_RTL_OBJ_BASE (1 << 2) /**< The base image. */
+#define RTEMS_RTL_OBJ_RELOC_TAG (1 << 3) /**< Tag the object as visited when reloc
+ * parsing. */
/**
* RTL Object. There is one for each object module loaded plus one for the base
@@ -154,7 +177,8 @@ struct rtems_rtl_obj
{
rtems_chain_node link; /**< The node's link in the chain. */
uint32_t flags; /**< The status of the object file. */
- uint32_t users; /**< References to the object file. */
+ size_t users; /**< Users of this object file, number of loads. */
+ size_t refs; /**< References to the object file. */
int format; /**< The format of the object file. */
const char* fname; /**< The file name for the object. */
const char* oname; /**< The object file name. Can be
@@ -164,27 +188,28 @@ struct rtems_rtl_obj
* in a lib */
off_t ooffset; /**< The object offset in the archive. */
size_t fsize; /**< Size of the object file. */
- rtems_chain_control sections; /**< The sections of interest in the
- * object file. */
+ rtems_chain_control sections; /**< The sections of interest in the object
+ * file. */
+ rtems_chain_control dependents; /**< The dependent object files. */
rtems_rtl_obj_sym* local_table; /**< Local symbol table. */
size_t local_syms; /**< Local symbol count. */
size_t local_size; /**< Local symbol memory usage. */
rtems_rtl_obj_sym* global_table; /**< Global symbol table. */
size_t global_syms; /**< Global symbol count. */
size_t global_size; /**< Global symbol memory usage. */
- uint32_t unresolved; /**< The number of unresolved relocations. */
+ size_t unresolved; /**< The number of unresolved relocations. */
void* text_base; /**< The base address of the text section
* in memory. */
size_t text_size; /**< The size of the text section. */
void* const_base; /**< The base address of the const section
* in memory. */
- void* eh_base; /**< The base address of the eh section
- * in memory. */
+ void* eh_base; /**< The base address of the eh section in
+ * memory. */
size_t eh_size; /**< The size of the eh section. */
void* data_base; /**< The base address of the data section
* in memory. */
- void* bss_base; /**< The base address of the bss section
- * in memory. */
+ void* bss_base; /**< The base address of the bss section in
+ * memory. */
size_t bss_size; /**< The size of the bss section. */
size_t exec_size; /**< The amount of executable memory
* allocated */
@@ -192,9 +217,11 @@ struct rtems_rtl_obj
uint32_t checksum; /**< The checksum of the text sections. A
* zero means do not checksum. */
uint32_t* sec_num; /**< The sec nums of each obj. */
- uint32_t obj_num; /**< The count of elf files in an rtl obj. */
+ uint32_t obj_num; /**< The count of elf files in an rtl
+ * obj. */
struct link_map* linkmap; /**< For GDB. */
- void* loader; /**< The file details specific to a loader. */
+ void* loader; /**< The file details specific to a
+ * loader. */
};
/**
@@ -443,6 +470,46 @@ rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj
uint32_t mask);
/**
+ * Allocate a table for dependent objects.
+ *
+ * @param obj The object file's descriptor.
+ * @param dependents The size of the table.
+ * @retval true The table was allocated.
+ * @retval false The alloction failed.
+ */
+bool rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents);
+
+/**
+ * Erase the object file descriptor's dependents.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj);
+
+/**
+ * Add an object file to the dependents table.
+ *
+ * @param obj The object file's descriptor.
+ * @param dependent The dependent object file to add.
+ * @retval true The dependent has been added to the table.
+ * @retval false There is no space in the table.
+ */
+bool rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent);
+
+/**
+ * Iterate over the module dependenices.
+ *
+ * @param obj The object file's descriptor.
+ * @param handler The iterator handler. Returns true to end.
+ * @param data User data passed to the iterator.
+ * @retval true The iterator handler returned true.
+ * @retval false The iterator handler returned false.
+ */
+bool rtems_rtl_obj_iterate_dependents (rtems_rtl_obj* obj,
+ rtems_rtl_obj_depends_iterator iterator,
+ void* data);
+
+/**
* The text section size. Only use once all the sections has been added. It
* includes alignments between sections that are part of the object's text
* area. The consts sections are included in this section.
@@ -643,6 +710,20 @@ void rtems_rtl_obj_run_ctors (rtems_rtl_obj* obj);
void rtems_rtl_obj_run_dtors (rtems_rtl_obj* obj);
/**
+ * Increment the object file reference count.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj);
+
+/**
+ * Decrement the object file reference count.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj);
+
+/**
* Load the object file, reading all sections into memory, symbols and
* performing any relocation fixups.
*
diff --git a/cpukit/include/rtems/rtl/rtl-sym.h b/cpukit/include/rtems/rtl/rtl-sym.h
index be246a908d..aff9339ea1 100644
--- a/cpukit/include/rtems/rtl/rtl-sym.h
+++ b/cpukit/include/rtems/rtl/rtl-sym.h
@@ -92,7 +92,7 @@ bool rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
*
* @param name The name as an ASCIIZ string.
* @retval NULL No symbol found.
- * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ * @return rtems_rtl_obj_sym* Reference to the symbol.
*/
rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
@@ -102,7 +102,7 @@ rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
* @param obj The object file to search.
* @param name The name as an ASCIIZ string.
* @retval NULL No symbol found.
- * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ * @return rtems_rtl_obj_sym* Reference to the symbol.
*/
rtems_rtl_obj_sym* rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj,
const char* name);
diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h
index e30dba90ef..398ac2cd3f 100644
--- a/cpukit/include/rtems/rtl/rtl.h
+++ b/cpukit/include/rtems/rtl/rtl.h
@@ -28,6 +28,7 @@
#include <rtems/rtl/rtl-obj.h>
#include <rtems/rtl/rtl-obj-cache.h>
#include <rtems/rtl/rtl-obj-comp.h>
+#include <rtems/rtl/rtl-sym.h>
#include <rtems/rtl/rtl-unresolved.h>
#ifdef __cplusplus
@@ -71,6 +72,11 @@ extern "C" {
#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
/**
+ * The number of dependency record per block in the dependency table.
+ */
+#define RTEMS_RTL_DEPENDENCY_BLOCK_SIZE (16)
+
+/**
* The global debugger interface variable.
*/
extern struct r_debug _rtld_debug;
@@ -173,6 +179,16 @@ void rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp,
off_t offset);
/**
+ * Update the mask in the object files. You can clear flags and then set
+ * flags. A zero (0) does not clear or set the flags. This is global to all
+ * object files that are laoded.
+ *
+ * @param clear The flag's clear mask, a 0 does not clear any flags.
+ * @param set The flag's set mask, a 0 does not set any flags.
+ */
+void rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set);
+
+/**
* Lock the Run-time Linker.
*
* @return rtems_rtl_data* The RTL data after being locked.
@@ -207,6 +223,15 @@ rtems_rtl_obj* rtems_rtl_check_handle (void* handle);
rtems_rtl_obj* rtems_rtl_find_obj (const char* name);
/**
+ * Find the object file a symbol is exported from.
+ *
+ * @param sym The symbol to search with.
+ * @retval NULL No object file found.
+ * @return rtems_rtl_obj* Reference to the symbol.
+ */
+rtems_rtl_obj* rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym);
+
+/**
* Load an object file into memory relocating it. It will not be resolved
* against other symbols in other object files or the base image.
*
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index c1821bcfda..762130b9e7 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -64,31 +64,40 @@ rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
return true;
}
-bool
-rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
- const Elf_Sym* sym,
- const char* symname,
- Elf_Word* value)
+static bool
+rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
+ const Elf_Sym* sym,
+ const char* symname,
+ rtems_rtl_obj_sym** symbol,
+ Elf_Word* value)
{
rtems_rtl_obj_sect* sect;
- if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE ||
- sym->st_shndx == SHN_COMMON)
+ /*
+ * If the symbol type is STT_NOTYPE the symbol references a global
+ * symbol. The gobal symbol table is searched to find it and that value
+ * returned. If the symbol is local to the object module the section for the
+ * symbol is located and it's base added to the symbol's value giving an
+ * absolute location.
+ */
+ if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
{
/*
* Search the object file then the global table for the symbol.
*/
- rtems_rtl_obj_sym* symbol = rtems_rtl_symbol_obj_find (obj, symname);
- if (!symbol)
+ *symbol = rtems_rtl_symbol_obj_find (obj, symname);
+ if (!*symbol)
{
rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
return false;
}
- *value = (Elf_Addr) symbol->value;
+ *value = (Elf_Addr) (*symbol)->value;
return true;
}
+ *symbol = NULL;
+
sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
if (!sect)
{
@@ -100,11 +109,161 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
return true;
}
+/**
+ * Relocation worker routine.
+ */
+typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj* obj,
+ bool is_rela,
+ void* relbuf,
+ rtems_rtl_obj_sect* targetsect,
+ rtems_rtl_obj_sym* symbol,
+ Elf_Sym* sym,
+ const char* symname,
+ Elf_Word symvalue,
+ bool resolved,
+ void* data);
+
+/**
+ * Relocation parser data.
+ */
+typedef struct
+{
+ size_t dependents; /**< The number of dependent object files. */
+ size_t unresolved; /**< The number of unresolved symbols. */
+} rtems_rtl_elf_reloc_data;
+
+static bool
+rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
+ bool is_rela,
+ void* relbuf,
+ rtems_rtl_obj_sect* targetsect,
+ rtems_rtl_obj_sym* symbol,
+ Elf_Sym* sym,
+ const char* symname,
+ Elf_Word symvalue,
+ bool resolved,
+ void* data)
+{
+ rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
+ /*
+ * If the symbol has been resolved and there is a symbol name it is a global
+ * symbol and from another object file so add it as a dependency.
+ */
+ if (!resolved)
+ {
+ ++rd->unresolved;
+ }
+ else if (resolved && symname != NULL)
+ {
+ /*
+ * Find the symbol's object file. It cannot be NULL so ignore that result
+ * if returned, it means something is corrupted. We are in an iterator.
+ */
+ rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
+ if (sobj != NULL)
+ {
+ /*
+ * A dependency is not the base kernel image or itself. Tag the object as
+ * having been visited so we count it only once.
+ */
+ if (sobj != rtems_rtl_baseimage () && obj != sobj &&
+ (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
+ {
+ sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
+ ++rd->dependents;
+ }
+ }
+ }
+ return true;
+}
+
+static bool
+rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
+ bool is_rela,
+ void* relbuf,
+ rtems_rtl_obj_sect* targetsect,
+ rtems_rtl_obj_sym* symbol,
+ Elf_Sym* sym,
+ const char* symname,
+ Elf_Word symvalue,
+ bool resolved,
+ void* data)
+{
+ const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+ const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+
+ if (!resolved)
+ {
+ uint16_t flags = 0;
+ rtems_rtl_word rel_words[3];
+
+ if (is_rela)
+ {
+ flags = 1;
+ rel_words[REL_R_OFFSET] = rela->r_offset;
+ rel_words[REL_R_INFO] = rela->r_info;
+ rel_words[REL_R_ADDEND] = rela->r_addend;
+ }
+ else
+ {
+ rel_words[REL_R_OFFSET] = rel->r_offset;
+ rel_words[REL_R_INFO] = rel->r_info;
+ rel_words[REL_R_ADDEND] = 0;
+ }
+
+ if (!rtems_rtl_unresolved_add (obj,
+ flags,
+ symname,
+ targetsect->section,
+ rel_words))
+ return false;
+
+ ++obj->unresolved;
+ }
+ else
+ {
+ rtems_rtl_obj* sobj;
+
+ if (is_rela)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
+ symname, (int) ELF_R_SYM (rela->r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
+ (uintmax_t) rela->r_offset, (int) rela->r_addend);
+ if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
+ symname, sym->st_info, symvalue))
+ return false;
+ }
+ else
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
+ symname, (int) ELF_R_SYM (rel->r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
+ (uintmax_t) rel->r_offset);
+ if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
+ symname, sym->st_info, symvalue))
+ return false;
+ }
+
+ sobj = rtems_rtl_find_obj_with_symbol (symbol);
+ if (sobj != NULL)
+ {
+ if (rtems_rtl_obj_add_dependent (obj, sobj))
+ rtems_rtl_obj_inc_reference (sobj);
+ }
+ }
+
+ return true;
+}
+
static bool
-rtems_rtl_elf_relocator (rtems_rtl_obj* obj,
- int fd,
- rtems_rtl_obj_sect* sect,
- void* data)
+rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ rtems_rtl_elf_reloc_handler handler,
+ void* data)
{
rtems_rtl_obj_cache* symbols;
rtems_rtl_obj_cache* strings;
@@ -155,15 +314,16 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj,
for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
{
- uint8_t relbuf[reloc_size];
- const Elf_Rela* rela = (const Elf_Rela*) relbuf;
- const Elf_Rel* rel = (const Elf_Rel*) relbuf;
- Elf_Sym sym;
- const char* symname = NULL;
- off_t off;
- Elf_Word type;
- Elf_Word symvalue = 0;
- bool relocate;
+ uint8_t relbuf[reloc_size];
+ const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+ const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+ rtems_rtl_obj_sym* symbol = NULL;
+ Elf_Sym sym;
+ const char* symname = NULL;
+ off_t off;
+ Elf_Word rel_type;
+ Elf_Word symvalue = 0;
+ bool resolved;
off = obj->ooffset + sect->offset + (reloc * reloc_size);
@@ -203,75 +363,26 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj,
/*
* See if the record references an external symbol. If it does find the
* symbol value. If the symbol cannot be found flag the object file as
- * having unresolved externals and store the externals. The load of an
+ * having unresolved externals and store the external. The load of an
* object after this one may provide the unresolved externals.
*/
if (is_rela)
- type = ELF_R_TYPE(rela->r_info);
+ rel_type = ELF_R_TYPE(rela->r_info);
else
- type = ELF_R_TYPE(rel->r_info);
-
- relocate = true;
-
- if (rtems_rtl_elf_rel_resolve_sym (type))
- {
- if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue))
- {
- uint16_t flags = 0;
- rtems_rtl_word rel_words[3];
-
- relocate = false;
-
- if (is_rela)
- {
- flags = 1;
- rel_words[REL_R_OFFSET] = rela->r_offset;
- rel_words[REL_R_INFO] = rela->r_info;
- rel_words[REL_R_ADDEND] = rela->r_addend;
- }
- else
- {
- rel_words[REL_R_OFFSET] = rel->r_offset;
- rel_words[REL_R_INFO] = rel->r_info;
- rel_words[REL_R_ADDEND] = 0;
- }
+ rel_type = ELF_R_TYPE(rel->r_info);
- if (!rtems_rtl_unresolved_add (obj,
- flags,
- symname,
- targetsect->section,
- rel_words))
- return false;
+ resolved = true;
- ++obj->unresolved;
- }
- }
+ if (rtems_rtl_elf_rel_resolve_sym (rel_type))
+ resolved = rtems_rtl_elf_find_symbol (obj,
+ &sym, symname,
+ &symbol, &symvalue);
- if (relocate)
- {
- if (is_rela)
- {
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
- symname, (int) ELF_R_SYM (rela->r_info),
- (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
- (uintmax_t) rela->r_offset, (int) rela->r_addend);
- if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
- symname, sym.st_info, symvalue))
- return false;
- }
- else
- {
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
- symname, (int) ELF_R_SYM (rel->r_info),
- (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
- (uintmax_t) rel->r_offset);
- if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
- symname, sym.st_info, symvalue))
- return false;
- }
- }
+ if (!handler (obj,
+ is_rela, relbuf, targetsect,
+ symbol, &sym, symname, symvalue, resolved,
+ data))
+ return false;
}
/*
@@ -283,6 +394,28 @@ rtems_rtl_elf_relocator (rtems_rtl_obj* obj,
return true;
}
+static bool
+rtems_rtl_elf_relocs_parser (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ void* data)
+{
+ 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;
+}
+
+static bool
+rtems_rtl_elf_relocs_locator (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ void* data)
+{
+ return rtems_rtl_elf_relocate_worker (obj, fd, sect,
+ rtems_rtl_elf_reloc_relocator, data);
+}
+
bool
rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
rtems_rtl_obj_sym* sym)
@@ -290,8 +423,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
rtems_rtl_obj_sect* sect;
bool is_rela;
Elf_Word symvalue;
+ rtems_rtl_obj* sobj;
- is_rela =reloc->flags & 1;
+ is_rela = reloc->flags & 1;
sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
if (!sect)
@@ -329,13 +463,20 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
return false;
}
- if (reloc->obj->unresolved)
+ if (reloc->obj->unresolved > 0)
{
--reloc->obj->unresolved;
- if (!reloc->obj->unresolved)
+ if (reloc->obj->unresolved == 0)
reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
}
+ sobj = rtems_rtl_find_obj_with_symbol (sym);
+ if (sobj != NULL)
+ {
+ if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
+ rtems_rtl_obj_inc_reference (sobj);
+ }
+
return true;
}
@@ -402,6 +543,24 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
}
static bool
+rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
+{
+ /*
+ * If there are dependencies and no unresolved externals allocate and size
+ * the dependency table to the number of dependent object files. If there are
+ * unresolved externals the number of dependencies is unknown at this point
+ * in time so use dynamic allocation to allocate the block size number of
+ * entries when the entries are added.
+ */
+ if (reloc->dependents > 0 && reloc->unresolved == 0)
+ {
+ if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
+ return false;
+ }
+ return true;
+}
+
+static bool
rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
int fd,
rtems_rtl_obj_sect* sect,
@@ -1024,7 +1183,8 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
{
rtems_rtl_obj_cache* header;
Elf_Ehdr ehdr;
- rtems_rtl_elf_common_data common = { .size = 0, .alignment = 0 };
+ rtems_rtl_elf_reloc_data relocs = { 0 };
+ rtems_rtl_elf_common_data common = { 0 };
rtems_rtl_obj_caches (&header, NULL, NULL);
@@ -1102,10 +1262,16 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
+ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
+ return false;
+
+ if (!rtems_rtl_elf_dependents (obj, &relocs))
+ return false;
+
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
return false;
- if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
+ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
return false;
rtems_rtl_obj_synchronize_cache (obj);
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index 5d560a0b34..1f5f82eb89 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -123,28 +123,6 @@ bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
const Elf_Word symvalue);
/**
- * Find the symbol. The symbol is passed as an ELF type symbol with the name
- * and the value returned is the absolute address of the symbol.
- *
- * If the symbol type is STT_NOTYPE the symbol references a global symbol. The
- * gobal symbol table is searched to find it and that value returned. If the
- * symbol is local to the object module the section for the symbol is located
- * and it's base added to the symbol's value giving an absolute location.
- *
- * @param obj The object the symbol is being resolved for.
- * @param sym The ELF type symbol.
- * @param symname The sym's name read from the symbol string table.
- * @param value Return the value of the symbol. Only valid if the return value
- * is true.
- * @retval true The symbol resolved.
- * @retval false The symbol could not be result. The RTL error is set.
- */
-bool rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
- const Elf_Sym* sym,
- const char* symname,
- Elf_Word* value);
-
-/**
* The ELF format check handler.
*
* @param obj The object being checked.
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 7109b86fe8..0f58bf9bda 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -83,6 +83,7 @@ rtems_rtl_obj_alloc (void)
* Initialise the chains.
*/
rtems_chain_initialize_empty (&obj->sections);
+ rtems_chain_initialize_empty (&obj->dependents);
/*
* No valid format.
*/
@@ -114,6 +115,8 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj)
rtems_chain_extract (&obj->link);
rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
&obj->data_base, &obj->bss_base);
+ rtems_rtl_obj_erase_sections (obj);
+ rtems_rtl_obj_erase_dependents (obj);
rtems_rtl_symbol_obj_erase (obj);
rtems_rtl_obj_free_names (obj);
if (obj->sec_num)
@@ -550,6 +553,110 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
return match.sect;
}
+bool
+rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
+{
+ rtems_rtl_obj_depends* depends;
+ size_t size;
+
+ size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents;
+
+ depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ size,
+ true);
+ if (depends == NULL)
+ {
+ rtems_rtl_set_error (ENOMEM, "no memory for the dependency");
+ }
+ else
+ {
+ depends->dependents = dependents;
+ rtems_chain_append (&obj->dependents, &depends->node);
+ }
+
+ return depends != NULL;
+}
+
+void
+rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj)
+{
+ rtems_chain_node* node = rtems_chain_first (&obj->dependents);
+ while (!rtems_chain_is_tail (&obj->dependents, node))
+ {
+ rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+ rtems_chain_node* next_node = rtems_chain_next (node);
+ rtems_chain_extract (node);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends);
+ node = next_node;
+ }
+}
+
+bool
+rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent)
+{
+ rtems_rtl_obj** free_slot;
+ rtems_chain_node* node;
+ if (obj == dependent || dependent == rtems_rtl_baseimage ())
+ return false;
+ free_slot = NULL;
+ node = rtems_chain_first (&obj->dependents);
+ while (!rtems_chain_is_tail (&obj->dependents, node))
+ {
+ rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+ size_t d;
+ for (d = 0; d < depends->dependents; ++d)
+ {
+ if (free_slot == NULL && depends->depends[d] == NULL)
+ free_slot = &(depends->depends[d]);
+ if (depends->depends[d] == dependent)
+ return false;
+ }
+ node = rtems_chain_next (node);
+ }
+ if (free_slot == NULL)
+ {
+ if (rtems_rtl_obj_alloc_dependents (obj,
+ RTEMS_RTL_DEPENDENCY_BLOCK_SIZE))
+ {
+ rtems_rtl_obj_depends* depends;
+ node = rtems_chain_last (&obj->dependents);
+ depends = (rtems_rtl_obj_depends*) node;
+ free_slot = &(depends->depends[0]);
+ if (*free_slot != NULL)
+ {
+ rtems_rtl_set_error (EINVAL, "new dependency node not empty");
+ free_slot = NULL;
+ }
+ }
+ }
+ if (free_slot != NULL)
+ *free_slot = dependent;
+ return free_slot != NULL;
+}
+
+bool
+rtems_rtl_obj_iterate_dependents (rtems_rtl_obj* obj,
+ rtems_rtl_obj_depends_iterator iterator,
+ void* data)
+{
+ rtems_chain_node* node = rtems_chain_first (&obj->dependents);
+ while (!rtems_chain_is_tail (&obj->dependents, node))
+ {
+ rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+ size_t d;
+ for (d = 0; d < depends->dependents; ++d)
+ {
+ if (depends->depends[d])
+ {
+ if (iterator (obj, depends->depends[d], data))
+ return true;
+ }
+ }
+ node = rtems_chain_next (node);
+ }
+ return false;
+}
+
size_t
rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
{
@@ -1220,10 +1327,42 @@ static bool
rtems_rtl_obj_file_unload (rtems_rtl_obj* obj)
{
if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
- return loaders[obj->format].unload (obj);
+ {
+ rtems_chain_node* node;
+
+ if (!loaders[obj->format].unload (obj))
+ return false;
+
+ node = rtems_chain_first (&obj->dependents);
+ while (!rtems_chain_is_tail (&obj->dependents, node))
+ {
+ rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+ size_t d;
+ for (d = 0; d < depends->dependents; ++d)
+ {
+ if (depends->depends[d] != NULL)
+ rtems_rtl_obj_dec_reference (depends->depends[d]);
+ }
+ node = rtems_chain_next (node);
+ }
+ }
+
return false;
}
+void
+rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj)
+{
+ ++obj->refs;
+}
+
+void
+rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj)
+{
+ if (obj->refs)
+ --obj->refs;
+}
+
bool
rtems_rtl_obj_load (rtems_rtl_obj* obj)
{
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index 5c144977a0..f3471d8d8e 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -117,13 +117,14 @@ rtems_rtl_shell_status (rtems_rtl_data* rtl, int argc, char *argv[])
*/
typedef struct
{
- rtems_rtl_data* rtl; /**< The RTL data. */
- int indent; /**< Spaces to indent. */
- bool oname; /**< Print object names. */
- bool names; /**< Print details of all names. */
- bool memory_map; /**< Print the memory map. */
- bool symbols; /**< Print the global symbols. */
- bool base; /**< Include the base object file. */
+ rtems_rtl_data* rtl; /**< The RTL data. */
+ int indent; /**< Spaces to indent. */
+ bool oname; /**< Print object names. */
+ bool names; /**< Print details of all names. */
+ bool memory_map; /**< Print the memory map. */
+ bool symbols; /**< Print the global symbols. */
+ bool dependencies; /**< Print any dependencies. */
+ bool base; /**< Include the base object file. */
} rtems_rtl_obj_print;
/**
@@ -169,6 +170,29 @@ rtems_rtl_symbols_arg (int argc, char *argv[])
}
/**
+ * Dependenncies printer.
+ */
+typedef struct
+{
+ bool first; /**< Is this the first line printed. */
+ size_t indent; /**< The indent. */
+} rtems_rtl_dep_data;
+
+static bool
+rtems_rtl_dependencies (rtems_rtl_obj* obj,
+ rtems_rtl_obj* dependent,
+ void* data)
+{
+ rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
+ if (!dd->first)
+ printf ("\n%-*c: ", dd->indent, ' ');
+ else
+ dd->first = false;
+ printf ("%s", dependent->oname);
+ return false;
+}
+
+/**
* Object printer.
*/
static bool
@@ -214,7 +238,9 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ',
obj->bss_base, obj->bss_size);
}
- printf ("%-*cunresolved : %" PRIu32 "\n", print->indent, ' ', obj->unresolved);
+ printf ("%-*cunresolved : %zu\n", print->indent, ' ', obj->unresolved);
+ printf ("%-*cusers : %zu\n", print->indent, ' ', obj->users);
+ printf ("%-*creferences : %zu\n", print->indent, ' ', obj->refs);
printf ("%-*csymbols : %zi\n", print->indent, ' ', obj->global_syms);
printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
if (print->symbols)
@@ -231,6 +257,16 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
max_len, obj->global_table[s].name, obj->global_table[s].value);
}
+ if (print->dependencies)
+ {
+ rtems_rtl_dep_data dd = {
+ .first = true,
+ .indent = strlen ("dependencies :") + print->indent
+ };
+ printf ("%-*cdependencies : ", print->indent, ' ');
+ rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
+ printf ("\n");
+ }
printf ("\n");
return true;
}
@@ -269,6 +305,7 @@ rtems_rtl_shell_list (rtems_rtl_data* rtl, int argc, char *argv[])
print.names = true;
print.memory_map = true;
print.symbols = rtems_rtl_symbols_arg (argc, argv);
+ print.dependencies = true;
print.base = false;
rtems_rtl_chain_iterate (&rtl->objects,
rtems_rtl_obj_print_iterator,
@@ -286,6 +323,7 @@ rtems_rtl_shell_sym (rtems_rtl_data* rtl, int argc, char *argv[])
print.names = false;
print.memory_map = false;
print.symbols = true;
+ print.dependencies = false;
print.base = rtems_rtl_base_arg (argc, argv);
rtems_rtl_chain_iterate (&rtl->objects,
rtems_rtl_obj_print_iterator,
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index 4c0f6b3bf1..4992c3bb4a 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -171,7 +171,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
rtems_rtl_unresolved_reloc_data* rd;
rd = (rtems_rtl_unresolved_reloc_data*) data;
- if (rec->rec.reloc.name == rd->name)
+ if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL)
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name);
@@ -185,7 +185,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
* names with a reference count of 0.
*/
rec->rec.reloc.obj = NULL;
- if (rd->name_rec && rd->name_rec->rec.name.refs)
+ if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
--rd->name_rec->rec.name.refs;
}
}
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
index 628fc771bc..fdf4c1229f 100644
--- a/cpukit/libdl/rtl.c
+++ b/cpukit/libdl/rtl.c
@@ -216,6 +216,11 @@ rtems_rtl_data_init (void)
*/
rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
+ /*
+ * Lock the base image and flag it as the base image.
+ */
+ rtl->base->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_BASE;
+
rtems_chain_append (&rtl->objects, &rtl->base->link);
}
@@ -312,6 +317,21 @@ rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp,
}
}
+void
+rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set)
+{
+ rtems_chain_node* node = rtems_chain_first (&rtl->objects);
+ while (!rtems_chain_is_tail (&rtl->objects, node))
+ {
+ rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ if (clear != 0)
+ obj->flags &= ~clear;
+ if (set != 0)
+ obj->flags |= set;
+ node = rtems_chain_next (node);
+ }
+}
+
rtems_rtl_data*
rtems_rtl_lock (void)
{
@@ -386,6 +406,21 @@ rtems_rtl_find_obj (const char* name)
}
rtems_rtl_obj*
+rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
+{
+ rtems_chain_node* node = rtems_chain_first (&rtl->objects);
+ while (!rtems_chain_is_tail (&rtl->objects, node))
+ {
+ rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ if (sym >= obj->global_table &&
+ sym < (obj->global_table + obj->global_syms))
+ return obj;
+ node = rtems_chain_next (node);
+ }
+ return NULL;
+}
+
+rtems_rtl_obj*
rtems_rtl_load_object (const char* name, int mode)
{
rtems_rtl_obj* obj;
@@ -489,6 +524,11 @@ rtems_rtl_unload_object (rtems_rtl_obj* obj)
if (obj->users == 0)
{
+ if (obj->refs != 0)
+ {
+ rtems_rtl_set_error (EBUSY, "object file referenced");
+ return false;
+ }
obj->flags |= RTEMS_RTL_OBJ_LOCKED;
rtems_rtl_unlock ();
rtems_rtl_obj_run_dtors (obj);
@@ -618,5 +658,11 @@ rtems_rtl_base_sym_global_add (const unsigned char* esyms,
rtems_rtl_obj*
rtems_rtl_baseimage (void)
{
- return NULL;
+ rtems_rtl_obj* base = NULL;
+ if (rtems_rtl_lock ())
+ {
+ base = rtl->base;
+ rtems_rtl_unlock ();
+ }
+ return base;
}
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 9e3d2143d6..810f65db8e 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -512,6 +512,45 @@ CLEANFILES += dl06.pre dl06-sym.o dl06-o1.o dl06-o2.o dl06.tar dl06-tar.h
endif
endif
+if DLTESTS
+if TEST_dl07
+lib_tests += dl07
+lib_screens += dl07/dl07.scn
+lib_docs += dl07/dl07.doc
+dl07_SOURCES = dl07/init.c dl07/dl-load.c dl07-tar.c dl07-tar.h
+dl07_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl07) $(support_includes)
+dl07/init.c: dl07-tar.o
+dl07.pre: $(dl07_OBJECTS) $(dl07_DEPENDENCIES)
+ @rm -f dl07.pre
+ $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+dl07-o1.o: dl07/dl-o1.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o2.o: dl07/dl-o2.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o3.o: dl07/dl-o3.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o4.o: dl07/dl-o4.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o5.o: dl07/dl-o5.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07.tar: dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o
+ @rm -f $@
+ $(AM_V_GEN)$(PAX) -w -f $@ $+
+dl07-tar.c: dl07.tar
+ $(AM_V_GEN)$(BIN2C) -C $< $@
+dl07-tar.h: dl07.tar
+ $(AM_V_GEN)$(BIN2C) -H $< $@
+dl07-tar.o: dl07-tar.c dl07-tar.h
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-sym.o: dl07.pre
+ $(AM_V_GEN)rtems-syms -e -c "$(CFLAGS)" -o $@ $<
+dl07$(EXEEXT): $(dl07_OBJECTS) $(dl07_DEPENDENCIES) dl07-sym.o
+ @rm -f $@
+ $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+CLEANFILES += dl07.pre dl07-sym.o dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o dl07.tar dl07-tar.h
+endif
+endif
+
if TEST_dumpbuf01
lib_tests += dumpbuf01
lib_screens += dumpbuf01/dumpbuf01.scn
@@ -1358,4 +1397,3 @@ endif
rtems_tests_PROGRAMS = $(lib_tests)
dist_rtems_tests_DATA = $(lib_screens) $(lib_docs)
-
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 303a165731..a2a0df01f1 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -131,6 +131,7 @@ RTEMS_TEST_CHECK([dl03])
RTEMS_TEST_CHECK([dl04])
RTEMS_TEST_CHECK([dl05])
RTEMS_TEST_CHECK([dl06])
+RTEMS_TEST_CHECK([dl07])
RTEMS_TEST_CHECK([dumpbuf01])
RTEMS_TEST_CHECK([dup2])
RTEMS_TEST_CHECK([exit01])
diff --git a/testsuites/libtests/dl02/dl-load.c b/testsuites/libtests/dl02/dl-load.c
index 601d62113c..a00581ab42 100644
--- a/testsuites/libtests/dl02/dl-load.c
+++ b/testsuites/libtests/dl02/dl-load.c
@@ -12,6 +12,11 @@
#include "dl-load.h"
+#include <rtems/rtl/rtl-trace.h>
+
+#define DL02_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
+#define DL02_RTL_CMDS 0
+
typedef int (*call_t)(int argc, const char* argv[]);
static const char* call_args[] = { "1", "2", "3", "4" };
@@ -49,6 +54,10 @@ int dl_load_test(void)
int call_ret;
int ret;
+#if DL02_DEBUG_TRACE
+ rtems_rtl_trace_set_mask (DL02_DEBUG_TRACE);
+#endif
+
o1 = dl_load_obj("/dl02-o1.o");
if (!o1)
return 1;
@@ -56,7 +65,7 @@ int dl_load_test(void)
if (!o1)
return 1;
-#if 0
+#if DL02_RTL_CMDS
{
char* list[] = { "rtl", "list", NULL };
rtems_rtl_shell_command (2, list);
diff --git a/testsuites/libtests/dl07/dl-load.c b/testsuites/libtests/dl07/dl-load.c
new file mode 100644
index 0000000000..6e0262c7df
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-load.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#define DL07_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
+#define DL07_RTL_CMDS 0
+
+#include <dlfcn.h>
+
+#include "dl-load.h"
+
+#include <tmacros.h>
+
+#include <rtems/rtl/rtl-trace.h>
+
+typedef int (*call_sig)(void);
+
+int rtems_rtl_shell_command (int argc, char* argv[]);
+
+static void dl_load_dump (void)
+{
+#if DL07_RTL_CMDS
+ char* list[] = { "rtl", "list", NULL };
+ char* sym[] = { "rtl", "sym", NULL };
+ printf ("RTL List:\n");
+ rtems_rtl_shell_command (2, list);
+ printf ("RTL Sym:\n");
+ rtems_rtl_shell_command (2, sym);
+#endif
+}
+
+static void dl_check_resolved(void* handle, bool has_unresolved)
+{
+ int unresolved = 0;
+ rtems_test_assert (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) == 0);
+ if (has_unresolved)
+ {
+ if (unresolved == 0)
+ {
+ dl_load_dump();
+ rtems_test_assert (unresolved != 0);
+ }
+ }
+ else
+ {
+ if (unresolved != 0)
+ {
+ dl_load_dump();
+ rtems_test_assert (unresolved == 0);
+ }
+ }
+}
+
+static void* dl_load_obj(const char* name, bool has_unresolved)
+{
+ void* handle;
+
+ printf("load: %s\n", name);
+
+ handle = dlopen (name, RTLD_NOW | RTLD_GLOBAL);
+ if (!handle)
+ {
+ printf("dlopen failed: %s\n", dlerror());
+ return NULL;
+ }
+
+ dl_check_resolved (handle, has_unresolved);
+
+ printf ("handle: %p loaded\n", handle);
+
+ return handle;
+}
+
+static void dl_close (void* handle)
+{
+ int r;
+ printf ("handle: %p closing\n", handle);
+ r = dlclose (handle);
+ if (r != 0)
+ printf("dlclose failed: %s\n", dlerror());
+ rtems_test_assert (r == 0);
+}
+
+static int dl_call (void* handle, const char* func)
+{
+ call_sig call = dlsym (handle, func);
+ if (call == NULL)
+ {
+ printf("dlsym failed: symbol not found: %s\n", func);
+ return 1;
+ }
+ call ();
+ return 0;
+}
+
+int dl_load_test(void)
+{
+ void* o1;
+ void* o2;
+ void* o3;
+ void* o4;
+ void* o5;
+
+ printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
+
+#if DL07_DEBUG_TRACE
+ rtems_rtl_trace_set_mask (DL07_DEBUG_TRACE);
+#endif
+
+ o1 = dl_load_obj("/dl07-o1.o", false);
+ if (!o1)
+ return 1;
+ o2 = dl_load_obj("/dl07-o2.o", false);
+ if (!o1)
+ return 1;
+ o3 = dl_load_obj("/dl07-o3.o", true);
+ if (!o1)
+ return 1;
+ o4 = dl_load_obj("/dl07-o4.o", false);
+ if (!o1)
+ return 1;
+ o5 = dl_load_obj("/dl07-o5.o", false);
+ if (!o1)
+ return 1;
+
+ dl_check_resolved (o3, false);
+
+ dl_load_dump ();
+
+ printf ("\n\nRun mains in each module:\n\n");
+ if (dl_call (o1, "rtems_main_o1"))
+ return 1;
+ if (dl_call (o2, "rtems_main_o2"))
+ return 1;
+ if (dl_call (o3, "rtems_main_o3"))
+ return 1;
+ if (dl_call (o4, "rtems_main_o4"))
+ return 1;
+ if (dl_call (o5, "rtems_main_o5"))
+ return 1;
+
+ /*
+ * Try and close the dependent modules, we should get an error.
+ */
+ rtems_test_assert (dlclose (o1) != 0);
+ rtems_test_assert (dlclose (o2) != 0);
+ rtems_test_assert (dlclose (o4) != 0);
+ rtems_test_assert (dlclose (o5) != 0);
+
+ dl_close (o3);
+ rtems_test_assert (dlclose (o1) != 0);
+ dl_close (o4);
+ rtems_test_assert (dlclose (o1) != 0);
+ dl_close (o5);
+ rtems_test_assert (dlclose (o1) != 0);
+ dl_close (o2);
+ dl_close (o1);
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-load.h b/testsuites/libtests/dl07/dl-load.h
new file mode 100644
index 0000000000..72872917aa
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-load.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014, 2018 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#if !defined(_DL_LOAD_H_)
+#define _DL_LOAD_H_
+
+static inline const char* dl_localise_file (const char* file)
+{
+ return (const char*) strstr (file, "testsuites");
+}
+
+int dl_load_test(void);
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o1.c b/testsuites/libtests/dl07/dl-o1.c
new file mode 100644
index 0000000000..af5ad1bd17
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o1.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-o1.h"
+
+#include <rtems/test.h>
+#include "dl-load.h"
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+/*
+ * Create some symbols. The uninitialised will be in the common section with
+ * separated text and data and this means there is no actual section in the ELF
+ * file, the details for this are in the symbols.
+ */
+int dl01_bss1; /* unitialised, .bss */
+float dl01_bss2[30]; /* unitialised, .bss */
+char dl01_bss3[10]; /* unitialised, .bss */
+int dl01_data1 = 1; /* initialised, .data */
+float dl01_data2 = 0.3333; /* initialised, .data */
+const int dl01_const1 = 3; /* read-only, .const */
+const float dl01_const2 = 0.666; /* read-only, .const */
+int dl01_func1(void) /* code, .text */
+{
+ return 4;
+}
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o1 (void);
+
+#define DL_NAME "dlo1"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o1 (void)
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl01_bss1: %4u: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4u: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4u: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4u: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4u: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4u: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4u: %p\n", sizeof(dl01_func1), &dl01_func1);
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o1.h b/testsuites/libtests/dl07/dl-o1.h
new file mode 100644
index 0000000000..bf07eb6a45
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o1.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL01_H)
+#define DL01_H
+
+extern int dl01_bss1;
+extern float dl01_bss2[30];
+extern char dl01_bss3[10];
+extern int dl01_data1;
+extern float dl01_data2;
+extern const int dl01_const1;
+extern const float dl01_const2;
+int dl01_func1(void);
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o2.c b/testsuites/libtests/dl07/dl-o2.c
new file mode 100644
index 0000000000..423f05a16a
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o2.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o2.h"
+
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+int dl02_bss1;
+float dl02_bss2[7];
+char dl02_bss3[21];
+int dl02_data1;
+float dl02_data2;
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o2 (int argc, const char* argv[]);
+
+#define DL_NAME "dlo2"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o2 (int argc, const char* argv[])
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl01_bss1: %4u: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4u: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4u: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4u: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4u: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4u: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4u: %p\n", sizeof(dl01_func1), &dl01_func1);
+ printf (DL_NAME ": dl02_bss1: %4u: %p: %d\n", PAINT_VAR (dl02_bss1));
+ printf (DL_NAME ": dl02_bss2: %4u: %p: %f\n", PAINT_VAR (dl02_bss2[0]));
+ printf (DL_NAME ": dl02_bss3: %4u: %p: %02x\n", PAINT_VAR (dl02_bss3[0]));
+ printf (DL_NAME ": dl02_data1: %4u: %p: %d\n", PAINT_VAR (dl02_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl02_data2: %4u: %p: %f\n", PAINT_VAR (dl02_data2));
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o2.h b/testsuites/libtests/dl07/dl-o2.h
new file mode 100644
index 0000000000..0d97c5cff9
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o2.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL02_H)
+#define DL02_H
+
+/*
+ * A set of variables in dl-o2 reference by dl-03.
+ */
+
+extern int dl02_bss1;
+extern float dl02_bss2[7];
+extern char dl02_bss3[21];
+extern int dl02_data1;
+extern float dl02_data2;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o3.c b/testsuites/libtests/dl07/dl-o3.c
new file mode 100644
index 0000000000..573e3df1a0
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o3.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o2.h"
+#include "dl-o4.h"
+#include "dl-o5.h"
+
+#include <inttypes.h>
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o3 (int argc, const char* argv[]);
+
+#define DL_NAME "dlo3"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o3 (int argc, const char* argv[])
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl01_bss1: %4u: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4u: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4u: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4u: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4u: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4u: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4u: %p\n", sizeof(dl01_func1), &dl01_func1);
+ printf (DL_NAME ": dl02_bss1: %4u: %p: %d\n", PAINT_VAR (dl02_bss1));
+ printf (DL_NAME ": dl02_bss2: %4u: %p: %f\n", PAINT_VAR (dl02_bss2[0]));
+ printf (DL_NAME ": dl02_bss3: %4u: %p: %02x\n", PAINT_VAR (dl02_bss3[0]));
+ printf (DL_NAME ": dl02_data1: %4u: %p: %d\n", PAINT_VAR (dl02_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl02_data2: %4u: %p: %f\n", PAINT_VAR (dl02_data2));
+ printf (DL_NAME ": dl04_unresolv_1: %4u: %p: %d\n", PAINT_VAR (dl04_unresolv_1));
+ printf (DL_NAME ": dl04_unresolv_2: %4u: %p: %f\n", PAINT_VAR (dl04_unresolv_2));
+ printf (DL_NAME ": dl04_unresolv_3: %4u: %p: %02x\n", PAINT_VAR (dl04_unresolv_3));
+ printf (DL_NAME ": dl04_unresolv_4: %4u: %p: %p\n", PAINT_VAR (dl04_unresolv_4));
+ printf (DL_NAME ": dl04_unresolv_5: %4u: %p: %d\n", PAINT_VAR (dl04_unresolv_5));
+ printf (DL_NAME ": dl04_unresolv_6: %4u: %p: %s\n", PAINT_VAR (dl04_unresolv_6));
+ printf (DL_NAME ": dl05_unresolv_1: %4u: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+ printf (DL_NAME ": dl05_unresolv_2: %4u: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+ printf (DL_NAME ": dl05_unresolv_3: %4u: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+ printf (DL_NAME ": dl05_unresolv_4: %4u: %p: %" PRIu8 "\n", PAINT_VAR (dl05_unresolv_4));
+ printf (DL_NAME ": dl05_unresolv_5: %4u: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o4.c b/testsuites/libtests/dl07/dl-o4.c
new file mode 100644
index 0000000000..a3cb1fb6c5
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o4.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o4.h"
+
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+
+int dl04_unresolv_1;
+float dl04_unresolv_2;
+char dl04_unresolv_3;
+char* dl04_unresolv_4;
+const int dl04_unresolv_5 = 4;
+const char* dl04_unresolv_6 = "dl-O4";
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o4 (int argc, const char* argv[]);
+
+#define DL_NAME "dlo4"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o4 (int argc, const char* argv[])
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl01_bss1: %4u: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4u: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4u: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4u: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4u: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4u: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4u: %p\n", sizeof(dl01_func1), &dl01_func1);
+ printf (DL_NAME ": dl04_unresolv_1: %4u: %p: %d\n", PAINT_VAR (dl04_unresolv_1));
+ printf (DL_NAME ": dl04_unresolv_2: %4u: %p: %f\n", PAINT_VAR (dl04_unresolv_2));
+ printf (DL_NAME ": dl04_unresolv_3: %4u: %p: %02x\n", PAINT_VAR (dl04_unresolv_3));
+ printf (DL_NAME ": dl04_unresolv_4: %4u: %p: %p\n", PAINT_VAR (dl04_unresolv_4));
+ printf (DL_NAME ": dl04_unresolv_5: %4u: %p: %d\n", PAINT_VAR (dl04_unresolv_5));
+ printf (DL_NAME ": dl04_unresolv_6: %4u: %p: %s\n", PAINT_VAR (dl04_unresolv_6));
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o4.h b/testsuites/libtests/dl07/dl-o4.h
new file mode 100644
index 0000000000..371279be9e
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o4.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL04_H)
+#define DL04_H
+
+/*
+ * A set of variables in dl-o4 referenced by dl-03 and unresolved when dl-o3 is
+ * loaded. They are all uninitialised variables with various sizes in a mixed
+ * order to get various alignments. These and dl-o5 variables are designed to
+ * force the dependent tables to grow.
+ */
+
+extern int dl04_unresolv_1;
+extern float dl04_unresolv_2;
+extern char dl04_unresolv_3;
+extern char* dl04_unresolv_4;
+extern const int dl04_unresolv_5;
+extern const char* dl04_unresolv_6;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o5.c b/testsuites/libtests/dl07/dl-o5.c
new file mode 100644
index 0000000000..49502b3247
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o5.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o5.h"
+
+#include <inttypes.h>
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+
+uint64_t dl05_unresolv_1;
+uint16_t dl05_unresolv_2;
+uint32_t dl05_unresolv_3;
+uint8_t dl05_unresolv_4;
+int64_t dl05_unresolv_5;
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o5 (int argc, const char* argv[]);
+
+#define DL_NAME "dlo5"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o5 (int argc, const char* argv[])
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl01_bss1: %4u: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4u: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4u: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4u: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4u: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4u: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4u: %p\n", sizeof(dl01_func1), &dl01_func1);
+ printf (DL_NAME ": dl05_unresolv_1: %4u: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+ printf (DL_NAME ": dl05_unresolv_2: %4u: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+ printf (DL_NAME ": dl05_unresolv_3: %4u: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+ printf (DL_NAME ": dl05_unresolv_4: %4u: %p: %" PRIu8 "\n", PAINT_VAR (dl05_unresolv_4));
+ printf (DL_NAME ": dl05_unresolv_5: %4u: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+ return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o5.h b/testsuites/libtests/dl07/dl-o5.h
new file mode 100644
index 0000000000..04974a03d4
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o5.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include <stdint.h>
+
+#if !defined(DL05_H)
+#define DL05_H
+
+/*
+ * A set of variables in dl-o5 referenced by dl-03 and unresolved when dl-o3 is
+ * loaded. They are all uninitialised variables with various sizes in a mixed
+ * order to get various alignments. These and dl-o4 variables are designed to
+ * force the dependent tables to grow.
+ */
+
+extern uint64_t dl05_unresolv_1;
+extern uint16_t dl05_unresolv_2;
+extern uint32_t dl05_unresolv_3;
+extern uint8_t dl05_unresolv_4;
+extern int64_t dl05_unresolv_5;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl07.doc b/testsuites/libtests/dl07/dl07.doc
new file mode 100644
index 0000000000..9a06de16fc
--- /dev/null
+++ b/testsuites/libtests/dl07/dl07.doc
@@ -0,0 +1,27 @@
+# Copyright (c) 2018 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.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: dl07
+
+directives:
+
+ dlopen
+ dlinfo
+ dlsym
+ dlclose
+
+concepts:
+
++ Load 5 interdependent ELF object files.
++ Check there are no unreolved externals. There should be unresolved
+ externals after dl07-o3.c is loaded but resolved with o4 and o5.
++ Locate the main symbol in each lodaed object file and call.
++ Unload the ELF files in an order that checks dependent objects cannot
+ be unloaded until the references have been unloaded.
++ Repeat 100 times.
diff --git a/testsuites/libtests/dl07/dl07.scn b/testsuites/libtests/dl07/dl07.scn
new file mode 100644
index 0000000000..0c8f7891b2
--- /dev/null
+++ b/testsuites/libtests/dl07/dl07.scn
@@ -0,0 +1,510 @@
+*** BEGIN OF TEST libdl (RTL) 7 ***
+*** TEST VERSION: 5.0.0.6de8cc8ad871a197d7233a9221786d8efee87840-modified
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_NETWORKING RTEMS_POSIX_API
+*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 30da0c720b78eba16a3f5272206c07415368617b, Newlib 2ab57ad59bc35dafffa69cd4da5e228971de069f)
+--------------------------------------------------
+ Run: 0
+load: /dl07-o1.o
+handle: 0x2091160 loaded
+load: /dl07-o2.o
+handle: 0x2091ef8 loaded
+load: /dl07-o3.o
+handle: 0x2092c88 loaded
+load: /dl07-o4.o
+handle: 0x2094190 loaded
+load: /dl07-o5.o
+handle: 0x2095008 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1: dl01_bss1: 4: 0x2091bd0: 0
+dlo1: dl01_bss2: 4: 0x2091bd4: %f
+dlo1: dl01_bss3: 1: 0x2091c50: 00
+dlo1: dl01_data1: 4: 0x2091bbc: 1
+dlo1: dl01_data2: 4: 0x2091bb8: %f
+dlo1: dl01_const1: 4: 0x2091b98: 3
+dlo1: dl01_const2: 4: 0x2091b94: %f
+dlo1: dl01_func1: 1: 0x2091888
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2: dl01_bss1: 4: 0x2091bd0: 0
+dlo2: dl01_bss2: 4: 0x2091bd4: %f
+dlo2: dl01_bss3: 1: 0x2091c50: 00
+dlo2: dl01_data1: 4: 0x2091bbc: 1
+dlo2: dl01_data2: 4: 0x2091bb8: %f
+dlo2: dl01_const1: 4: 0x2091b98: 3
+dlo2: dl01_const2: 4: 0x2091b94: %f
+dlo2: dl01_func1: 1: 0x2091888
+dlo2: dl02_bss1: 4: 0x2092928: 0
+dlo2: dl02_bss2: 4: 0x209292c: %f
+dlo2: dl02_bss3: 1: 0x2092948: 00
+dlo2: dl02_data1: 4: 0x2092960: 0
+dlo2: dl02_data2: 4: 0x2092964: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3: dl01_bss1: 4: 0x2091bd0: 0
+dlo3: dl01_bss2: 4: 0x2091bd4: %f
+dlo3: dl01_bss3: 1: 0x2091c50: 00
+dlo3: dl01_data1: 4: 0x2091bbc: 1
+dlo3: dl01_data2: 4: 0x2091bb8: %f
+dlo3: dl01_const1: 4: 0x2091b98: 3
+dlo3: dl01_const2: 4: 0x2091b94: %f
+dlo3: dl01_func1: 1: 0x2091888
+dlo3: dl02_bss1: 4: 0x2092928: 0
+dlo3: dl02_bss2: 4: 0x209292c: %f
+dlo3: dl02_bss3: 1: 0x2092948: 00
+dlo3: dl02_data1: 4: 0x2092960: 0
+dlo3: dl02_data2: 4: 0x2092964: %f
+dlo3: dl04_unresolv_1: 4: 0x2094d98: 0
+dlo3: dl04_unresolv_2: 4: 0x2094d9c: %f
+dlo3: dl04_unresolv_3: 1: 0x2094da0: 00
+dlo3: dl04_unresolv_4: 4: 0x2094da4: 0
+dlo3: dl04_unresolv_5: 4: 0x2094d68: 4
+dlo3: dl04_unresolv_6: 4: 0x2094d88: dl-O4
+dlo3: dl05_unresolv_1: 8: 0x2095a20: 0
+dlo3: dl05_unresolv_2: 2: 0x2095a28: 0
+dlo3: dl05_unresolv_3: 4: 0x2095a2c: 0
+dlo3: dl05_unresolv_4: 1: 0x2095a30: 0
+dlo3: dl05_unresolv_5: 8: 0x2095a38: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4: dl01_bss1: 4: 0x2091bd0: 0
+dlo4: dl01_bss2: 4: 0x2091bd4: %f
+dlo4: dl01_bss3: 1: 0x2091c50: 00
+dlo4: dl01_data1: 4: 0x2091bbc: 1
+dlo4: dl01_data2: 4: 0x2091bb8: %f
+dlo4: dl01_const1: 4: 0x2091b98: 3
+dlo4: dl01_const2: 4: 0x2091b94: %f
+dlo4: dl01_func1: 1: 0x2091888
+dlo4: dl04_unresolv_1: 4: 0x2094d98: 0
+dlo4: dl04_unresolv_2: 4: 0x2094d9c: %f
+dlo4: dl04_unresolv_3: 1: 0x2094da0: 00
+dlo4: dl04_unresolv_4: 4: 0x2094da4: 0
+dlo4: dl04_unresolv_5: 4: 0x2094d68: 4
+dlo4: dl04_unresolv_6: 4: 0x2094d88: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5: dl01_bss1: 4: 0x2091bd0: 0
+dlo5: dl01_bss2: 4: 0x2091bd4: %f
+dlo5: dl01_bss3: 1: 0x2091c50: 00
+dlo5: dl01_data1: 4: 0x2091bbc: 1
+dlo5: dl01_data2: 4: 0x2091bb8: %f
+dlo5: dl01_const1: 4: 0x2091b98: 3
+dlo5: dl01_const2: 4: 0x2091b94: %f
+dlo5: dl01_func1: 1: 0x2091888
+dlo5: dl05_unresolv_1: 8: 0x2095a20: 0
+dlo5: dl05_unresolv_2: 2: 0x2095a28: 0
+dlo5: dl05_unresolv_3: 4: 0x2095a2c: 0
+dlo5: dl05_unresolv_4: 1: 0x2095a30: 0
+dlo5: dl05_unresolv_5: 8: 0x2095a38: 0
+handle: 0x2092c88 closing
+handle: 0x2094190 closing
+handle: 0x2095008 closing
+handle: 0x2091ef8 closing
+handle: 0x2091160 closing
+--------------------------------------------------
+ Run: 1
+load: /dl07-o1.o
+handle: 0x2091178 loaded
+load: /dl07-o2.o
+handle: 0x2091f40 loaded
+load: /dl07-o3.o
+handle: 0x2095010 loaded
+load: /dl07-o4.o
+handle: 0x20964e0 loaded
+load: /dl07-o5.o
+handle: 0x2097358 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1: dl01_bss1: 4: 0x2091d00: 0
+dlo1: dl01_bss2: 4: 0x2091d04: %f
+dlo1: dl01_bss3: 1: 0x2091d80: 00
+dlo1: dl01_data1: 4: 0x2091bd4: 1
+dlo1: dl01_data2: 4: 0x2091bd0: %f
+dlo1: dl01_const1: 4: 0x2091bb0: 3
+dlo1: dl01_const2: 4: 0x2091bac: %f
+dlo1: dl01_func1: 1: 0x20918a0
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2: dl01_bss1: 4: 0x2091d00: 0
+dlo2: dl01_bss2: 4: 0x2091d04: %f
+dlo2: dl01_bss3: 1: 0x2091d80: 00
+dlo2: dl01_data1: 4: 0x2091bd4: 1
+dlo2: dl01_data2: 4: 0x2091bd0: %f
+dlo2: dl01_const1: 4: 0x2091bb0: 3
+dlo2: dl01_const2: 4: 0x2091bac: %f
+dlo2: dl01_func1: 1: 0x20918a0
+dlo2: dl02_bss1: 4: 0x2094df8: 0
+dlo2: dl02_bss2: 4: 0x2094dfc: %f
+dlo2: dl02_bss3: 1: 0x2094e18: 00
+dlo2: dl02_data1: 4: 0x2094e30: 0
+dlo2: dl02_data2: 4: 0x2094e34: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3: dl01_bss1: 4: 0x2091d00: 0
+dlo3: dl01_bss2: 4: 0x2091d04: %f
+dlo3: dl01_bss3: 1: 0x2091d80: 00
+dlo3: dl01_data1: 4: 0x2091bd4: 1
+dlo3: dl01_data2: 4: 0x2091bd0: %f
+dlo3: dl01_const1: 4: 0x2091bb0: 3
+dlo3: dl01_const2: 4: 0x2091bac: %f
+dlo3: dl01_func1: 1: 0x20918a0
+dlo3: dl02_bss1: 4: 0x2094df8: 0
+dlo3: dl02_bss2: 4: 0x2094dfc: %f
+dlo3: dl02_bss3: 1: 0x2094e18: 00
+dlo3: dl02_data1: 4: 0x2094e30: 0
+dlo3: dl02_data2: 4: 0x2094e34: %f
+dlo3: dl04_unresolv_1: 4: 0x20970e8: 0
+dlo3: dl04_unresolv_2: 4: 0x20970ec: %f
+dlo3: dl04_unresolv_3: 1: 0x20970f0: 00
+dlo3: dl04_unresolv_4: 4: 0x20970f4: 0
+dlo3: dl04_unresolv_5: 4: 0x20970b8: 4
+dlo3: dl04_unresolv_6: 4: 0x20970d8: dl-O4
+dlo3: dl05_unresolv_1: 8: 0x2097d70: 0
+dlo3: dl05_unresolv_2: 2: 0x2097d78: 0
+dlo3: dl05_unresolv_3: 4: 0x2097d7c: 0
+dlo3: dl05_unresolv_4: 1: 0x2097d80: 0
+dlo3: dl05_unresolv_5: 8: 0x2097d88: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4: dl01_bss1: 4: 0x2091d00: 0
+dlo4: dl01_bss2: 4: 0x2091d04: %f
+dlo4: dl01_bss3: 1: 0x2091d80: 00
+dlo4: dl01_data1: 4: 0x2091bd4: 1
+dlo4: dl01_data2: 4: 0x2091bd0: %f
+dlo4: dl01_const1: 4: 0x2091bb0: 3
+dlo4: dl01_const2: 4: 0x2091bac: %f
+dlo4: dl01_func1: 1: 0x20918a0
+dlo4: dl04_unresolv_1: 4: 0x20970e8: 0
+dlo4: dl04_unresolv_2: 4: 0x20970ec: %f
+dlo4: dl04_unresolv_3: 1: 0x20970f0: 00
+dlo4: dl04_unresolv_4: 4: 0x20970f4: 0
+dlo4: dl04_unresolv_5: 4: 0x20970b8: 4
+dlo4: dl04_unresolv_6: 4: 0x20970d8: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5: dl01_bss1: 4: 0x2091d00: 0
+dlo5: dl01_bss2: 4: 0x2091d04: %f
+dlo5: dl01_bss3: 1: 0x2091d80: 00
+dlo5: dl01_data1: 4: 0x2091bd4: 1
+dlo5: dl01_data2: 4: 0x2091bd0: %f
+dlo5: dl01_const1: 4: 0x2091bb0: 3
+dlo5: dl01_const2: 4: 0x2091bac: %f
+dlo5: dl01_func1: 1: 0x20918a0
+dlo5: dl05_unresolv_1: 8: 0x2097d70: 0
+dlo5: dl05_unresolv_2: 2: 0x2097d78: 0
+dlo5: dl05_unresolv_3: 4: 0x2097d7c: 0
+dlo5: dl05_unresolv_4: 1: 0x2097d80: 0
+dlo5: dl05_unresolv_5: 8: 0x2097d88: 0
+handle: 0x2095010 closing
+handle: 0x20964e0 closing
+handle: 0x2097358 closing
+handle: 0x2091f40 closing
+handle: 0x2091178 closing
+--------------------------------------------------
+ Run: 2
+load: /dl07-o1.o
+handle: 0x2091190 loaded
+load: /dl07-o2.o
+handle: 0x2092000 loaded
+load: /dl07-o3.o
+handle: 0x20951b0 loaded
+load: /dl07-o4.o
+handle: 0x2095b40 loaded
+load: /dl07-o5.o
+handle: 0x20989a0 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1: dl01_bss1: 4: 0x2091d00: 0
+dlo1: dl01_bss2: 4: 0x2091d04: %f
+dlo1: dl01_bss3: 1: 0x2091d80: 00
+dlo1: dl01_data1: 4: 0x2091bec: 1
+dlo1: dl01_data2: 4: 0x2091be8: %f
+dlo1: dl01_const1: 4: 0x2091bc8: 3
+dlo1: dl01_const2: 4: 0x2091bc4: %f
+dlo1: dl01_func1: 1: 0x20918b8
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2: dl01_bss1: 4: 0x2091d00: 0
+dlo2: dl01_bss2: 4: 0x2091d04: %f
+dlo2: dl01_bss3: 1: 0x2091d80: 00
+dlo2: dl01_data1: 4: 0x2091bec: 1
+dlo2: dl01_data2: 4: 0x2091be8: %f
+dlo2: dl01_const1: 4: 0x2091bc8: 3
+dlo2: dl01_const2: 4: 0x2091bc4: %f
+dlo2: dl01_func1: 1: 0x20918b8
+dlo2: dl02_bss1: 4: 0x2092738: 0
+dlo2: dl02_bss2: 4: 0x209273c: %f
+dlo2: dl02_bss3: 1: 0x2092758: 00
+dlo2: dl02_data1: 4: 0x2092770: 0
+dlo2: dl02_data2: 4: 0x2092774: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3: dl01_bss1: 4: 0x2091d00: 0
+dlo3: dl01_bss2: 4: 0x2091d04: %f
+dlo3: dl01_bss3: 1: 0x2091d80: 00
+dlo3: dl01_data1: 4: 0x2091bec: 1
+dlo3: dl01_data2: 4: 0x2091be8: %f
+dlo3: dl01_const1: 4: 0x2091bc8: 3
+dlo3: dl01_const2: 4: 0x2091bc4: %f
+dlo3: dl01_func1: 1: 0x20918b8
+dlo3: dl02_bss1: 4: 0x2092738: 0
+dlo3: dl02_bss2: 4: 0x209273c: %f
+dlo3: dl02_bss3: 1: 0x2092758: 00
+dlo3: dl02_data1: 4: 0x2092770: 0
+dlo3: dl02_data2: 4: 0x2092774: %f
+dlo3: dl04_unresolv_1: 4: 0x2098730: 0
+dlo3: dl04_unresolv_2: 4: 0x2098734: %f
+dlo3: dl04_unresolv_3: 1: 0x2098738: 00
+dlo3: dl04_unresolv_4: 4: 0x209873c: 0
+dlo3: dl04_unresolv_5: 4: 0x2098700: 4
+dlo3: dl04_unresolv_6: 4: 0x2098720: dl-O4
+dlo3: dl05_unresolv_1: 8: 0x20993b8: 0
+dlo3: dl05_unresolv_2: 2: 0x20993c0: 0
+dlo3: dl05_unresolv_3: 4: 0x20993c4: 0
+dlo3: dl05_unresolv_4: 1: 0x20993c8: 0
+dlo3: dl05_unresolv_5: 8: 0x20993d0: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4: dl01_bss1: 4: 0x2091d00: 0
+dlo4: dl01_bss2: 4: 0x2091d04: %f
+dlo4: dl01_bss3: 1: 0x2091d80: 00
+dlo4: dl01_data1: 4: 0x2091bec: 1
+dlo4: dl01_data2: 4: 0x2091be8: %f
+dlo4: dl01_const1: 4: 0x2091bc8: 3
+dlo4: dl01_const2: 4: 0x2091bc4: %f
+dlo4: dl01_func1: 1: 0x20918b8
+dlo4: dl04_unresolv_1: 4: 0x2098730: 0
+dlo4: dl04_unresolv_2: 4: 0x2098734: %f
+dlo4: dl04_unresolv_3: 1: 0x2098738: 00
+dlo4: dl04_unresolv_4: 4: 0x209873c: 0
+dlo4: dl04_unresolv_5: 4: 0x2098700: 4
+dlo4: dl04_unresolv_6: 4: 0x2098720: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5: dl01_bss1: 4: 0x2091d00: 0
+dlo5: dl01_bss2: 4: 0x2091d04: %f
+dlo5: dl01_bss3: 1: 0x2091d80: 00
+dlo5: dl01_data1: 4: 0x2091bec: 1
+dlo5: dl01_data2: 4: 0x2091be8: %f
+dlo5: dl01_const1: 4: 0x2091bc8: 3
+dlo5: dl01_const2: 4: 0x2091bc4: %f
+dlo5: dl01_func1: 1: 0x20918b8
+dlo5: dl05_unresolv_1: 8: 0x20993b8: 0
+dlo5: dl05_unresolv_2: 2: 0x20993c0: 0
+dlo5: dl05_unresolv_3: 4: 0x20993c4: 0
+dlo5: dl05_unresolv_4: 1: 0x20993c8: 0
+dlo5: dl05_unresolv_5: 8: 0x20993d0: 0
+handle: 0x20951b0 closing
+handle: 0x2095b40 closing
+handle: 0x20989a0 closing
+handle: 0x2092000 closing
+handle: 0x2091190 closing
+--------------------------------------------------
+ Run: 3
+load: /dl07-o1.o
+handle: 0x20911a8 loaded
+load: /dl07-o2.o
+handle: 0x2092040 loaded
+load: /dl07-o3.o
+handle: 0x2095290 loaded
+load: /dl07-o4.o
+handle: 0x2095890 loaded
+load: /dl07-o5.o
+handle: 0x209a338 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1: dl01_bss1: 4: 0x2091d18: 0
+dlo1: dl01_bss2: 4: 0x2091d1c: %f
+dlo1: dl01_bss3: 1: 0x2091d98: 00
+dlo1: dl01_data1: 4: 0x2091d04: 1
+dlo1: dl01_data2: 4: 0x2091d00: %f
+dlo1: dl01_const1: 4: 0x2091be0: 3
+dlo1: dl01_const2: 4: 0x2091bdc: %f
+dlo1: dl01_func1: 1: 0x20918d0
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2: dl01_bss1: 4: 0x2091d18: 0
+dlo2: dl01_bss2: 4: 0x2091d1c: %f
+dlo2: dl01_bss3: 1: 0x2091d98: 00
+dlo2: dl01_data1: 4: 0x2091d04: 1
+dlo2: dl01_data2: 4: 0x2091d00: %f
+dlo2: dl01_const1: 4: 0x2091be0: 3
+dlo2: dl01_const2: 4: 0x2091bdc: %f
+dlo2: dl01_func1: 1: 0x20918d0
+dlo2: dl02_bss1: 4: 0x2095078: 0
+dlo2: dl02_bss2: 4: 0x209507c: %f
+dlo2: dl02_bss3: 1: 0x2095098: 00
+dlo2: dl02_data1: 4: 0x20950b0: 0
+dlo2: dl02_data2: 4: 0x20950b4: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3: dl01_bss1: 4: 0x2091d18: 0
+dlo3: dl01_bss2: 4: 0x2091d1c: %f
+dlo3: dl01_bss3: 1: 0x2091d98: 00
+dlo3: dl01_data1: 4: 0x2091d04: 1
+dlo3: dl01_data2: 4: 0x2091d00: %f
+dlo3: dl01_const1: 4: 0x2091be0: 3
+dlo3: dl01_const2: 4: 0x2091bdc: %f
+dlo3: dl01_func1: 1: 0x20918d0
+dlo3: dl02_bss1: 4: 0x2095078: 0
+dlo3: dl02_bss2: 4: 0x209507c: %f
+dlo3: dl02_bss3: 1: 0x2095098: 00
+dlo3: dl02_data1: 4: 0x20950b0: 0
+dlo3: dl02_data2: 4: 0x20950b4: %f
+dlo3: dl04_unresolv_1: 4: 0x209a0c8: 0
+dlo3: dl04_unresolv_2: 4: 0x209a0cc: %f
+dlo3: dl04_unresolv_3: 1: 0x209a0d0: 00
+dlo3: dl04_unresolv_4: 4: 0x209a0d4: 0
+dlo3: dl04_unresolv_5: 4: 0x209a098: 4
+dlo3: dl04_unresolv_6: 4: 0x209a0b8: dl-O4
+dlo3: dl05_unresolv_1: 8: 0x209ad50: 0
+dlo3: dl05_unresolv_2: 2: 0x209ad58: 0
+dlo3: dl05_unresolv_3: 4: 0x209ad5c: 0
+dlo3: dl05_unresolv_4: 1: 0x209ad60: 0
+dlo3: dl05_unresolv_5: 8: 0x209ad68: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4: dl01_bss1: 4: 0x2091d18: 0
+dlo4: dl01_bss2: 4: 0x2091d1c: %f
+dlo4: dl01_bss3: 1: 0x2091d98: 00
+dlo4: dl01_data1: 4: 0x2091d04: 1
+dlo4: dl01_data2: 4: 0x2091d00: %f
+dlo4: dl01_const1: 4: 0x2091be0: 3
+dlo4: dl01_const2: 4: 0x2091bdc: %f
+dlo4: dl01_func1: 1: 0x20918d0
+dlo4: dl04_unresolv_1: 4: 0x209a0c8: 0
+dlo4: dl04_unresolv_2: 4: 0x209a0cc: %f
+dlo4: dl04_unresolv_3: 1: 0x209a0d0: 00
+dlo4: dl04_unresolv_4: 4: 0x209a0d4: 0
+dlo4: dl04_unresolv_5: 4: 0x209a098: 4
+dlo4: dl04_unresolv_6: 4: 0x209a0b8: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5: dl01_bss1: 4: 0x2091d18: 0
+dlo5: dl01_bss2: 4: 0x2091d1c: %f
+dlo5: dl01_bss3: 1: 0x2091d98: 00
+dlo5: dl01_data1: 4: 0x2091d04: 1
+dlo5: dl01_data2: 4: 0x2091d00: %f
+dlo5: dl01_const1: 4: 0x2091be0: 3
+dlo5: dl01_const2: 4: 0x2091bdc: %f
+dlo5: dl01_func1: 1: 0x20918d0
+dlo5: dl05_unresolv_1: 8: 0x209ad50: 0
+dlo5: dl05_unresolv_2: 2: 0x209ad58: 0
+dlo5: dl05_unresolv_3: 4: 0x209ad5c: 0
+dlo5: dl05_unresolv_4: 1: 0x209ad60: 0
+dlo5: dl05_unresolv_5: 8: 0x209ad68: 0
+handle: 0x2095290 closing
+handle: 0x2095890 closing
+handle: 0x209a338 closing
+handle: 0x2092040 closing
+handle: 0x20911a8 closing
+--------------------------------------------------
+
+ REPEAT 100 TIMES
+
+--------------------------------------------------
+ Run: 99
+load: /dl07-o1.o
+handle: 0x211fbc0 loaded
+load: /dl07-o2.o
+handle: 0x212ed58 loaded
+load: /dl07-o3.o
+handle: 0x214d6d0 loaded
+load: /dl07-o4.o
+handle: 0x214eba0 loaded
+load: /dl07-o5.o
+handle: 0x214fa18 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1: dl01_bss1: 4: 0x2136578: 0
+dlo1: dl01_bss2: 4: 0x213657c: %f
+dlo1: dl01_bss3: 1: 0x21365f8: 00
+dlo1: dl01_data1: 4: 0x2136564: 1
+dlo1: dl01_data2: 4: 0x2136560: %f
+dlo1: dl01_const1: 4: 0x213fa18: 3
+dlo1: dl01_const2: 4: 0x213fa14: %f
+dlo1: dl01_func1: 1: 0x213f560
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2: dl01_bss1: 4: 0x2136578: 0
+dlo2: dl01_bss2: 4: 0x213657c: %f
+dlo2: dl01_bss3: 1: 0x21365f8: 00
+dlo2: dl01_data1: 4: 0x2136564: 1
+dlo2: dl01_data2: 4: 0x2136560: %f
+dlo2: dl01_const1: 4: 0x213fa18: 3
+dlo2: dl01_const2: 4: 0x213fa14: %f
+dlo2: dl01_func1: 1: 0x213f560
+dlo2: dl02_bss1: 4: 0x214d460: 0
+dlo2: dl02_bss2: 4: 0x214d464: %f
+dlo2: dl02_bss3: 1: 0x214d480: 00
+dlo2: dl02_data1: 4: 0x214d498: 0
+dlo2: dl02_data2: 4: 0x214d49c: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3: dl01_bss1: 4: 0x2136578: 0
+dlo3: dl01_bss2: 4: 0x213657c: %f
+dlo3: dl01_bss3: 1: 0x21365f8: 00
+dlo3: dl01_data1: 4: 0x2136564: 1
+dlo3: dl01_data2: 4: 0x2136560: %f
+dlo3: dl01_const1: 4: 0x213fa18: 3
+dlo3: dl01_const2: 4: 0x213fa14: %f
+dlo3: dl01_func1: 1: 0x213f560
+dlo3: dl02_bss1: 4: 0x214d460: 0
+dlo3: dl02_bss2: 4: 0x214d464: %f
+dlo3: dl02_bss3: 1: 0x214d480: 00
+dlo3: dl02_data1: 4: 0x214d498: 0
+dlo3: dl02_data2: 4: 0x214d49c: %f
+dlo3: dl04_unresolv_1: 4: 0x214f7a8: 0
+dlo3: dl04_unresolv_2: 4: 0x214f7ac: %f
+dlo3: dl04_unresolv_3: 1: 0x214f7b0: 00
+dlo3: dl04_unresolv_4: 4: 0x214f7b4: 0
+dlo3: dl04_unresolv_5: 4: 0x214f778: 4
+dlo3: dl04_unresolv_6: 4: 0x214f798: dl-O4
+dlo3: dl05_unresolv_1: 8: 0x2150430: 0
+dlo3: dl05_unresolv_2: 2: 0x2150438: 0
+dlo3: dl05_unresolv_3: 4: 0x215043c: 0
+dlo3: dl05_unresolv_4: 1: 0x2150440: 0
+dlo3: dl05_unresolv_5: 8: 0x2150448: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4: dl01_bss1: 4: 0x2136578: 0
+dlo4: dl01_bss2: 4: 0x213657c: %f
+dlo4: dl01_bss3: 1: 0x21365f8: 00
+dlo4: dl01_data1: 4: 0x2136564: 1
+dlo4: dl01_data2: 4: 0x2136560: %f
+dlo4: dl01_const1: 4: 0x213fa18: 3
+dlo4: dl01_const2: 4: 0x213fa14: %f
+dlo4: dl01_func1: 1: 0x213f560
+dlo4: dl04_unresolv_1: 4: 0x214f7a8: 0
+dlo4: dl04_unresolv_2: 4: 0x214f7ac: %f
+dlo4: dl04_unresolv_3: 1: 0x214f7b0: 00
+dlo4: dl04_unresolv_4: 4: 0x214f7b4: 0
+dlo4: dl04_unresolv_5: 4: 0x214f778: 4
+dlo4: dl04_unresolv_6: 4: 0x214f798: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5: dl01_bss1: 4: 0x2136578: 0
+dlo5: dl01_bss2: 4: 0x213657c: %f
+dlo5: dl01_bss3: 1: 0x21365f8: 00
+dlo5: dl01_data1: 4: 0x2136564: 1
+dlo5: dl01_data2: 4: 0x2136560: %f
+dlo5: dl01_const1: 4: 0x213fa18: 3
+dlo5: dl01_const2: 4: 0x213fa14: %f
+dlo5: dl01_func1: 1: 0x213f560
+dlo5: dl05_unresolv_1: 8: 0x2150430: 0
+dlo5: dl05_unresolv_2: 2: 0x2150438: 0
+dlo5: dl05_unresolv_3: 4: 0x215043c: 0
+dlo5: dl05_unresolv_4: 1: 0x2150440: 0
+dlo5: dl05_unresolv_5: 8: 0x2150448: 0
+handle: 0x214d6d0 closing
+handle: 0x214eba0 closing
+handle: 0x214fa18 closing
+handle: 0x212ed58 closing
+handle: 0x211fbc0 closing
+
+*** END OF TEST libdl (RTL) 7 ***
+
+
+*** FATAL ***
+fatal source: 5 (RTEMS_FATAL_SOURCE_EXIT)
+fatal code: 0 (0x00000000)
+RTEMS version: 5.0.0.6de8cc8ad871a197d7233a9221786d8efee87840-modified
+RTEMS tools: 7.3.0 20180125 (RTEMS 5, RSB 30da0c720b78eba16a3f5272206c07415368617b, Newlib 2ab57ad59bc35dafffa69cd4da5e228971de069f)
+executing thread ID: 0x08a010001
+executing thread name: UI1
diff --git a/testsuites/libtests/dl07/init.c b/testsuites/libtests/dl07/init.c
new file mode 100644
index 0000000000..7c482c4944
--- /dev/null
+++ b/testsuites/libtests/dl07/init.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj@rtems.org>. All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl.h>
+#include <rtems/untar.h>
+
+#include "dl-load.h"
+
+const char rtems_test_name[] = "libdl (RTL) 7";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+#include "dl07-tar.h"
+
+#define TARFILE_START dl07_tar
+#define TARFILE_SIZE dl07_tar_size
+
+static int test(void)
+{
+ int ret;
+ ret = dl_load_test();
+ if (ret)
+ rtems_test_exit(ret);
+ return 0;
+}
+
+static void Init(rtems_task_argument arg)
+{
+ int te;
+ int i;
+
+ TEST_BEGIN();
+
+ te = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE);
+ if (te != 0)
+ {
+ printf("untar failed: %d\n", te);
+ rtems_test_exit(1);
+ exit (1);
+ }
+
+ for (i = 0; i < 100; ++i)
+ {
+ printf ("--------------------------------------------------\n");
+ printf (" Run: %d\n", i);
+ test();
+ }
+
+ TEST_END();
+
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT_TASK_STACK_SIZE (8U * 1024U)
+
+#define CONFIGURE_INIT_TASK_ATTRIBUTES (RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT)
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>