Changeset 89c59be in rtems


Ignore:
Timestamp:
Dec 17, 2018, 5:36:48 AM (5 months ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
85b59974
Parents:
b08278e
git-author:
Chris Johns <chrisj@…> (12/17/18 05:36:48)
git-committer:
Chris Johns <chrisj@…> (02/08/19 23:06:34)
Message:

libdl: Add symbol searching and loading from archives.

  • Load archive symbol tables to support searching of archives for symbols.
  • Search archive symbols and load the object file that contains the symbol.
  • Search the global and archives until all remaining unresolved symbols are not found. Group the loaded object files in the pending queue.
  • Run the object file and loaded dependents as a group before adding to the main object list.
  • Remove orphaned object files after references are removed.

Updates #3686

Location:
cpukit
Files:
2 added
13 edited
1 moved

Legend:

Unmodified
Added
Removed
  • cpukit/Makefile.am

    rb08278e r89c59be  
    11411141librtemscpu_a_SOURCES += libdl/rtl-allocator.c
    11421142librtemscpu_a_SOURCES += libdl/rtl-alloc-heap.c
     1143librtemscpu_a_SOURCES += libdl/rtl-archive.c
    11431144librtemscpu_a_SOURCES += libdl/rtl.c
    11441145librtemscpu_a_SOURCES += libdl/rtl-chain-iterator.c
  • cpukit/include/rtems/rtl/rtl-obj.h

    rb08278e r89c59be  
    9393#define RTEMS_RTL_OBJ_SECT_BSS   (1 << 3)  /**< Section holds program bss. */
    9494#define RTEMS_RTL_OBJ_SECT_EH    (1 << 4)  /**< Section holds exception data. */
    95 #define RTEMS_RTL_OBJ_SECT_REL   (1 << 5)  /**< Section holds relocation records. */
    96 #define RTEMS_RTL_OBJ_SECT_RELA  (1 << 6)  /**< Section holds relocation addend
    97                                             *   records. */
     95#define RTEMS_RTL_OBJ_SECT_REL   (1 << 5)  /**< Section holds relocation recs. */
     96#define RTEMS_RTL_OBJ_SECT_RELA  (1 << 6)  /**< Section holds reloc addend recs. */
    9897#define RTEMS_RTL_OBJ_SECT_SYM   (1 << 7)  /**< Section holds symbols. */
    9998#define RTEMS_RTL_OBJ_SECT_STR   (1 << 8)  /**< Section holds strings. */
     
    169168#define RTEMS_RTL_OBJ_RELOC_TAG    (1 << 3) /**< Tag the object as visited when reloc
    170169                                             *   parsing. */
     170#define RTEMS_RTL_OBJ_DEP_VISITED  (1 << 4) /**< Dependency loop detection. */
    171171
    172172/**
     
    339339
    340340/**
     341 * Is the symbol in this object's files globa symbol table?
     342 *
     343 * @param obj The object file's descriptor to search.
     344 * @param sym The symbol to check.
     345 * @retval bool Returns @true if present else @false is returned.
     346 */
     347static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj*     obj,
     348                                             const rtems_rtl_obj_sym* sym)
     349{
     350  return (sym >= obj->global_table &&
     351          sym < (obj->global_table + obj->global_syms));
     352}
     353
     354/**
    341355 * Allocate an object structure on the heap.
    342356 *
     
    379393                           const char** oname,
    380394                           off_t*       ooffset);
    381 
    382 /**
    383  * Check of the name matches the object file's object name.
    384  *
    385  * @param obj The object file's descriptor.
    386  * @param name The name to match.
    387  */
    388 bool rtems_rtl_match_name (rtems_rtl_obj* obj, const char* name);
    389395
    390396/**
     
    498504
    499505/**
     506 * Remove dependencies. This decrements the dependent object file references.
     507 *
     508 * @param obj The object file's descriptor.
     509 * @retval true The dependencies have been removed.
     510 * @retval false There is no space in the table.
     511 */
     512bool rtems_rtl_obj_remove_dependencies (rtems_rtl_obj* obj);
     513
     514/**
    500515 * Iterate over the module dependenices.
    501516 *
     
    691706
    692707/**
     708 * Does the object have constructors to run?
     709 *
     710 * @return bool True if there are constructors to run.
     711 */
     712bool rtems_rtl_obj_ctors_to_run (rtems_rtl_obj* obj);
     713
     714/**
    693715 * Invoke the constructors the object has. Constructors are a table of pointers
    694716 * to "void (*)(void);" where NULL pointers are skipped. The table's size is
     
    701723
    702724/**
     725 * Does the object have destructors to run?
     726 *
     727 * @return bool True if there are destructors to run.
     728 */
     729bool rtems_rtl_obj_dtors_to_run (rtems_rtl_obj* obj);
     730
     731/**
    703732 * Invoke the destructors the object has. Destructors are a table of pointers
    704733 * to "void (*)(void);" where NULL pointers are skipped. The table's size is
     
    711740
    712741/**
     742 * Get the object file reference count.
     743 *
     744 * @retval int The object file's reference count.
     745 */
     746size_t rtems_rtl_obj_get_reference (rtems_rtl_obj* obj);
     747
     748/**
    713749 * Increment the object file reference count.
    714750 *
     
    723759 */
    724760void rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj);
     761
     762/**
     763 * Is the object file orphaned? An orphaned object file is not locked, has no
     764 * users and it not being referenced.
     765 *
     766 * @param obj The object file's descriptor.
     767 */
     768bool rtems_rtl_obj_orphaned (rtems_rtl_obj* obj);
    725769
    726770/**
  • cpukit/include/rtems/rtl/rtl-shell.h

    rb08278e r89c59be  
    2121#endif /* __cplusplus */
    2222
    23 #include <stdint.h>
    24 
    2523/**
    2624 * The RTL single shell command contains sub-commands.
  • cpukit/include/rtems/rtl/rtl-trace.h

    rb08278e r89c59be  
    4949#define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 10)
    5050#define RTEMS_RTL_TRACE_CACHE                  (1UL << 11)
     51#define RTEMS_RTL_TRACE_ARCHIVES               (1UL << 12)
     52#define RTEMS_RTL_TRACE_DEPENDENCY             (1UL << 13)
    5153#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE))
    5254
  • cpukit/include/rtems/rtl/rtl-unresolved.h

    rb08278e r89c59be  
    7272{
    7373  rtems_rtl_unresolved_empty = 0,  /**< The records is empty. Must always be 0 */
    74   rtems_rtl_unresolved_name = 1,   /**< The record is a name. */
     74  rtems_rtl_unresolved_symbol = 1, /**< The record is a symbol. */
    7575  rtems_rtl_unresolved_reloc = 2   /**< The record is a relocation record. */
    7676} rtems_rtl_unresolved_rtype;
    7777
    7878/**
    79  * Unresolved externals symbol names. The names are reference counted and
    80  * separate from the relocation records because a number of records could
    81  * reference the same symbol name.
    82  */
    83 typedef struct rtems_rtl_unresolv_name
     79 * Unresolved external symbol flags.
     80 */
     81#define RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE (1 << 0) /**< Search the archive. */
     82
     83/**
     84 * Unresolved externals symbols. The symbols are reference counted and separate
     85 * from the relocation records because a number of records could reference the
     86 * same symbol.
     87 *
     88 * The name is extended in the allocator of the record in the unresolved data
     89 * block. The 10 is a minimum that is added to by joining more than one record.
     90 */
     91typedef struct rtems_rtl_unresolv_symbol
    8492{
    8593  uint16_t   refs;     /**< The number of references to this name. */
     94  uint16_t   flags;    /**< Flags to manage the symbol. */
    8695  uint16_t   length;   /**< The length of this name. */
    87   const char name[12]; /**< The symbol name. */
    88 } rtems_rtl_unresolv_name;
     96  const char name[10]; /**< The symbol name. */
     97} rtems_rtl_unresolv_symbol;
    8998
    9099/**
     
    109118  union
    110119  {
    111     rtems_rtl_unresolv_name  name;   /**< The name, or */
    112     rtems_rtl_unresolv_reloc reloc;  /**< the relocation record. */
     120    rtems_rtl_unresolv_symbol name;   /**< The symnbol, or */
     121    rtems_rtl_unresolv_reloc  reloc;  /**< the relocation record. */
    113122  } rec;
    114123} rtems_rtl_unresolv_rec;
     
    167176 * Iterate over the table of unresolved entries.
    168177 */
    169 bool rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator iterator,
    170                                     void*                         data);
     178bool rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_iterator iterator,
     179                                   void*                         data);
    171180
    172181/**
     
    207216
    208217/**
     218 * Set all symbols to be archive searchable. This is done when the available
     219 * archives have been refreshed and there are new archives to search for.
     220 */
     221void rtems_rtl_unresolved_set_archive_search (void);
     222
     223/**
    209224 * Dump the RTL unresolved data.
    210225 */
  • cpukit/include/rtems/rtl/rtl.h

    rb08278e r89c59be  
    2525
    2626#include <rtems/rtl/rtl-allocator.h>
     27#include <rtems/rtl/rtl-archive.h>
    2728#include <rtems/rtl/rtl-fwd.h>
    2829#include <rtems/rtl/rtl-obj.h>
     
    106107  rtems_rtl_alloc_data  allocator;      /**< The allocator data. */
    107108  rtems_chain_control   objects;        /**< List if loaded object files. */
     109  rtems_chain_control   pending;        /**< Listof object files needing work. */
    108110  const char*           paths;          /**< Search paths for archives. */
    109111  rtems_rtl_symbols     globals;        /**< Global symbol table. */
     112  rtems_rtl_archives    archives;       /**< Archive search and loader. */
    110113  rtems_rtl_unresolved  unresolved;     /**< Unresolved symbols. */
    111114  rtems_rtl_obj*        base;           /**< Base object file. */
     
    127130
    128131/**
    129  * Get the RTL global symbol table with out locking. This call assmes the RTL
     132 * Get the RTL global symbol table with out locking. This call assumes
     133 * the RTL is locked.
     134 *
     135 * @return rtems_rtl_symbols* The RTL global symbols after being locked.
     136 * @retval NULL The RTL data is not initialised.
     137 */
     138rtems_rtl_symbols* rtems_rtl_global_symbols (void);
     139
     140/**
     141 * Get the RTL objects table with out locking. This call assumes the RTL
    130142 * is locked.
    131143 *
    132  * @return rtems_rtl_symbols* The RTL global symbols after being locked.
    133  * @retval NULL The RTL data is not initialised.
    134  */
    135 rtems_rtl_symbols* rtems_rtl_global_symbols (void);
    136 
    137 /**
    138  * Get the RTL resolved table with out locking. This call assmes the RTL
     144 * @return rtems_chain_control* The RTL objects chain.
     145 * @retval NULL The RTL data is not initialised.
     146 */
     147rtems_chain_control* rtems_rtl_objects_unprotected (void);
     148
     149/**
     150 * Get the RTL pending with out locking. This call assumes the RTL is locked.
     151 *
     152 * @return rtems_chain_control* The RTL pending list control.
     153 * @retval NULL The RTL data is not initialised.
     154 */
     155rtems_chain_control* rtems_rtl_pending_unprotected (void);
     156
     157/**
     158 * Get the RTL unresolved table with out locking. This call assumes the RTL
    139159 * is locked.
    140160 *
     
    143163 */
    144164rtems_rtl_unresolved* rtems_rtl_unresolved_unprotected (void);
     165
     166/**
     167 * Get the RTL archives with out locking. This call assumes the RTL is locked.
     168 *
     169 * @return rtems_rtl_archives* The RTL acrhives.
     170 * @retval NULL The RTL data is not initialised.
     171 */
     172rtems_rtl_archives* rtems_rtl_archives_unprotected (void);
    145173
    146174/**
     
    277305
    278306/**
    279  * Run any constructor functions the object file may contain. This call
    280  * assumes the linker is unlocked.
    281  *
    282  * @param obj The object file.
    283  */
    284 void rtems_rtl_run_ctors (rtems_rtl_obj* obj);
     307 * Load an object file.  This is the user accessable interface to unloading an
     308 * object file. See @rtems_rtl_load_object.
     309 *
     310 * @param name The name of the object file.
     311 * @param mode The mode of the load as defined by the dlopen call.
     312 * @return rtl_obj* The object file descriptor. NULL is returned if the load fails.
     313 */
     314rtems_rtl_obj* rtems_rtl_load (const char* name, int mode);
     315
     316/**
     317 * Unload an object file. This is the user accessable interface to unloading an
     318 * object file. See @rtems_rtl_unload_object.
     319 *
     320 * Assumes the RTL has been locked.
     321 *
     322 * @param obj The object file descriptor.
     323 * @retval true The object file has been unloaded.
     324 * @retval false The object file could not be unloaded.
     325 */
     326bool rtems_rtl_unload (rtems_rtl_obj* obj);
    285327
    286328/**
  • cpukit/libdl/dlfcn.c

    rb08278e r89c59be  
    5353
    5454  if (name)
    55     obj = rtems_rtl_load_object (name, mode);
     55    obj = rtems_rtl_load (name, mode);
    5656  else
    5757    obj = rtems_rtl_baseimage ();
     
    8484  _rtld_debug_state ();
    8585
    86   r = rtems_rtl_unload_object (obj) ? 0 : -1;
     86  r = rtems_rtl_unload (obj) ? 0 : -1;
    8787
    8888  _rtld_debug.r_state = RT_CONSISTENT;
  • cpukit/libdl/rtl-elf.c

    rb08278e r89c59be  
    249249
    250250    sobj = rtems_rtl_find_obj_with_symbol (symbol);
     251
     252    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
     253      printf ("rtl: depend: %s -> %s:%s\n",
     254              obj->oname,
     255              sobj == NULL ? "not-found" : sobj->oname,
     256              symname);
     257
    251258    if (sobj != NULL)
    252259    {
     
    472479
    473480  sobj = rtems_rtl_find_obj_with_symbol (sym);
     481
     482  if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
     483    printf ("rtl: depend: %s -> %s:%s\n",
     484            reloc->obj->oname,
     485            sobj == NULL ? "not-found" : sobj->oname,
     486            sym->name);
     487
    474488  if (sobj != NULL)
    475489  {
     
    12751289    return false;
    12761290
    1277   rtems_rtl_obj_synchronize_cache (obj);
    1278 
    12791291  rtems_rtl_symbol_obj_erase_local (obj);
    12801292
  • cpukit/libdl/rtl-obj.c

    rb08278e r89c59be  
    107107rtems_rtl_obj_free (rtems_rtl_obj* obj)
    108108{
    109   if (obj->users || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
     109  if (obj->users > 0 || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
    110110  {
    111111    rtems_rtl_set_error (EINVAL, "cannot free obj still in use");
     
    120120  rtems_rtl_symbol_obj_erase (obj);
    121121  rtems_rtl_obj_free_names (obj);
    122   if (obj->sec_num)
     122  if (obj->sec_num != NULL)
    123123    free (obj->sec_num);
    124   if (obj->linkmap)
     124  if (obj->linkmap != NULL)
    125125    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->linkmap);
    126126  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
     
    128128}
    129129
     130typedef struct rtems_rtl_obj_unresolved_data
     131{
     132  bool has_unresolved;
     133} rtems_rtl_obj_unresolved_data;
     134
     135static bool
     136rtems_rtl_obj_unresolved_dependent (rtems_rtl_obj* obj,
     137                                    rtems_rtl_obj* dependent,
     138                                    void*          data)
     139{
     140  rtems_rtl_obj_unresolved_data* ud;
     141  ud = (rtems_rtl_obj_unresolved_data*) data;
     142  if ((dependent->flags & RTEMS_RTL_OBJ_DEP_VISITED) == 0)
     143  {
     144    dependent->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
     145    if ((dependent->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0)
     146      ud->has_unresolved = true;
     147    else
     148    {
     149      rtems_rtl_obj_iterate_dependents (dependent,
     150                                        rtems_rtl_obj_unresolved_dependent,
     151                                        ud);
     152    }
     153    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
     154      printf ("rtl: obj: unresolved: dep: %s is %s\n",
     155              dependent->oname, ud->has_unresolved ? "unresolved" : "resolved");
     156  }
     157  return ud->has_unresolved;
     158}
     159
    130160bool
    131161rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
    132162{
    133   return (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0 ? true : false;
     163  rtems_rtl_obj_unresolved_data ud = {
     164    .has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0
     165  };
     166  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
     167    printf ("rtl: obj: unresolved: dep: %s is %s\n",
     168            obj->oname, ud.has_unresolved ? "unresolved" : "resolved");
     169  if (!ud.has_unresolved)
     170  {
     171    rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
     172    obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
     173    rtems_rtl_obj_iterate_dependents (obj,
     174                                      rtems_rtl_obj_unresolved_dependent,
     175                                      &ud);
     176    rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
     177  }
     178  return ud.has_unresolved;
    134179}
    135180
     
    149194   * is an object file. If an archive check the name for a '@' to see if the
    150195   * archive contains an offset.
     196   *
     197   * Note, if an archive the object file oofset may be know but the
     198   *       object file is not. Leave the object name as a NULL.
    151199   */
    152200  end = name + strlen (name);
     
    156204
    157205  loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, colon - name + 1, true);
    158   if (!oname)
     206  if (!loname)
    159207  {
    160208    rtems_rtl_set_error (ENOMEM, "no memory for object file name");
     
    218266{
    219267  return rtems_rtl_parse_name (name, &(obj->aname), &(obj->oname), &(obj->ooffset));
    220 }
    221 
    222 static bool
    223 rtems_rtl_seek_read (int fd, off_t off, size_t len, uint8_t* buffer)
    224 {
    225   if (lseek (fd, off, SEEK_SET) < 0)
    226     return false;
    227   if (read (fd, buffer, len) != len)
    228     return false;
    229   return true;
    230 }
    231 
    232 /**
    233  * Scan the decimal number returning the value found.
    234  */
    235 static uint64_t
    236 rtems_rtl_scan_decimal (const uint8_t* string, size_t len)
    237 {
    238   uint64_t value = 0;
    239 
    240   while (len && (*string != ' '))
    241   {
    242     value *= 10;
    243     value += *string - '0';
    244     ++string;
    245     --len;
    246   }
    247 
    248   return value;
    249268}
    250269
     
    338357  }
    339358  return true;
    340 }
    341 
    342 bool
    343 rtems_rtl_match_name (rtems_rtl_obj* obj, const char* name)
    344 {
    345   const char* n1 = obj->oname;
    346   while ((*n1 != '\0') && (*n1 != '\n') && (*n1 != '/') &&
    347          (*name != '\0') && (*name != '/') && (*n1 == *name))
    348   {
    349     ++n1;
    350     ++name;
    351   }
    352   if (((*n1 == '\0') || (*n1 == '\n') || (*n1 == '/')) &&
    353       ((*name == '\0') || (*name == '/')))
    354     return true;
    355   return false;
    356359}
    357360
     
    597600  rtems_rtl_obj**   free_slot;
    598601  rtems_chain_node* node;
     602
    599603  if (obj == dependent || dependent == rtems_rtl_baseimage ())
    600604    return false;
     605
     606  if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
     607    printf ("rtl: depend: add: %s -> %s\n", obj->oname, dependent->oname);
     608
    601609  free_slot = NULL;
     610
    602611  node = rtems_chain_first (&obj->dependents);
    603612  while (!rtems_chain_is_tail (&obj->dependents, node))
     
    614623    node = rtems_chain_next (node);
    615624  }
     625
    616626  if (free_slot == NULL)
    617627  {
     
    630640    }
    631641  }
     642
    632643  if (free_slot != NULL)
    633644    *free_slot = dependent;
     645
    634646  return free_slot != NULL;
     647}
     648
     649
     650bool
     651rtems_rtl_obj_remove_dependencies (rtems_rtl_obj* obj)
     652{
     653  /*
     654   * If there are no references unload the object.
     655   */
     656  if (obj->refs == 0)
     657  {
     658    /*
     659     * Remove the refences from the object files this file depend on. The
     660     * unload happens once the list of objects to be unloaded has been made and
     661     * the destructors have been called for all those modules.
     662     */
     663    rtems_chain_node* node = rtems_chain_first (&obj->dependents);
     664    while (!rtems_chain_is_tail (&obj->dependents, node))
     665    {
     666      rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
     667      size_t                 d;
     668      for (d = 0; d < depends->dependents; ++d)
     669      {
     670        if (depends->depends[d] != NULL)
     671        {
     672          rtems_rtl_obj_dec_reference (depends->depends[d]);
     673          depends->depends[d] = NULL;
     674        }
     675      }
     676      node = rtems_chain_next (node);
     677    }
     678    return true;
     679  }
     680  return false;
    635681}
    636682
     
    10661112}
    10671113
     1114static bool
     1115rtems_rtl_obj_cdtors_to_run (rtems_rtl_obj* obj, uint32_t mask)
     1116{
     1117  rtems_chain_node* node = rtems_chain_first (&obj->sections);
     1118  while (!rtems_chain_is_tail (&obj->sections, node))
     1119  {
     1120    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
     1121    if ((sect->flags & mask) == mask)
     1122      return true;
     1123    node = rtems_chain_next (node);
     1124  }
     1125  return false;
     1126}
     1127
     1128bool
     1129rtems_rtl_obj_ctors_to_run (rtems_rtl_obj* obj)
     1130{
     1131  return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_CTOR);
     1132}
     1133
    10681134void
    10691135rtems_rtl_obj_run_ctors (rtems_rtl_obj* obj)
    10701136{
    1071   return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR);
     1137  rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR);
     1138}
     1139
     1140bool
     1141rtems_rtl_obj_dtors_to_run (rtems_rtl_obj* obj)
     1142{
     1143  return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_DTOR);
    10721144}
    10731145
     
    10751147rtems_rtl_obj_run_dtors (rtems_rtl_obj* obj)
    10761148{
    1077   return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR);
    1078 }
    1079 
    1080 /**
    1081  * Find a module in an archive returning the offset in the archive in the
    1082  * object descriptor.
    1083  */
    1084 static bool
    1085 rtems_rtl_obj_archive_find (rtems_rtl_obj* obj, int fd)
    1086 {
    1087 #define RTEMS_RTL_AR_IDENT      "!<arch>\n"
    1088 #define RTEMS_RTL_AR_IDENT_SIZE (sizeof (RTEMS_RTL_AR_IDENT) - 1)
    1089 #define RTEMS_RTL_AR_FHDR_BASE  RTEMS_RTL_AR_IDENT_SIZE
    1090 #define RTEMS_RTL_AR_FNAME      (0)
    1091 #define RTEMS_RTL_AR_FNAME_SIZE (16)
    1092 #define RTEMS_RTL_AR_SIZE       (48)
    1093 #define RTEMS_RTL_AR_SIZE_SIZE  (10)
    1094 #define RTEMS_RTL_AR_MAGIC      (58)
    1095 #define RTEMS_RTL_AR_MAGIC_SIZE (2)
    1096 #define RTEMS_RTL_AR_FHDR_SIZE  (60)
    1097 
    1098   size_t  fsize = obj->fsize;
    1099   off_t   extended_file_names;
    1100   uint8_t header[RTEMS_RTL_AR_FHDR_SIZE];
    1101   bool    scanning;
    1102 
    1103   if (read (fd, &header[0], RTEMS_RTL_AR_IDENT_SIZE) !=  RTEMS_RTL_AR_IDENT_SIZE)
    1104   {
    1105     rtems_rtl_set_error (errno, "reading archive identifer");
    1106     return false;
    1107   }
    1108 
    1109   if (memcmp (header, RTEMS_RTL_AR_IDENT, RTEMS_RTL_AR_IDENT_SIZE) != 0)
    1110   {
    1111     rtems_rtl_set_error (EINVAL, "invalid archive identifer");
    1112     return false;
    1113   }
    1114 
    1115   /*
    1116    * Seek to the current offset in the archive and if we have a valid archive
    1117    * file header present check the file name for a match with the oname field
    1118    * of the object descriptor. If the archive header is not valid and it is the
    1119    * first pass reset the offset and start the search again in case the offset
    1120    * provided is not valid any more.
    1121    *
    1122    * The archive can have a symbol table at the start. Ignore it. A symbol
    1123    * table has the file name '/'.
    1124    *
    1125    * The archive can also have the GNU extended file name table. This
    1126    * complicates the processing. If the object's file name starts with '/' the
    1127    * remainder of the file name is an offset into the extended file name
    1128    * table. To find the extended file name table we need to scan from start of
    1129    * the archive for a file name of '//'. Once found we remeber the table's
    1130    * start and can direct seek to file name location. In other words the scan
    1131    * only happens once.
    1132    *
    1133    * If the name had the offset encoded we go straight to that location.
    1134    */
    1135 
    1136   if (obj->ooffset != 0)
    1137     scanning = false;
    1138   else
    1139   {
    1140     scanning = true;
    1141     obj->ooffset = RTEMS_RTL_AR_FHDR_BASE;
    1142   }
    1143 
    1144   extended_file_names = 0;
    1145 
    1146   while (obj->ooffset < fsize)
    1147   {
    1148     /*
    1149      * Clean up any existing data.
    1150      */
    1151     memset (header, 0, sizeof (header));
    1152 
    1153     if (!rtems_rtl_seek_read (fd, obj->ooffset, RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
    1154     {
    1155       rtems_rtl_set_error (errno, "seek/read archive file header");
    1156       obj->ooffset = 0;
    1157       obj->fsize = 0;
    1158       return false;
    1159     }
    1160 
    1161     if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
    1162         (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
    1163     {
    1164       if (scanning)
    1165       {
    1166         rtems_rtl_set_error (EINVAL, "invalid archive file header");
    1167         obj->ooffset = 0;
    1168         obj->fsize = 0;
    1169         return false;
    1170       }
    1171 
    1172       scanning = true;
    1173       obj->ooffset = RTEMS_RTL_AR_FHDR_BASE;
    1174       continue;
    1175     }
    1176 
    1177     /*
    1178      * The archive header is always aligned to an even address.
    1179      */
    1180     obj->fsize = (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
    1181                                           RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
    1182 
    1183     /*
    1184      * Check for the GNU extensions.
    1185      */
    1186     if (header[0] == '/')
    1187     {
    1188       off_t extended_off;
    1189 
    1190       switch (header[1])
    1191       {
    1192         case ' ':
    1193           /*
    1194            * Symbols table. Ignore the table.
    1195            */
    1196           break;
    1197         case '/':
    1198           /*
    1199            * Extended file names table. Remember.
    1200            */
    1201           extended_file_names = obj->ooffset + RTEMS_RTL_AR_FHDR_SIZE;
    1202           break;
    1203         case '0':
    1204         case '1':
    1205         case '2':
    1206         case '3':
    1207         case '4':
    1208         case '5':
    1209         case '6':
    1210         case '7':
    1211         case '8':
    1212         case '9':
    1213           /*
    1214            * Offset into the extended file name table. If we do not have the
    1215            * offset to the extended file name table find it.
    1216            */
    1217           extended_off =
    1218             rtems_rtl_scan_decimal (&header[1], RTEMS_RTL_AR_FNAME_SIZE);
    1219 
    1220           if (extended_file_names == 0)
    1221           {
    1222             off_t off = obj->ooffset;
    1223             while (extended_file_names == 0)
    1224             {
    1225               off_t esize =
    1226                 (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE],
    1227                                          RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1;
    1228               off += esize + RTEMS_RTL_AR_FHDR_SIZE;
    1229 
    1230               if (!rtems_rtl_seek_read (fd, off,
    1231                                         RTEMS_RTL_AR_FHDR_SIZE, &header[0]))
    1232               {
    1233                 rtems_rtl_set_error (errno,
    1234                                      "seeking/reading archive ext file name header");
    1235                 obj->ooffset = 0;
    1236                 obj->fsize = 0;
    1237                 return false;
    1238               }
    1239 
    1240               if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) ||
    1241                   (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a))
    1242               {
    1243                 rtems_rtl_set_error (errno, "invalid archive file header");
    1244                 obj->ooffset = 0;
    1245                 obj->fsize = 0;
    1246                 return false;
    1247               }
    1248 
    1249               if ((header[0] == '/') && (header[1] == '/'))
    1250               {
    1251                 extended_file_names = off + RTEMS_RTL_AR_FHDR_SIZE;
    1252                 break;
    1253               }
    1254             }
    1255           }
    1256 
    1257           if (extended_file_names)
    1258           {
    1259             /*
    1260              * We know the offset in the archive to the extended file. Read the
    1261              * name from the table and compare with the name we are after.
    1262              */
    1263 #define RTEMS_RTL_MAX_FILE_SIZE (256)
    1264             char name[RTEMS_RTL_MAX_FILE_SIZE];
    1265 
    1266             if (!rtems_rtl_seek_read (fd, extended_file_names + extended_off,
    1267                                       RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &name[0]))
    1268             {
    1269               rtems_rtl_set_error (errno,
    1270                                    "invalid archive ext file seek/read");
    1271               obj->ooffset = 0;
    1272               obj->fsize = 0;
    1273               return false;
    1274             }
    1275 
    1276             if (rtems_rtl_match_name (obj, name))
    1277             {
    1278               obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE;
    1279               return true;
    1280             }
    1281           }
    1282           break;
    1283         default:
    1284           /*
    1285            * Ignore the file because we do not know what it it.
    1286            */
    1287           break;
    1288       }
    1289     }
    1290     else
    1291     {
    1292       if (rtems_rtl_match_name (obj, (const char*) &header[RTEMS_RTL_AR_FNAME]))
    1293       {
    1294         obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE;
    1295         return true;
    1296       }
    1297     }
    1298 
    1299     obj->ooffset += obj->fsize + RTEMS_RTL_AR_FHDR_SIZE;
    1300   }
    1301 
    1302   rtems_rtl_set_error (ENOENT, "object file not found");
    1303   obj->ooffset = 0;
    1304   obj->fsize = 0;
    1305   return false;
     1149  rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR);
    13061150}
    13071151
     
    13241168}
    13251169
    1326 static bool
    1327 rtems_rtl_obj_file_unload (rtems_rtl_obj* obj)
    1328 {
    1329   if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
    1330   {
    1331     rtems_chain_node* node;
    1332 
    1333     if (!loaders[obj->format].unload (obj))
    1334       return false;
    1335 
    1336     node = rtems_chain_first (&obj->dependents);
    1337     while (!rtems_chain_is_tail (&obj->dependents, node))
    1338     {
    1339       rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
    1340       size_t                 d;
    1341       for (d = 0; d < depends->dependents; ++d)
    1342       {
    1343         if (depends->depends[d] != NULL)
    1344           rtems_rtl_obj_dec_reference (depends->depends[d]);
    1345       }
    1346       node = rtems_chain_next (node);
    1347     }
    1348   }
    1349 
    1350   return false;
     1170static void
     1171rtems_rtl_obj_set_error (int num, const char* text)
     1172{
     1173  rtems_rtl_set_error (num, text);
     1174}
     1175
     1176size_t
     1177rtems_rtl_obj_get_reference (rtems_rtl_obj* obj)
     1178{
     1179  return obj->refs;
    13511180}
    13521181
     
    13651194
    13661195bool
     1196rtems_rtl_obj_orphaned (rtems_rtl_obj* obj)
     1197{
     1198  return ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == 0 &&
     1199          obj->users == 0 &&
     1200          rtems_rtl_obj_get_reference (obj) == 0);
     1201}
     1202
     1203bool
    13671204rtems_rtl_obj_load (rtems_rtl_obj* obj)
    13681205{
     
    13781215  if (fd < 0)
    13791216  {
    1380     rtems_rtl_set_error (ENOMEM, "opening for object file");
     1217    rtems_rtl_set_error (errno, "opening for object file");
    13811218    return false;
    13821219  }
     
    13881225  if (rtems_rtl_obj_aname_valid (obj))
    13891226  {
    1390     if (!rtems_rtl_obj_archive_find (obj, fd))
     1227    off_t enames = 0;
     1228    if (!rtems_rtl_obj_archive_find_obj (fd,
     1229                                         obj->fsize,
     1230                                         &obj->oname,
     1231                                         &obj->ooffset,
     1232                                         &obj->fsize,
     1233                                         &enames,
     1234                                         rtems_rtl_obj_set_error))
    13911235    {
    13921236      close (fd);
     
    14041248  }
    14051249
    1406   if (!_rtld_linkmap_add (obj)) /* For GDB */
     1250   /*
     1251    * For GDB
     1252    */
     1253  if (!_rtld_linkmap_add (obj))
    14071254  {
    14081255    close (fd);
     
    14181265rtems_rtl_obj_unload (rtems_rtl_obj* obj)
    14191266{
    1420   _rtld_linkmap_delete(obj);
    1421   rtems_rtl_obj_file_unload (obj);
    1422   return true;
    1423 }
     1267  bool ok = false;
     1268  if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
     1269  {
     1270    _rtld_linkmap_delete(obj);
     1271    ok = loaders[obj->format].unload (obj);
     1272  }
     1273  else
     1274  {
     1275    rtems_rtl_set_error (EINVAL, "invalid object loader format");
     1276  }
     1277  return ok;
     1278}
  • cpukit/libdl/rtl-shell.c

    rb08278e r89c59be  
    2727
    2828#include <rtems/rtl/rtl.h>
     29#include <rtems/rtl/rtl-shell.h>
     30#include <rtems/rtl/rtl-trace.h>
    2931#include "rtl-chain-iterator.h"
    30 #include "rtl-shell.h"
    31 #include <rtems/rtl/rtl-trace.h>
    3232
    3333/**
     
    120120  rtems_rtl_data* rtl;          /**< The RTL data. */
    121121  int             indent;       /**< Spaces to indent. */
     122  bool            sep1;         /**< Print a separator. */
    122123  bool            oname;        /**< Print object names. */
    123124  bool            names;        /**< Print details of all names. */
     
    207208      return true;
    208209
     210  if (print->sep1)
     211  {
     212    printf ("%-*c--------------\n", print->indent, ' ');
     213  }
    209214  if (print->oname)
    210215  {
     
    280285{
    281286  rtems_rtl_obj_print* print = (rtems_rtl_obj_print*) data;
    282   if (rec->type == rtems_rtl_unresolved_name)
     287  if (rec->type == rtems_rtl_unresolved_symbol)
    283288    printf ("%-*c%s\n", print->indent + 2, ' ', rec->rec.name.name);
    284289  return false;
     
    302307  print.rtl = rtl;
    303308  print.indent = 1;
     309  print.sep1 = true;
    304310  print.oname = true;
    305311  print.names = true;
     
    320326  print.rtl = rtl;
    321327  print.indent = 1;
     328  print.sep1 = true;
    322329  print.oname = true;
    323330  print.names = false;
     
    330337                           &print);
    331338  printf ("Unresolved:\n");
    332   rtems_rtl_unresolved_interate (rtems_rtl_unresolved_printer, &print);
     339  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_printer, &print);
    333340  return 0;
    334341}
  • cpukit/libdl/rtl-string.h

    rb08278e r89c59be  
    1717#define _RTEMS_RTL_STRING_H_
    1818
    19 #include <rtems/rtl/rtl-indirect-ptr.h>
    20 
    2119#ifdef __cplusplus
    2220extern "C" {
  • cpukit/libdl/rtl-trace.c

    rb08278e r89c59be  
    7070    "allocator",
    7171    "unresolved",
    72     "cache"
     72    "cache",
     73    "archives",
     74    "dependency"
    7375  };
    7476
  • cpukit/libdl/rtl-unresolved.c

    rb08278e r89c59be  
    5252
    5353static size_t
    54 rtems_rtl_unresolved_name_recs (const char* name)
    55 {
    56   size_t length = strlen (name);
    57   return ((length + sizeof(rtems_rtl_unresolv_name) - 1) /
    58           sizeof(rtems_rtl_unresolv_name));
     54rtems_rtl_unresolved_symbol_rec_count (size_t length)
     55{
     56  return ((length + sizeof(rtems_rtl_unresolv_symbol) - 1) /
     57          sizeof(rtems_rtl_unresolv_symbol));
     58}
     59
     60
     61static size_t
     62rtems_rtl_unresolved_symbol_recs (const char* name)
     63{
     64  return rtems_rtl_unresolved_symbol_rec_count (strlen (name));
    5965}
    6066
     
    8490      break;
    8591
    86     case rtems_rtl_unresolved_name:
     92    case rtems_rtl_unresolved_symbol:
    8793      /*
    8894       * Determine how many records the name occupies. Round up.
    8995       */
    90       rec += ((rec->rec.name.length + sizeof(rtems_rtl_unresolv_name) - 1) /
    91               sizeof(rtems_rtl_unresolv_name));
     96      rec += rtems_rtl_unresolved_symbol_rec_count (rec->rec.name.length);
    9297      break;
    9398
     
    133138    while (!rtems_rtl_unresolved_rec_is_last (block, rec))
    134139    {
    135       if (rec->type == rtems_rtl_unresolved_name)
     140      if (rec->type == rtems_rtl_unresolved_symbol)
    136141      {
    137142        if ((rec->rec.name.length == length)
     
    169174  if (rec->type == rtems_rtl_unresolved_reloc)
    170175  {
     176    rtems_chain_control*             pending;
    171177    rtems_rtl_unresolved_reloc_data* rd;
     178
    172179    rd = (rtems_rtl_unresolved_reloc_data*) data;
    173180
     
    180187
    181188      /*
    182        * Set the object pointer to NULL to indicate the record is not used
     189       * If all unresolved externals are resolved add the obj module
     190       * to the pending queue. This will flush the object module's
     191       * data from the cache and call it's constructors.
     192       */
     193      if (rec->rec.reloc.obj->unresolved == 0)
     194      {
     195        pending = rtems_rtl_pending_unprotected ();
     196        rtems_chain_append (pending, &rec->rec.reloc.obj->link);
     197      }
     198
     199      /*
     200       * Check Set the object pointer to NULL to indicate the record is not used
    183201       * anymore. Update the reference count of the name. The sweep after
    184202       * relocating will remove the reloc records with obj set to NULL and
     
    197215                                       void*                   data)
    198216{
    199   if (rec->type == rtems_rtl_unresolved_name)
     217  if (rec->type == rtems_rtl_unresolved_symbol)
    200218  {
    201219    rtems_rtl_unresolved_reloc_data* rd;
     
    216234      rd->name_rec = rec;
    217235
    218       rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_reloc, rd);
     236      rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_resolve_reloc, rd);
    219237
    220238      rd->name_rec = NULL;
     
    223241  }
    224242
     243  return false;
     244}
     245
     246/**
     247 * Struct to pass archive relocation data in the iterator.
     248 */
     249typedef struct rtems_rtl_unresolved_archive_reloc_data
     250{
     251  uint16_t            name;     /**< Name index. */
     252  bool                loaded;   /**< Object file loaded. */
     253  rtems_rtl_archives* archives; /**< The archives to search. */
     254} rtems_rtl_unresolved_archive_reloc_data;
     255
     256static bool
     257rtems_rtl_unresolved_archive_iterator (rtems_rtl_unresolv_rec* rec,
     258                                       void*                   data)
     259{
     260  if (rec->type == rtems_rtl_unresolved_symbol)
     261  {
     262    rtems_rtl_unresolved_archive_reloc_data* ard;
     263    ard = (rtems_rtl_unresolved_archive_reloc_data*) data;
     264
     265    ++ard->name;
     266
     267    if ((rec->rec.name.flags & RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE) != 0)
     268    {
     269      rtems_rtl_archive_search load;
     270
     271      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
     272        printf ("rtl: unresolv: archive lookup: %d: %s\n",
     273                ard->name, rec->rec.name.name);
     274
     275      load = rtems_rtl_archive_obj_load (ard->archives,
     276                                         rec->rec.name.name, true);
     277      if (load == rtems_rtl_archive_search_loaded)
     278      {
     279        ard->loaded = true;
     280        return true;
     281      }
     282    }
     283  }
     284
     285  return false;
     286}
     287
     288static bool
     289rtems_rtl_unresolved_archive_search_iterator (rtems_rtl_unresolv_rec* rec,
     290                                              void*                   data)
     291{
     292  if (rec->type == rtems_rtl_unresolved_symbol)
     293    rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
    225294  return false;
    226295}
     
    249318  {
    250319    /*
    251      * Iterate over the blocks removing any empty strings. If a string is removed
    252      * update the indexes of all strings above this level.
     320     * Iterate over the blocks removing any empty strings. If a string is
     321     * removed update the indexes of all strings above this level.
    253322     */
    254323    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
     
    262331      {
    263332        bool next_rec = true;
    264         if (rec->type == rtems_rtl_unresolved_name)
     333        if (rec->type == rtems_rtl_unresolved_symbol)
    265334        {
    266335          ++index;
     
    306375             * Compact the block removing the name record.
    307376             */
    308             name_recs = rtems_rtl_unresolved_name_recs (rec->rec.name.name);
     377            name_recs = rtems_rtl_unresolved_symbol_recs (rec->rec.name.name);
    309378            rtems_rtl_unresolved_clean_block (block, rec, name_recs,
    310379                                              unresolved->block_recs);
     
    361430  {
    362431    rtems_chain_node* next = rtems_chain_next (node);
    363     free (node);
     432    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, node);
    364433    node = next;
    365434  }
     
    367436
    368437bool
    369 rtems_rtl_unresolved_interate (rtems_rtl_unresolved_iterator iterator,
    370                                void*                         data)
     438rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_iterator iterator,
     439                              void*                         data)
    371440{
    372441  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
     
    439508
    440509  name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
    441   name_recs = rtems_rtl_unresolved_name_recs (name);
     510  name_recs = rtems_rtl_unresolved_symbol_recs (name);
    442511
    443512  /*
     
    460529
    461530    rec = rtems_rtl_unresolved_rec_first_free (name_block);
    462     rec->type = rtems_rtl_unresolved_name;
     531    rec->type = rtems_rtl_unresolved_symbol;
    463532    rec->rec.name.refs = 1;
     533    rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
    464534    rec->rec.name.length = strlen (name) + 1;
    465535    memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
     
    497567rtems_rtl_unresolved_resolve (void)
    498568{
    499   rtems_rtl_unresolved_reloc_data rd;
     569  bool resolving = true;
     570
    500571  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
    501572    printf ("rtl: unresolv: global resolve\n");
    502   rd.name = 0;
    503   rd.name_rec = NULL;
    504   rd.sym = NULL;
    505   rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_iterator, &rd);
    506   rtems_rtl_unresolved_compact ();
     573
     574  /*
     575   * The resolving process is two separate stages, The first stage is to
     576   * iterate over the unresolved symbols search the global symbol table. If a
     577   * symbol is found iterate over the unresolved relocation records for the
     578   * symbol fixing up the relocations. The second stage is to search the
     579   * archives for symbols we have not been search before and if a symbol if
     580   * found in an archve loaded the object file. Loading an object file stops
     581   * the search of the archives for symbols and stage one is performed
     582   * again. The process repeats until no more symbols are resolved.
     583   */
     584  while (resolving)
     585  {
     586    rtems_rtl_unresolved_reloc_data rd = {
     587      .name = 0,
     588      .name_rec = NULL,
     589      .sym = NULL
     590    };
     591    rtems_rtl_unresolved_archive_reloc_data ard = {
     592      .name = 0,
     593      .loaded = false,
     594      .archives = rtems_rtl_archives_unprotected ()
     595    };
     596
     597    rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_resolve_iterator, &rd);
     598    rtems_rtl_unresolved_compact ();
     599    rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_iterator, &ard);
     600
     601    resolving = ard.loaded;
     602  }
     603
    507604  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
    508605    rtems_rtl_unresolved_dump ();
     
    542639    printf (" %03zu: 0: empty\n", dd->rec);
    543640    break;
    544   case rtems_rtl_unresolved_name:
     641  case rtems_rtl_unresolved_symbol:
    545642    ++dd->names;
    546643    printf (" %3zu: 1:  name: %3d refs: %2d: %2d: %s\n",
     
    564661
    565662void
     663rtems_rtl_unresolved_set_archive_search (void)
     664{
     665  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
     666                                NULL);
     667}
     668
     669void
    566670rtems_rtl_unresolved_dump (void)
    567671{
    568672  rtems_rtl_unresolved_dump_data dd = { 0 };
    569673  printf ("RTL Unresolved data:\n");
    570   rtems_rtl_unresolved_interate (rtems_rtl_unresolved_dump_iterator, &dd);
    571 }
     674  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_dump_iterator, &dd);
     675}
  • cpukit/libdl/rtl.c

    rb08278e r89c59be  
    2828#include <rtems/rtl/rtl.h>
    2929#include <rtems/rtl/rtl-allocator.h>
     30#include <rtems/rtl/rtl-trace.h>
     31#include "rtl-chain-iterator.h"
    3032#include "rtl-error.h"
    3133#include "rtl-string.h"
    32 #include <rtems/rtl/rtl-trace.h>
    3334
    3435/**
     
    124125
    125126      /*
    126        * Initialise the objects list and create any required services.
     127       * Initialise the objects and pending list.
    127128       */
    128129      rtems_chain_initialize_empty (&rtl->objects);
    129 
     130      rtems_chain_initialize_empty (&rtl->pending);
     131
     132      /*
     133       * Open the global symbol table.
     134       */
    130135      if (!rtems_rtl_symbol_table_open (&rtl->globals,
    131136                                        RTEMS_RTL_SYMS_GLOBAL_BUCKETS))
     
    137142      }
    138143
     144      /*
     145       * Open the archives.
     146       */
     147      rtems_rtl_archives_open (&rtl->archives, "/etc/rtl-libs.conf");
     148
     149      /*
     150       * Open the unresolved table.
     151       */
    139152      if (!rtems_rtl_unresolved_table_open (&rtl->unresolved,
    140153                                            RTEMS_RTL_UNRESOLVED_BLOCK_SIZE))
     
    253266}
    254267
     268rtems_chain_control*
     269rtems_rtl_objects_unprotected (void)
     270{
     271  if (!rtl)
     272  {
     273    rtems_rtl_set_error (ENOENT, "no rtl");
     274    return NULL;
     275  }
     276  return &rtl->objects;
     277}
     278
     279rtems_chain_control*
     280rtems_rtl_pending_unprotected (void)
     281{
     282  if (!rtl)
     283  {
     284    rtems_rtl_set_error (ENOENT, "no rtl");
     285    return NULL;
     286  }
     287  return &rtl->pending;
     288}
     289
    255290rtems_rtl_unresolved*
    256291rtems_rtl_unresolved_unprotected (void)
     
    262297  }
    263298  return &rtl->unresolved;
     299}
     300
     301rtems_rtl_archives*
     302rtems_rtl_archives_unprotected (void)
     303{
     304  if (!rtl)
     305  {
     306    rtems_rtl_set_error (ENOENT, "no rtl");
     307    return NULL;
     308  }
     309  return &rtl->archives;
    264310}
    265311
     
    318364}
    319365
     366typedef struct rtems_rtl_obj_flags_data
     367{
     368  uint32_t clear;   /**< Flags to clear, do not invert. */
     369  uint32_t set;     /**< Flags to set, applied after clearing. */
     370} rtems_rtl_obj_flags_data;
     371
     372static bool
     373rtems_rtl_obj_flags_iterator (rtems_chain_node* node, void* data)
     374{
     375  rtems_rtl_obj* obj              = (rtems_rtl_obj*) node;
     376  rtems_rtl_obj_flags_data* flags = (rtems_rtl_obj_flags_data*) data;
     377  if (flags->clear != 0)
     378    obj->flags &= ~flags->clear;
     379  if (flags->set != 0)
     380    obj->flags |= flags->set;
     381  return true;
     382}
     383
    320384void
    321385rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set)
    322386{
    323   rtems_chain_node* node  = rtems_chain_first (&rtl->objects);
    324   while (!rtems_chain_is_tail (&rtl->objects, node))
    325   {
    326     rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
    327     if (clear != 0)
    328       obj->flags &= ~clear;
    329     if (set != 0)
    330       obj->flags |= set;
    331     node = rtems_chain_next (node);
    332   }
     387  rtems_rtl_obj_flags_data flags = {
     388    .clear = clear,
     389    .set   = set
     390  };
     391  rtems_rtl_chain_iterate (&rtl->objects,
     392                           rtems_rtl_obj_flags_iterator,
     393                           &flags);
    333394}
    334395
     
    391452         strcmp (obj->aname, aname) == 0 && strcmp (obj->oname, oname) == 0))
    392453    {
    393         found = obj;
    394         break;
     454      found = obj;
     455      break;
    395456    }
    396457    node = rtems_chain_next (node);
    397458  }
    398459
    399   if (!aname)
     460  if (aname != NULL)
    400461    rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) aname);
    401462
    402   if (!oname)
     463  if (oname != NULL)
    403464    rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) oname);
    404465
     
    413474  {
    414475    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
    415     if (sym >= obj->global_table &&
    416         sym < (obj->global_table + obj->global_syms))
     476    if (rtems_rtl_obj_has_symbol (obj, sym))
     477      return obj;
     478    node = rtems_chain_next (node);
     479  }
     480  node = rtems_chain_first (&rtl->pending);
     481  while (!rtems_chain_is_tail (&rtl->pending, node))
     482  {
     483    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
     484    if (rtems_rtl_obj_has_symbol (obj, sym))
    417485      return obj;
    418486    node = rtems_chain_next (node);
     
    456524    }
    457525
    458     rtems_chain_append (&rtl->objects, &obj->link);
     526    rtems_chain_append (&rtl->pending, &obj->link);
    459527
    460528    if (!rtems_rtl_obj_load (obj))
    461529    {
     530      rtems_chain_extract (&obj->link);
    462531      rtems_rtl_obj_free (obj);
    463532      rtems_rtl_obj_caches_flush ();
     
    466535
    467536    rtems_rtl_obj_caches_flush ();
    468 
    469     rtems_rtl_unresolved_resolve ();
    470537  }
    471538
     
    475542  ++obj->users;
    476543
     544  return obj;
     545}
     546
     547rtems_rtl_obj*
     548rtems_rtl_load (const char* name, int mode)
     549{
     550  rtems_rtl_obj* obj;
     551
    477552  /*
    478    * FIXME: Resolving existing unresolved symbols could add more constructors
    479    *        lists that need to be called. Make a list in the obj load layer and
    480    *        invoke the list here.
     553   * Refesh the archives.
    481554   */
     555  rtems_rtl_archives_refresh (&rtl->archives);
    482556
    483557  /*
    484    * Run any local constructors if this is the first user because the object
    485    * file will have just been loaded. Unlock the linker to avoid any dead locks
    486    * if the object file needs to load files or update the symbol table. We also
    487    * do not want a constructor to unload this object file.
     558   * Collect the loaded object files.
    488559   */
    489   if (obj->users == 1)
    490   {
    491     obj->flags |= RTEMS_RTL_OBJ_LOCKED;
    492     rtems_rtl_unlock ();
    493     rtems_rtl_obj_run_ctors (obj);
    494     rtems_rtl_lock ();
    495     obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
     560  rtems_chain_initialize_empty (&rtl->pending);
     561
     562  obj = rtems_rtl_load_object (name, mode);
     563  if (obj != NULL)
     564  {
     565    rtems_chain_node* node;
     566
     567    rtems_rtl_unresolved_resolve ();
     568
     569    /*
     570     * Iterator over the pending list of object files that have been loaded.
     571     */
     572    node = rtems_chain_first (&rtl->pending);
     573    while (!rtems_chain_is_tail (&rtl->pending, node))
     574    {
     575      rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
     576
     577      /*
     578       * Move to the next pending object file and place this object file on the
     579       * RTL's objects list.
     580       */
     581      node = rtems_chain_next (&obj->link);
     582      rtems_chain_extract (&obj->link);
     583      rtems_chain_append (&rtl->objects, &obj->link);
     584
     585      /*
     586       * Make sure the object file and cache is synchronized.
     587       */
     588      rtems_rtl_obj_synchronize_cache (obj);
     589
     590      /*
     591       * Run any local constructors if this is the first user because the
     592       * object file will have just been loaded. Unlock the linker to avoid any
     593       * dead locks if the object file needs to load files or update the symbol
     594       * table. We also do not want a constructor to unload this object file.
     595       */
     596      if (obj->users == 1)
     597      {
     598        obj->flags |= RTEMS_RTL_OBJ_LOCKED;
     599        rtems_rtl_unlock ();
     600        rtems_rtl_obj_run_ctors (obj);
     601        rtems_rtl_lock ();
     602        obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
     603      }
     604    }
    496605  }
    497606
     
    502611rtems_rtl_unload_object (rtems_rtl_obj* obj)
    503612{
    504   bool ok = true;
    505 
    506613  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
    507     printf ("rtl: unloading '%s'\n", rtems_rtl_obj_fname (obj));
     614    printf ("rtl: unload object '%s'\n", rtems_rtl_obj_fname (obj));
    508615
    509616  /*
     
    512619  if ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == RTEMS_RTL_OBJ_LOCKED)
    513620  {
    514     rtems_rtl_set_error (EINVAL, "cannot unload when locked");
     621    rtems_rtl_set_error (EINVAL, "object file is locked");
    515622    return false;
    516623  }
    517624
    518625  /*
    519    * Check the number of users in a safe manner. If this is the last user unload the
    520    * object file from memory.
     626   * Move the object file from the objects list to the pending list if unloaded.
     627   */
     628  if (rtems_rtl_obj_get_reference (obj) > 0)
     629  {
     630    rtems_rtl_set_error (EINVAL, "object file has references to it");
     631    return false;
     632  }
     633
     634  /*
     635   * Check the number of users in a safe manner. If this is the last user unload
     636   * the object file from memory.
    521637   */
    522638  if (obj->users > 0)
    523639    --obj->users;
    524640
    525   if (obj->users == 0)
    526   {
    527     if (obj->refs != 0)
     641  return true;
     642}
     643
     644bool
     645rtems_rtl_unload (rtems_rtl_obj* obj)
     646{
     647  bool ok = rtems_rtl_unload_object (obj);
     648  if (ok && obj->users == 0)
     649  {
     650    rtems_chain_control unloading;
     651    rtems_chain_node*   node;
     652
     653    /*
     654     * Remove the orphaned object files from the objects list. This makes the
     655     * list private and any changes in any desctructors will effect the run.
     656     */
     657    rtems_chain_initialize_empty (&unloading);
     658
     659    node = rtems_chain_first (&rtl->objects);
     660    while (!rtems_chain_is_tail (&rtl->objects, node))
    528661    {
    529       rtems_rtl_set_error (EBUSY, "object file referenced");
    530       return false;
     662      rtems_chain_node* next_node = rtems_chain_next (node);
     663      rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
     664      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
     665        printf ("rtl: unload object: %s: %s\n",
     666                rtems_rtl_obj_oname (obj),
     667                rtems_rtl_obj_orphaned (uobj) ? "orphaned" : "inuse");
     668      if (rtems_rtl_obj_orphaned (uobj))
     669      {
     670        rtems_rtl_obj_remove_dependencies (uobj);
     671        rtems_chain_extract (&uobj->link);
     672        rtems_chain_append (&unloading, &uobj->link);
     673        uobj->flags |= RTEMS_RTL_OBJ_LOCKED;
     674      }
     675      node = next_node;
    531676    }
    532     obj->flags |= RTEMS_RTL_OBJ_LOCKED;
     677
     678    /*
     679     * Call the desctructors unlocked. An RTL call will not deadlock.
     680     */
    533681    rtems_rtl_unlock ();
    534     rtems_rtl_obj_run_dtors (obj);
     682
     683    node = rtems_chain_first (&unloading);
     684    while (!rtems_chain_is_tail (&unloading, node))
     685    {
     686      rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
     687      rtems_rtl_obj_run_dtors (uobj);
     688      node = rtems_chain_next (node);
     689    }
     690
    535691    rtems_rtl_lock ();
    536     obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
    537 
    538     ok = rtems_rtl_obj_unload (obj);
    539 
    540     rtems_rtl_obj_free (obj);
    541     rtems_rtl_obj_caches_flush ();
    542   }
    543 
     692
     693    /*
     694     * Unload the object files.
     695     */
     696    node = rtems_chain_first (&unloading);
     697    while (!rtems_chain_is_tail (&unloading, node))
     698    {
     699      rtems_chain_node* next_node = rtems_chain_next (node);
     700      rtems_rtl_obj*    uobj = (rtems_rtl_obj*) node;
     701      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
     702        printf ("rtl: unloading '%s'\n", rtems_rtl_obj_oname (uobj));
     703      uobj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
     704      if (!rtems_rtl_obj_unload (uobj))
     705        ok = false;
     706      rtems_rtl_obj_free (uobj);
     707      rtems_rtl_obj_caches_flush ();
     708      node = next_node;
     709    }
     710  }
    544711  return ok;
    545 }
    546 
    547 void
    548 rtems_rtl_run_ctors (rtems_rtl_obj* obj)
    549 {
    550   rtems_rtl_obj_run_ctors (obj);
    551712}
    552713
Note: See TracChangeset for help on using the changeset viewer.