Changeset 03139d5b in rtems


Ignore:
Timestamp:
Nov 20, 2018, 3:56:11 AM (5 months ago)
Author:
Chris Johns <chrisj@…>
Branches:
master
Children:
9dfb9a98
Parents:
8e7c72a7
git-author:
Chris Johns <chrisj@…> (11/20/18 03:56:11)
git-committer:
Chris Johns <chrisj@…> (11/22/18 01:43:31)
Message:

libdl: Add object file dependencies to track references

Tracking references lets us manage when an object file can be
unloaded. If an object file has references to it, it cannot be
unloaded.

Modules that depend on each other cannot be unloaded.

Updates #3605

Files:
14 added
13 edited

Legend:

Unmodified
Added
Removed
  • cpukit/include/rtems/rtl/rtl-obj-fwd.h

    r8e7c72a7 r03139d5b  
    2828
    2929/**
     30 * The forward declaration of the obj depends structure.
     31 */
     32struct rtems_rtl_obj_depends;
     33typedef struct rtems_rtl_obj_depends rtems_rtl_obj_depends;
     34
     35/**
    3036 * The forward declaration of the obj structure.
    3137 */
  • cpukit/include/rtems/rtl/rtl-obj.h

    r8e7c72a7 r03139d5b  
    140140
    141141/**
     142 * Object file dependents. This is a list of tables of pointers to the object
     143 * modules the object file depends on. The table is a list of tables because
     144 * unresolved externals can exist when an object file is loaded and resolved
     145 * later when the dependent object file is loaded.
     146 */
     147struct rtems_rtl_obj_depends
     148{
     149  rtems_chain_node node;        /**< The node's link in the chain. */
     150  size_t           dependents;  /**< The number of dependent object pointers. */
     151  rtems_rtl_obj*   depends[];   /**< Dependtent objects. More follow. */
     152};
     153
     154/**
     155 * Dependency iterator.
     156 */
     157typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj,
     158                                                rtems_rtl_obj* dependent,
     159                                                void*          data);
     160
     161/**
    142162 * Object file descriptor flags.
    143163 */
    144 #define RTEMS_RTL_OBJ_LOCKED     (1 << 0) /**< Lock the object file so it cannot
    145                                            *   be unloaded. */
    146 #define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
    147                                            *   external symbols. */
     164#define RTEMS_RTL_OBJ_LOCKED       (1 << 0) /**< Lock the object file so it cannot
     165                                             *   be unloaded. */
     166#define RTEMS_RTL_OBJ_UNRESOLVED   (1 << 1) /**< The object file has unresolved
     167                                             *   external symbols. */
     168#define RTEMS_RTL_OBJ_BASE         (1 << 2) /**< The base image. */
     169#define RTEMS_RTL_OBJ_RELOC_TAG    (1 << 3) /**< Tag the object as visited when reloc
     170                                             *   parsing. */
    148171
    149172/**
     
    155178  rtems_chain_node    link;         /**< The node's link in the chain. */
    156179  uint32_t            flags;        /**< The status of the object file. */
    157   uint32_t            users;        /**< References to the object file. */
     180  size_t              users;        /**< Users of this object file, number of loads. */
     181  size_t              refs;         /**< References to the object file. */
    158182  int                 format;       /**< The format of the object file. */
    159183  const char*         fname;        /**< The file name for the object. */
     
    165189  off_t               ooffset;      /**< The object offset in the archive. */
    166190  size_t              fsize;        /**< Size of the object file. */
    167   rtems_chain_control sections;     /**< The sections of interest in the
    168                                      *   object file. */
     191  rtems_chain_control sections;     /**< The sections of interest in the object
     192                                     *   file. */
     193  rtems_chain_control dependents;   /**< The dependent object files. */
    169194  rtems_rtl_obj_sym*  local_table;  /**< Local symbol table. */
    170195  size_t              local_syms;   /**< Local symbol count. */
     
    173198  size_t              global_syms;  /**< Global symbol count. */
    174199  size_t              global_size;  /**< Global symbol memory usage. */
    175   uint32_t            unresolved;   /**< The number of unresolved relocations. */
     200  size_t              unresolved;   /**< The number of unresolved relocations. */
    176201  void*               text_base;    /**< The base address of the text section
    177202                                     *   in memory. */
     
    179204  void*               const_base;   /**< The base address of the const section
    180205                                     *   in memory. */
    181   void*               eh_base;      /**< The base address of the eh section
    182                                      *   in memory. */
     206  void*               eh_base;      /**< The base address of the eh section in
     207                                     *   memory. */
    183208  size_t              eh_size;      /**< The size of the eh section. */
    184209  void*               data_base;    /**< The base address of the data section
    185210                                     *   in memory. */
    186   void*               bss_base;     /**< The base address of the bss section
    187                                      *   in memory. */
     211  void*               bss_base;     /**< The base address of the bss section in
     212                                     *   memory. */
    188213  size_t              bss_size;     /**< The size of the bss section. */
    189214  size_t              exec_size;    /**< The amount of executable memory
     
    193218                                     *   zero means do not checksum. */
    194219  uint32_t*           sec_num;      /**< The sec nums of each obj. */
    195   uint32_t            obj_num;      /**< The count of elf files in an rtl obj. */
     220  uint32_t            obj_num;      /**< The count of elf files in an rtl
     221                                     *   obj. */
    196222  struct link_map*    linkmap;      /**< For GDB. */
    197   void*               loader;       /**< The file details specific to a loader. */
     223  void*               loader;       /**< The file details specific to a
     224                                     *   loader. */
    198225};
    199226
     
    444471
    445472/**
     473 * Allocate a table for dependent objects.
     474 *
     475 * @param obj The object file's descriptor.
     476 * @param dependents The size of the table.
     477 * @retval true The table was allocated.
     478 * @retval false The alloction failed.
     479 */
     480bool rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents);
     481
     482/**
     483 * Erase the object file descriptor's dependents.
     484 *
     485 * @param obj The object file's descriptor.
     486 */
     487void rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj);
     488
     489/**
     490 * Add an object file to the dependents table.
     491 *
     492 * @param obj The object file's descriptor.
     493 * @param dependent The dependent object file to add.
     494 * @retval true The dependent has been added to the table.
     495 * @retval false There is no space in the table.
     496 */
     497bool rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent);
     498
     499/**
     500 * Iterate over the module dependenices.
     501 *
     502 * @param obj The object file's descriptor.
     503 * @param handler The iterator handler. Returns true to end.
     504 * @param data User data passed to the iterator.
     505 * @retval true The iterator handler returned true.
     506 * @retval false The iterator handler returned false.
     507 */
     508bool rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
     509                                       rtems_rtl_obj_depends_iterator iterator,
     510                                       void*                          data);
     511
     512/**
    446513 * The text section size. Only use once all the sections has been added. It
    447514 * includes alignments between sections that are part of the object's text
     
    644711
    645712/**
     713 * Increment the object file reference count.
     714 *
     715 * @param obj The object file's descriptor.
     716 */
     717void rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj);
     718
     719/**
     720 * Decrement the object file reference count.
     721 *
     722 * @param obj The object file's descriptor.
     723 */
     724void rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj);
     725
     726/**
    646727 * Load the object file, reading all sections into memory, symbols and
    647728 * performing any relocation fixups.
  • cpukit/include/rtems/rtl/rtl-sym.h

    r8e7c72a7 r03139d5b  
    9393 * @param name The name as an ASCIIZ string.
    9494 * @retval NULL No symbol found.
    95  * @return rtems_rtl_obj_sym_t* Reference to the symbol.
     95 * @return rtems_rtl_obj_sym* Reference to the symbol.
    9696 */
    9797rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
     
    103103 * @param name The name as an ASCIIZ string.
    104104 * @retval NULL No symbol found.
    105  * @return rtems_rtl_obj_sym_t* Reference to the symbol.
     105 * @return rtems_rtl_obj_sym* Reference to the symbol.
    106106 */
    107107rtems_rtl_obj_sym* rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj,
  • cpukit/include/rtems/rtl/rtl.h

    r8e7c72a7 r03139d5b  
    2929#include <rtems/rtl/rtl-obj-cache.h>
    3030#include <rtems/rtl/rtl-obj-comp.h>
     31#include <rtems/rtl/rtl-sym.h>
    3132#include <rtems/rtl/rtl-unresolved.h>
    3233
     
    7071 */
    7172#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
     73
     74/**
     75 * The number of dependency record per block in the dependency table.
     76 */
     77#define RTEMS_RTL_DEPENDENCY_BLOCK_SIZE (16)
    7278
    7379/**
     
    174180
    175181/**
     182 * Update the mask in the object files. You can clear flags and then set
     183 * flags. A zero (0) does not clear or set the flags. This is global to all
     184 * object files that are laoded.
     185 *
     186 * @param clear The flag's clear mask, a 0 does not clear any flags.
     187 * @param set The flag's set mask, a 0 does not set any flags.
     188 */
     189void rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set);
     190
     191/**
    176192 * Lock the Run-time Linker.
    177193 *
     
    206222 */
    207223rtems_rtl_obj* rtems_rtl_find_obj (const char* name);
     224
     225/**
     226 * Find the object file a symbol is exported from.
     227 *
     228 * @param sym The symbol to search with.
     229 * @retval NULL No object file found.
     230 * @return rtems_rtl_obj* Reference to the symbol.
     231 */
     232rtems_rtl_obj* rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym);
    208233
    209234/**
  • cpukit/libdl/rtl-elf.c

    r8e7c72a7 r03139d5b  
    6565}
    6666
    67 bool
    68 rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
    69                            const Elf_Sym* sym,
    70                            const char*    symname,
    71                            Elf_Word*      value)
     67static bool
     68rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
     69                           const Elf_Sym*      sym,
     70                           const char*         symname,
     71                           rtems_rtl_obj_sym** symbol,
     72                           Elf_Word*           value)
    7273{
    7374  rtems_rtl_obj_sect* sect;
    7475
    75   if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE ||
    76       sym->st_shndx == SHN_COMMON)
     76  /*
     77   * If the symbol type is STT_NOTYPE the symbol references a global
     78   * symbol. The gobal symbol table is searched to find it and that value
     79   * returned. If the symbol is local to the object module the section for the
     80   * symbol is located and it's base added to the symbol's value giving an
     81   * absolute location.
     82   */
     83  if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
    7784  {
    7885    /*
    7986     * Search the object file then the global table for the symbol.
    8087     */
    81     rtems_rtl_obj_sym* symbol = rtems_rtl_symbol_obj_find (obj, symname);
    82     if (!symbol)
     88    *symbol = rtems_rtl_symbol_obj_find (obj, symname);
     89    if (!*symbol)
    8390    {
    8491      rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
     
    8693    }
    8794
    88     *value = (Elf_Addr) symbol->value;
     95    *value = (Elf_Addr) (*symbol)->value;
    8996    return true;
    9097  }
     98
     99  *symbol = NULL;
    91100
    92101  sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
     
    101110}
    102111
     112/**
     113 * Relocation worker routine.
     114 */
     115typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj*      obj,
     116                                            bool                is_rela,
     117                                            void*               relbuf,
     118                                            rtems_rtl_obj_sect* targetsect,
     119                                            rtems_rtl_obj_sym*  symbol,
     120                                            Elf_Sym*            sym,
     121                                            const char*         symname,
     122                                            Elf_Word            symvalue,
     123                                            bool                resolved,
     124                                            void*               data);
     125
     126/**
     127 * Relocation parser data.
     128 */
     129typedef struct
     130{
     131  size_t dependents; /**< The number of dependent object files. */
     132  size_t unresolved; /**< The number of unresolved symbols. */
     133} rtems_rtl_elf_reloc_data;
     134
    103135static bool
    104 rtems_rtl_elf_relocator (rtems_rtl_obj*      obj,
    105                          int                 fd,
    106                          rtems_rtl_obj_sect* sect,
    107                          void*               data)
     136rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
     137                            bool                is_rela,
     138                            void*               relbuf,
     139                            rtems_rtl_obj_sect* targetsect,
     140                            rtems_rtl_obj_sym*  symbol,
     141                            Elf_Sym*            sym,
     142                            const char*         symname,
     143                            Elf_Word            symvalue,
     144                            bool                resolved,
     145                            void*               data)
     146{
     147  rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
     148  /*
     149   * If the symbol has been resolved and there is a symbol name it is a global
     150   * symbol and from another object file so add it as a dependency.
     151   */
     152  if (!resolved)
     153  {
     154    ++rd->unresolved;
     155  }
     156  else if (resolved && symname != NULL)
     157  {
     158    /*
     159     * Find the symbol's object file. It cannot be NULL so ignore that result
     160     * if returned, it means something is corrupted. We are in an iterator.
     161     */
     162    rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
     163    if (sobj != NULL)
     164    {
     165      /*
     166       * A dependency is not the base kernel image or itself. Tag the object as
     167       * having been visited so we count it only once.
     168       */
     169      if (sobj != rtems_rtl_baseimage () && obj != sobj &&
     170          (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
     171      {
     172        sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
     173        ++rd->dependents;
     174      }
     175    }
     176  }
     177  return true;
     178}
     179
     180static bool
     181rtems_rtl_elf_reloc_relocator (rtems_rtl_obj*      obj,
     182                               bool                is_rela,
     183                               void*               relbuf,
     184                               rtems_rtl_obj_sect* targetsect,
     185                               rtems_rtl_obj_sym*  symbol,
     186                               Elf_Sym*            sym,
     187                               const char*         symname,
     188                               Elf_Word            symvalue,
     189                               bool                resolved,
     190                               void*               data)
     191{
     192  const Elf_Rela* rela = (const Elf_Rela*) relbuf;
     193  const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
     194
     195  if (!resolved)
     196  {
     197    uint16_t       flags = 0;
     198    rtems_rtl_word rel_words[3];
     199
     200    if (is_rela)
     201    {
     202      flags = 1;
     203      rel_words[REL_R_OFFSET] = rela->r_offset;
     204      rel_words[REL_R_INFO] = rela->r_info;
     205      rel_words[REL_R_ADDEND] = rela->r_addend;
     206    }
     207    else
     208    {
     209      rel_words[REL_R_OFFSET] = rel->r_offset;
     210      rel_words[REL_R_INFO] = rel->r_info;
     211      rel_words[REL_R_ADDEND] = 0;
     212    }
     213
     214    if (!rtems_rtl_unresolved_add (obj,
     215                                   flags,
     216                                   symname,
     217                                   targetsect->section,
     218                                   rel_words))
     219      return false;
     220
     221    ++obj->unresolved;
     222  }
     223  else
     224  {
     225    rtems_rtl_obj* sobj;
     226
     227    if (is_rela)
     228    {
     229      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
     230        printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
     231                symname, (int) ELF_R_SYM (rela->r_info),
     232                (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
     233                (uintmax_t) rela->r_offset, (int) rela->r_addend);
     234      if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
     235                                        symname, sym->st_info, symvalue))
     236        return false;
     237    }
     238    else
     239    {
     240      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
     241        printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
     242                symname, (int) ELF_R_SYM (rel->r_info),
     243                (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
     244                (uintmax_t) rel->r_offset);
     245      if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
     246                                       symname, sym->st_info, symvalue))
     247        return false;
     248    }
     249
     250    sobj = rtems_rtl_find_obj_with_symbol (symbol);
     251    if (sobj != NULL)
     252    {
     253      if (rtems_rtl_obj_add_dependent (obj, sobj))
     254        rtems_rtl_obj_inc_reference (sobj);
     255    }
     256  }
     257
     258  return true;
     259}
     260
     261static bool
     262rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
     263                               int                         fd,
     264                               rtems_rtl_obj_sect*         sect,
     265                               rtems_rtl_elf_reloc_handler handler,
     266                               void*                       data)
    108267{
    109268  rtems_rtl_obj_cache* symbols;
     
    156315  for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
    157316  {
    158     uint8_t         relbuf[reloc_size];
    159     const Elf_Rela* rela = (const Elf_Rela*) relbuf;
    160     const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
    161     Elf_Sym         sym;
    162     const char*     symname = NULL;
    163     off_t           off;
    164     Elf_Word        type;
    165     Elf_Word        symvalue = 0;
    166     bool            relocate;
     317    uint8_t            relbuf[reloc_size];
     318    const Elf_Rela*    rela = (const Elf_Rela*) relbuf;
     319    const Elf_Rel*     rel = (const Elf_Rel*) relbuf;
     320    rtems_rtl_obj_sym* symbol = NULL;
     321    Elf_Sym            sym;
     322    const char*        symname = NULL;
     323    off_t              off;
     324    Elf_Word           rel_type;
     325    Elf_Word           symvalue = 0;
     326    bool               resolved;
    167327
    168328    off = obj->ooffset + sect->offset + (reloc * reloc_size);
     
    204364     * See if the record references an external symbol. If it does find the
    205365     * symbol value. If the symbol cannot be found flag the object file as
    206      * having unresolved externals and store the externals. The load of an
     366     * having unresolved externals and store the external. The load of an
    207367     * object after this one may provide the unresolved externals.
    208368     */
    209369    if (is_rela)
    210       type = ELF_R_TYPE(rela->r_info);
     370      rel_type = ELF_R_TYPE(rela->r_info);
    211371    else
    212       type = ELF_R_TYPE(rel->r_info);
    213 
    214     relocate = true;
    215 
    216     if (rtems_rtl_elf_rel_resolve_sym (type))
    217     {
    218       if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue))
    219       {
    220         uint16_t       flags = 0;
    221         rtems_rtl_word rel_words[3];
    222 
    223         relocate = false;
    224 
    225         if (is_rela)
    226         {
    227           flags = 1;
    228           rel_words[REL_R_OFFSET] = rela->r_offset;
    229           rel_words[REL_R_INFO] = rela->r_info;
    230           rel_words[REL_R_ADDEND] = rela->r_addend;
    231         }
    232         else
    233         {
    234           rel_words[REL_R_OFFSET] = rel->r_offset;
    235           rel_words[REL_R_INFO] = rel->r_info;
    236           rel_words[REL_R_ADDEND] = 0;
    237         }
    238 
    239         if (!rtems_rtl_unresolved_add (obj,
    240                                        flags,
    241                                        symname,
    242                                        targetsect->section,
    243                                        rel_words))
    244           return false;
    245 
    246         ++obj->unresolved;
    247       }
    248     }
    249 
    250     if (relocate)
    251     {
    252       if (is_rela)
    253       {
    254         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
    255           printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
    256                   symname, (int) ELF_R_SYM (rela->r_info),
    257                   (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
    258                   (uintmax_t) rela->r_offset, (int) rela->r_addend);
    259         if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
    260                                           symname, sym.st_info, symvalue))
    261           return false;
    262       }
    263       else
    264       {
    265         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
    266           printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
    267                   symname, (int) ELF_R_SYM (rel->r_info),
    268                   (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
    269                   (uintmax_t) rel->r_offset);
    270         if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
    271                                          symname, sym.st_info, symvalue))
    272           return false;
    273       }
    274     }
     372      rel_type = ELF_R_TYPE(rel->r_info);
     373
     374    resolved = true;
     375
     376    if (rtems_rtl_elf_rel_resolve_sym (rel_type))
     377      resolved = rtems_rtl_elf_find_symbol (obj,
     378                                            &sym, symname,
     379                                            &symbol, &symvalue);
     380
     381    if (!handler (obj,
     382                  is_rela, relbuf, targetsect,
     383                  symbol, &sym, symname, symvalue, resolved,
     384                  data))
     385      return false;
    275386  }
    276387
     
    282393
    283394  return true;
     395}
     396
     397static bool
     398rtems_rtl_elf_relocs_parser (rtems_rtl_obj*      obj,
     399                             int                 fd,
     400                             rtems_rtl_obj_sect* sect,
     401                             void*               data)
     402{
     403  bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
     404                                          rtems_rtl_elf_reloc_parser, data);
     405  rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
     406  return r;
     407}
     408
     409static bool
     410rtems_rtl_elf_relocs_locator (rtems_rtl_obj*      obj,
     411                              int                 fd,
     412                              rtems_rtl_obj_sect* sect,
     413                              void*               data)
     414{
     415  return rtems_rtl_elf_relocate_worker (obj, fd, sect,
     416                                        rtems_rtl_elf_reloc_relocator, data);
    284417}
    285418
     
    291424  bool                is_rela;
    292425  Elf_Word            symvalue;
    293 
    294   is_rela =reloc->flags & 1;
     426  rtems_rtl_obj*      sobj;
     427
     428  is_rela = reloc->flags & 1;
    295429
    296430  sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
     
    330464  }
    331465
    332   if (reloc->obj->unresolved)
     466  if (reloc->obj->unresolved > 0)
    333467  {
    334468    --reloc->obj->unresolved;
    335     if (!reloc->obj->unresolved)
     469    if (reloc->obj->unresolved == 0)
    336470      reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
     471  }
     472
     473  sobj = rtems_rtl_find_obj_with_symbol (sym);
     474  if (sobj != NULL)
     475  {
     476    if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
     477      rtems_rtl_obj_inc_reference (sobj);
    337478  }
    338479
     
    399540  }
    400541
     542  return true;
     543}
     544
     545static bool
     546rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
     547{
     548  /*
     549   * If there are dependencies and no unresolved externals allocate and size
     550   * the dependency table to the number of dependent object files. If there are
     551   * unresolved externals the number of dependencies is unknown at this point
     552   * in time so use dynamic allocation to allocate the block size number of
     553   * entries when the entries are added.
     554   */
     555  if (reloc->dependents > 0 && reloc->unresolved == 0)
     556  {
     557    if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
     558      return false;
     559  }
    401560  return true;
    402561}
     
    10251184  rtems_rtl_obj_cache*      header;
    10261185  Elf_Ehdr                  ehdr;
    1027   rtems_rtl_elf_common_data common = { .size = 0, .alignment = 0 };
     1186  rtems_rtl_elf_reloc_data  relocs = { 0 };
     1187  rtems_rtl_elf_common_data common = { 0 };
    10281188
    10291189  rtems_rtl_obj_caches (&header, NULL, NULL);
     
    11031263    return false;
    11041264
     1265  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
     1266    return false;
     1267
     1268  if (!rtems_rtl_elf_dependents (obj, &relocs))
     1269    return false;
     1270
    11051271  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
    11061272    return false;
    11071273
    1108   if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
     1274  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
    11091275    return false;
    11101276
  • cpukit/libdl/rtl-elf.h

    r8e7c72a7 r03139d5b  
    124124
    125125/**
    126  * Find the symbol. The symbol is passed as an ELF type symbol with the name
    127  * and the value returned is the absolute address of the symbol.
    128  *
    129  * If the symbol type is STT_NOTYPE the symbol references a global symbol. The
    130  * gobal symbol table is searched to find it and that value returned. If the
    131  * symbol is local to the object module the section for the symbol is located
    132  * and it's base added to the symbol's value giving an absolute location.
    133  *
    134  * @param obj The object the symbol is being resolved for.
    135  * @param sym The ELF type symbol.
    136  * @param symname The sym's name read from the symbol string table.
    137  * @param value Return the value of the symbol. Only valid if the return value
    138  *              is true.
    139  * @retval true The symbol resolved.
    140  * @retval false The symbol could not be result. The RTL error is set.
    141  */
    142 bool rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
    143                                 const Elf_Sym* sym,
    144                                 const char*    symname,
    145                                 Elf_Word*      value);
    146 
    147 /**
    148126 * The ELF format check handler.
    149127 *
  • cpukit/libdl/rtl-obj.c

    r8e7c72a7 r03139d5b  
    8484     */
    8585    rtems_chain_initialize_empty (&obj->sections);
     86    rtems_chain_initialize_empty (&obj->dependents);
    8687    /*
    8788     * No valid format.
     
    115116  rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
    116117                              &obj->data_base, &obj->bss_base);
     118  rtems_rtl_obj_erase_sections (obj);
     119  rtems_rtl_obj_erase_dependents (obj);
    117120  rtems_rtl_symbol_obj_erase (obj);
    118121  rtems_rtl_obj_free_names (obj);
     
    549552                           &match);
    550553  return match.sect;
     554}
     555
     556bool
     557rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
     558{
     559  rtems_rtl_obj_depends* depends;
     560  size_t                 size;
     561
     562  size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents;
     563
     564  depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
     565                                 size,
     566                                 true);
     567  if (depends == NULL)
     568  {
     569    rtems_rtl_set_error (ENOMEM, "no memory for the dependency");
     570  }
     571  else
     572  {
     573    depends->dependents = dependents;
     574    rtems_chain_append (&obj->dependents, &depends->node);
     575  }
     576
     577  return depends != NULL;
     578}
     579
     580void
     581rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj)
     582{
     583  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
     584  while (!rtems_chain_is_tail (&obj->dependents, node))
     585  {
     586    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
     587    rtems_chain_node*      next_node = rtems_chain_next (node);
     588    rtems_chain_extract (node);
     589    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends);
     590    node = next_node;
     591  }
     592}
     593
     594bool
     595rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent)
     596{
     597  rtems_rtl_obj**   free_slot;
     598  rtems_chain_node* node;
     599  if (obj == dependent || dependent == rtems_rtl_baseimage ())
     600    return false;
     601  free_slot = NULL;
     602  node = rtems_chain_first (&obj->dependents);
     603  while (!rtems_chain_is_tail (&obj->dependents, node))
     604  {
     605    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
     606    size_t                 d;
     607    for (d = 0; d < depends->dependents; ++d)
     608    {
     609      if (free_slot == NULL && depends->depends[d] == NULL)
     610        free_slot = &(depends->depends[d]);
     611      if (depends->depends[d] == dependent)
     612        return false;
     613    }
     614    node = rtems_chain_next (node);
     615  }
     616  if (free_slot == NULL)
     617  {
     618    if (rtems_rtl_obj_alloc_dependents (obj,
     619                                        RTEMS_RTL_DEPENDENCY_BLOCK_SIZE))
     620    {
     621      rtems_rtl_obj_depends* depends;
     622      node = rtems_chain_last (&obj->dependents);
     623      depends = (rtems_rtl_obj_depends*) node;
     624      free_slot = &(depends->depends[0]);
     625      if (*free_slot != NULL)
     626      {
     627        rtems_rtl_set_error (EINVAL, "new dependency node not empty");
     628        free_slot = NULL;
     629      }
     630    }
     631  }
     632  if (free_slot != NULL)
     633    *free_slot = dependent;
     634  return free_slot != NULL;
     635}
     636
     637bool
     638rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
     639                                  rtems_rtl_obj_depends_iterator iterator,
     640                                  void*                          data)
     641{
     642  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
     643  while (!rtems_chain_is_tail (&obj->dependents, node))
     644  {
     645    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
     646    size_t                 d;
     647    for (d = 0; d < depends->dependents; ++d)
     648    {
     649      if (depends->depends[d])
     650      {
     651        if (iterator (obj, depends->depends[d], data))
     652          return true;
     653      }
     654    }
     655    node = rtems_chain_next (node);
     656  }
     657  return false;
    551658}
    552659
     
    12211328{
    12221329  if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
    1223       return loaders[obj->format].unload (obj);
     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
    12241350  return false;
     1351}
     1352
     1353void
     1354rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj)
     1355{
     1356  ++obj->refs;
     1357}
     1358
     1359void
     1360rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj)
     1361{
     1362  if (obj->refs)
     1363    --obj->refs;
    12251364}
    12261365
  • cpukit/libdl/rtl-shell.c

    r8e7c72a7 r03139d5b  
    118118typedef struct
    119119{
    120   rtems_rtl_data* rtl;        /**< The RTL data. */
    121   int             indent;     /**< Spaces to indent. */
    122   bool            oname;      /**< Print object names. */
    123   bool            names;      /**< Print details of all names. */
    124   bool            memory_map; /**< Print the memory map. */
    125   bool            symbols;    /**< Print the global symbols. */
    126   bool            base;       /**< Include the base object file. */
     120  rtems_rtl_data* rtl;          /**< The RTL data. */
     121  int             indent;       /**< Spaces to indent. */
     122  bool            oname;        /**< Print object names. */
     123  bool            names;        /**< Print details of all names. */
     124  bool            memory_map;   /**< Print the memory map. */
     125  bool            symbols;      /**< Print the global symbols. */
     126  bool            dependencies; /**< Print any dependencies. */
     127  bool            base;         /**< Include the base object file. */
    127128} rtems_rtl_obj_print;
    128129
     
    167168{
    168169  return rtems_rtl_parse_arg ("-s", argc, argv);
     170}
     171
     172/**
     173 * Dependenncies printer.
     174 */
     175typedef struct
     176{
     177  bool   first;   /**< Is this the first line printed. */
     178  size_t indent;  /**< The indent. */
     179} rtems_rtl_dep_data;
     180
     181static bool
     182rtems_rtl_dependencies (rtems_rtl_obj* obj,
     183                        rtems_rtl_obj* dependent,
     184                        void*          data)
     185{
     186  rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
     187  if (!dd->first)
     188    printf ("\n%-*c: ", dd->indent, ' ');
     189  else
     190    dd->first = false;
     191  printf ("%s", dependent->oname);
     192  return false;
    169193}
    170194
     
    215239            obj->bss_base, obj->bss_size);
    216240  }
    217   printf ("%-*cunresolved    : %" PRIu32 "\n", print->indent, ' ', obj->unresolved);
     241  printf ("%-*cunresolved    : %zu\n", print->indent, ' ', obj->unresolved);
     242  printf ("%-*cusers         : %zu\n", print->indent, ' ', obj->users);
     243  printf ("%-*creferences    : %zu\n", print->indent, ' ', obj->refs);
    218244  printf ("%-*csymbols       : %zi\n", print->indent, ' ', obj->global_syms);
    219245  printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
     
    232258              max_len, obj->global_table[s].name, obj->global_table[s].value);
    233259  }
     260  if (print->dependencies)
     261  {
     262    rtems_rtl_dep_data dd = {
     263      .first = true,
     264      .indent = strlen ("dependencies :") + print->indent
     265    };
     266    printf ("%-*cdependencies  : ", print->indent, ' ');
     267    rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
     268    printf ("\n");
     269  }
    234270  printf ("\n");
    235271  return true;
     
    270306  print.memory_map = true;
    271307  print.symbols = rtems_rtl_symbols_arg (argc, argv);
     308  print.dependencies = true;
    272309  print.base = false;
    273310  rtems_rtl_chain_iterate (&rtl->objects,
     
    287324  print.memory_map = false;
    288325  print.symbols = true;
     326  print.dependencies = false;
    289327  print.base = rtems_rtl_base_arg (argc, argv);
    290328  rtems_rtl_chain_iterate (&rtl->objects,
  • cpukit/libdl/rtl-unresolved.c

    r8e7c72a7 r03139d5b  
    172172    rd = (rtems_rtl_unresolved_reloc_data*) data;
    173173
    174     if (rec->rec.reloc.name == rd->name)
     174    if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL)
    175175    {
    176176      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
     
    186186       */
    187187      rec->rec.reloc.obj = NULL;
    188       if (rd->name_rec && rd->name_rec->rec.name.refs)
     188      if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
    189189        --rd->name_rec->rec.name.refs;
    190190    }
  • cpukit/libdl/rtl.c

    r8e7c72a7 r03139d5b  
    217217      rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
    218218
     219      /*
     220       * Lock the base image and flag it as the base image.
     221       */
     222      rtl->base->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_BASE;
     223
    219224      rtems_chain_append (&rtl->objects, &rtl->base->link);
    220225    }
     
    310315    *decomp = &rtl->decomp;
    311316    rtems_rtl_obj_comp_set (*decomp, cache, fd, compression, offset);
     317  }
     318}
     319
     320void
     321rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set)
     322{
     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);
    312332  }
    313333}
     
    384404
    385405  return found;
     406}
     407
     408rtems_rtl_obj*
     409rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
     410{
     411  rtems_chain_node* node = rtems_chain_first (&rtl->objects);
     412  while (!rtems_chain_is_tail (&rtl->objects, node))
     413  {
     414    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
     415    if (sym >= obj->global_table &&
     416        sym < (obj->global_table + obj->global_syms))
     417      return obj;
     418    node = rtems_chain_next (node);
     419  }
     420  return NULL;
    386421}
    387422
     
    490525  if (obj->users == 0)
    491526  {
     527    if (obj->refs != 0)
     528    {
     529      rtems_rtl_set_error (EBUSY, "object file referenced");
     530      return false;
     531    }
    492532    obj->flags |= RTEMS_RTL_OBJ_LOCKED;
    493533    rtems_rtl_unlock ();
     
    619659rtems_rtl_baseimage (void)
    620660{
    621   return NULL;
    622 }
     661  rtems_rtl_obj* base = NULL;
     662  if (rtems_rtl_lock ())
     663  {
     664    base = rtl->base;
     665    rtems_rtl_unlock ();
     666  }
     667  return base;
     668}
  • testsuites/libtests/Makefile.am

    r8e7c72a7 r03139d5b  
    510510        $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
    511511CLEANFILES += dl06.pre dl06-sym.o dl06-o1.o dl06-o2.o dl06.tar dl06-tar.h
     512endif
     513endif
     514
     515if DLTESTS
     516if TEST_dl07
     517lib_tests += dl07
     518lib_screens += dl07/dl07.scn
     519lib_docs += dl07/dl07.doc
     520dl07_SOURCES = dl07/init.c dl07/dl-load.c dl07-tar.c dl07-tar.h
     521dl07_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl07) $(support_includes)
     522dl07/init.c: dl07-tar.o
     523dl07.pre: $(dl07_OBJECTS) $(dl07_DEPENDENCIES)
     524        @rm -f dl07.pre
     525        $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
     526dl07-o1.o: dl07/dl-o1.c Makefile
     527        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     528dl07-o2.o: dl07/dl-o2.c Makefile
     529        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     530dl07-o3.o: dl07/dl-o3.c Makefile
     531        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     532dl07-o4.o: dl07/dl-o4.c Makefile
     533        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     534dl07-o5.o: dl07/dl-o5.c Makefile
     535        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     536dl07.tar: dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o
     537        @rm -f $@
     538        $(AM_V_GEN)$(PAX) -w -f $@ $+
     539dl07-tar.c: dl07.tar
     540        $(AM_V_GEN)$(BIN2C) -C $< $@
     541dl07-tar.h: dl07.tar
     542        $(AM_V_GEN)$(BIN2C) -H $< $@
     543dl07-tar.o: dl07-tar.c dl07-tar.h
     544        $(AM_V_CC)$(COMPILE) -c -o $@ $<
     545dl07-sym.o: dl07.pre
     546        $(AM_V_GEN)rtems-syms -e -c "$(CFLAGS)" -o $@ $<
     547dl07$(EXEEXT):  $(dl07_OBJECTS) $(dl07_DEPENDENCIES) dl07-sym.o
     548        @rm -f $@
     549        $(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
     550CLEANFILES += dl07.pre dl07-sym.o dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o dl07.tar dl07-tar.h
    512551endif
    513552endif
     
    13591398rtems_tests_PROGRAMS = $(lib_tests)
    13601399dist_rtems_tests_DATA = $(lib_screens) $(lib_docs)
    1361 
  • testsuites/libtests/configure.ac

    r8e7c72a7 r03139d5b  
    132132RTEMS_TEST_CHECK([dl05])
    133133RTEMS_TEST_CHECK([dl06])
     134RTEMS_TEST_CHECK([dl07])
    134135RTEMS_TEST_CHECK([dumpbuf01])
    135136RTEMS_TEST_CHECK([dup2])
  • testsuites/libtests/dl02/dl-load.c

    r8e7c72a7 r03139d5b  
    1212
    1313#include "dl-load.h"
     14
     15#include <rtems/rtl/rtl-trace.h>
     16
     17#define DL02_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
     18#define DL02_RTL_CMDS    0
    1419
    1520typedef int (*call_t)(int argc, const char* argv[]);
     
    5055  int    ret;
    5156
     57#if DL02_DEBUG_TRACE
     58  rtems_rtl_trace_set_mask (DL02_DEBUG_TRACE);
     59#endif
     60
    5261  o1 = dl_load_obj("/dl02-o1.o");
    5362  if (!o1)
     
    5766    return 1;
    5867
    59 #if 0
     68#if DL02_RTL_CMDS
    6069  {
    6170    char* list[] = { "rtl", "list", NULL };
Note: See TracChangeset for help on using the changeset viewer.