From dad6fd4333c4b05af08bd78714acefb5a86f1af9 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Sun, 10 Mar 2019 07:04:42 +1300 Subject: 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. --- cpukit/include/rtems/rtl/rtl-archive.h | 1 + cpukit/include/rtems/rtl/rtl-shell.h | 28 + cpukit/include/rtems/rtl/rtl-trace.h | 6 +- cpukit/libdl/rtl-archive.c | 49 +- cpukit/libdl/rtl-shell.c | 1052 +++++++++++++++++++++++++++----- cpukit/libdl/rtl-trace.c | 16 +- testsuites/libtests/Makefile.am | 52 ++ testsuites/libtests/configure.ac | 1 + testsuites/libtests/dl10/dl-load.c | 141 +++++ testsuites/libtests/dl10/dl-load.h | 21 + testsuites/libtests/dl10/dl-o1.c | 61 ++ testsuites/libtests/dl10/dl-o1.h | 23 + testsuites/libtests/dl10/dl-o2.c | 39 ++ testsuites/libtests/dl10/dl-o2.h | 25 + testsuites/libtests/dl10/dl-o3.c | 40 ++ testsuites/libtests/dl10/dl-o3.h | 15 + testsuites/libtests/dl10/dl-o4.c | 40 ++ testsuites/libtests/dl10/dl-o4.h | 29 + testsuites/libtests/dl10/dl-o5.c | 36 ++ testsuites/libtests/dl10/dl-o5.h | 30 + testsuites/libtests/dl10/dl-o6.c | 18 + testsuites/libtests/dl10/dl10.doc | 22 + testsuites/libtests/dl10/dl10.scn | 41 ++ testsuites/libtests/dl10/init.c | 137 +++++ testsuites/testdata/rtems.tcfg | 1 + 25 files changed, 1752 insertions(+), 172 deletions(-) create mode 100644 testsuites/libtests/dl10/dl-load.c create mode 100644 testsuites/libtests/dl10/dl-load.h create mode 100644 testsuites/libtests/dl10/dl-o1.c create mode 100644 testsuites/libtests/dl10/dl-o1.h create mode 100644 testsuites/libtests/dl10/dl-o2.c create mode 100644 testsuites/libtests/dl10/dl-o2.h create mode 100644 testsuites/libtests/dl10/dl-o3.c create mode 100644 testsuites/libtests/dl10/dl-o3.h create mode 100644 testsuites/libtests/dl10/dl-o4.c create mode 100644 testsuites/libtests/dl10/dl-o4.h create mode 100644 testsuites/libtests/dl10/dl-o5.c create mode 100644 testsuites/libtests/dl10/dl-o5.h create mode 100644 testsuites/libtests/dl10/dl-o6.c create mode 100644 testsuites/libtests/dl10/dl10.doc create mode 100644 testsuites/libtests/dl10/dl10.scn create mode 100644 testsuites/libtests/dl10/init.c 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 #include +#include #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 + #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 #include +#include + /** * 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 @@ -33,12 +33,6 @@ #include "rtl-string.h" #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. */ @@ -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 #include -#include +#include +#include #include +#include + +#include #include +#include #include #include #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", + ®e, 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", ®e, 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", ®e, 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 (®e); + + 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", + ®e, print->re_name)) + { + return false; + } + + if (rtems_rtl_obj_aname (obj) != NULL) + { + r = rtems_rtl_regx_match (print->printer, + "aname match", + ®e, + rtems_rtl_obj_aname (obj)); + if (r < 0) + return false; + } + + if (r == 0) + { + r = rtems_rtl_regx_match (print->printer, + "oname match", + ®e, + rtems_rtl_obj_oname (obj)); + if (r < 0) + return false; + } + + regfree (®e); + + 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 \n"); + rtems_printf (printer, " unload \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", + ®e, + 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", + ®e, + 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 (®e); + + 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] \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] \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 [], sym -o []" }, { "obj", rtems_rtl_shell_object, - "\tDisplay the object details, obj " } + "\tDisplay the object details, obj " }, + { "call", rtems_rtl_shell_call, + "\tCall a symbol" }, + { "ar", rtems_rtl_shell_archive, + "\tDisplay the archive details, ar [-ls] " }, + { "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 . + * 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 + +#include "dl-load.h" + +#include + +#include +#include + +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 . 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 + +#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 . + * 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 +#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 . + * 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 . 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 + +#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 . + * 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 . 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 +#include + +#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 . + * 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 . 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 + +#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 . + * 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 . 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 +#include + +#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 . + * 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 + +#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 . 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 +#include + +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 +# +# 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 . 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 + +#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 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 -- cgit v1.2.3