File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041
0042 #include <inttypes.h>
0043 #include <rtems/inttypes.h>
0044
0045 #include <sys/stat.h>
0046 #include <regex.h>
0047 #include <string.h>
0048
0049 #include <dlfcn.h>
0050
0051 #include <rtems/printer.h>
0052 #include <rtems/rtl/rtl.h>
0053 #include <rtems/rtl/rtl-archive.h>
0054 #include <rtems/rtl/rtl-shell.h>
0055 #include <rtems/rtl/rtl-trace.h>
0056 #include "rtl-chain-iterator.h"
0057
0058
0059
0060
0061 typedef int (*rtems_rtl_shell_handler) (const rtems_printer* printer, int argc, char *argv[]);
0062
0063
0064
0065
0066 typedef struct
0067 {
0068 const char* name;
0069 rtems_rtl_shell_handler handler;
0070 const char* help;
0071 } rtems_rtl_shell_cmd;
0072
0073
0074
0075
0076 typedef struct
0077 {
0078 int count;
0079 size_t exec;
0080 size_t symbols;
0081 } rtems_rtl_obj_summary;
0082
0083
0084
0085
0086 static bool
0087 rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data)
0088 {
0089 rtems_rtl_obj_summary* summary = data;
0090 rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
0091 ++summary->count;
0092 summary->exec += obj->exec_size;
0093 summary->symbols += obj->global_size;
0094 return true;
0095 }
0096
0097
0098
0099
0100 static int
0101 rtems_rtl_count_symbols (rtems_rtl_data* rtl)
0102 {
0103 int count;
0104 int bucket;
0105 for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket)
0106 count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]);
0107 return count;
0108 }
0109
0110 static int
0111 rtems_rtl_shell_status (const rtems_printer* printer,
0112 int argc,
0113 char* argv[])
0114 {
0115 rtems_rtl_obj_summary summary;
0116 size_t total_memory;
0117 rtems_rtl_data* rtl;
0118
0119 rtl = rtems_rtl_lock ();
0120 if (rtl == NULL)
0121 {
0122 rtems_printf (printer, "error: cannot lock the linker\n");
0123 return 1;
0124 }
0125
0126 summary.count = 0;
0127 summary.exec = 0;
0128 summary.symbols = 0;
0129 rtems_rtl_chain_iterate (&rtl->objects,
0130 rtems_rtl_obj_summary_iterator,
0131 &summary);
0132
0133
0134
0135 total_memory =
0136 sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj)) +
0137 summary.exec + summary.symbols;
0138
0139 rtems_printf (printer, "Runtime Linker Status:\n");
0140 rtems_printf (printer, " paths: %s\n", rtl->paths);
0141 rtems_printf (printer, " objects: %d\n", summary.count);
0142 rtems_printf (printer, " total memory: %zi\n", total_memory);
0143 rtems_printf (printer, " exec memory: %zi\n", summary.exec);
0144 rtems_printf (printer, " sym memory: %zi\n", summary.symbols);
0145 rtems_printf (printer, " symbols: %d\n", rtems_rtl_count_symbols (rtl));
0146
0147 rtems_rtl_unlock ();
0148
0149 return 0;
0150 }
0151
0152
0153
0154
0155 typedef struct
0156 {
0157 const rtems_printer* printer;
0158 rtems_rtl_data* rtl;
0159 int indent;
0160 bool oname;
0161 bool names;
0162 bool stats;
0163 bool memory_map;
0164 bool symbols;
0165 bool dependencies;
0166 bool trampolines;
0167 bool base;
0168 const char* re_name;
0169 const char* re_symbol;
0170 } rtems_rtl_obj_print;
0171
0172
0173
0174
0175 static bool
0176 rtems_rtl_parse_opt (const char opt, int argc, char *argv[])
0177 {
0178 size_t arg;
0179 for (arg = 1; arg < argc; ++arg)
0180 {
0181 if (argv[arg][0] == '-')
0182 {
0183 size_t len = strlen (argv[arg]);
0184 size_t i;
0185 for (i = 1; i < len; ++i)
0186 if (argv[arg][i] == opt)
0187 return true;
0188 }
0189 }
0190 return false;
0191 }
0192
0193 static bool
0194 rtems_rtl_check_opts (const rtems_printer* printer,
0195 const char* opts,
0196 int argc,
0197 char* argv[])
0198 {
0199 size_t olen = strlen (opts);
0200 size_t arg;
0201 for (arg = 1; arg < argc; ++arg)
0202 {
0203 if (argv[arg][0] == '-')
0204 {
0205 size_t len = strlen (argv[arg]);
0206 size_t i;
0207 for (i = 1; i < len; ++i)
0208 {
0209 bool found = false;
0210 size_t o;
0211 for (o = 0; o < olen; ++o)
0212 {
0213 if (argv[arg][i] == opts[o])
0214 {
0215 found = true;
0216 break;
0217 }
0218 }
0219 if (!found)
0220 {
0221 rtems_printf (printer, "error: invalid option: %c (%s)\n",
0222 argv[arg][i], argv[arg]);
0223 return false;
0224 }
0225 }
0226 }
0227 }
0228 return true;
0229 }
0230
0231 static ssize_t
0232 rtems_rtl_parse_arg_index (const char opt,
0233 const char* skip_opts,
0234 int argc,
0235 char* argv[])
0236 {
0237 ssize_t arg;
0238 for (arg = 1; arg < argc; ++arg)
0239 {
0240 if (argv[arg][0] == '-')
0241 {
0242
0243
0244
0245
0246 if (argv[arg][1] != '\0')
0247 {
0248 size_t len = skip_opts != NULL ? strlen (skip_opts) : 0;
0249 size_t i;
0250 for (i = 0; i < len; ++i)
0251 {
0252 if (skip_opts[i] == argv[arg][1])
0253 {
0254 ++arg;
0255 break;
0256 }
0257 }
0258 }
0259 }
0260 else
0261 {
0262 if (opt == ' ')
0263 return arg;
0264 }
0265
0266
0267
0268 if (arg < argc && argv[arg][0] == '-' && argv[arg][1] == opt)
0269 return arg + 1;
0270 }
0271 return -1;
0272 }
0273
0274 static const char*
0275 rtems_rtl_parse_arg (const char opt,
0276 const char* skip_opts,
0277 int argc,
0278 char* argv[])
0279 {
0280 ssize_t arg = rtems_rtl_parse_arg_index (opt, skip_opts, argc, argv);
0281 if (arg < 0)
0282 return NULL;
0283 return argv[arg];
0284 }
0285
0286
0287
0288
0289 static bool
0290 rtems_rtl_regx_compile (const rtems_printer* printer,
0291 const char* label,
0292 regex_t* rege,
0293 const char* expression)
0294 {
0295 int r = regcomp (rege, expression, REG_EXTENDED | REG_NOSUB);
0296 if (r != 0)
0297 {
0298 char rerror[128];
0299 regerror (r, rege, rerror, sizeof(rerror));
0300 rtems_printf (printer, "error: %s: %s\n", label, rerror);
0301 return false;
0302 }
0303 return true;
0304 }
0305
0306 static int
0307 rtems_rtl_regx_match (const rtems_printer* printer,
0308 const char* label,
0309 regex_t* rege,
0310 const char* string)
0311 {
0312 int r = regexec (rege, string, 0, NULL, 0);
0313 if (r != 0 && r != REG_NOMATCH)
0314 {
0315 char rerror[128];
0316 regerror (r, rege, rerror, sizeof(rerror));
0317 rtems_printf (printer, "error: %s: %s\n", label, rerror);
0318 regfree (rege);
0319 return -1;
0320 }
0321 return r == 0 ? 1 : 0;
0322 }
0323
0324
0325
0326
0327 static void
0328 rtems_rtl_print_obj_name (const rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
0329 {
0330 rtems_printf (print->printer, "%-*c", print->indent, ' ');
0331 if (rtems_rtl_obj_aname (obj) != NULL)
0332 rtems_printf (print->printer, "%s:", rtems_rtl_obj_aname (obj));
0333 rtems_printf (print->printer, "%s\n", rtems_rtl_obj_oname (obj));
0334 }
0335
0336
0337
0338
0339 static bool
0340 rtems_rtl_print_symbols (rtems_rtl_obj_print* print,
0341 rtems_rtl_obj* obj,
0342 int indent,
0343 bool show_name)
0344 {
0345 regex_t rege;
0346 int max_len = 0;
0347 int s;
0348
0349 if (print->re_symbol != NULL &&
0350 !rtems_rtl_regx_compile (print->printer,
0351 "symbol filter",
0352 ®e, print->re_symbol))
0353 {
0354 return false;
0355 }
0356
0357 for (s = 0; s < obj->global_syms; ++s)
0358 {
0359 const char* sym = obj->global_table[s].name;
0360 int len;
0361
0362 if (print->re_symbol != NULL)
0363 {
0364 int r = rtems_rtl_regx_match (print->printer, "symbol match", ®e, sym);
0365 if (r < 0)
0366 return false;
0367 if (!r)
0368 continue;
0369 }
0370
0371 len = strlen (obj->global_table[s].name);
0372 if (len > max_len)
0373 max_len = len;
0374 }
0375
0376 for (s = 0; s < obj->global_syms; ++s)
0377 {
0378 const char* sym = obj->global_table[s].name;
0379 if (print->re_symbol != NULL)
0380 {
0381 int r = rtems_rtl_regx_match (print->printer, "symbol match", ®e, sym);
0382 if (r < 0)
0383 return false;
0384 if (r == 0)
0385 continue;
0386 }
0387 if (show_name)
0388 {
0389 show_name = false;
0390 rtems_rtl_print_obj_name (print, obj);
0391 }
0392 rtems_printf (print->printer, "%-*c%-*s = %p\n", indent + 2, ' ',
0393 max_len, sym, obj->global_table[s].value);
0394 }
0395
0396 regfree (®e);
0397
0398 return true;
0399 }
0400
0401
0402
0403
0404 typedef struct
0405 {
0406 const rtems_rtl_obj_print* print;
0407 bool first;
0408 bool show_name;
0409 int indent;
0410 } rtems_rtl_dep_data;
0411
0412 static bool
0413 rtems_rtl_dependencies (rtems_rtl_obj* obj, rtems_rtl_obj* dependent, void* data)
0414 {
0415 rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
0416 if (dd->first)
0417 {
0418 dd->first = false;
0419 if (dd->show_name)
0420 {
0421 dd->show_name = false;
0422 rtems_rtl_print_obj_name (dd->print, obj);
0423 }
0424 rtems_printf (dd->print->printer, "%-*cdependencies : ", dd->indent, ' ');
0425 dd->indent += strlen ("dependencies :");
0426 }
0427 else
0428 {
0429 rtems_printf (dd->print->printer, "\n%-*c: ", (int) dd->indent, ' ');
0430 }
0431 rtems_printf (dd->print->printer, "%s", dependent->oname);
0432 return false;
0433 }
0434
0435
0436
0437
0438 static bool
0439 rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
0440 {
0441 char flags_str[33];
0442 int indent = print->indent + 1;
0443 bool show_name = true;
0444
0445
0446
0447
0448 if (!print->base && (obj == print->rtl->base))
0449 return true;
0450
0451 if (print->re_name != NULL)
0452 {
0453 regex_t rege;
0454 int r = 0;
0455
0456 if (!rtems_rtl_regx_compile (print->printer,
0457 "name filter",
0458 ®e, print->re_name))
0459 {
0460 return false;
0461 }
0462
0463 if (rtems_rtl_obj_aname (obj) != NULL)
0464 {
0465 r = rtems_rtl_regx_match (print->printer,
0466 "aname match",
0467 ®e,
0468 rtems_rtl_obj_aname (obj));
0469 if (r < 0)
0470 return false;
0471 }
0472
0473 if (r == 0)
0474 {
0475 r = rtems_rtl_regx_match (print->printer,
0476 "oname match",
0477 ®e,
0478 rtems_rtl_obj_oname (obj));
0479 if (r < 0)
0480 return false;
0481 }
0482
0483 regfree (®e);
0484
0485 if (r == 0)
0486 return true;
0487 }
0488
0489 if (print->names || print->memory_map || print->stats ||
0490 (!print->names && !print->memory_map && !print->stats &&
0491 !print->symbols && !print->dependencies))
0492 {
0493 show_name = false;
0494 rtems_rtl_print_obj_name (print, obj);
0495 }
0496
0497 if (print->names)
0498 {
0499 rtems_printf (print->printer,
0500 "%-*cfile name : %s\n",
0501 indent, ' ', rtems_rtl_obj_fname (obj));
0502 rtems_printf (print->printer,
0503 "%-*carchive name : %s\n",
0504 indent, ' ', rtems_rtl_obj_aname (obj));
0505 strcpy (flags_str, "--");
0506 if (obj->flags & RTEMS_RTL_OBJ_LOCKED)
0507 flags_str[0] = 'L';
0508 if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED)
0509 flags_str[1] = 'U';
0510 rtems_printf (print->printer,
0511 "%-*cflags : %s\n", indent, ' ', flags_str);
0512 rtems_printf (print->printer,
0513 "%-*cfile offset : %" PRIdoff_t "\n", indent, ' ', obj->ooffset);
0514 rtems_printf (print->printer,
0515 "%-*cfile size : %zi\n", indent, ' ', obj->fsize);
0516 }
0517 if (print->memory_map)
0518 {
0519 rtems_printf (print->printer,
0520 "%-*cexec size : %zi\n", indent, ' ', obj->exec_size);
0521 rtems_printf (print->printer,
0522 "%-*ctext base : %p (%zi)\n", indent, ' ',
0523 obj->text_base, obj->text_size);
0524 rtems_printf (print->printer,
0525 "%-*cconst base : %p (%zi)\n", indent, ' ',
0526 obj->const_base, obj->const_size);
0527 rtems_printf (print->printer,
0528 "%-*cdata base : %p (%zi)\n", indent, ' ',
0529 obj->data_base, obj->data_size);
0530 rtems_printf (print->printer,
0531 "%-*cbss base : %p (%zi)\n", indent, ' ',
0532 obj->bss_base, obj->bss_size);
0533 }
0534 if (print->stats)
0535 {
0536 rtems_printf (print->printer, "%-*cunresolved : %zu\n", indent, ' ', obj->unresolved);
0537 rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users);
0538 rtems_printf (print->printer, "%-*creferences : %zu\n", indent, ' ', obj->refs);
0539 rtems_printf (print->printer, "%-*ctrampolines : %zu\n", indent, ' ',
0540 rtems_rtl_obj_trampolines (obj));
0541 rtems_printf (print->printer, "%-*csymbols : %zi\n", indent, ' ', obj->global_syms);
0542 rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
0543 }
0544 if (print->symbols)
0545 {
0546 if (!rtems_rtl_print_symbols (print, obj, indent, show_name))
0547 return false;
0548 }
0549 if (print->dependencies)
0550 {
0551 rtems_rtl_dep_data dd = {
0552 .print = print,
0553 .first = true,
0554 .show_name = show_name,
0555 .indent = indent
0556 };
0557 rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
0558 if (!dd.first)
0559 rtems_printf (print->printer, "\n");
0560 }
0561 if (print->trampolines)
0562 {
0563 if (obj->tramp_size == 0)
0564 {
0565 rtems_printf (print->printer, "%-*ctrampolines: not supported\n", indent, ' ');
0566 }
0567 else
0568 {
0569 size_t slots = rtems_rtl_obj_trampoline_slots (obj);
0570 size_t used = rtems_rtl_obj_trampolines (obj);
0571 rtems_printf (print->printer, "%-*ctrampolines:\n", indent, ' ');
0572 rtems_printf (print->printer, "%-*cslots : %zu\n", indent + 4, ' ',
0573 slots);
0574 rtems_printf (print->printer, "%-*csize : %zu\n", indent + 4, ' ',
0575 obj->tramp_size);
0576 rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ',
0577 obj->tramp_size);
0578 rtems_printf (print->printer, "%-*cused : %zu\n", indent + 4, ' ',
0579 used);
0580 rtems_printf (print->printer, "%-*crelocs : %zu\n", indent + 4, ' ',
0581 obj->tramp_relocs);
0582 rtems_printf (print->printer, "%-*cunresolved: %zu\n", indent + 4, ' ',
0583 slots - obj->tramp_relocs);
0584 rtems_printf (print->printer, "%-*cyield : %zu%%\n", indent + 4, ' ',
0585 slots ? (used * 100) / slots : 0);
0586 }
0587 }
0588 return true;
0589 }
0590
0591
0592
0593
0594 static bool
0595 rtems_rtl_unresolved_printer (rtems_rtl_unresolv_rec* rec,
0596 void* data)
0597 {
0598 rtems_rtl_obj_print* print = (rtems_rtl_obj_print*) data;
0599 if (rec->type == rtems_rtl_unresolved_symbol)
0600 rtems_printf (print->printer,
0601 "%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
0602 return false;
0603 }
0604
0605
0606
0607
0608 static bool
0609 rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data)
0610 {
0611 rtems_rtl_obj_print* print = data;
0612 rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
0613 return rtems_rtl_obj_printer (print, obj);
0614 }
0615
0616 int
0617 rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
0618 {
0619 rtems_rtl_obj_print print = { 0 };
0620 if (!rtems_rtl_check_opts (printer, "anlmsdbt", argc, argv))
0621 return 1;
0622 print.printer = printer;
0623 print.indent = 1;
0624 print.oname = true;
0625 if (rtems_rtl_parse_opt ('a', argc, argv))
0626 {
0627 print.names = true;
0628 print.stats = true;
0629 print.memory_map = true;
0630 print.symbols = true;
0631 print.dependencies = true;
0632 print.trampolines = true;
0633 }
0634 else
0635 {
0636 print.names = rtems_rtl_parse_opt ('n', argc, argv);
0637 print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
0638 print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
0639 print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
0640 print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
0641 print.trampolines = rtems_rtl_parse_opt ('t', argc, argv);;
0642 print.base = rtems_rtl_parse_opt ('b', argc, argv);;
0643 print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
0644 }
0645 print.re_symbol = NULL;
0646 print.rtl = rtems_rtl_lock ();
0647 if (print.rtl == NULL)
0648 {
0649 rtems_printf (print.printer, "error: cannot lock the linker\n");
0650 return 1;
0651 }
0652 rtems_rtl_chain_iterate (&print.rtl->objects,
0653 rtems_rtl_obj_print_iterator,
0654 &print);
0655 rtems_rtl_unlock ();
0656 return 0;
0657 }
0658
0659 int
0660 rtems_rtl_shell_sym (const rtems_printer* printer, int argc, char* argv[])
0661 {
0662 rtems_rtl_obj_print print = { 0 };
0663 if (!rtems_rtl_check_opts (printer, "buo", argc, argv))
0664 return 1;
0665 print.printer = printer;
0666 print.indent = 1;
0667 print.oname = true;
0668 print.names = false;
0669 print.stats = false;
0670 print.memory_map = false;
0671 print.symbols = !rtems_rtl_parse_opt ('u', argc, argv);;
0672 print.dependencies = false;
0673 print.base = rtems_rtl_parse_opt ('b', argc, argv);
0674 print.re_name = rtems_rtl_parse_arg ('o', NULL, argc, argv);;
0675 print.re_symbol = rtems_rtl_parse_arg (' ', "ou", argc, argv);
0676 print.rtl = rtems_rtl_lock ();
0677 if (print.rtl == NULL)
0678 {
0679 rtems_printf (print.printer, "error: cannot lock the linker\n");
0680 return 1;
0681 }
0682 if (print.symbols)
0683 {
0684 rtems_rtl_chain_iterate (&print.rtl->objects,
0685 rtems_rtl_obj_print_iterator,
0686 &print);
0687 }
0688 if (rtems_rtl_parse_opt ('u', argc, argv))
0689 {
0690 rtems_printf (printer, "Unresolved:\n");
0691 rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_printer, &print);
0692 }
0693 rtems_rtl_unlock ();
0694 return 0;
0695 }
0696
0697 int
0698 rtems_rtl_shell_object (const rtems_printer* printer, int argc, char* argv[])
0699 {
0700 size_t arg;
0701
0702 --argc;
0703 ++argv;
0704
0705 for (arg = 0; arg < argc; ++arg)
0706 {
0707 if (argv[arg][0] == '-')
0708 {
0709 switch (argv[arg][1])
0710 {
0711 case 'h':
0712 case '?':
0713 rtems_printf (printer, "obj commands:\n");
0714 rtems_printf (printer, " load <file>\n");
0715 rtems_printf (printer, " unload <file>\n");
0716 break;
0717 default:
0718 rtems_printf (printer, "error: invalid option: %s\n", argv[arg]);
0719 return 1;
0720 }
0721 }
0722 else
0723 {
0724 break;
0725 }
0726 }
0727
0728 if (arg >= argc)
0729 {
0730 rtems_printf (printer, "error: no obj command\n");
0731 return 1;
0732 }
0733
0734 if (strcmp (argv[arg], "load") == 0)
0735 {
0736 void* handle;
0737 int unresolved;
0738
0739 ++arg;
0740 if (arg >= argc)
0741 {
0742 rtems_printf (printer, "error: no object file to load\n");
0743 return 1;
0744 }
0745
0746 handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL);
0747 if (handle == NULL)
0748 {
0749 rtems_printf (printer, "error: load: %s: %s\n", argv[arg], dlerror ());
0750 return 1;
0751 }
0752
0753 if (dlinfo (RTLD_SELF, RTLD_DI_UNRESOLVED, &unresolved) < 0)
0754 {
0755 rtems_printf (printer, "error: %s: %s\n", argv[arg], dlerror ());
0756 return 1;
0757 }
0758
0759 if (unresolved != 0)
0760 {
0761 rtems_printf (printer, "warning: unresolved symbols present\n");
0762 return 1;
0763 }
0764 }
0765 else if (strcmp (argv[arg], "unload") == 0)
0766 {
0767 rtems_rtl_data* rtl;
0768 rtems_rtl_obj* obj;
0769
0770 ++arg;
0771 if (arg >= argc)
0772 {
0773 rtems_printf (printer, "error: no object file to load\n");
0774 return 1;
0775 }
0776
0777 rtl = rtems_rtl_lock ();
0778 if (rtl == NULL)
0779 {
0780 rtems_printf (printer, "error: cannot lock RTL\n");
0781 return 1;
0782 }
0783
0784 obj = rtems_rtl_find_obj (argv[arg]);
0785 if (obj == NULL)
0786 {
0787 rtems_rtl_unlock ();
0788 rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
0789 return 1;
0790 }
0791
0792 if (!rtems_rtl_unload (obj))
0793 {
0794 rtems_rtl_unlock ();
0795 rtems_printf (printer, "error: unload: %s: %s\n", argv[arg], dlerror ());
0796 return 1;
0797 }
0798
0799 rtems_rtl_unlock ();
0800 }
0801 else
0802 {
0803 rtems_printf (printer, "error: unknown obj command: %s\n", argv[arg]);
0804 return 1;
0805 }
0806
0807 return 0;
0808 }
0809
0810 int
0811 rtems_rtl_shell_archive (const rtems_printer* printer, int argc, char* argv[])
0812 {
0813 rtems_rtl_data* rtl;
0814 rtems_chain_node* node;
0815 const char* re_name;
0816 bool details;
0817 bool symbols;
0818 bool duplicates;
0819 regex_t rege;
0820
0821 if (!rtems_rtl_check_opts (printer, "dsl", argc, argv))
0822 return 1;
0823
0824 details = rtems_rtl_parse_opt ('l', argc, argv);
0825 symbols = rtems_rtl_parse_opt ('s', argc, argv);
0826 duplicates = rtems_rtl_parse_opt ('d', argc, argv);
0827
0828 re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
0829
0830 if (re_name != NULL)
0831 {
0832 if (!rtems_rtl_regx_compile (printer,
0833 "name filter",
0834 ®e,
0835 re_name))
0836 {
0837 return false;
0838 }
0839 }
0840
0841 rtl = rtems_rtl_lock ();
0842 if (rtl == NULL)
0843 {
0844 rtems_printf (printer, "error: cannot lock the linker\n");
0845 return 1;
0846 }
0847
0848 node = rtems_chain_first (&rtl->archives.archives);
0849
0850 while (!rtems_chain_is_tail (&rtl->archives.archives, node))
0851 {
0852 #define SYM_DUPLICATE (((size_t) 1) << ((8 * sizeof (size_t)) - 1))
0853
0854 rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
0855
0856 if (re_name != NULL)
0857 {
0858 int r = rtems_rtl_regx_match (printer,
0859 "name match",
0860 ®e,
0861 archive->name);
0862 if (r < 0)
0863 {
0864 rtems_rtl_unlock ();
0865 return false;
0866 }
0867
0868 if (r == 0)
0869 {
0870 node = rtems_chain_next (node);
0871 continue;
0872 }
0873 }
0874
0875 rtems_printf (printer, "%s%c\n",
0876 archive->name,
0877 details | symbols | duplicates ? ':' : ' ');
0878
0879 if (details)
0880 {
0881 rtems_printf (printer, " size : %zu\n", archive->size);
0882 rtems_printf (printer, " symbols : %zu\n", archive->symbols.entries);
0883 rtems_printf (printer, " refs : %zu\n", archive->refs);
0884 rtems_printf (printer, " flags : %" PRIx32 "\n", archive->flags);
0885 }
0886
0887 if (symbols)
0888 {
0889 const char* symbol = archive->symbols.names;
0890 int indent = 0;
0891 size_t s;
0892
0893 rtems_printf (printer, " symbols :");
0894
0895 for (s = 0; s < archive->symbols.entries; ++s)
0896 {
0897 if (archive->symbols.symbols != NULL)
0898 symbol = archive->symbols.symbols[s].label;
0899
0900 rtems_printf (printer, "%-*c%s\n", indent, ' ', symbol);
0901 indent = 12;
0902
0903 if (archive->symbols.symbols == NULL)
0904 symbol += strlen (symbol) + 1;
0905 }
0906
0907 if (indent == 0)
0908 rtems_printf (printer, "\n");
0909 }
0910
0911 if (duplicates)
0912 {
0913 rtems_chain_node* match_node;
0914 int indent = 0;
0915 bool show_dups = true;
0916
0917 match_node = rtems_chain_first (&rtl->archives.archives);
0918
0919 while (!rtems_chain_is_tail (&rtl->archives.archives, match_node))
0920 {
0921 rtems_rtl_archive* match_archive = (rtems_rtl_archive*) match_node;
0922 const char* symbol = archive->symbols.names;
0923 size_t s;
0924
0925 for (s = 0; s < archive->symbols.entries; ++s)
0926 {
0927 if (archive->symbols.symbols == NULL ||
0928 (archive->symbols.symbols[s].entry & SYM_DUPLICATE) == 0)
0929 {
0930 const char* match_symbol = match_archive->symbols.names;
0931 size_t ms;
0932
0933 if (archive->symbols.symbols != NULL)
0934 symbol = archive->symbols.symbols[s].label;
0935
0936 for (ms = 0; ms < match_archive->symbols.entries; ++ms)
0937 {
0938 if (match_archive->symbols.symbols != NULL)
0939 match_symbol = match_archive->symbols.symbols[ms].label;
0940
0941 if (symbol != match_symbol && strcmp (symbol, match_symbol) == 0)
0942 {
0943 if (show_dups)
0944 {
0945 show_dups = false;
0946 rtems_printf (printer, " dups :");
0947 }
0948 rtems_printf (printer, "%-*c%s (%s)\n",
0949 indent, ' ', symbol, archive->name);
0950 indent = 12;
0951
0952 if (match_archive->symbols.symbols != NULL)
0953 match_archive->symbols.symbols[ms].entry |= SYM_DUPLICATE;
0954 }
0955
0956 if (match_archive->symbols.symbols == NULL)
0957 match_symbol += strlen (match_symbol) + 1;
0958 }
0959 }
0960
0961 if (archive->symbols.symbols == NULL)
0962 symbol += strlen (symbol) + 1;
0963 }
0964
0965 match_node = rtems_chain_next (match_node);
0966 }
0967
0968 if (indent == 0)
0969 rtems_printf (printer, "\n");
0970 }
0971
0972 node = rtems_chain_next (node);
0973 }
0974
0975 regfree (®e);
0976
0977 node = rtems_chain_first (&rtl->archives.archives);
0978
0979 while (!rtems_chain_is_tail (&rtl->archives.archives, node))
0980 {
0981 rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
0982 if (archive->symbols.symbols != NULL)
0983 {
0984 size_t s;
0985 for (s = 0; s < archive->symbols.entries; ++s)
0986 archive->symbols.symbols[s].entry &= ~SYM_DUPLICATE;
0987 }
0988 node = rtems_chain_next (node);
0989 }
0990
0991 rtems_rtl_unlock ();
0992
0993 return 0;
0994 }
0995
0996 int
0997 rtems_rtl_shell_call (const rtems_printer* printer, int argc, char* argv[])
0998 {
0999 #define CALL_ARG_COUNT (4)
1000
1001 typedef void (*csig_none)(void);
1002 typedef void (*csig_argv)(int argc, const char* argv[]);
1003 typedef void (*csig_s)(const char* str);
1004 typedef void (*csig_u)(unsigned int i1, unsigned int i2, unsigned int i3, unsigned int i4);
1005 typedef void (*csig_i)(int i1, int i2, int i3, int i4);
1006
1007 union {
1008 char s[64 + 1];
1009 unsigned int u[CALL_ARG_COUNT];
1010 int i[CALL_ARG_COUNT];
1011 } values = { 0 };
1012 bool keep_locked = false;
1013 bool args_s = false;
1014 bool args_i = false;
1015 bool args_u = false;
1016 ssize_t label;
1017 rtems_rtl_data* rtl;
1018 rtems_rtl_obj_sym* sym;
1019 rtems_rtl_obj* obj;
1020
1021
1022 if (!rtems_rtl_check_opts (printer, "lsui", argc, argv))
1023 return 1;
1024
1025 keep_locked = rtems_rtl_parse_opt ('l', argc, argv);
1026 args_s = rtems_rtl_parse_opt ('s', argc, argv);
1027 args_u = rtems_rtl_parse_opt ('u', argc, argv);
1028 args_i = rtems_rtl_parse_opt ('i', argc, argv);
1029
1030 if (args_s || args_u || args_i)
1031 {
1032 int c = 0;
1033 c += args_s ? 1 : 0;
1034 c += args_u ? 1 : 0;
1035 c += args_i ? 1 : 0;
1036 if (c > 1)
1037 {
1038 rtems_printf (printer,
1039 "error: too many options, only one -sul at a time\n");
1040 return 1;
1041 }
1042 }
1043
1044 label = rtems_rtl_parse_arg_index (' ', NULL, argc, argv);
1045 if (label < 0)
1046 {
1047 rtems_printf (printer, "error: no symbol found on command line\n");
1048 return 1;
1049 }
1050
1051 if ((label + 1) < argc)
1052 {
1053 if (args_s)
1054 {
1055 size_t arg;
1056 for (arg = label + 1; arg < argc; ++arg)
1057 {
1058 size_t o = strlen (values.s);
1059 if (strlen (argv[arg]) + 1 >= (sizeof (values.s) - o))
1060 {
1061 rtems_printf (printer, "error: string args too big\n");
1062 return 1;
1063 }
1064 if (o > 0)
1065 values.s[o++] = ' ';
1066 strcat (values.s, argv[arg]);
1067 }
1068 }
1069 else if (args_u || args_i)
1070 {
1071 size_t arg;
1072 size_t i;
1073 if (argc > (label + 1 + CALL_ARG_COUNT))
1074 {
1075 rtems_printf (printer, "error: too many args\n");
1076 return 1;
1077 }
1078 for (i = 0, arg = label + 1; arg < argc; ++arg)
1079 {
1080 if (args_u)
1081 values.u[i] = strtoul (argv[arg], 0, 0);
1082 else
1083 values.i[i] = strtol (argv[arg], 0, 0);
1084 ++i;
1085 }
1086 }
1087 }
1088
1089 rtl = rtems_rtl_lock ();
1090 if (rtl == NULL)
1091 {
1092 rtems_printf (printer, "error: cannot lock the linker\n");
1093 return 1;
1094 }
1095
1096 sym = rtems_rtl_symbol_global_find (argv[label]);
1097 if (sym == NULL)
1098 {
1099 rtems_rtl_unlock ();
1100 rtems_printf (printer, "error: symbol not found: %s\n", argv[label]);
1101 return 1;
1102 }
1103
1104 obj = rtems_rtl_find_obj_with_symbol (sym);
1105 if (obj == NULL)
1106 {
1107 rtems_rtl_unlock ();
1108 rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
1109 return 1;
1110 }
1111
1112 if (!rtems_rtl_obj_text_inside (obj, (const void*) sym->value))
1113 {
1114 rtems_rtl_unlock ();
1115 rtems_printf (printer, "error: symbol not in obj text: %s\n", argv[label]);
1116 return 1;
1117 }
1118
1119
1120
1121
1122 rtems_rtl_obj_inc_reference (obj);
1123
1124 rtems_rtl_unlock ();
1125
1126 if (args_s)
1127 {
1128 csig_s call = (csig_s) sym->value;
1129 call (values.s);
1130 }
1131 else if (args_u)
1132 {
1133 csig_u call = (csig_u) sym->value;
1134 call (values.u[0], values.u[1], values.u[2], values.u[3]);
1135 }
1136 else if (args_i)
1137 {
1138 csig_i call = (csig_i) sym->value;
1139 call (values.i[0], values.i[1], values.i[2], values.i[3]);
1140 }
1141 else
1142 {
1143 int cargc = argc - (label + 1);
1144 if (cargc == 0)
1145 {
1146 csig_none call = (csig_none) sym->value;
1147 call ();
1148 }
1149 else
1150 {
1151 csig_argv call = (csig_argv) sym->value;
1152 const char* cargv = argv[label + 1];
1153 call (cargc, &cargv);
1154 }
1155 }
1156
1157 if (!keep_locked)
1158 {
1159 rtl = rtems_rtl_lock ();
1160 if (rtl == NULL)
1161 {
1162 rtems_printf (printer, "error: cannot lock the linker\n");
1163 return 1;
1164 }
1165
1166 obj = rtems_rtl_find_obj_with_symbol (sym);
1167 if (obj == NULL)
1168 {
1169 rtems_rtl_unlock ();
1170 rtems_printf (printer, "error: symbol obj not found: %s\n", argv[label]);
1171 return 1;
1172 }
1173
1174 rtems_rtl_obj_dec_reference (obj);
1175
1176 rtems_rtl_unlock ();
1177 }
1178
1179 return 0;
1180 }
1181
1182 static void
1183 rtems_rtl_shell_usage (const rtems_printer* printer, const char* arg)
1184 {
1185 rtems_printf (printer, "%s: Runtime Linker\n", arg);
1186 rtems_printf (printer, " %s [-hl] <command>\n", arg);
1187 rtems_printf (printer, " where:\n");
1188 rtems_printf (printer, " command: A n RTL command. See -l for a list plus help.\n");
1189 rtems_printf (printer, " -h: This help\n");
1190 rtems_printf (printer, " -l: The command list.\n");
1191 }
1192
1193 int
1194 rtems_rtl_shell_command (int argc, char* argv[])
1195 {
1196 const rtems_rtl_shell_cmd table[] =
1197 {
1198 { "status", rtems_rtl_shell_status,
1199 "Display the status of the RTL" },
1200 { "list", rtems_rtl_shell_list,
1201 "\tList the object files currently loaded" },
1202 { "sym", rtems_rtl_shell_sym,
1203 "\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" },
1204 { "obj", rtems_rtl_shell_object,
1205 "\tDisplay the object details, obj <name>" },
1206 { "call", rtems_rtl_shell_call,
1207 "\tCall a symbol" },
1208 { "ar", rtems_rtl_shell_archive,
1209 "\tDisplay the archive details, ar [-ls] <name>" },
1210 { "trace", rtems_rtl_trace_shell_command,
1211 "\tControl the RTL trace flags, trace [-h]" }
1212 };
1213
1214 rtems_printer printer;
1215 int arg;
1216 int t;
1217
1218 rtems_print_printer_printf (&printer);
1219
1220 for (arg = 1; arg < argc; arg++)
1221 {
1222 if (argv[arg][0] != '-')
1223 break;
1224
1225 switch (argv[arg][1])
1226 {
1227 case 'h':
1228 rtems_rtl_shell_usage (&printer, argv[0]);
1229 return 0;
1230 case 'l':
1231 rtems_printf (&printer, "%s: commands are:\n", argv[0]);
1232 for (t = 0;
1233 t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd));
1234 ++t)
1235 rtems_printf (&printer, " %s\t%s\n", table[t].name, table[t].help);
1236 return 0;
1237 default:
1238 rtems_printf (&printer, "error: unknown option: %s\n", argv[arg]);
1239 return 1;
1240 }
1241 }
1242
1243 if ((argc - arg) < 1)
1244 rtems_printf (&printer, "error: you need to provide a command, try %s -h\n",
1245 argv[0]);
1246 else
1247 {
1248 for (t = 0;
1249 t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd));
1250 ++t)
1251 {
1252 if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0)
1253 return table[t].handler (&printer, argc - 1, argv + 1);
1254 }
1255 rtems_printf (&printer, "error: command not found: %s (try -h)\n", argv[arg]);
1256 }
1257
1258 return 1;
1259 }