summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl
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 /cpukit/libdl
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.
Diffstat (limited to 'cpukit/libdl')
-rw-r--r--cpukit/libdl/rtl-archive.c49
-rw-r--r--cpukit/libdl/rtl-shell.c1052
-rw-r--r--cpukit/libdl/rtl-trace.c16
3 files changed, 946 insertions, 171 deletions
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;
}
}