summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-03-10 07:04:42 +1300
committerChris Johns <chrisj@rtems.org>2019-03-22 14:16:52 +1100
commitdad6fd4333c4b05af08bd78714acefb5a86f1af9 (patch)
tree232b39b72ad54f69a25291f77eb999a1c1e4cb1e
parentbsp/atsam: Fix SPI driver DMA support (diff)
downloadrtems-dad6fd4333c4b05af08bd78714acefb5a86f1af9.tar.bz2
libdl: Add an archive command
- The archive command lists archives, symbols and any duplicate symbols. - Change the RTL shell commands to the rtems_printer to allow the output to be captured.
-rw-r--r--cpukit/include/rtems/rtl/rtl-archive.h1
-rw-r--r--cpukit/include/rtems/rtl/rtl-shell.h28
-rw-r--r--cpukit/include/rtems/rtl/rtl-trace.h6
-rw-r--r--cpukit/libdl/rtl-archive.c49
-rw-r--r--cpukit/libdl/rtl-shell.c1052
-rw-r--r--cpukit/libdl/rtl-trace.c16
-rw-r--r--testsuites/libtests/Makefile.am52
-rw-r--r--testsuites/libtests/configure.ac1
-rw-r--r--testsuites/libtests/dl10/dl-load.c141
-rw-r--r--testsuites/libtests/dl10/dl-load.h21
-rw-r--r--testsuites/libtests/dl10/dl-o1.c61
-rw-r--r--testsuites/libtests/dl10/dl-o1.h23
-rw-r--r--testsuites/libtests/dl10/dl-o2.c39
-rw-r--r--testsuites/libtests/dl10/dl-o2.h25
-rw-r--r--testsuites/libtests/dl10/dl-o3.c40
-rw-r--r--testsuites/libtests/dl10/dl-o3.h15
-rw-r--r--testsuites/libtests/dl10/dl-o4.c40
-rw-r--r--testsuites/libtests/dl10/dl-o4.h29
-rw-r--r--testsuites/libtests/dl10/dl-o5.c36
-rw-r--r--testsuites/libtests/dl10/dl-o5.h30
-rw-r--r--testsuites/libtests/dl10/dl-o6.c18
-rw-r--r--testsuites/libtests/dl10/dl10.doc22
-rw-r--r--testsuites/libtests/dl10/dl10.scn41
-rw-r--r--testsuites/libtests/dl10/init.c137
-rw-r--r--testsuites/testdata/rtems.tcfg1
25 files changed, 1752 insertions, 172 deletions
diff --git a/cpukit/include/rtems/rtl/rtl-archive.h b/cpukit/include/rtems/rtl/rtl-archive.h
index 8aa163e782..174bebb68b 100644
--- a/cpukit/include/rtems/rtl/rtl-archive.h
+++ b/cpukit/include/rtems/rtl/rtl-archive.h
@@ -31,6 +31,7 @@
#include <rtems.h>
#include <rtems/chain.h>
+#include <rtems/printer.h>
#ifdef __cplusplus
extern "C" {
diff --git a/cpukit/include/rtems/rtl/rtl-shell.h b/cpukit/include/rtems/rtl/rtl-shell.h
index b0a6e8d8d4..9230b619c6 100644
--- a/cpukit/include/rtems/rtl/rtl-shell.h
+++ b/cpukit/include/rtems/rtl/rtl-shell.h
@@ -16,6 +16,8 @@
#if !defined (_RTEMS_RTL_SHELL_H_)
#define _RTEMS_RTL_SHELL_H_
+#include <rtems/print.h>
+
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -30,6 +32,32 @@ extern "C" {
*/
int rtems_rtl_shell_command (int argc, char* argv[]);
+/**
+ * List object files.
+ */
+int rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[]);
+
+/**
+ * Symbols.
+ */
+int rtems_rtl_shell_sym (const rtems_printer* printer, int argc, char* argv[]);
+
+/**
+ * Object files.
+ */
+int rtems_rtl_shell_object (const rtems_printer* printer, int argc, char* argv[]);
+
+
+/**
+ * Archive files.
+ */
+int rtems_rtl_shell_archive (const rtems_printer* printer, int argc, char* argv[]);
+
+/**
+ * Call text symbol.
+ */
+int rtems_rtl_shell_call (const rtems_printer* printer, int argc, char* argv[]);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/cpukit/include/rtems/rtl/rtl-trace.h b/cpukit/include/rtems/rtl/rtl-trace.h
index cd3921400c..06c72c8992 100644
--- a/cpukit/include/rtems/rtl/rtl-trace.h
+++ b/cpukit/include/rtems/rtl/rtl-trace.h
@@ -23,6 +23,8 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>
+#include <rtems/printer.h>
+
/**
* Set to 1 to build trace support in to the RTL code.
*/
@@ -98,7 +100,9 @@ rtems_rtl_trace_mask rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask);
* Add shell trace shell command.
*/
#if RTEMS_RTL_TRACE
-int rtems_rtl_trace_shell_command (int argc, char *argv[]);
+int rtems_rtl_trace_shell_command (const rtems_printer* printer,
+ int argc,
+ char* argv[]);
#endif
#ifdef __cplusplus
diff --git a/cpukit/libdl/rtl-archive.c b/cpukit/libdl/rtl-archive.c
index 77ad2b0d30..34e45357ba 100644
--- a/cpukit/libdl/rtl-archive.c
+++ b/cpukit/libdl/rtl-archive.c
@@ -34,12 +34,6 @@
#include "rtl-error.h"
/**
- * The archive symbols threshold after which a sorted symbol table is
- * created.
- */
-#define RTEMS_RTL_ARCHIVE_SYMBOLS_SORT (8)
-
-/**
* Archive headers.
*/
#define RTEMS_RTL_AR_IDENT "!<arch>\n"
@@ -223,8 +217,8 @@ rtems_rtl_archive_find (rtems_rtl_archives* archives,
*
* The symbol search is performance sensitive. The archive's symbol table being
* searched is the symbol table in the archive created by ranlib. This table is
- * not sorted so a sorted table of pointered to the symbols is generated after
- * loading if there are enough symbols. For small symbol tables the searc is
+ * not sorted so a sorted table of pointeres to the symbols is generated after
+ * loading if there are enough symbols. For small symbol tables the search is
* linear. The entire table is held in memory. At the time of writing this code
* the symbol table for the SPARC architecture's libc is 16k.
*
@@ -286,7 +280,7 @@ rtems_rtl_archive_obj_finder (rtems_rtl_archive* archive, void* data)
{
search->archive = archive;
search->offset =
- rtems_rtl_archive_read_32 (symbols->base + (entry * 4));
+ rtems_rtl_archive_read_32 (symbols->base + ((entry + 1) * 4));
return false;
}
symbol += strlen (symbol) + 1;
@@ -647,8 +641,8 @@ rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
offset, size);
/*
- * Reallocation the symbol table memory if it has changed size.
- * Note, an updated library may have te same symbol table.
+ * Reallocate the symbol table memory if it has changed size.
+ * Note, an updated library may have the same symbol table.
*/
if (archive->symbols.size != size)
{
@@ -697,28 +691,25 @@ rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
archive->symbols.names += (archive->symbols.entries + 1) * 4;
/*
- * Created a sorted symbol table if over the threshold number of symbols.
+ * Create a sorted symbol table.
*/
- if (archive->symbols.entries > RTEMS_RTL_ARCHIVE_SYMBOLS_SORT)
+ size = archive->symbols.entries * sizeof (rtems_rtl_archive_symbol);
+ archive->symbols.symbols =
+ rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, size, true);
+ if (archive->symbols.symbols != NULL)
{
- size = archive->symbols.entries * sizeof (rtems_rtl_archive_symbol);
- archive->symbols.symbols =
- rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, size, true);
- if (archive->symbols.symbols != NULL)
+ const char* symbol = archive->symbols.names;
+ size_t e;
+ for (e = 0; e < archive->symbols.entries; ++e)
{
- const char* symbol = archive->symbols.names;
- size_t e;
- for (e = 0; e < archive->symbols.entries; ++e)
- {
- archive->symbols.symbols[e].entry = e + 1;
- archive->symbols.symbols[e].label = symbol;
- symbol += strlen (symbol) + 1;
- }
- qsort (archive->symbols.symbols,
- archive->symbols.entries,
- sizeof (rtems_rtl_archive_symbol),
- rtems_rtl_archive_symbol_compare);
+ archive->symbols.symbols[e].entry = e + 1;
+ archive->symbols.symbols[e].label = symbol;
+ symbol += strlen (symbol) + 1;
}
+ qsort (archive->symbols.symbols,
+ archive->symbols.entries,
+ sizeof (rtems_rtl_archive_symbol),
+ rtems_rtl_archive_symbol_compare);
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index 7458fb5608..56418303ff 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -22,10 +22,15 @@
#include <inttypes.h>
#include <rtems/inttypes.h>
-#include <stdio.h>
+#include <sys/stat.h>
+#include <regex.h>
#include <string.h>
+#include <dlfcn.h>
+
+#include <rtems/printer.h>
#include <rtems/rtl/rtl.h>
+#include <rtems/rtl/rtl-archive.h>
#include <rtems/rtl/rtl-shell.h>
#include <rtems/rtl/rtl-trace.h>
#include "rtl-chain-iterator.h"
@@ -33,7 +38,7 @@
/**
* The type of the shell handlers we have.
*/
-typedef int (*rtems_rtl_shell_handler) (rtems_rtl_data* rtl, int argc, char *argv[]);
+typedef int (*rtems_rtl_shell_handler) (const rtems_printer* printer, int argc, char *argv[]);
/**
* Table of handlers we parse to invoke the command.
@@ -83,10 +88,20 @@ rtems_rtl_count_symbols (rtems_rtl_data* rtl)
}
static int
-rtems_rtl_shell_status (rtems_rtl_data* rtl, int argc, char *argv[])
+rtems_rtl_shell_status (const rtems_printer* printer,
+ int argc,
+ char* argv[])
{
rtems_rtl_obj_summary summary;
size_t total_memory;
+ rtems_rtl_data* rtl;
+
+ rtl = rtems_rtl_lock ();
+ if (rtl == NULL)
+ {
+ rtems_printf (printer, "error: cannot lock the linker\n");
+ return 1;
+ }
summary.count = 0;
summary.exec = 0;
@@ -101,13 +116,15 @@ rtems_rtl_shell_status (rtems_rtl_data* rtl, int argc, char *argv[])
sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj)) +
summary.exec + summary.symbols;
- printf ("Runtime Linker Status:\n");
- printf (" paths: %s\n", rtl->paths);
- printf (" objects: %d\n", summary.count);
- printf (" total memory: %zi\n", total_memory);
- printf (" exec memory: %zi\n", summary.exec);
- printf (" sym memory: %zi\n", summary.symbols);
- printf (" symbols: %d\n", rtems_rtl_count_symbols (rtl));
+ rtems_printf (printer, "Runtime Linker Status:\n");
+ rtems_printf (printer, " paths: %s\n", rtl->paths);
+ rtems_printf (printer, " objects: %d\n", summary.count);
+ rtems_printf (printer, " total memory: %zi\n", total_memory);
+ rtems_printf (printer, " exec memory: %zi\n", summary.exec);
+ rtems_printf (printer, " sym memory: %zi\n", summary.symbols);
+ rtems_printf (printer, " symbols: %d\n", rtems_rtl_count_symbols (rtl));
+
+ rtems_rtl_unlock ();
return 0;
}
@@ -117,68 +134,280 @@ 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 sep1; /**< Print a separator. */
- 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. */
+ const rtems_printer* printer; /**< The RTEMS printer. */
+ 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 stats; /**< Print stats. */
+ 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. */
+ const char* re_name; /**< Name regx to filter on. */
+ const char* re_symbol; /**< Symbol regx to filter on. */
} rtems_rtl_obj_print;
/**
* Parse an argument.
*/
static bool
-rtems_rtl_parse_arg (const char* opt, int argc, char *argv[])
+rtems_rtl_parse_opt (const char opt, int argc, char *argv[])
{
- int arg;
- for (arg = 0; arg < argc; ++arg)
- if (strncmp (opt, argv[arg], 2) == 0)
- return true;
+ size_t arg;
+ for (arg = 1; arg < argc; ++arg)
+ {
+ if (argv[arg][0] == '-')
+ {
+ size_t len = strlen (argv[arg]);
+ size_t i;
+ for (i = 1; i < len; ++i)
+ if (argv[arg][i] == opt)
+ return true;
+ }
+ }
return false;
}
+static bool
+rtems_rtl_check_opts (const rtems_printer* printer,
+ const char* opts,
+ int argc,
+ char* argv[])
+{
+ size_t olen = strlen (opts);
+ size_t arg;
+ for (arg = 1; arg < argc; ++arg)
+ {
+ if (argv[arg][0] == '-')
+ {
+ size_t len = strlen (argv[arg]);
+ size_t i;
+ for (i = 1; i < len; ++i)
+ {
+ bool found = false;
+ size_t o;
+ for (o = 0; o < olen; ++o)
+ {
+ if (argv[arg][i] == opts[o])
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ {
+ rtems_printf (printer, "error: invalid option: %c (%s)\n",
+ argv[arg][i], argv[arg]);
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+static ssize_t
+rtems_rtl_parse_arg_index (const char opt,
+ const char* skip_opts,
+ int argc,
+ char* argv[])
+{
+ ssize_t arg;
+ for (arg = 1; arg < argc; ++arg)
+ {
+ if (argv[arg][0] == '-')
+ {
+ /*
+ * We can check the next char because there has to be a valid char or a
+ * nul.
+ */
+ if (argv[arg][1] != '\0')
+ {
+ size_t len = skip_opts != NULL ? strlen (skip_opts) : 0;
+ size_t i;
+ for (i = 0; i < len; ++i)
+ {
+ if (skip_opts[i] == argv[arg][1])
+ {
+ ++arg;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (opt == ' ')
+ return arg;
+ }
+ /*
+ * Is this an option and does it match what we are looking for?
+ */
+ if (argv[arg][0] == '-' && argv[arg][1] == opt && arg < argc)
+ return arg + 1;
+ }
+ return -1;
+}
+
+static const char*
+rtems_rtl_parse_arg (const char opt,
+ const char* skip_opts,
+ int argc,
+ char* argv[])
+{
+ ssize_t arg = rtems_rtl_parse_arg_index (opt, skip_opts, argc, argv);
+ if (arg < 0)
+ return NULL;
+ return argv[arg];
+}
+
/**
- * See if -b for base is set.
+ * Regx matching.
*/
static bool
-rtems_rtl_base_arg (int argc, char *argv[])
+rtems_rtl_regx_compile (const rtems_printer* printer,
+ const char* label,
+ regex_t* rege,
+ const char* expression)
{
- return rtems_rtl_parse_arg ("-b", argc, argv);
+ int r = regcomp (rege, expression, REG_EXTENDED | REG_NOSUB);
+ if (r != 0)
+ {
+ char rerror[128];
+ regerror (r, rege, rerror, sizeof(rerror));
+ rtems_printf (printer, "error: %s: %s\n", label, rerror);
+ return false;
+ }
+ return true;
+}
+
+static int
+rtems_rtl_regx_match (const rtems_printer* printer,
+ const char* label,
+ regex_t* rege,
+ const char* string)
+{
+ int r = regexec (rege, string, 0, NULL, 0);
+ if (r != 0 && r != REG_NOMATCH)
+ {
+ char rerror[128];
+ regerror (r, rege, rerror, sizeof(rerror));
+ rtems_printf (printer, "error: %s: %s\n", label, rerror);
+ regfree (rege);
+ return -1;
+ }
+ return r == 0 ? 1 : 0;
}
/**
- * See if -s for base is set.
+ * Print the obj name.
+ */
+static void
+rtems_rtl_print_obj_name (const rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
+{
+ rtems_printf (print->printer, "%-*c", print->indent, ' ');
+ if (rtems_rtl_obj_aname (obj) != NULL)
+ rtems_printf (print->printer, "%s:", rtems_rtl_obj_aname (obj));
+ rtems_printf (print->printer, "%s\n", rtems_rtl_obj_oname (obj));
+}
+
+/**
+ * Print symbols.
*/
static bool
-rtems_rtl_symbols_arg (int argc, char *argv[])
+rtems_rtl_print_symbols (rtems_rtl_obj_print* print,
+ rtems_rtl_obj* obj,
+ int indent,
+ bool show_name)
{
- return rtems_rtl_parse_arg ("-s", argc, argv);
+ regex_t rege;
+ int max_len = 0;
+ int s;
+
+ if (print->re_symbol != NULL &&
+ !rtems_rtl_regx_compile (print->printer,
+ "symbol filter",
+ &rege, print->re_symbol))
+ {
+ return false;
+ }
+
+ for (s = 0; s < obj->global_syms; ++s)
+ {
+ const char* sym = obj->global_table[s].name;
+ int len;
+
+ if (print->re_symbol != NULL)
+ {
+ int r = rtems_rtl_regx_match (print->printer, "symbol match", &rege, sym);
+ if (r < 0)
+ return false;
+ if (!r)
+ continue;
+ }
+
+ len = strlen (obj->global_table[s].name);
+ if (len > max_len)
+ max_len = len;
+ }
+
+ for (s = 0; s < obj->global_syms; ++s)
+ {
+ const char* sym = obj->global_table[s].name;
+ if (print->re_symbol != NULL)
+ {
+ int r = rtems_rtl_regx_match (print->printer, "symbol match", &rege, sym);
+ if (r < 0)
+ return false;
+ if (r == 0)
+ continue;
+ }
+ if (show_name)
+ {
+ show_name = false;
+ rtems_rtl_print_obj_name (print, obj);
+ }
+ rtems_printf (print->printer, "%-*c%-*s = %p\n", indent + 2, ' ',
+ max_len, sym, obj->global_table[s].value);
+ }
+
+ regfree (&rege);
+
+ return true;
}
/**
- * Dependenncies printer.
+ * Dependencies printer.
*/
typedef struct
{
- bool first; /**< Is this the first line printed. */
- size_t indent; /**< The indent. */
+ const rtems_rtl_obj_print* print; /**< The print data. */
+ bool first; /**< Is this the first line printed. */
+ bool show_name; /**< Show the object name. */
+ 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_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: ", (int) dd->indent, ' ');
- else
+ if (dd->first)
+ {
dd->first = false;
- printf ("%s", dependent->oname);
+ if (dd->show_name)
+ {
+ dd->show_name = false;
+ rtems_rtl_print_obj_name (dd->print, obj);
+ }
+ rtems_printf (dd->print->printer, "%-*cdependencies : ", dd->indent, ' ');
+ dd->indent += strlen ("dependencies :");
+ }
+ else
+ {
+ rtems_printf (dd->print->printer, "\n%-*c: ", (int) dd->indent, ' ');
+ }
+ rtems_printf (dd->print->printer, "%s", dependent->oname);
return false;
}
@@ -189,6 +418,8 @@ static bool
rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
{
char flags_str[33];
+ int indent = print->indent + 1;
+ bool show_name = true;
/*
* Skip the base module unless asked to show it.
@@ -196,72 +427,114 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
if (!print->base && (obj == print->rtl->base))
return true;
- if (print->sep1)
+ if (print->re_name != NULL)
{
- printf ("%-*c--------------\n", print->indent, ' ');
+ regex_t rege;
+ int r = 0;
+
+ if (!rtems_rtl_regx_compile (print->printer,
+ "name filter",
+ &rege, print->re_name))
+ {
+ return false;
+ }
+
+ if (rtems_rtl_obj_aname (obj) != NULL)
+ {
+ r = rtems_rtl_regx_match (print->printer,
+ "aname match",
+ &rege,
+ rtems_rtl_obj_aname (obj));
+ if (r < 0)
+ return false;
+ }
+
+ if (r == 0)
+ {
+ r = rtems_rtl_regx_match (print->printer,
+ "oname match",
+ &rege,
+ rtems_rtl_obj_oname (obj));
+ if (r < 0)
+ return false;
+ }
+
+ regfree (&rege);
+
+ if (r == 0)
+ return true;
}
- if (print->oname)
+
+ if (print->names || print->memory_map || print->stats ||
+ (!print->names && !print->memory_map && !print->stats &&
+ !print->symbols && !print->dependencies))
{
- printf ("%-*cobject name : %s\n",
- print->indent, ' ', rtems_rtl_obj_oname (obj));
+ show_name = false;
+ rtems_rtl_print_obj_name (print, obj);
}
+
if (print->names)
{
- printf ("%-*cfile name : %s\n",
- print->indent, ' ', rtems_rtl_obj_fname (obj));
- printf ("%-*carchive name : %s\n",
- print->indent, ' ', rtems_rtl_obj_aname (obj));
+ rtems_printf (print->printer,
+ "%-*cfile name : %s\n",
+ indent, ' ', rtems_rtl_obj_fname (obj));
+ rtems_printf (print->printer,
+ "%-*carchive name : %s\n",
+ indent, ' ', rtems_rtl_obj_aname (obj));
strcpy (flags_str, "--");
if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
flags_str[0] = 'L';
if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
flags_str[1] = 'U';
- printf ("%-*cflags : %s\n", print->indent, ' ', flags_str);
- printf ("%-*cfile offset : %" PRIdoff_t "\n", print->indent, ' ', obj->ooffset);
- printf ("%-*cfile size : %zi\n", print->indent, ' ', obj->fsize);
+ rtems_printf (print->printer,
+ "%-*cflags : %s\n", indent, ' ', flags_str);
+ rtems_printf (print->printer,
+ "%-*cfile offset : %" PRIdoff_t "\n", indent, ' ', obj->ooffset);
+ rtems_printf (print->printer,
+ "%-*cfile size : %zi\n", indent, ' ', obj->fsize);
}
if (print->memory_map)
{
- printf ("%-*cexec size : %zi\n", print->indent, ' ', obj->exec_size);
- printf ("%-*ctext base : %p (%zi)\n", print->indent, ' ',
- obj->text_base, obj->text_size);
- printf ("%-*cconst base : %p (%zi)\n", print->indent, ' ',
- obj->const_base, obj->const_size);
- printf ("%-*cdata base : %p (%zi)\n", print->indent, ' ',
- obj->data_base, obj->data_size);
- printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ',
- obj->bss_base, obj->bss_size);
- }
- 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);
+ rtems_printf (print->printer,
+ "%-*cexec size : %zi\n", indent, ' ', obj->exec_size);
+ rtems_printf (print->printer,
+ "%-*ctext base : %p (%zi)\n", indent, ' ',
+ obj->text_base, obj->text_size);
+ rtems_printf (print->printer,
+ "%-*cconst base : %p (%zi)\n", indent, ' ',
+ obj->const_base, obj->const_size);
+ rtems_printf (print->printer,
+ "%-*cdata base : %p (%zi)\n", indent, ' ',
+ obj->data_base, obj->data_size);
+ rtems_printf (print->printer,
+ "%-*cbss base : %p (%zi)\n", indent, ' ',
+ obj->bss_base, obj->bss_size);
+ }
+ if (print->stats)
+ {
+ rtems_printf (print->printer, "%-*cunresolved : %zu\n", indent, ' ', obj->unresolved);
+ rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users);
+ rtems_printf (print->printer, "%-*creferences : %zu\n", indent, ' ', obj->refs);
+ rtems_printf (print->printer, "%-*csymbols : %zi\n", indent, ' ', obj->global_syms);
+ rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
+ }
if (print->symbols)
{
- int max_len = 0;
- int s;
- for (s = 0; s < obj->global_syms; ++s)
- {
- int len = strlen (obj->global_table[s].name);
- if (len > max_len)
- max_len = len;
- }
- for (s = 0; s < obj->global_syms; ++s)
- printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
- max_len, obj->global_table[s].name, obj->global_table[s].value);
+ if (!rtems_rtl_print_symbols (print, obj, indent, show_name))
+ return false;
}
if (print->dependencies)
{
rtems_rtl_dep_data dd = {
+ .print = print,
.first = true,
- .indent = strlen ("dependencies :") + print->indent
+ .show_name = show_name,
+ .indent = indent
};
- printf ("%-*cdependencies : ", print->indent, ' ');
rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
- printf ("\n");
+ if (!dd.first)
+ rtems_printf (print->printer, "\n");
}
- printf ("\n");
return true;
}
@@ -274,7 +547,8 @@ rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec* rec,
{
rtems_rtl_obj_print* print = (rtems_rtl_obj_print*) data;
if (rec->type == rtems_rtl_unresolved_symbol)
- printf ("%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
+ rtems_printf (print->printer,
+ "%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
return false;
}
@@ -289,61 +563,568 @@ rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
return rtems_rtl_obj_printer (print, obj);
}
-static int
-rtems_rtl_shell_list (rtems_rtl_data* rtl, int argc, char *argv[])
+int
+rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
{
- rtems_rtl_obj_print print;
- print.rtl = rtl;
+ rtems_rtl_obj_print print = { 0 };
+ if (!rtems_rtl_check_opts (printer, "nlmsdb", argc, argv))
+ return 1;
+ print.printer = printer;
print.indent = 1;
- print.sep1 = true;
print.oname = true;
- 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,
+ print.names = rtems_rtl_parse_opt ('n', argc, argv);
+ print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
+ print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
+ print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
+ print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
+ print.base = rtems_rtl_parse_opt ('b', argc, argv);;
+ print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+ print.re_symbol = NULL;
+ print.rtl = rtems_rtl_lock ();
+ if (print.rtl == NULL)
+ {
+ rtems_printf (print.printer, "error: cannot lock the linker\n");
+ return 1;
+ }
+ rtems_rtl_chain_iterate (&print.rtl->objects,
rtems_rtl_obj_print_iterator,
&print);
+ rtems_rtl_unlock ();
return 0;
}
-static int
-rtems_rtl_shell_sym (rtems_rtl_data* rtl, int argc, char *argv[])
+int
+rtems_rtl_shell_sym (const rtems_printer* printer, int argc, char* argv[])
{
- rtems_rtl_obj_print print;
- print.rtl = rtl;
+ rtems_rtl_obj_print print = { 0 };
+ if (!rtems_rtl_check_opts (printer, "buo", argc, argv))
+ return 1;
+ print.printer = printer;
print.indent = 1;
- print.sep1 = true;
print.oname = true;
print.names = false;
+ print.stats = false;
print.memory_map = false;
- print.symbols = true;
+ print.symbols = !rtems_rtl_parse_opt ('u', argc, argv);;
print.dependencies = false;
- print.base = rtems_rtl_base_arg (argc, argv);
- rtems_rtl_chain_iterate (&rtl->objects,
- rtems_rtl_obj_print_iterator,
- &print);
- printf ("Unresolved:\n");
- rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_printer, &print);
+ print.base = rtems_rtl_parse_opt ('b', argc, argv);
+ print.re_name = rtems_rtl_parse_arg ('o', NULL, argc, argv);;
+ print.re_symbol = rtems_rtl_parse_arg (' ', "ou", argc, argv);
+ print.rtl = rtems_rtl_lock ();
+ if (print.rtl == NULL)
+ {
+ rtems_printf (print.printer, "error: cannot lock the linker\n");
+ return 1;
+ }
+ if (print.symbols)
+ {
+ rtems_rtl_chain_iterate (&print.rtl->objects,
+ rtems_rtl_obj_print_iterator,
+ &print);
+ }
+ if (rtems_rtl_parse_opt ('u', argc, argv))
+ {
+ rtems_printf (printer, "Unresolved:\n");
+ rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_printer, &print);
+ }
+ rtems_rtl_unlock ();
return 0;
}
-static int
-rtems_rtl_shell_object (rtems_rtl_data* rtl, int argc, char *argv[])
+int
+rtems_rtl_shell_object (const rtems_printer* printer, int argc, char* argv[])
{
+ size_t arg;
+
+ --argc;
+ ++argv;
+
+ for (arg = 0; arg < argc; ++arg)
+ {
+ if (argv[arg][0] == '-')
+ {
+ switch (argv[arg][1])
+ {
+ case 'h':
+ case '?':
+ rtems_printf (printer, "obj commands:\n");
+ rtems_printf (printer, " load <file>\n");
+ rtems_printf (printer, " unload <file>\n");
+ break;
+ default:
+ rtems_printf (printer, "error: invalid option: %s\n", argv[arg]);
+ return 1;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (arg >= argc)
+ {
+ rtems_printf (printer, "error: no obj command\n");
+ return 1;
+ }
+
+ if (strcmp (argv[arg], "load") == 0)
+ {
+ void* handle;
+ int unresolved;
+
+ ++arg;
+ if (arg >= argc)
+ {
+ rtems_printf (printer, "error: no object file to load\n");
+ return 1;
+ }
+
+ handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL);
+ if (handle == NULL)
+ {
+ rtems_printf (printer, "error: load: %s: %s\n", argv[arg], dlerror ());
+ return 1;
+ }
+
+ if (dlinfo (RTLD_SELF, RTLD_DI_UNRESOLVED, &unresolved) < 0)
+ {
+ rtems_printf (printer, "error: %s: %s\n", argv[arg], dlerror ());
+ return 1;
+ }
+
+ if (unresolved != 0)
+ {
+ rtems_printf (printer, "warning: unresolved symbols present\n");
+ return 1;
+ }
+ }
+ else if (strcmp (argv[arg], "unload") == 0)
+ {
+ rtems_rtl_data* rtl;
+ rtems_rtl_obj* obj;
+
+ ++arg;
+ if (arg >= argc)
+ {
+ rtems_printf (printer, "error: no object file to load\n");
+ return 1;
+ }
+
+ rtl = rtems_rtl_lock ();
+ if (rtl == NULL)
+ {
+ rtems_printf (printer, "error: cannot lock RTL\n");
+ return 1;
+ }
+
+ obj = rtems_rtl_find_obj (argv[arg]);
+ if (obj == NULL)
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
+ return 1;
+ }
+
+ if (!rtems_rtl_unload (obj))
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
+ return 1;
+ }
+
+ rtems_rtl_unlock ();
+ }
+ else
+ {
+ rtems_printf (printer, "error: unknown obj command: %s\n", argv[arg]);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+rtems_rtl_shell_archive (const rtems_printer* printer, int argc, char* argv[])
+{
+ rtems_rtl_data* rtl;
+ rtems_chain_node* node;
+ const char* re_name;
+ bool details;
+ bool symbols;
+ bool duplicates;
+ regex_t rege;
+
+ if (!rtems_rtl_check_opts (printer, "dsl", argc, argv))
+ return 1;
+
+ details = rtems_rtl_parse_opt ('l', argc, argv);
+ symbols = rtems_rtl_parse_opt ('s', argc, argv);
+ duplicates = rtems_rtl_parse_opt ('d', argc, argv);
+
+ re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+
+ if (re_name != NULL)
+ {
+ if (!rtems_rtl_regx_compile (printer,
+ "name filter",
+ &rege,
+ re_name))
+ {
+ return false;
+ }
+ }
+
+ rtl = rtems_rtl_lock ();
+ if (rtl == NULL)
+ {
+ rtems_printf (printer, "error: cannot lock the linker\n");
+ return 1;
+ }
+
+ node = rtems_chain_first (&rtl->archives.archives);
+
+ while (!rtems_chain_is_tail (&rtl->archives.archives, node))
+ {
+ #define SYM_DUPLICATE (1 << ((8 * sizeof (size_t)) - 1))
+
+ rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
+
+ if (re_name != NULL)
+ {
+ int r = rtems_rtl_regx_match (printer,
+ "name match",
+ &rege,
+ archive->name);
+ if (r < 0)
+ {
+ rtems_rtl_unlock ();
+ return false;
+ }
+
+ if (r == 0)
+ {
+ node = rtems_chain_next (node);
+ continue;
+ }
+ }
+
+ rtems_printf (printer, "%s%c\n",
+ archive->name,
+ details | symbols | duplicates ? ':' : ' ');
+
+ if (details)
+ {
+ rtems_printf (printer, " size : %zu\n", archive->size);
+ rtems_printf (printer, " symbols : %zu\n", archive->symbols.entries);
+ rtems_printf (printer, " refs : %zu\n", archive->refs);
+ rtems_printf (printer, " flags : %" PRIx32 "\n", archive->flags);
+ }
+
+ if (symbols)
+ {
+ const char* symbol = archive->symbols.names;
+ int indent = 0;
+ size_t s;
+
+ rtems_printf (printer, " symbols :");
+
+ for (s = 0; s < archive->symbols.entries; ++s)
+ {
+ if (archive->symbols.symbols != NULL)
+ symbol = archive->symbols.symbols[s].label;
+
+ rtems_printf (printer, "%-*c%s\n", indent, ' ', symbol);
+ indent = 12;
+
+ if (archive->symbols.symbols == NULL)
+ symbol += strlen (symbol) + 1;
+ }
+
+ if (indent == 0)
+ rtems_printf (printer, "\n");
+ }
+
+ if (duplicates)
+ {
+ rtems_chain_node* match_node;
+ int indent = 0;
+ bool show_dups = true;
+
+ match_node = rtems_chain_first (&rtl->archives.archives);
+
+ while (!rtems_chain_is_tail (&rtl->archives.archives, match_node))
+ {
+ rtems_rtl_archive* match_archive = (rtems_rtl_archive*) match_node;
+ const char* symbol = archive->symbols.names;
+ size_t s;
+
+ for (s = 0; s < archive->symbols.entries; ++s)
+ {
+ if (archive->symbols.symbols == NULL ||
+ (archive->symbols.symbols[s].entry & SYM_DUPLICATE) == 0)
+ {
+ const char* match_symbol = match_archive->symbols.names;
+ size_t ms;
+
+ if (archive->symbols.symbols != NULL)
+ symbol = archive->symbols.symbols[s].label;
+
+ for (ms = 0; ms < match_archive->symbols.entries; ++ms)
+ {
+ if (match_archive->symbols.symbols != NULL)
+ match_symbol = match_archive->symbols.symbols[ms].label;
+
+ if (symbol != match_symbol && strcmp (symbol, match_symbol) == 0)
+ {
+ if (show_dups)
+ {
+ show_dups = false;
+ rtems_printf (printer, " dups :");
+ }
+ rtems_printf (printer, "%-*c%s (%s)\n",
+ indent, ' ', symbol, archive->name);
+ indent = 12;
+
+ if (match_archive->symbols.symbols != NULL)
+ match_archive->symbols.symbols[ms].entry |= SYM_DUPLICATE;
+ }
+
+ if (match_archive->symbols.symbols == NULL)
+ match_symbol += strlen (match_symbol) + 1;
+ }
+ }
+
+ if (archive->symbols.symbols == NULL)
+ symbol += strlen (symbol) + 1;
+ }
+
+ match_node = rtems_chain_next (match_node);
+ }
+
+ if (indent == 0)
+ rtems_printf (printer, "\n");
+ }
+
+ node = rtems_chain_next (node);
+ }
+
+ regfree (&rege);
+
+ node = rtems_chain_first (&rtl->archives.archives);
+
+ while (!rtems_chain_is_tail (&rtl->archives.archives, node))
+ {
+ rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
+ if (archive->symbols.symbols != NULL)
+ {
+ size_t s;
+ for (s = 0; s < archive->symbols.entries; ++s)
+ archive->symbols.symbols[s].entry &= ~SYM_DUPLICATE;
+ }
+ node = rtems_chain_next (node);
+ }
+
+ rtems_rtl_unlock ();
+
+ return 0;
+}
+
+int
+rtems_rtl_shell_call (const rtems_printer* printer, int argc, char* argv[])
+{
+ #define CALL_ARG_COUNT (4)
+
+ typedef void (*csig_none)(void);
+ typedef void (*csig_argv)(int argc, const char* argv[]);
+ typedef void (*csig_s)(const char* str);
+ typedef void (*csig_u)(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4);
+ typedef void (*csig_i)(int i1, int i2, int i3, int i4);
+
+ union {
+ char s[64 + 1];
+ unsigned int u[CALL_ARG_COUNT];
+ int i[CALL_ARG_COUNT];
+ } values = { 0 };
+ bool keep_locked = false;
+ bool args_s = false;
+ bool args_i = false;
+ bool args_u = false;
+ ssize_t label;
+ rtems_rtl_data* rtl;
+ rtems_rtl_obj_sym* sym;
+ rtems_rtl_obj* obj;
+
+
+ if (!rtems_rtl_check_opts (printer, "lsui", argc, argv))
+ return 1;
+
+ keep_locked = rtems_rtl_parse_opt ('l', argc, argv);
+ args_s = rtems_rtl_parse_opt ('s', argc, argv);
+ args_u = rtems_rtl_parse_opt ('u', argc, argv);
+ args_i = rtems_rtl_parse_opt ('i', argc, argv);
+
+ if (args_s || args_u || args_i)
+ {
+ int c = 0;
+ c += args_s ? 1 : 0;
+ c += args_u ? 1 : 0;
+ c += args_i ? 1 : 0;
+ if (c > 1)
+ {
+ rtems_printf (printer,
+ "error: too many options, only one -sul at a time\n");
+ return 1;
+ }
+ }
+
+ label = rtems_rtl_parse_arg_index (' ', NULL, argc, argv);
+ if (label < 0)
+ {
+ rtems_printf (printer, "error: no symbol found on command line\n");
+ return 1;
+ }
+
+ if ((label + 1) < argc)
+ {
+ if (args_s)
+ {
+ size_t arg;
+ for (arg = label + 1; arg < argc; ++arg)
+ {
+ size_t o = strlen (values.s);
+ if (strlen (argv[arg]) + 1 >= (sizeof (values.s) - o))
+ {
+ rtems_printf (printer, "error: string args too big\n");
+ return 1;
+ }
+ if (o > 0)
+ values.s[o++] = ' ';
+ strcat (values.s, argv[arg]);
+ }
+ }
+ else if (args_u || args_i)
+ {
+ size_t arg;
+ size_t i;
+ if (argc > (label + 1 + CALL_ARG_COUNT))
+ {
+ rtems_printf (printer, "error: too many args\n");
+ return 1;
+ }
+ for (i = 0, arg = label + 1; arg < argc; ++arg)
+ {
+ if (args_u)
+ values.u[i] = strtoul (argv[arg], 0, 0);
+ else
+ values.i[i] = strtol (argv[arg], 0, 0);
+ ++i;
+ }
+ }
+ }
+
+ rtl = rtems_rtl_lock ();
+ if (rtl == NULL)
+ {
+ rtems_printf (printer, "error: cannot lock the linker\n");
+ return 1;
+ }
+
+ sym = rtems_rtl_symbol_global_find (argv[label]);
+ if (sym == NULL)
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: symbol not found: %s\n", argv[label]);
+ return 1;
+ }
+
+ obj = rtems_rtl_find_obj_with_symbol (sym);
+ if (obj == NULL)
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
+ return 1;
+ }
+
+ if (!rtems_rtl_obj_text_inside (obj, (const void*) sym->value))
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: symbol not in obj text: %s\n", argv[label]);
+ return 1;
+ }
+
+ /*
+ * Lock the object file while it is being called.
+ */
+ rtems_rtl_obj_inc_reference (obj);
+
+ rtems_rtl_unlock ();
+
+ if (args_s)
+ {
+ csig_s call = (csig_s) sym->value;
+ call (values.s);
+ }
+ else if (args_u)
+ {
+ csig_u call = (csig_u) sym->value;
+ call (values.u[0], values.u[1], values.u[2], values.u[3]);
+ }
+ else if (args_i)
+ {
+ csig_i call = (csig_i) sym->value;
+ call (values.i[0], values.i[1], values.i[2], values.i[3]);
+ }
+ else
+ {
+ int cargc = argc - (label + 1);
+ if (cargc == 0)
+ {
+ csig_none call = (csig_none) sym->value;
+ call ();
+ }
+ else
+ {
+ csig_argv call = (csig_argv) sym->value;
+ const char* cargv = argv[label + 1];
+ call (cargc, &cargv);
+ }
+ }
+
+ if (!keep_locked)
+ {
+ rtl = rtems_rtl_lock ();
+ if (rtl == NULL)
+ {
+ rtems_printf (printer, "error: cannot lock the linker\n");
+ return 1;
+ }
+
+ obj = rtems_rtl_find_obj_with_symbol (sym);
+ if (obj == NULL)
+ {
+ rtems_rtl_unlock ();
+ rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
+ return 1;
+ }
+
+ rtems_rtl_obj_dec_reference (obj);
+
+ rtems_rtl_unlock ();
+ }
+
return 0;
}
static void
-rtems_rtl_shell_usage (const char* arg)
+rtems_rtl_shell_usage (const rtems_printer* printer, const char* arg)
{
- printf ("%s: Runtime Linker\n", arg);
- printf (" %s [-hl] <command>\n", arg);
- printf (" where:\n");
- printf (" command: A n RTL command. See -l for a list plus help.\n");
- printf (" -h: This help\n");
- printf (" -l: The command list.\n");
+ rtems_printf (printer, "%s: Runtime Linker\n", arg);
+ rtems_printf (printer, " %s [-hl] <command>\n", arg);
+ rtems_printf (printer, " where:\n");
+ rtems_printf (printer, " command: A n RTL command. See -l for a list plus help.\n");
+ rtems_printf (printer, " -h: This help\n");
+ rtems_printf (printer, " -l: The command list.\n");
}
int
@@ -358,11 +1139,20 @@ rtems_rtl_shell_command (int argc, char* argv[])
{ "sym", rtems_rtl_shell_sym,
"\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
{ "obj", rtems_rtl_shell_object,
- "\tDisplay the object details, obj <name>" }
+ "\tDisplay the object details, obj <name>" },
+ { "call", rtems_rtl_shell_call,
+ "\tCall a symbol" },
+ { "ar", rtems_rtl_shell_archive,
+ "\tDisplay the archive details, ar [-ls] <name>" },
+ { "trace", rtems_rtl_trace_shell_command,
+ "\tControl the RTL trace flags, trace [-h]" }
};
- int arg;
- int t;
+ rtems_printer printer;
+ int arg;
+ int t;
+
+ rtems_print_printer_printf (&printer);
for (arg = 1; arg < argc; arg++)
{
@@ -372,23 +1162,24 @@ rtems_rtl_shell_command (int argc, char* argv[])
switch (argv[arg][1])
{
case 'h':
- rtems_rtl_shell_usage (argv[0]);
+ rtems_rtl_shell_usage (&printer, argv[0]);
return 0;
case 'l':
- printf ("%s: commands are:\n", argv[0]);
+ rtems_printf (&printer, "%s: commands are:\n", argv[0]);
for (t = 0;
t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd));
++t)
- printf (" %s\t%s\n", table[t].name, table[t].help);
+ rtems_printf (&printer, " %s\t%s\n", table[t].name, table[t].help);
return 0;
default:
- printf ("error: unknown option: %s\n", argv[arg]);
+ rtems_printf (&printer, "error: unknown option: %s\n", argv[arg]);
return 1;
}
}
if ((argc - arg) < 1)
- printf ("error: you need to provide a command, try %s -h\n", argv[0]);
+ rtems_printf (&printer, "error: you need to provide a command, try %s -h\n",
+ argv[0]);
else
{
for (t = 0;
@@ -396,20 +1187,9 @@ rtems_rtl_shell_command (int argc, char* argv[])
++t)
{
if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
- {
- rtems_rtl_data* rtl = rtems_rtl_lock ();
- int r;
- if (!rtl)
- {
- printf ("error: cannot lock the linker\n");
- return 1;
- }
- r = table[t].handler (rtl, argc - 1, argv + 1);
- rtems_rtl_unlock ();
- return r;
- }
+ return table[t].handler (&printer, argc - 1, argv + 1);
}
- printf ("error: command not found: %s (try -h)\n", argv[arg]);
+ rtems_printf (&printer, "error: command not found: %s (try -h)\n", argv[arg]);
}
return 1;
diff --git a/cpukit/libdl/rtl-trace.c b/cpukit/libdl/rtl-trace.c
index e09ec06758..2793baa7cb 100644
--- a/cpukit/libdl/rtl-trace.c
+++ b/cpukit/libdl/rtl-trace.c
@@ -54,7 +54,9 @@ rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask)
}
int
-rtems_rtl_trace_shell_command (int argc, char *argv[])
+rtems_rtl_trace_shell_command (const rtems_printer* printer,
+ int argc,
+ char* argv[])
{
const char* table[] =
{
@@ -71,7 +73,9 @@ rtems_rtl_trace_shell_command (int argc, char *argv[])
"unresolved",
"cache",
"archives",
- "dependency"
+ "archive-syms",
+ "dependency",
+ "bit-alloc"
};
rtems_rtl_trace_mask set_value = 0;
@@ -87,15 +91,15 @@ rtems_rtl_trace_shell_command (int argc, char *argv[])
switch (argv[arg][1])
{
case 'h':
- printf ("usage: %s [-hl] [set/clear] [flags]\n", argv[0]);
+ rtems_printf (printer, "usage: %s [-hl] [set/clear] [flags]\n", argv[0]);
return 0;
case 'l':
- printf ("%s: valid flags to set or clear are:\n", argv[0]);
+ rtems_printf (printer, "%s: valid flags to set or clear are:\n", argv[0]);
for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++)
- printf (" %s\n", table[t]);
+ rtems_printf (printer, " %s\n", table[t]);
return 0;
default:
- printf ("error: unknown option\n");
+ rtems_printf (printer, "error: unknown option\n");
return 1;
}
}
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 789380ce72..fe6f7d8ee8 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -649,6 +649,58 @@ CLEANFILES += dl09.pre dl09-sym.o dl09-o1.o dl09-o2.o dl09-o3.o dl09-o4.o \
endif
endif
+if DLTESTS
+if TEST_dl10
+lib_tests += dl10
+lib_screens += dl10/dl10.scn
+lib_docs += dl10/dl10.doc
+dl10_SOURCES = dl10/init.c dl10/dl-load.c dl10-tar.c dl10-tar.h
+dl10_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl10) $(support_includes)
+dl10/init.c: dl10-tar.o
+dl10.pre: $(dl10_OBJECTS) $(dl10_DEPENDENCIES)
+ @rm -f dl10.pre dl10-syms.o
+ $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+dl10-o1.o: dl10/dl-o1.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-o2.o: dl10/dl-o2.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-o3.o: dl10/dl-o3.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-o4.o: dl10/dl-o4.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-o5.o: dl10/dl-o5.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-o6.o: dl10/dl-o6.c Makefile
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+etc/libdl-dl10.conf:
+ mkdir etc; \
+ echo "#" > $@
+ echo " # blah blah" >> $@
+ echo "/libdl10*.a" >> $@
+ echo "" >> $@
+noinst_LIBRARIES = libdl10_1.a libdl10_2.a
+libdl10_1_a_SOURCES = dl10-o2.c dl10-o4.c
+libdl10_2_a_SOURCES = dl10-o3.c dl10-o5.c dl10-o6.c
+dl10.tar: etc/libdl-dl10.conf dl10-o1.o libdl10_1.a libdl10_2.a
+ @rm -f $@
+ $(AM_V_GEN)$(PAX) -w -f $@ $+
+dl10-tar.c: dl10.tar
+ $(AM_V_GEN)$(BIN2C) -C $< $@
+dl10-tar.h: dl10.tar
+ $(AM_V_GEN)$(BIN2C) -H $< $@
+dl10-tar.o: dl10-tar.c dl10-tar.h
+ $(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl10-sym.o: dl10.pre
+ $(AM_V_GEN)rtems-syms -e -c "$(CFLAGS)" -o $@ $<
+dl10$(EXEEXT): $(dl10_OBJECTS) $(dl10_DEPENDENCIES) dl10-sym.o
+ @rm -f $@
+ $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+CLEANFILES += dl10.pre dl10-sym.o libdl10_1.a libdl10_2.a dl10-o1.o dl10-o2.o \
+ dl10-o3.o dl10-o4.o dl10-o5.o dl10-o6.o \
+ dl10.tar dl10-tar.h etc/libdl-dl10.conf
+endif
+endif
+
if TEST_dumpbuf01
lib_tests += dumpbuf01
lib_screens += dumpbuf01/dumpbuf01.scn
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 3bcc0ec5c4..a6879a7430 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -134,6 +134,7 @@ RTEMS_TEST_CHECK([dl06])
RTEMS_TEST_CHECK([dl07])
RTEMS_TEST_CHECK([dl08])
RTEMS_TEST_CHECK([dl09])
+RTEMS_TEST_CHECK([dl10])
RTEMS_TEST_CHECK([dumpbuf01])
RTEMS_TEST_CHECK([dup2])
RTEMS_TEST_CHECK([exit01])
diff --git a/testsuites/libtests/dl10/dl-load.c b/testsuites/libtests/dl10/dl-load.c
new file mode 100644
index 0000000000..dee1d6e9cc
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-load.c
@@ -0,0 +1,141 @@
+/*
+ * 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 TEST_TRACE 0
+#if TEST_TRACE
+ #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
+ RTEMS_RTL_TRACE_WARNING | \
+ RTEMS_RTL_TRACE_LOAD | \
+ RTEMS_RTL_TRACE_UNLOAD | \
+ RTEMS_RTL_TRACE_SYMBOL | \
+ RTEMS_RTL_TRACE_RELOC | \
+ RTEMS_RTL_TRACE_LOAD_SECT | \
+ RTEMS_RTL_TRACE_ALLOCATOR | \
+ RTEMS_RTL_TRACE_UNRESOLVED | \
+ RTEMS_RTL_TRACE_ARCHIVES | \
+ RTEMS_RTL_TRACE_DEPENDENCY)
+ /* RTEMS_RTL_TRACE_ALL */
+#define DL_DEBUG_TRACE DEBUG_TRACE
+#define DL_DEBUG_CMD 1
+#else
+#define DL_DEBUG_TRACE 0
+#define DL_DEBUG_CMD 0
+#endif
+
+#include <dlfcn.h>
+
+#include "dl-load.h"
+
+#include <tmacros.h>
+
+#include <rtems/rtl/rtl-shell.h>
+#include <rtems/rtl/rtl-trace.h>
+
+typedef int (*call_sig)(void);
+
+static void dl_load_dump (void)
+{
+#if DL_DEBUG_CMD
+ 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 bool dl_check_resolved(void* handle, bool has_unresolved)
+{
+ int unresolved = 0;
+ if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) == 0)
+ return 1;
+ if (has_unresolved)
+ {
+ if (unresolved == 0)
+ {
+ dl_load_dump();
+ return false;
+ }
+ }
+ else
+ {
+ if (unresolved != 0)
+ {
+ dl_load_dump();
+ return false;
+ }
+ }
+ printf ("handel: %p: no unresolved externals\n", handle);
+ return true;
+}
+
+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;
+
+ printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
+
+#if DL_DEBUG_TRACE
+ rtems_rtl_trace_set_mask (DL_DEBUG_TRACE);
+#endif
+
+ o1 = dl_load_obj("/dl10-o1.o", false);
+ if (!o1)
+ return 1;
+
+ if (!dl_check_resolved (o1, false))
+ return 1;
+
+ dl_load_dump ();
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-load.h b/testsuites/libtests/dl10/dl-load.h
new file mode 100644
index 0000000000..72872917aa
--- /dev/null
+++ b/testsuites/libtests/dl10/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/dl10/dl-o1.c b/testsuites/libtests/dl10/dl-o1.c
new file mode 100644
index 0000000000..e6173f3a78
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o1.c
@@ -0,0 +1,61 @@
+/*
+ * 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"
+#include "dl-o1.h"
+#include "dl-o2.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: %4zu: %p: %d\n", PAINT_VAR (dl01_bss1));
+ printf (DL_NAME ": dl01_bss2: %4zu: %p: %f\n", PAINT_VAR (dl01_bss2[0]));
+ printf (DL_NAME ": dl01_bss3: %4zu: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+ printf (DL_NAME ": dl01_data1: %4zu: %p: %d\n", PAINT_VAR (dl01_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl01_data2: %4zu: %p: %f\n", PAINT_VAR (dl01_data2));
+ printf (DL_NAME ": dl01_const1: %4zu: %p: %d\n", PAINT_VAR (dl01_const1));
+ printf (DL_NAME ": dl01_const2: %4zu: %p: %f\n", PAINT_VAR (dl01_const2));
+ printf (DL_NAME ": dl01_func1: %4zu: %p\n", sizeof(dl01_func1), &dl01_func1);
+
+ rtems_main_o2 ();
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-o1.h b/testsuites/libtests/dl10/dl-o1.h
new file mode 100644
index 0000000000..f6a10f1481
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o1.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(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/dl10/dl-o2.c b/testsuites/libtests/dl10/dl-o2.c
new file mode 100644
index 0000000000..e58c8750e9
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o2.c
@@ -0,0 +1,39 @@
+/*
+ * 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-o2.h"
+#include "dl-o3.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;
+
+#define DL_NAME "dlo2"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o2 (void)
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl02_bss1: %4zu: %p: %d\n", PAINT_VAR (dl02_bss1));
+ printf (DL_NAME ": dl02_bss2: %4zu: %p: %f\n", PAINT_VAR (dl02_bss2[0]));
+ printf (DL_NAME ": dl02_bss3: %4zu: %p: %02x\n", PAINT_VAR (dl02_bss3[0]));
+ printf (DL_NAME ": dl02_data1: %4zu: %p: %d\n", PAINT_VAR (dl02_data1));
+ /* no %f in the rtems test printer */
+ printf (DL_NAME ": dl02_data2: %4zu: %p: %f\n", PAINT_VAR (dl02_data2));
+
+ rtems_main_o3 ();
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-o2.h b/testsuites/libtests/dl10/dl-o2.h
new file mode 100644
index 0000000000..d6c1820f46
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o2.h
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+int rtems_main_o2 (void);
+
+#endif
diff --git a/testsuites/libtests/dl10/dl-o3.c b/testsuites/libtests/dl10/dl-o3.c
new file mode 100644
index 0000000000..c84b3d72ad
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o3.c
@@ -0,0 +1,40 @@
+/*
+ * 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-o3.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__);
+
+#define DL_NAME "dlo3"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o3 ()
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl04_unresolv_1: %4zu: %p: %d\n", PAINT_VAR (dl04_unresolv_1));
+ printf (DL_NAME ": dl04_unresolv_2: %4zu: %p: %f\n", PAINT_VAR (dl04_unresolv_2));
+ printf (DL_NAME ": dl04_unresolv_3: %4zu: %p: %02x\n", PAINT_VAR (dl04_unresolv_3));
+ printf (DL_NAME ": dl04_unresolv_4: %4zu: %p: %p\n", PAINT_VAR (dl04_unresolv_4));
+ printf (DL_NAME ": dl04_unresolv_5: %4zu: %p: %d\n", PAINT_VAR (dl04_unresolv_5));
+ printf (DL_NAME ": dl04_unresolv_6: %4zu: %p: %s\n", PAINT_VAR (dl04_unresolv_6));
+ printf (DL_NAME ": dl05_unresolv_1: %4zu: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+ printf (DL_NAME ": dl05_unresolv_2: %4zu: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+ printf (DL_NAME ": dl05_unresolv_3: %4zu: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+ printf (DL_NAME ": dl05_unresolv_4: %4zu: %p: %" PRIu8 "\n", PAINT_VAR (dl05_unresolv_4));
+ printf (DL_NAME ": dl05_unresolv_5: %4zu: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+
+ rtems_main_o4 ();
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-o3.h b/testsuites/libtests/dl10/dl-o3.h
new file mode 100644
index 0000000000..8c5d18dfb1
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o3.h
@@ -0,0 +1,15 @@
+/*
+ * 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(DL03_H)
+#define DL03_H
+
+int rtems_main_o3 (void);
+
+#endif
diff --git a/testsuites/libtests/dl10/dl-o4.c b/testsuites/libtests/dl10/dl-o4.c
new file mode 100644
index 0000000000..72dfbc6850
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o4.c
@@ -0,0 +1,40 @@
+/*
+ * 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-o4.h"
+#include "dl-o5.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";
+
+#define DL_NAME "dlo4"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o4 (void)
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl04_unresolv_1: %4zu: %p: %d\n", PAINT_VAR (dl04_unresolv_1));
+ printf (DL_NAME ": dl04_unresolv_2: %4zu: %p: %f\n", PAINT_VAR (dl04_unresolv_2));
+ printf (DL_NAME ": dl04_unresolv_3: %4zu: %p: %02x\n", PAINT_VAR (dl04_unresolv_3));
+ printf (DL_NAME ": dl04_unresolv_4: %4zu: %p: %p\n", PAINT_VAR (dl04_unresolv_4));
+ printf (DL_NAME ": dl04_unresolv_5: %4zu: %p: %d\n", PAINT_VAR (dl04_unresolv_5));
+ printf (DL_NAME ": dl04_unresolv_6: %4zu: %p: %s\n", PAINT_VAR (dl04_unresolv_6));
+
+ rtems_main_o5 ();
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-o4.h b/testsuites/libtests/dl10/dl-o4.h
new file mode 100644
index 0000000000..bab9fc1ae4
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o4.h
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+int rtems_main_o4 (void);
+
+#endif
diff --git a/testsuites/libtests/dl10/dl-o5.c b/testsuites/libtests/dl10/dl-o5.c
new file mode 100644
index 0000000000..be496392c9
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o5.c
@@ -0,0 +1,36 @@
+/*
+ * 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-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;
+
+#define DL_NAME "dlo5"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o5 (void)
+{
+ printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+ printf (DL_NAME ": dl05_unresolv_1: %4zu: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+ printf (DL_NAME ": dl05_unresolv_2: %4zu: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+ printf (DL_NAME ": dl05_unresolv_3: %4zu: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+ printf (DL_NAME ": dl05_unresolv_4: %4zu: %p: %" PRIu8 "\n", PAINT_VAR (dl05_unresolv_4));
+ printf (DL_NAME ": dl05_unresolv_5: %4zu: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl-o5.h b/testsuites/libtests/dl10/dl-o5.h
new file mode 100644
index 0000000000..bb4ce468a2
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o5.h
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+int rtems_main_o5 (void);
+
+#endif
diff --git a/testsuites/libtests/dl10/dl-o6.c b/testsuites/libtests/dl10/dl-o6.c
new file mode 100644
index 0000000000..5e03a30773
--- /dev/null
+++ b/testsuites/libtests/dl10/dl-o6.c
@@ -0,0 +1,18 @@
+/*
+ * 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 <inttypes.h>
+#include <rtems/test.h>
+
+int rtems_main_o5 (void)
+{
+ /* duplicate symbol in archive */
+ return 0;
+}
diff --git a/testsuites/libtests/dl10/dl10.doc b/testsuites/libtests/dl10/dl10.doc
new file mode 100644
index 0000000000..82469da593
--- /dev/null
+++ b/testsuites/libtests/dl10/dl10.doc
@@ -0,0 +1,22 @@
+# 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.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: dl10
+
+directives:
+
+ dlopen
+ dlinfo
+ dlsym
+ dlclose
+
+concepts:
+
++ Load modules from archives that have duplicate symbols.
++ Wait a shell prompt to test the RTL commands.
diff --git a/testsuites/libtests/dl10/dl10.scn b/testsuites/libtests/dl10/dl10.scn
new file mode 100644
index 0000000000..dec2c42c68
--- /dev/null
+++ b/testsuites/libtests/dl10/dl10.scn
@@ -0,0 +1,41 @@
+*** BEGIN OF TEST libdl (RTL) 10 ***
+*** TEST VERSION: 5.0.0.c1aa9685eaa9d5d321c965a2aa44f868b7834c23
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_NETWORKING RTEMS_POSIX_API
+*** TEST TOOLS: 7.4.0 20181206 (RTEMS 5, RSB 98588a55961a92f5d27bfd756dfc9e31b2b1bf98, Newlib 3e24fbf6f)
+RTL (libdl) commands: dl, rtl
+
+
+RTEMS Shell on /dev/foobar. Use 'help' to list commands.
+SHLL [/] # rtl obj load dl10-o1.o
+SHLL [/] # rtl list -l
+ dl10-o1.o
+ unresolved : 0
+ users : 1
+ references : 0
+ symbols : 9
+ symbol memory : 281
+ /libdl10_1.a:dl10-o2.o
+ unresolved : 0
+ users : 0
+ references : 1
+ symbols : 6
+ symbol memory : 186
+ /libdl10_2.a:dl10-o5.o
+ unresolved : 0
+ users : 0
+ references : 2
+ symbols : 6
+ symbol memory : 214
+ /libdl10_2.a:dl10-o3.o
+ unresolved : 0
+ users : 0
+ references : 1
+ symbols : 1
+ symbol memory : 34
+ /libdl10_1.a:dl10-o4.o
+ unresolved : 0
+ users : 0
+ references : 1
+ symbols : 7
+ symbol memory : 250
diff --git a/testsuites/libtests/dl10/init.c b/testsuites/libtests/dl10/init.c
new file mode 100644
index 0000000000..d297567f84
--- /dev/null
+++ b/testsuites/libtests/dl10/init.c
@@ -0,0 +1,137 @@
+/*
+ * 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/dlfcn-shell.h>
+#include <rtems/rtl/rtl.h>
+#include <rtems/rtl/rtl-shell.h>
+#include <rtems/shell.h>
+#include <rtems/untar.h>
+
+#include "dl-load.h"
+
+const char rtems_test_name[] = "libdl (RTL) 10";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+#include "dl10-tar.h"
+
+#define TARFILE_START dl10_tar
+#define TARFILE_SIZE dl10_tar_size
+
+static int test(void)
+{
+#if USE_SHELL_CMD
+ int ret;
+ ret = dl_load_test();
+ if (ret)
+ rtems_test_exit(ret);
+#endif
+ return 0;
+}
+
+static void Init(rtems_task_argument arg)
+{
+ int e;
+
+ TEST_BEGIN();
+
+ e = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE);
+ if (e != 0)
+ {
+ printf ("error: untar failed: %d\n", e);
+ rtems_test_exit (1);
+ exit (1);
+ }
+
+ e = symlink ("libdl-dl10.conf", "/etc/libdl.conf");
+ if (e != 0)
+ {
+ printf ("error: untar failed: %d\n", e);
+ rtems_test_exit (1);
+ exit (1);
+ }
+
+ test();
+
+ rtems_shell_init_environment ();
+
+ printf ("RTL (libdl) commands: dl, rtl\n\n");
+
+ if (rtems_shell_add_cmd ("rtl",
+ "rtl",
+ "rtl -l",
+ rtems_rtl_shell_command) == NULL)
+ {
+ printf("command add failed\n");
+ rtems_test_exit(1);
+ exit (1);
+ }
+
+ rtems_shell_init ("SHLL",
+ RTEMS_MINIMUM_STACK_SIZE * 4,
+ 100,
+ "/dev/foobar",
+ false,
+ true,
+ NULL);
+
+ TEST_END();
+
+ rtems_test_exit(0);
+}
+
+#define CONFIGURE_SHELL_COMMANDS_INIT
+#define CONFIGURE_SHELL_COMMANDS_ALL
+
+/*
+ * Remove the commands that pull in libblock.
+ */
+#define CONFIGURE_SHELL_NO_COMMAND_BLKSYNC
+#define CONFIGURE_SHELL_NO_COMMAND_BLKSTATS
+#define CONFIGURE_SHELL_NO_COMMAND_FDISK
+#define CONFIGURE_SHELL_NO_COMMAND_MKRFS
+#define CONFIGURE_SHELL_NO_COMMAND_DEBUGRFS
+
+#include <rtems/shellconfig.h>
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 10
+
+#define CONFIGURE_MAXIMUM_TASKS 4
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 4
+
+#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_UNIFIED_WORK_AREAS
+
+#define CONFIGURE_UNLIMITED_OBJECTS
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
diff --git a/testsuites/testdata/rtems.tcfg b/testsuites/testdata/rtems.tcfg
index 255a5e1e86..f58cd4a173 100644
--- a/testsuites/testdata/rtems.tcfg
+++ b/testsuites/testdata/rtems.tcfg
@@ -19,6 +19,7 @@ user-input: fileio
user-input: monitor
user-input: termios
user-input: top
+user-input: dl10
#
# Benchmarks