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 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <ctype.h>
0041 #include <dirent.h>
0042 #include <errno.h>
0043 #include <fnmatch.h>
0044 #include <inttypes.h>
0045 #include <stdio.h>
0046 #include <string.h>
0047
0048 #include <rtems/libio_.h>
0049
0050 #include <rtems/rtl/rtl.h>
0051 #include "rtl-chain-iterator.h"
0052 #include <rtems/rtl/rtl-trace.h>
0053 #include "rtl-string.h"
0054 #include "rtl-error.h"
0055
0056
0057
0058
0059 #define RTEMS_RTL_AR_IDENT "!<arch>\n"
0060 #define RTEMS_RTL_AR_IDENT_SIZE (sizeof (RTEMS_RTL_AR_IDENT) - 1)
0061 #define RTEMS_RTL_AR_FHDR_BASE RTEMS_RTL_AR_IDENT_SIZE
0062 #define RTEMS_RTL_AR_FNAME (0)
0063 #define RTEMS_RTL_AR_FNAME_SIZE (16)
0064 #define RTEMS_RTL_AR_SIZE (48)
0065 #define RTEMS_RTL_AR_SIZE_SIZE (10)
0066 #define RTEMS_RTL_AR_MAGIC (58)
0067 #define RTEMS_RTL_AR_MAGIC_SIZE (2)
0068 #define RTEMS_RTL_AR_FHDR_SIZE (60)
0069
0070
0071
0072
0073 static unsigned int
0074 rtems_rtl_archive_read_32 (void* data)
0075 {
0076 uint8_t* b = (uint8_t*) data;
0077 unsigned int v = b[0];
0078 v = (v << 8) | b[1];
0079 v = (v << 8) | b[2];
0080 v = (v << 8) | b[3];
0081 return v;
0082 }
0083
0084 static void
0085 rtems_rtl_archive_set_error (int num, const char* text)
0086 {
0087 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0088 printf ("rtl: archive: error: %3d: %s\n", num, text);
0089 }
0090
0091 static uint64_t
0092 rtems_rtl_scan_decimal (const uint8_t* string, size_t len)
0093 {
0094 uint64_t value = 0;
0095
0096 while (len && (*string != ' '))
0097 {
0098 value *= 10;
0099 value += *string - '0';
0100 ++string;
0101 --len;
0102 }
0103
0104 return value;
0105 }
0106
0107 static bool
0108 rtems_rtl_seek_read (int fd, off_t off, size_t len, uint8_t* buffer)
0109 {
0110 if (lseek (fd, off, SEEK_SET) < 0)
0111 return false;
0112 if (read (fd, buffer, len) != len)
0113 return false;
0114 return true;
0115 }
0116
0117
0118
0119
0120 typedef bool (*rtems_rtl_archive_iterator) (rtems_rtl_archive* archive,
0121 void* data);
0122
0123
0124
0125
0126 typedef struct rtems_rtl_archive_chain_data
0127 {
0128 void* data;
0129 rtems_rtl_archive_iterator iterator;
0130 } rtems_rtl_archive_chain_data;
0131
0132 static bool
0133 rtems_rtl_archive_node_iterator (rtems_chain_node* node, void* data)
0134 {
0135 rtems_rtl_archive* archive;
0136 rtems_rtl_archive_chain_data* chain_data;
0137 archive = (rtems_rtl_archive*) node;
0138 chain_data = (rtems_rtl_archive_chain_data*) data;
0139 return chain_data->iterator (archive, chain_data->data);
0140 }
0141
0142 static void
0143 rtems_rtl_archive_iterate_archives (rtems_rtl_archives* archives,
0144 rtems_rtl_archive_iterator iterator,
0145 void* data)
0146 {
0147 rtems_rtl_archive_chain_data chain_data = {
0148 .data = data,
0149 .iterator = iterator
0150 };
0151 rtems_rtl_chain_iterate (&archives->archives,
0152 rtems_rtl_archive_node_iterator,
0153 &chain_data);
0154 }
0155
0156 static bool
0157 rtems_rtl_rchive_name_end (const char c)
0158 {
0159 return c == '\0' || c == '\n' || c == '/';
0160 }
0161
0162 static const char*
0163 rtems_rtl_archive_dup_name (const char* name)
0164 {
0165 size_t len = 0;
0166 char* dup;
0167 while (!rtems_rtl_rchive_name_end (name[len]))
0168 ++len;
0169 dup = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, true);
0170 if (dup != NULL)
0171 memcpy (dup, name, len);
0172 return dup;
0173 }
0174
0175 static bool
0176 rtems_rtl_archive_match_name (const char* file_name, const char* name)
0177 {
0178 if (name != NULL)
0179 {
0180 while (!rtems_rtl_rchive_name_end (*file_name) &&
0181 !rtems_rtl_rchive_name_end (*name) && *file_name == *name)
0182 {
0183 ++file_name;
0184 ++name;
0185 }
0186 if (((*file_name == '\0') || (*file_name == '\n') || (*file_name == '/')) &&
0187 ((*name == '\0') || (*name == '/')))
0188 return true;
0189 }
0190 return false;
0191 }
0192
0193 static bool
0194 rtems_rtl_archive_set_flags (rtems_rtl_archive* archive, void* data)
0195 {
0196 uint32_t mask = *((uint32_t*) data);
0197 archive->flags |= mask;
0198 return true;
0199 }
0200
0201 typedef struct rtems_rtl_archive_find_data
0202 {
0203 rtems_rtl_archive* archive;
0204 const char* path;
0205 } rtems_rtl_archive_find_data;
0206
0207 static bool
0208 rtems_rtl_archive_finder (rtems_rtl_archive* archive, void* data)
0209 {
0210 rtems_rtl_archive_find_data* find;
0211 find = (rtems_rtl_archive_find_data*) data;
0212 if (strcmp (find->path, archive->name) == 0)
0213 {
0214 find->archive = archive;
0215 return false;
0216 }
0217 return true;
0218 }
0219
0220 static rtems_rtl_archive*
0221 rtems_rtl_archive_find (rtems_rtl_archives* archives,
0222 const char* path)
0223 {
0224 rtems_rtl_archive_find_data find = {
0225 .archive = NULL,
0226 .path = path
0227 };
0228 rtems_rtl_archive_iterate_archives (archives,
0229 rtems_rtl_archive_finder,
0230 &find);
0231 return find.archive;
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256 typedef struct rtems_rtl_archive_obj_data
0257 {
0258 const char* symbol;
0259 rtems_rtl_archive* archive;
0260
0261 off_t offset;
0262
0263 } rtems_rtl_archive_obj_data;
0264
0265 static int
0266 rtems_rtl_archive_symbol_compare (const void* a, const void* b)
0267 {
0268 const rtems_rtl_archive_symbol* sa;
0269 const rtems_rtl_archive_symbol* sb;
0270 sa = (const rtems_rtl_archive_symbol*) a;
0271 sb = (const rtems_rtl_archive_symbol*) b;
0272 return strcmp (sa->label, sb->label);
0273 }
0274
0275 static bool
0276 rtems_rtl_archive_obj_finder (rtems_rtl_archive* archive, void* data)
0277 {
0278 const rtems_rtl_archive_symbols* symbols = &archive->symbols;
0279
0280 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0281 printf ("rtl: archive: finder: %s: entries: %zu\n",
0282 archive->name, symbols->entries);
0283
0284
0285
0286
0287 if (symbols->base != NULL)
0288 {
0289
0290
0291
0292 rtems_rtl_archive_obj_data* search = (rtems_rtl_archive_obj_data*) data;
0293 if (symbols->symbols == NULL)
0294 {
0295 const char* symbol = symbols->names;
0296 size_t entry;
0297 for (entry = 0; entry < symbols->entries; ++entry)
0298 {
0299 if (strcmp (search->symbol, symbol) == 0)
0300 {
0301 search->archive = archive;
0302 search->offset =
0303 rtems_rtl_archive_read_32 (symbols->base + ((entry + 1) * 4));
0304 return false;
0305 }
0306 symbol += strlen (symbol) + 1;
0307 }
0308 }
0309 else
0310 {
0311 rtems_rtl_archive_symbol* match;
0312 const rtems_rtl_archive_symbol key = {
0313 .entry = -1,
0314 .label = search->symbol
0315 };
0316 match = bsearch (&key,
0317 symbols->symbols,
0318 symbols->entries,
0319 sizeof (symbols->symbols[0]),
0320 rtems_rtl_archive_symbol_compare);
0321 if (match != NULL)
0322 {
0323 search->archive = archive;
0324 search->offset =
0325 rtems_rtl_archive_read_32 (symbols->base + (match->entry * 4));
0326 return false;
0327 }
0328 }
0329 }
0330
0331
0332
0333
0334 return true;
0335 }
0336
0337 static rtems_rtl_archive*
0338 rtems_rtl_archive_new (rtems_rtl_archives* archives,
0339 const char* path,
0340 const char* name)
0341 {
0342 rtems_rtl_archive* archive;
0343 size_t path_size;
0344 size_t size;
0345
0346
0347
0348 path_size = strlen (path);
0349 size = sizeof(rtems_rtl_archive) + path_size + strlen (name) + 1;
0350 if (path_size > 1)
0351 ++size;
0352 archive = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, size, true);
0353 if (archive == NULL)
0354 {
0355 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0356 printf ("rtl: archive: new: %s: no memory\n", name);
0357 }
0358 else
0359 {
0360 char* aname;
0361 archive->name = ((const char*) archive) + sizeof(rtems_rtl_archive);
0362 aname = (char*) archive->name;
0363 strcpy (aname, path);
0364 if (path_size > 1)
0365 strcat (aname, "/");
0366 strcat (aname, name);
0367 rtems_chain_set_off_chain (&archive->node);
0368 archive->flags |= RTEMS_RTL_ARCHIVE_LOAD;
0369 }
0370 return archive;
0371 }
0372
0373 static void
0374 rtems_rtl_archive_del (rtems_rtl_archive* archive)
0375 {
0376 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0377 printf ("rtl: archive: del: %s\n", archive->name);
0378 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, archive->symbols.base);
0379 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, archive->symbols.symbols);
0380 if (!rtems_chain_is_node_off_chain (&archive->node))
0381 rtems_chain_extract (&archive->node);
0382 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, archive);
0383 }
0384
0385 static rtems_rtl_archive*
0386 rtems_rtl_archive_get (rtems_rtl_archives* archives,
0387 const char* path,
0388 const char* name)
0389 {
0390 rtems_rtl_archive* archive;
0391
0392
0393
0394
0395
0396 archive = rtems_rtl_archive_new (archives, path, name);
0397 if (archive != NULL)
0398 {
0399 struct stat sb;
0400 if (stat (archive->name, &sb) == 0)
0401 {
0402 if (S_ISREG (sb.st_mode))
0403 {
0404 rtems_rtl_archive* find_archive;
0405 find_archive = rtems_rtl_archive_find (archives, archive->name);
0406 if (find_archive == NULL)
0407 {
0408 rtems_chain_append (&archives->archives, &archive->node);
0409 }
0410 else
0411 {
0412 rtems_rtl_archive_del (archive);
0413 archive = find_archive;
0414 }
0415 archive->flags &= ~RTEMS_RTL_ARCHIVE_REMOVE;
0416 if (archive->mtime != sb.st_mtime)
0417 {
0418 archive->flags |= RTEMS_RTL_ARCHIVE_LOAD;
0419 archive->size = sb.st_size;
0420 archive->mtime = sb.st_mtime;
0421 }
0422 }
0423 }
0424 }
0425 return archive;
0426 }
0427
0428 static bool
0429 rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
0430 {
0431 struct stat sb;
0432
0433 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0434 printf ("rtl: archive: config load: %s\n", archives->config_name);
0435
0436 if (archives->config_name == NULL)
0437 return false;
0438
0439 if (stat (archives->config_name, &sb) < 0)
0440 {
0441 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0442 printf ("rtl: archive: no config: %s\n", archives->config_name);
0443 return false;
0444 }
0445
0446
0447
0448
0449 if (sb.st_mtime != archives->config_mtime)
0450 {
0451 int fd;
0452 ssize_t r;
0453 char* s;
0454 bool in_comment;
0455
0456 archives->config_mtime = sb.st_mtime;
0457 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
0458 archives->config_length = 0;
0459 archives->config =
0460 rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sb.st_size + 1, true);
0461 if (archives->config == NULL)
0462 {
0463 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0464 printf ("rtl: archive: no memory for config\n");
0465 return false;
0466 }
0467
0468 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0469 printf ("rtl: archive: config load: read %s\n", archives->config_name);
0470
0471 fd = open (archives->config_name, O_RDONLY);
0472 if (fd < 0)
0473 {
0474 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
0475 archives->config = NULL;
0476 archives->config_length = 0;
0477 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0478 printf ("rtl: archive: config open error: %s\n", strerror (errno));
0479 return false;
0480 }
0481
0482 r = read (fd, (void*) archives->config, sb.st_size);
0483 if (r < 0)
0484 {
0485 close (fd);
0486 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
0487 archives->config = NULL;
0488 archives->config_length = 0;
0489 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0490 printf ("rtl: archive: config read error: %s\n", strerror (errno));
0491 return false;
0492 }
0493
0494 close (fd);
0495 archives->config_length = r;
0496
0497
0498
0499
0500 s = (char*) archives->config;
0501 in_comment = false;
0502 for (r = 0; r < archives->config_length; ++r, ++s)
0503 {
0504 if (*s == '#')
0505 in_comment = true;
0506 if (in_comment)
0507 {
0508 if (*s == '\n')
0509 in_comment = false;
0510 *s = '\0';
0511 }
0512 }
0513
0514
0515
0516
0517 s = (char*) archives->config;
0518 for (r = 0; r < archives->config_length; ++r, ++s)
0519 {
0520 if (*s == '\r' || *s == '\n')
0521 *s = '\0';
0522 }
0523
0524
0525
0526
0527 s = (char*) archives->config;
0528 r = 0;
0529 while (r < archives->config_length)
0530 {
0531 if (s[r] == '\0')
0532 {
0533 ++r;
0534 }
0535 else
0536 {
0537 size_t ls = strlen (&s[r]);
0538 size_t b = 0;
0539 while (b < ls && isspace ((unsigned char) s[r + b]))
0540 {
0541 s[r + b] = '\0';
0542 ++b;
0543 }
0544 b = ls - 1;
0545 while (b > 0 && isspace ((unsigned char) s[r + b]))
0546 {
0547 s[r + b] = '\0';
0548 --b;
0549 }
0550 r += ls;
0551 }
0552 }
0553
0554 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0555 {
0556 int line = 1;
0557 printf ("rtl: archive: config:\n");
0558 r = 0;
0559 while (r < archives->config_length)
0560 {
0561 const char* cs = &archives->config[r];
0562 size_t len = strlen (cs);
0563 if (len > 0)
0564 {
0565 printf (" %3d: %s\n", line, cs);
0566 ++line;
0567 }
0568 r += len + 1;
0569 }
0570 }
0571 }
0572
0573 return true;
0574 }
0575
0576 void
0577 rtems_rtl_archives_open (rtems_rtl_archives* archives, const char* config)
0578 {
0579 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0580 printf ("rtl: archive: open: %s\n", config);
0581 memset (archives, 0, sizeof (rtems_rtl_archives));
0582 archives->config_name = rtems_rtl_strdup (config);
0583 rtems_chain_initialize_empty (&archives->archives);
0584 }
0585
0586 void
0587 rtems_rtl_archives_close (rtems_rtl_archives* archives)
0588 {
0589 rtems_chain_node* node;
0590 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0591 printf ("rtl: archive: close: count=%zu\n",
0592 rtems_chain_node_count_unprotected (&archives->archives));
0593 node = rtems_chain_first (&archives->archives);
0594 while (!rtems_chain_is_tail (&archives->archives, node))
0595 {
0596 rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
0597 rtems_chain_node* next_node = rtems_chain_next (node);
0598 rtems_rtl_archive_del (archive);
0599 node = next_node;
0600 }
0601 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
0602 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, archives);
0603 }
0604
0605 static void
0606 rtems_rtl_archives_remove (rtems_rtl_archives* archives)
0607 {
0608 rtems_chain_node* node = rtems_chain_first (&archives->archives);
0609 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0610 printf ("rtl: archive: refresh: remove: checking %zu archive(s)\n",
0611 rtems_chain_node_count_unprotected (&archives->archives));
0612 while (!rtems_chain_is_tail (&archives->archives, node))
0613 {
0614 rtems_rtl_archive* archive = (rtems_rtl_archive*) node;
0615 rtems_chain_node* next_node = rtems_chain_next (node);
0616 if ((archive->flags & RTEMS_RTL_ARCHIVE_REMOVE) != 0)
0617 {
0618 archive->flags &= ~RTEMS_RTL_ARCHIVE_REMOVE;
0619 if ((archive->flags & RTEMS_RTL_ARCHIVE_USER_LOAD) == 0)
0620 rtems_rtl_archive_del (archive);
0621 }
0622 node = next_node;
0623 }
0624 }
0625
0626 static bool
0627 rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
0628 {
0629 int* loaded = (int*) data;
0630
0631 if ((archive->flags & RTEMS_RTL_ARCHIVE_LOAD) != 0)
0632 {
0633 int fd;
0634 off_t offset = 0;
0635 size_t size = 0;
0636 const char* name = "/";
0637
0638 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0639 printf ("rtl: archive: loader: %s\n", archive->name);
0640
0641 fd = open (archive->name, O_RDONLY);
0642 if (fd < 0)
0643 {
0644 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0645 printf ("rtl: archive: loader: open error: %s: %s\n",
0646 archive->name, strerror (errno));
0647 rtems_rtl_archive_set_error (errno, "opening archive file");
0648 return true;
0649 }
0650
0651 if (rtems_rtl_obj_archive_find_obj (fd,
0652 archive->size,
0653 &name,
0654 &offset,
0655 &size,
0656 &archive->enames,
0657 rtems_rtl_archive_set_error))
0658 {
0659 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0660 printf ("rtl: archive: loader: symbols: off=0x%08jx size=%zu\n",
0661 offset, size);
0662
0663
0664
0665
0666
0667 if (archive->symbols.size != size)
0668 {
0669 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, archive->symbols.base);
0670 archive->symbols.base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
0671 size,
0672 false);
0673 if (archive->symbols.base == NULL)
0674 {
0675 close (fd);
0676 memset (&archive->symbols, 0, sizeof (archive->symbols));
0677 rtems_rtl_archive_set_error (ENOMEM, "symbol table memory");
0678 return true;
0679 }
0680 }
0681
0682
0683
0684
0685 if (!rtems_rtl_seek_read (fd, offset, size, archive->symbols.base))
0686 {
0687 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, archive->symbols.base);
0688 close (fd);
0689 memset (&archive->symbols, 0, sizeof (archive->symbols));
0690 rtems_rtl_archive_set_error (errno, "reading symbols");
0691 return true;
0692 }
0693
0694
0695
0696
0697
0698 archive->symbols.entries =
0699 rtems_rtl_archive_read_32 (archive->symbols.base);
0700 if (archive->symbols.entries >= (SIZE_MAX / sizeof (rtems_rtl_archive_symbol)))
0701 {
0702 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, archive->symbols.base);
0703 close (fd);
0704 memset (&archive->symbols, 0, sizeof (archive->symbols));
0705 rtems_rtl_archive_set_error (errno, "too many symbols");
0706 return true;
0707 }
0708
0709 archive->symbols.size = size;
0710 archive->symbols.names = archive->symbols.base;
0711 archive->symbols.names += (archive->symbols.entries + 1) * 4;
0712
0713
0714
0715
0716 size = archive->symbols.entries * sizeof (rtems_rtl_archive_symbol);
0717 archive->symbols.symbols =
0718 rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, size, true);
0719 if (archive->symbols.symbols != NULL)
0720 {
0721 const char* symbol = archive->symbols.names;
0722 size_t e;
0723 for (e = 0; e < archive->symbols.entries; ++e)
0724 {
0725 archive->symbols.symbols[e].entry = e + 1;
0726 archive->symbols.symbols[e].label = symbol;
0727 symbol += strlen (symbol) + 1;
0728 }
0729 qsort (archive->symbols.symbols,
0730 archive->symbols.entries,
0731 sizeof (rtems_rtl_archive_symbol),
0732 rtems_rtl_archive_symbol_compare);
0733 }
0734
0735 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0736 printf ("rtl: archive: loader: symbols: " \
0737 "base=%p entries=%zu names=%p (0x%08x) symbols=%p\n",
0738 archive->symbols.base,
0739 archive->symbols.entries,
0740 archive->symbols.names,
0741 (unsigned int) (archive->symbols.entries + 1) * 4,
0742 archive->symbols.symbols);
0743
0744 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVE_SYMS) &&
0745 archive->symbols.entries > 0)
0746 {
0747 size_t e;
0748 printf ("rtl: archive: symbols: %s\n", archive->name );
0749 for (e = 0; e < archive->symbols.entries; ++e)
0750 {
0751 printf(" %6zu: %6zu %s\n", e + 1,
0752 archive->symbols.symbols[e].entry,
0753 archive->symbols.symbols[e].label);
0754 }
0755 }
0756 }
0757
0758 close (fd);
0759
0760 archive->flags &= ~RTEMS_RTL_ARCHIVE_LOAD;
0761
0762 ++(*loaded);
0763 }
0764
0765 return true;
0766 }
0767
0768 static bool
0769 rtems_rtl_archives_load (rtems_rtl_archives* archives)
0770 {
0771 int loaded = 0;
0772 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0773 printf ("rtl: archive: archive: load\n");
0774 rtems_rtl_archive_iterate_archives (archives,
0775 rtems_rtl_archive_loader,
0776 &loaded);
0777 return loaded > 0;
0778 }
0779
0780 bool
0781 rtems_rtl_archives_refresh (rtems_rtl_archives* archives)
0782 {
0783 size_t config_path = 0;
0784 uint32_t flags = RTEMS_RTL_ARCHIVE_REMOVE;
0785
0786
0787
0788
0789
0790 if (!rtems_rtl_archives_load_config (archives))
0791 return false;
0792
0793
0794
0795
0796
0797
0798 rtems_rtl_archive_iterate_archives (archives,
0799 rtems_rtl_archive_set_flags,
0800 &flags);
0801
0802 while (config_path < archives->config_length)
0803 {
0804 const char* dirname = &archives->config[config_path];
0805 char* basename;
0806 const char root[2] = { '/', '\0' };
0807 DIR* dir;
0808
0809 if (*dirname == '\0')
0810 {
0811 ++config_path;
0812 continue;
0813 }
0814
0815 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0816 printf ("rtl: archive: refresh: %s\n", dirname);
0817
0818 config_path += strlen (dirname);
0819
0820
0821
0822
0823 if (dirname[0] != '/')
0824 {
0825 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0826 printf ("rtl: archive: refresh: relative paths ignored: %s\n", dirname);
0827 continue;
0828 }
0829
0830
0831
0832
0833 basename = strrchr (dirname, '/');
0834 if (basename == NULL)
0835 continue;
0836
0837 if (basename == dirname)
0838 dirname = &root[0];
0839
0840 *basename = '\0';
0841 ++basename;
0842
0843 dir = opendir (dirname);
0844
0845 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0846 printf ("rtl: archive: refresh: %s %sfound\n",
0847 dirname, dir == NULL ? ": not " : "");
0848
0849 if (dir != NULL)
0850 {
0851 while (true)
0852 {
0853 struct dirent entry;
0854 struct dirent* result = NULL;
0855
0856 if (readdir_r (dir, &entry, &result) != 0)
0857 {
0858 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0859 printf ("rtl: archive: refresh: readdir error\n");
0860 break;
0861 }
0862
0863 if (result == NULL)
0864 break;
0865
0866 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0867 printf ("rtl: archive: refresh: checking: %s (pattern: %s)\n",
0868 entry.d_name, basename);
0869
0870 if (fnmatch (basename, entry.d_name, 0) == 0)
0871 {
0872 rtems_rtl_archive* archive;
0873 archive = rtems_rtl_archive_get (archives, dirname, entry.d_name);
0874 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0875 printf ("rtl: archive: refresh: %s: %sfound\n",
0876 entry.d_name, archive == NULL ? ": not " : "");
0877 }
0878 }
0879 closedir (dir);
0880 }
0881
0882 --basename;
0883 *basename = '/';
0884 }
0885
0886
0887
0888
0889 rtems_rtl_archives_remove (archives);
0890
0891
0892
0893
0894
0895
0896
0897 if (rtems_rtl_archives_load (archives))
0898 rtems_rtl_unresolved_set_archive_search ();
0899
0900 return true;
0901 }
0902
0903 bool
0904 rtems_rtl_archive_load (rtems_rtl_archives* archives, const char* name)
0905 {
0906 if (archives != NULL)
0907 {
0908 rtems_rtl_archive* archive;
0909 int loaded = 0;
0910
0911 archive = rtems_rtl_archive_get (archives, "", name);
0912 if (archive == NULL)
0913 {
0914 rtems_rtl_set_error (ENOENT, "archive not found");
0915 return false;
0916 }
0917
0918 archive->flags |= RTEMS_RTL_ARCHIVE_USER_LOAD;
0919
0920 rtems_rtl_archive_loader (archive, &loaded);
0921 if (loaded == 0)
0922 {
0923 rtems_rtl_archive_del (archive);
0924 rtems_rtl_set_error (ENOENT, "archive load falied");
0925 }
0926
0927 return true;
0928 }
0929 return false;
0930 }
0931
0932 rtems_rtl_archive_search
0933 rtems_rtl_archive_obj_load (rtems_rtl_archives* archives,
0934 const char* symbol,
0935 bool load)
0936 {
0937 rtems_rtl_obj* obj;
0938 rtems_chain_control* pending;
0939 int fd;
0940 size_t archive_count;
0941
0942 rtems_rtl_archive_obj_data search = {
0943 .symbol = symbol,
0944 .archive = NULL,
0945 .offset = 0
0946 };
0947
0948 archive_count = rtems_chain_node_count_unprotected (&archives->archives);
0949
0950 if (archive_count == 0)
0951 {
0952 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0953 printf ("rtl: archive: load: no archives\n");
0954 return rtems_rtl_archive_search_no_config;
0955 }
0956
0957 pending = rtems_rtl_pending_unprotected ();
0958 if (pending == NULL)
0959 {
0960 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0961 printf ("rtl: archive: load: no pending list\n");
0962 return rtems_rtl_archive_search_not_found;
0963 }
0964
0965 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0966 printf ("rtl: archive: load: searching %zu archives\n", archive_count);
0967
0968 rtems_rtl_archive_iterate_archives (archives,
0969 rtems_rtl_archive_obj_finder,
0970 &search);
0971
0972 if (search.archive == NULL)
0973 {
0974 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0975 printf ("rtl: archive: load: not found: %s\n", symbol);
0976 return rtems_rtl_archive_search_not_found;
0977 }
0978
0979 if (!load)
0980 {
0981 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0982 printf ("rtl: archive: load: found (no load): %s\n", symbol);
0983 return rtems_rtl_archive_search_found;
0984 }
0985
0986 obj = rtems_rtl_obj_alloc ();
0987 if (obj == NULL)
0988 {
0989 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
0990 printf ("rtl: archive: alloc: no memory: %s\n",
0991 search.archive->name);
0992 return rtems_rtl_archive_search_error;
0993 }
0994
0995 obj->aname = rtems_rtl_strdup (search.archive->name);
0996
0997 fd = open (obj->aname, O_RDONLY);
0998 if (fd < 0)
0999 {
1000 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1001 printf ("rtl: archive: load: open error: %s: %s\n",
1002 obj->aname, strerror (errno));
1003 rtems_rtl_obj_free (obj);
1004 return rtems_rtl_archive_search_error;
1005 }
1006
1007 obj->oname = NULL;
1008 obj->ooffset = search.offset;
1009
1010 if (!rtems_rtl_obj_archive_find_obj (fd,
1011 search.archive->size,
1012 &obj->oname,
1013 &obj->ooffset,
1014 &obj->fsize,
1015 &search.archive->enames,
1016 rtems_rtl_archive_set_error))
1017 {
1018 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1019 printf ("rtl: archive: load: load error: %s:%s\n",
1020 obj->aname, obj->oname);
1021 close (fd);
1022 rtems_rtl_obj_free (obj);
1023 return rtems_rtl_archive_search_error;
1024 }
1025
1026 obj->fname = rtems_rtl_strdup (obj->aname);
1027 obj->ooffset -= RTEMS_RTL_AR_FHDR_SIZE;
1028 obj->fsize = search.archive->size;
1029
1030 close (fd);
1031
1032 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1033 printf ("rtl: archive: loading: %s:%s@0x%08jx size:%zu\n",
1034 obj->aname, obj->oname, obj->ooffset, obj->fsize);
1035
1036 rtems_chain_append (pending, &obj->link);
1037
1038 if (!rtems_rtl_obj_load (obj))
1039 {
1040 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1041 printf ("rtl: archive: loading: error: %s:%s@0x%08jx: %s\n",
1042 obj->aname, obj->oname, obj->ooffset,
1043 rtems_rtl_last_error_unprotected ());
1044 rtems_chain_extract (&obj->link);
1045 rtems_rtl_obj_free (obj);
1046 rtems_rtl_obj_caches_flush ();
1047 return rtems_rtl_archive_search_error;
1048 }
1049
1050 rtems_rtl_obj_caches_flush ();
1051
1052 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1053 printf ("rtl: archive: loading: loaded: %s:%s@0x%08jx\n",
1054 obj->aname, obj->oname, obj->ooffset);
1055
1056 return rtems_rtl_archive_search_loaded;
1057 }
1058
1059 bool
1060 rtems_rtl_obj_archive_find_obj (int fd,
1061 size_t fsize,
1062 const char** name,
1063 off_t* ooffset,
1064 size_t* osize,
1065 off_t* extended_file_names,
1066 rtems_rtl_archive_error error)
1067 {
1068 uint8_t header[RTEMS_RTL_AR_FHDR_SIZE];
1069 bool scanning;
1070
1071 if (name == NULL)
1072 {
1073 error (errno, "invalid object name");
1074 *ooffset = 0;
1075 *osize = 0;
1076 return false;
1077 }
1078
1079 if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
1080 printf ("rtl: archive: find obj: %s @ 0x%08jx\n", *name, *ooffset);
1081
1082 if (read (fd, &header[0], RTEMS_RTL_AR_IDENT_SIZE) != RTEMS_RTL_AR_IDENT_SIZE)
1083 {
1084 error (errno, "reading archive identifer");
1085 *ooffset = 0;
1086 *osize = 0;
1087 return false;
1088 }
1089
1090 if (memcmp (header, RTEMS_RTL_AR_IDENT, RTEMS_RTL_AR_IDENT_SIZE) != 0)
1091 {
1092 error (EINVAL, "invalid archive identifer");
1093 *ooffset = 0;
1094 *osize = 0;
1095 return false;
1096 }
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119 if (*ooffset != 0)
1120 scanning = false;
1121 else
1122 {
1123 if (*name == NULL)
1124 {
1125 error (errno, "invalid object name and archive offset");
1126 *ooffset = 0;
1127 *osize = 0;
1128 return false;
1129 }
1130 scanning = true;
1131 *ooffset = RTEMS_RTL_AR_FHDR_BASE;
1132 *osize = 0;
1133 }
1134
1135 while (*ooffset < fsize)
1136 {
1137
1138
1139
1140 memset (header, 0, sizeof (header));
1141
1142 if (!rtems_rtl_seek_read (fd, *ooffset, RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
1143 {
1144 error (errno, "seek/read archive file header");
1145 *ooffset = 0;
1146 *osize = 0;
1147 return false;
1148 }
1149
1150 if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
1151 (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
1152 {
1153 if (scanning)
1154 {
1155 error (EINVAL, "invalid archive file header");
1156 *ooffset = 0;
1157 *osize = 0;
1158 return false;
1159 }
1160
1161 scanning = true;
1162 *ooffset = RTEMS_RTL_AR_FHDR_BASE;
1163 continue;
1164 }
1165
1166
1167
1168
1169 *osize = (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
1170 RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
1171
1172
1173
1174
1175 if (header[0] == '/')
1176 {
1177 const char* name_ = *name;
1178 off_t extended_off;
1179
1180 switch (header[1])
1181 {
1182 case ' ':
1183
1184
1185
1186 *ooffset += RTEMS_RTL_AR_FHDR_SIZE;
1187 return true;
1188 case '/':
1189
1190
1191
1192
1193 *extended_file_names = *ooffset + RTEMS_RTL_AR_FHDR_SIZE;
1194 if (name_[0] == '/' && name_[1] == '/')
1195 {
1196 *ooffset = *ooffset + RTEMS_RTL_AR_FHDR_SIZE;
1197 return true;
1198 }
1199 break;
1200 case '0':
1201 case '1':
1202 case '2':
1203 case '3':
1204 case '4':
1205 case '5':
1206 case '6':
1207 case '7':
1208 case '8':
1209 case '9':
1210
1211
1212
1213
1214 extended_off =
1215 rtems_rtl_scan_decimal (&header[1], RTEMS_RTL_AR_FNAME_SIZE);
1216
1217 if (*extended_file_names == 0)
1218 {
1219 off_t off = RTEMS_RTL_AR_IDENT_SIZE;
1220 while (*extended_file_names == 0)
1221 {
1222 off_t esize;
1223
1224 if (!rtems_rtl_seek_read (fd, off,
1225 RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
1226 {
1227 error (errno, "seeking/reading archive ext file name header");
1228 *ooffset = 0;
1229 *osize = 0;
1230 return false;
1231 }
1232
1233 if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
1234 (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
1235 {
1236 error (errno, "invalid archive file header");
1237 *ooffset = 0;
1238 *osize = 0;
1239 return false;
1240 }
1241
1242 if ((header[0] == '/') && (header[1] == '/'))
1243 {
1244 *extended_file_names = off + RTEMS_RTL_AR_FHDR_SIZE;
1245 break;
1246 }
1247
1248 esize =
1249 (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
1250 RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
1251 off += esize + RTEMS_RTL_AR_FHDR_SIZE;
1252 }
1253 }
1254
1255 if (*extended_file_names != 0)
1256 {
1257
1258
1259
1260
1261 #define RTEMS_RTL_MAX_FILE_SIZE (256)
1262 char ename[RTEMS_RTL_MAX_FILE_SIZE];
1263
1264 if (!rtems_rtl_seek_read (fd, *extended_file_names + extended_off,
1265 RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &ename[0]))
1266 {
1267 error (errno, "invalid archive ext file seek/read");
1268 *ooffset = 0;
1269 *osize = 0;
1270 return false;
1271 }
1272
1273
1274
1275
1276
1277 if (*name == NULL)
1278 *name = rtems_rtl_archive_dup_name (ename);
1279 if (rtems_rtl_archive_match_name (*name, ename))
1280 {
1281 *ooffset += RTEMS_RTL_AR_FHDR_SIZE;
1282 return true;
1283 }
1284 }
1285 break;
1286 default:
1287
1288
1289
1290 break;
1291 }
1292 }
1293 else
1294 {
1295 const char* ename = (const char*) &header[RTEMS_RTL_AR_FNAME];
1296 if (*name == NULL)
1297 *name = rtems_rtl_archive_dup_name (ename);
1298 if (rtems_rtl_archive_match_name (*name, ename))
1299 {
1300 *ooffset += RTEMS_RTL_AR_FHDR_SIZE;
1301 return true;
1302 }
1303 }
1304
1305 *ooffset += *osize + RTEMS_RTL_AR_FHDR_SIZE;
1306 }
1307
1308 error (ENOENT, "object file not found");
1309 *ooffset = 0;
1310 *osize = 0;
1311 return false;
1312
1313 }