Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:16

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup rtl
0007  *
0008  * @brief RTEMS Run-Time Linker Error
0009  */
0010 
0011 /*
0012  *  COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <errno.h>
0041 #include <inttypes.h>
0042 #include <stdlib.h>
0043 #include <stdio.h>
0044 #include <string.h>
0045 
0046 #include <rtems/libio_.h>
0047 
0048 #include <rtems/rtl/rtl.h>
0049 #include "rtl-chain-iterator.h"
0050 #include <rtems/rtl/rtl-obj.h>
0051 #include "rtl-error.h"
0052 #include "rtl-find-file.h"
0053 #include "rtl-string.h"
0054 #include <rtems/rtl/rtl-trace.h>
0055 
0056 #define RTEMS_RTL_ELF_LOADER 1
0057 #define RTEMS_RTL_RAP_LOADER 1
0058 
0059 #if RTEMS_RTL_RAP_LOADER
0060 #include "rtl-rap.h"
0061 #define RTEMS_RTL_RAP_LOADER_COUNT 1
0062 #else
0063 #define RTEMS_RTL_RAP_LOADER_COUNT 0
0064 #endif
0065 
0066 #if RTEMS_RTL_ELF_LOADER
0067 #include "rtl-elf.h"
0068 #define RTEMS_RTL_ELF_LOADER_COUNT 1
0069 #else
0070 #define RTEMS_RTL_ELF_LOADER_COUNT 0
0071 #endif
0072 
0073 /**
0074  * The table of supported loader formats.
0075  */
0076 #define RTEMS_RTL_LOADERS (RTEMS_RTL_ELF_LOADER_COUNT + RTEMS_RTL_RAP_LOADER_COUNT)
0077 static const rtems_rtl_loader_table loaders[RTEMS_RTL_LOADERS] =
0078 {
0079 #if RTEMS_RTL_RAP_LOADER
0080   { .check     = rtems_rtl_rap_file_check,
0081     .load      = rtems_rtl_rap_file_load,
0082     .unload    = rtems_rtl_rap_file_unload,
0083     .signature = rtems_rtl_rap_file_sig },
0084 #endif
0085 #if RTEMS_RTL_ELF_LOADER
0086   { .check     = rtems_rtl_elf_file_check,
0087     .load      = rtems_rtl_elf_file_load,
0088     .unload    = rtems_rtl_elf_file_unload,
0089     .signature = rtems_rtl_elf_file_sig },
0090 #endif
0091 };
0092 
0093 rtems_rtl_obj*
0094 rtems_rtl_obj_alloc (void)
0095 {
0096   rtems_rtl_obj* obj = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
0097                                             sizeof (rtems_rtl_obj),
0098                                             true);
0099   if (obj)
0100   {
0101     /*
0102      * Initialise the chains.
0103      */
0104     rtems_chain_initialize_empty (&obj->sections);
0105     rtems_chain_initialize_empty (&obj->dependents);
0106     /*
0107      * No valid format.
0108      */
0109     obj->format = -1;
0110   }
0111   return obj;
0112 }
0113 
0114 static void
0115 rtems_rtl_obj_free_names (rtems_rtl_obj* obj)
0116 {
0117   if (rtems_rtl_obj_oname_valid (obj))
0118     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->oname);
0119   if (rtems_rtl_obj_aname_valid (obj))
0120     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->aname);
0121   if (rtems_rtl_obj_fname_valid (obj))
0122     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->fname);
0123 }
0124 
0125 bool
0126 rtems_rtl_obj_free (rtems_rtl_obj* obj)
0127 {
0128   if (obj->users > 0 || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
0129   {
0130     rtems_rtl_set_error (EINVAL, "cannot free obj still in use");
0131     return false;
0132   }
0133   if (!rtems_chain_is_node_off_chain (&obj->link))
0134     rtems_chain_extract (&obj->link);
0135   rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
0136                               &obj->data_base, &obj->bss_base);
0137   rtems_rtl_obj_erase_sections (obj);
0138   rtems_rtl_obj_erase_dependents (obj);
0139   rtems_rtl_symbol_obj_erase (obj);
0140   rtems_rtl_obj_free_names (obj);
0141   if (obj->sec_num != NULL)
0142     free (obj->sec_num);
0143   if (obj->linkmap != NULL)
0144     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->linkmap);
0145   rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
0146   return true;
0147 }
0148 
0149 typedef struct rtems_rtl_obj_unresolved_data
0150 {
0151   bool has_unresolved;
0152 } rtems_rtl_obj_unresolved_data;
0153 
0154 static bool
0155 rtems_rtl_obj_unresolved_dependent (rtems_rtl_obj* obj,
0156                                     rtems_rtl_obj* dependent,
0157                                     void*          data)
0158 {
0159   rtems_rtl_obj_unresolved_data* ud;
0160   ud = (rtems_rtl_obj_unresolved_data*) data;
0161   if ((dependent->flags & RTEMS_RTL_OBJ_DEP_VISITED) == 0)
0162   {
0163     dependent->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
0164     if ((dependent->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0)
0165       ud->has_unresolved = true;
0166     else
0167     {
0168       rtems_rtl_obj_iterate_dependents (dependent,
0169                                         rtems_rtl_obj_unresolved_dependent,
0170                                         ud);
0171     }
0172     if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
0173       printf ("rtl: obj: unresolved: dep: %s is %s\n",
0174               dependent->oname, ud->has_unresolved ? "unresolved" : "resolved");
0175   }
0176   return ud->has_unresolved;
0177 }
0178 
0179 static bool
0180 rtems_rtl_obj_unresolved_object (rtems_chain_node* node, void* data)
0181 {
0182   rtems_rtl_obj*                 obj = (rtems_rtl_obj*) node;
0183   rtems_rtl_obj_unresolved_data* ud;
0184   ud = (rtems_rtl_obj_unresolved_data*) data;
0185   ud->has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0;
0186   return !ud->has_unresolved;
0187 }
0188 
0189 bool
0190 rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
0191 {
0192   rtems_rtl_obj_unresolved_data ud = {
0193     .has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0
0194   };
0195   if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
0196     printf ("rtl: obj: unresolved: dep: %s is %s\n",
0197             obj->oname, ud.has_unresolved ? "unresolved" : "resolved");
0198   if (!ud.has_unresolved)
0199   {
0200     if ((obj->flags & RTEMS_RTL_OBJ_BASE) != 0)
0201     {
0202       rtems_rtl_data* rtl = rtems_rtl_data_unprotected ();
0203       rtems_rtl_chain_iterate (&rtl->objects,
0204                                rtems_rtl_obj_unresolved_object,
0205                                &ud);
0206     }
0207     else
0208     {
0209       rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
0210       obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
0211       rtems_rtl_obj_iterate_dependents (obj,
0212                                         rtems_rtl_obj_unresolved_dependent,
0213                                         &ud);
0214       rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
0215     }
0216   }
0217   return ud.has_unresolved;
0218 }
0219 
0220 bool
0221 rtems_rtl_parse_name (const char*  name,
0222                       const char** aname,
0223                       const char** oname,
0224                       off_t*       ooffset)
0225 {
0226   const char* laname = NULL;
0227   const char* loname = NULL;
0228   const char* colon;
0229   const char* end;
0230 
0231   /*
0232    * Parse the name to determine if the object file is part of an archive or it
0233    * is an object file. If an archive check the name for a '@' to see if the
0234    * archive contains an offset.
0235    *
0236    * Note, if an archive the object file oofset may be know but the
0237    *       object file is not. Leave the object name as a NULL.
0238    */
0239   end = name + strlen (name);
0240   colon = strrchr (name, ':');
0241   if (colon == NULL || colon < strrchr(name, '/'))
0242     colon = end;
0243 
0244   loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, colon - name + 1, true);
0245   if (!loname)
0246   {
0247     rtems_rtl_set_error (ENOMEM, "no memory for object file name");
0248     return false;
0249   }
0250 
0251   memcpy ((void*) loname, name, colon - name);
0252 
0253   /*
0254    * If the pointers match there is no ':' delimiter.
0255    */
0256   if (colon != end)
0257   {
0258     const char* at;
0259 
0260     /*
0261      * The file name is an archive and the object file name is next after the
0262      * delimiter. Move the pointer to the archive name.
0263      */
0264     laname = loname;
0265     ++colon;
0266 
0267     /*
0268      * See if there is a '@' to delimit an archive offset for the object in the
0269      * archive.
0270      */
0271     at = strchr (colon, '@');
0272 
0273     if (at == NULL)
0274       at = end;
0275 
0276 
0277     loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, at - colon + 1, true);
0278     if (!loname)
0279     {
0280       rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) laname);
0281       rtems_rtl_set_error (ENOMEM, "no memory for object file name");
0282       return false;
0283     }
0284 
0285     memcpy ((void*) loname, colon, at - colon);
0286 
0287     if (at != end)
0288     {
0289       /*
0290        * The object name has an archive offset. If the number
0291        * does not parse 0 will be returned and the archive will be
0292        * searched.
0293        */
0294       *ooffset = strtoul (at + 1, 0, 0);
0295     }
0296   }
0297 
0298   *oname = loname;
0299   *aname = laname;
0300   return true;
0301 }
0302 
0303 static bool
0304 rtems_rtl_obj_parse_name (rtems_rtl_obj* obj, const char* name)
0305 {
0306   return rtems_rtl_parse_name (name, &(obj->aname), &(obj->oname), &(obj->ooffset));
0307 }
0308 
0309 /**
0310  * Section size summer iterator data.
0311  */
0312 typedef struct
0313 {
0314   uint32_t mask; /**< The selection mask to sum. */
0315   size_t   size; /**< The size of all section fragments. */
0316 } rtems_rtl_obj_sect_summer_data;
0317 
0318 static bool
0319 rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data)
0320 {
0321   rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
0322   if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
0323   {
0324     rtems_rtl_obj_sect_summer_data* summer = data;
0325     if ((sect->flags & summer->mask) == summer->mask)
0326       summer->size =
0327         rtems_rtl_obj_align (summer->size, sect->alignment) + sect->size;
0328   }
0329   return true;
0330 }
0331 
0332 static size_t
0333 rtems_rtl_obj_section_size (const rtems_rtl_obj* obj, uint32_t mask)
0334 {
0335   rtems_rtl_obj_sect_summer_data summer;
0336   summer.mask = mask;
0337   summer.size = 0;
0338   rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
0339                            rtems_rtl_obj_sect_summer,
0340                            &summer);
0341   return summer.size;
0342 }
0343 
0344 /**
0345  * Section alignment iterator data. The first section's alignment sets the
0346  * alignment for that type of section.
0347  */
0348 typedef struct
0349 {
0350   uint32_t mask;      /**< The selection mask to look for alignment. */
0351   uint32_t alignment; /**< The alignment of the section type. */
0352 } rtems_rtl_obj_sect_aligner_data;
0353 
0354 /**
0355  * The section aligner iterator.
0356  */
0357 static bool
0358 rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data)
0359 {
0360   rtems_rtl_obj_sect*              sect = (rtems_rtl_obj_sect*) node;
0361   rtems_rtl_obj_sect_aligner_data* aligner = data;
0362   if ((sect->flags & aligner->mask) == aligner->mask)
0363   {
0364     aligner->alignment = sect->alignment;
0365     return false;
0366   }
0367   return true;
0368 }
0369 
0370 static size_t
0371 rtems_rtl_obj_section_alignment (const rtems_rtl_obj* obj, uint32_t mask)
0372 {
0373   rtems_rtl_obj_sect_aligner_data aligner;
0374   aligner.mask = mask;
0375   aligner.alignment = 0;
0376   rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
0377                            rtems_rtl_obj_sect_aligner,
0378                            &aligner);
0379   return aligner.alignment;
0380 }
0381 
0382 static bool
0383 rtems_rtl_obj_section_handler (uint32_t                   mask,
0384                                rtems_rtl_obj*             obj,
0385                                int                        fd,
0386                                rtems_rtl_obj_sect_handler handler,
0387                                void*                      data)
0388 {
0389   rtems_chain_node* node = rtems_chain_first (&obj->sections);
0390   while (!rtems_chain_is_tail (&obj->sections, node))
0391   {
0392     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
0393     if ((sect->flags & mask) != 0)
0394     {
0395       if (!handler (obj, fd, sect, data))
0396         return false;
0397     }
0398     node = rtems_chain_next (node);
0399   }
0400   return true;
0401 }
0402 
0403 bool
0404 rtems_rtl_obj_find_file (rtems_rtl_obj* obj, const char* name)
0405 {
0406   const char*     pname;
0407   rtems_rtl_data* rtl;
0408 
0409   /*
0410    * Parse the name. The object descriptor will have the archive name and/or
0411    * object name fields filled in. A find of the file will result in the file
0412    * name (fname) field pointing to the actual file if present on the file
0413    * system.
0414    */
0415   if (!rtems_rtl_obj_parse_name (obj, name))
0416     return false;
0417 
0418   /*
0419    * If the archive field (aname) is set we use that name else we use the
0420    * object field (oname). If selected name is absolute we just point the aname
0421    * field to the fname field to that name. If the field is relative we search
0422    * the paths set in the RTL for the file.
0423    */
0424   if (rtems_rtl_obj_aname_valid (obj))
0425     pname = rtems_rtl_obj_aname (obj);
0426   else
0427     pname = rtems_rtl_obj_oname (obj);
0428 
0429   rtl = rtems_rtl_lock ();
0430 
0431   if (!rtems_rtl_find_file (pname, rtl->paths, &obj->fname, &obj->fsize))
0432   {
0433     rtems_rtl_set_error (ENOENT, "file not found");
0434     rtems_rtl_unlock ();
0435     return false;
0436   }
0437 
0438   rtems_rtl_unlock ();
0439 
0440   return true;
0441 }
0442 
0443 bool
0444 rtems_rtl_obj_add_section (rtems_rtl_obj* obj,
0445                            int            section,
0446                            const char*    name,
0447                            size_t         size,
0448                            off_t          offset,
0449                            uint32_t       alignment,
0450                            int            link,
0451                            int            info,
0452                            uint32_t       flags)
0453 {
0454   if (size > 0)
0455   {
0456     rtems_rtl_obj_sect* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
0457                                                     sizeof (rtems_rtl_obj_sect),
0458                                                     true);
0459     if (!sect)
0460     {
0461       rtems_rtl_set_error (ENOMEM, "adding allocated section");
0462       return false;
0463     }
0464     sect->section = section;
0465     sect->name = rtems_rtl_strdup (name);
0466     sect->size = size;
0467     sect->offset = offset;
0468     sect->alignment = alignment;
0469     sect->link = link;
0470     sect->info = info;
0471     sect->flags = flags;
0472     sect->base = NULL;
0473     rtems_chain_append (&obj->sections, &sect->node);
0474 
0475     if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
0476       printf ("rtl: sect: add: %-2d: %s (%zu) 0x%08" PRIu32 "\n",
0477               section, name, size, flags);
0478   }
0479   return true;
0480 }
0481 
0482 void
0483 rtems_rtl_obj_erase_sections (rtems_rtl_obj* obj)
0484 {
0485   rtems_chain_node* node = rtems_chain_first (&obj->sections);
0486   while (!rtems_chain_is_tail (&obj->sections, node))
0487   {
0488     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
0489     rtems_chain_node*   next_node = rtems_chain_next (node);
0490     rtems_chain_extract (node);
0491     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) sect->name);
0492     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, sect);
0493     node = next_node;
0494   }
0495 }
0496 
0497 /**
0498  * Section finder iterator data.
0499  */
0500 typedef struct
0501 {
0502   rtems_rtl_obj_sect*  sect;  /**< The matching section. */
0503   const char*          name;  /**< The name to match. */
0504   int                  index; /**< The index to match. */
0505   uint32_t             mask;  /**< The mask to match. */
0506   unsigned int         flags; /**< The flags to use when matching. */
0507 } rtems_rtl_obj_sect_finder;
0508 
0509 static bool
0510 rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data)
0511 {
0512   rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
0513   rtems_rtl_obj_sect_finder* match = data;
0514   if (strcmp (sect->name, match->name) == 0)
0515   {
0516     match->sect = sect;
0517     return false;
0518   }
0519   return true;
0520 }
0521 
0522 rtems_rtl_obj_sect*
0523 rtems_rtl_obj_find_section (const rtems_rtl_obj* obj,
0524                             const char*          name)
0525 {
0526   rtems_rtl_obj_sect_finder match;
0527   match.sect = NULL;
0528   match.name = name;
0529   match.mask = 0;
0530   match.flags = 0;
0531   rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
0532                            rtems_rtl_obj_sect_match_name,
0533                            &match);
0534   return match.sect;
0535 }
0536 
0537 static bool
0538 rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data)
0539 {
0540   rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
0541   rtems_rtl_obj_sect_finder* match = data;
0542   if (sect->section == match->index)
0543   {
0544     match->sect = sect;
0545     return false;
0546   }
0547   return true;
0548 }
0549 
0550 rtems_rtl_obj_sect*
0551 rtems_rtl_obj_find_section_by_index (const rtems_rtl_obj* obj,
0552                                      int                  index)
0553 {
0554   rtems_rtl_obj_sect_finder match;
0555   match.sect = NULL;
0556   match.index = index;
0557   match.mask = 0;
0558   match.flags = 0;
0559   rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
0560                            rtems_rtl_obj_sect_match_index,
0561                            &match);
0562   return match.sect;
0563 }
0564 
0565 static bool
0566 rtems_rtl_obj_sect_match_mask (rtems_chain_node* node, void* data)
0567 {
0568   rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
0569   rtems_rtl_obj_sect_finder* match = data;
0570   if (match->flags == 0)
0571   {
0572     if (match->index < 0 || sect->section == match->index)
0573       match->flags = 1;
0574     if (match->index >= 0)
0575       return true;
0576   }
0577   if ((sect->flags & match->mask) != 0)
0578   {
0579     match->sect = sect;
0580     return false;
0581   }
0582   return true;
0583 }
0584 
0585 rtems_rtl_obj_sect*
0586 rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
0587                                     int                  index,
0588                                     uint32_t             mask)
0589 {
0590   rtems_rtl_obj_sect_finder match;
0591   match.sect = NULL;
0592   match.index = index;
0593   match.mask = mask;
0594   match.flags = 0;
0595   rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
0596                            rtems_rtl_obj_sect_match_mask,
0597                            &match);
0598   return match.sect;
0599 }
0600 
0601 bool
0602 rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
0603 {
0604   rtems_rtl_obj_depends* depends;
0605   size_t                 size;
0606 
0607   size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents;
0608 
0609   depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
0610                                  size,
0611                                  true);
0612   if (depends == NULL)
0613   {
0614     rtems_rtl_set_error (ENOMEM, "no memory for the dependency");
0615   }
0616   else
0617   {
0618     depends->dependents = dependents;
0619     rtems_chain_append (&obj->dependents, &depends->node);
0620   }
0621 
0622   return depends != NULL;
0623 }
0624 
0625 void
0626 rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj)
0627 {
0628   rtems_chain_node* node = rtems_chain_first (&obj->dependents);
0629   while (!rtems_chain_is_tail (&obj->dependents, node))
0630   {
0631     rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
0632     rtems_chain_node*      next_node = rtems_chain_next (node);
0633     rtems_chain_extract (node);
0634     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends);
0635     node = next_node;
0636   }
0637 }
0638 
0639 bool
0640 rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent)
0641 {
0642   rtems_rtl_obj**   free_slot;
0643   rtems_chain_node* node;
0644 
0645   if (obj == dependent || dependent == rtems_rtl_baseimage ())
0646     return false;
0647 
0648   if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
0649     printf ("rtl: depend: add: %s -> %s\n", obj->oname, dependent->oname);
0650 
0651   free_slot = NULL;
0652 
0653   node = rtems_chain_first (&obj->dependents);
0654   while (!rtems_chain_is_tail (&obj->dependents, node))
0655   {
0656     rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
0657     size_t                 d;
0658     for (d = 0; d < depends->dependents; ++d)
0659     {
0660       if (free_slot == NULL && depends->depends[d] == NULL)
0661         free_slot = &(depends->depends[d]);
0662       if (depends->depends[d] == dependent)
0663         return false;
0664     }
0665     node = rtems_chain_next (node);
0666   }
0667 
0668   if (free_slot == NULL)
0669   {
0670     if (rtems_rtl_obj_alloc_dependents (obj,
0671                                         RTEMS_RTL_DEPENDENCY_BLOCK_SIZE))
0672     {
0673       rtems_rtl_obj_depends* depends;
0674       node = rtems_chain_last (&obj->dependents);
0675       depends = (rtems_rtl_obj_depends*) node;
0676       free_slot = &(depends->depends[0]);
0677       if (*free_slot != NULL)
0678       {
0679         rtems_rtl_set_error (EINVAL, "new dependency node not empty");
0680         free_slot = NULL;
0681       }
0682     }
0683   }
0684 
0685   if (free_slot != NULL)
0686     *free_slot = dependent;
0687 
0688   return free_slot != NULL;
0689 }
0690 
0691 
0692 bool
0693 rtems_rtl_obj_remove_dependencies (rtems_rtl_obj* obj)
0694 {
0695   /*
0696    * If there are no references unload the object.
0697    */
0698   if (obj->refs == 0)
0699   {
0700     /*
0701      * Remove the refences from the object files this file depend on. The
0702      * unload happens once the list of objects to be unloaded has been made and
0703      * the destructors have been called for all those modules.
0704      */
0705     rtems_chain_node* node = rtems_chain_first (&obj->dependents);
0706     while (!rtems_chain_is_tail (&obj->dependents, node))
0707     {
0708       rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
0709       size_t                 d;
0710       for (d = 0; d < depends->dependents; ++d)
0711       {
0712         if (depends->depends[d] != NULL)
0713         {
0714           rtems_rtl_obj_dec_reference (depends->depends[d]);
0715           depends->depends[d] = NULL;
0716         }
0717       }
0718       node = rtems_chain_next (node);
0719     }
0720     return true;
0721   }
0722   return false;
0723 }
0724 
0725 bool
0726 rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
0727                                   rtems_rtl_obj_depends_iterator iterator,
0728                                   void*                          data)
0729 {
0730   rtems_chain_node* node = rtems_chain_first (&obj->dependents);
0731   while (!rtems_chain_is_tail (&obj->dependents, node))
0732   {
0733     rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
0734     size_t                 d;
0735     for (d = 0; d < depends->dependents; ++d)
0736     {
0737       if (depends->depends[d])
0738       {
0739         if (iterator (obj, depends->depends[d], data))
0740           return true;
0741       }
0742     }
0743     node = rtems_chain_next (node);
0744   }
0745   return false;
0746 }
0747 
0748 size_t
0749 rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
0750 {
0751   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
0752   return rtems_rtl_obj_section_size (obj, flags);
0753 }
0754 
0755 uint32_t
0756 rtems_rtl_obj_text_alignment (const rtems_rtl_obj* obj)
0757 {
0758   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
0759   return rtems_rtl_obj_section_alignment (obj, flags);
0760 }
0761 
0762 size_t
0763 rtems_rtl_obj_const_size (const rtems_rtl_obj* obj)
0764 {
0765   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
0766   return rtems_rtl_obj_section_size (obj, flags);
0767 }
0768 
0769 uint32_t
0770 rtems_rtl_obj_const_alignment (const rtems_rtl_obj* obj)
0771 {
0772   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
0773   return rtems_rtl_obj_section_alignment (obj, flags);
0774 }
0775 
0776 uint32_t
0777 rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
0778 {
0779   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
0780   return rtems_rtl_obj_section_alignment (obj, flags);
0781 }
0782 
0783 size_t
0784 rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
0785 {
0786   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
0787   return rtems_rtl_obj_section_size (obj, flags);
0788 }
0789 
0790 size_t
0791 rtems_rtl_obj_data_size (const rtems_rtl_obj* obj)
0792 {
0793   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
0794   return rtems_rtl_obj_section_size (obj, flags);
0795 }
0796 
0797 uint32_t
0798 rtems_rtl_obj_data_alignment (const rtems_rtl_obj* obj)
0799 {
0800   const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
0801   return rtems_rtl_obj_section_alignment (obj, flags);
0802 }
0803 
0804 size_t
0805 rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj)
0806 {
0807   return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS);
0808 }
0809 
0810 size_t
0811 rtems_rtl_obj_tramp_size (const rtems_rtl_obj* obj)
0812 {
0813   return obj->tramp_slots * obj->tramp_slot_size;
0814 }
0815 
0816 uint32_t
0817 rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj)
0818 {
0819   return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS);
0820 }
0821 
0822 bool
0823 rtems_rtl_obj_relocate (rtems_rtl_obj*             obj,
0824                         int                        fd,
0825                         rtems_rtl_obj_sect_handler handler,
0826                         void*                      data)
0827 {
0828   const uint32_t flags = (RTEMS_RTL_OBJ_SECT_LOAD |
0829                           RTEMS_RTL_OBJ_SECT_REL |
0830                           RTEMS_RTL_OBJ_SECT_RELA);
0831   bool r = rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
0832   rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
0833   return r;
0834 }
0835 
0836 /**
0837  * Cache synchronization after runtime object load (dlopen)
0838  */
0839 typedef struct
0840 {
0841   uint32_t mask;
0842   void     *start_va;
0843   void     *end_va;
0844   size_t   cache_line_size;
0845 } rtems_rtl_obj_sect_sync_ctx;
0846 
0847 static bool
0848 rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data)
0849 {
0850   rtems_rtl_obj_sect*          sect = (rtems_rtl_obj_sect*) node;
0851   rtems_rtl_obj_sect_sync_ctx* sync_ctx = data;
0852   uintptr_t                    old_end;
0853   uintptr_t                    new_start;
0854 
0855   if ((sect->flags & sync_ctx->mask) == 0 || sect->size == 0)
0856     return true;
0857 
0858   if (sync_ctx->end_va == sync_ctx->start_va)
0859   {
0860     sync_ctx->start_va = sect->base;
0861   }
0862   else
0863   {
0864     old_end = (uintptr_t) sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1);
0865     new_start = (uintptr_t) sect->base & ~(sync_ctx->cache_line_size - 1);
0866     if ((sect->base <  sync_ctx->start_va) ||
0867         (new_start - old_end > sync_ctx->cache_line_size))
0868     {
0869       rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va,
0870                              sync_ctx->end_va - sync_ctx->start_va + 1);
0871       sync_ctx->start_va = sect->base;
0872     }
0873   }
0874 
0875   sync_ctx->end_va = sect->base + sect->size;
0876 
0877   return true;
0878 }
0879 
0880 void
0881 rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
0882 {
0883   rtems_rtl_obj_sect_sync_ctx sync_ctx;
0884 
0885   if (rtems_cache_get_instruction_line_size() == 0)
0886     return;
0887 
0888   sync_ctx.cache_line_size = rtems_cache_get_maximal_line_size();
0889 
0890   sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST |
0891                   RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS |
0892                   RTEMS_RTL_OBJ_SECT_EH   | RTEMS_RTL_OBJ_SECT_EXEC;
0893 
0894   sync_ctx.start_va = 0;
0895   sync_ctx.end_va = sync_ctx.start_va;
0896   rtems_rtl_chain_iterate (&obj->sections,
0897                            rtems_rtl_obj_sect_sync_handler,
0898                            &sync_ctx);
0899 
0900   if (sync_ctx.end_va != sync_ctx.start_va)
0901   {
0902     size_t size = sync_ctx.end_va - sync_ctx.start_va;
0903     rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
0904                                                    size);
0905   }
0906 
0907   if (obj->tramp_base != NULL)
0908   {
0909     rtems_cache_instruction_sync_after_code_change(obj->tramp_base,
0910                                                    obj->tramp_size);
0911   }
0912 }
0913 
0914 bool
0915 rtems_rtl_obj_load_symbols (rtems_rtl_obj*             obj,
0916                             int                        fd,
0917                             rtems_rtl_obj_sect_handler handler,
0918                             void*                      data)
0919 {
0920   uint32_t mask = RTEMS_RTL_OBJ_SECT_SYM;
0921   bool     ok;
0922   ok = rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
0923   if (ok)
0924     rtems_rtl_symbol_obj_sort (obj);
0925   return ok;
0926 }
0927 
0928 static int
0929 rtems_rtl_obj_sections_linked_to_order (rtems_rtl_obj* obj,
0930                                         int            section,
0931                                         uint32_t       visited_mask)
0932 {
0933   rtems_chain_control* sections = &obj->sections;
0934   rtems_chain_node*    node = rtems_chain_first (sections);
0935   /*
0936    * Find the section being linked-to. If the linked-to link field is 0 we have
0937    * the end and the section's order is the position we are after.
0938    */
0939   while (!rtems_chain_is_tail (sections, node))
0940   {
0941     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
0942     if (sect->section == section)
0943     {
0944       const uint32_t mask = sect->flags & RTEMS_RTL_OBJ_SECT_TYPES;
0945       int            order = 0;
0946       if (sect->link != 0)
0947       {
0948         /*
0949          * Have we already visited this type of section? Avoid nesting for
0950          * ever.
0951          */
0952         if ((sect->flags & visited_mask) != 0)
0953         {
0954           rtems_rtl_set_error (errno, "section link loop");
0955           return -1;
0956         }
0957         return rtems_rtl_obj_sections_linked_to_order (obj,
0958                                                        sect->link,
0959                                                        visited_mask | mask);
0960       }
0961       node = rtems_chain_first (sections);
0962       while (!rtems_chain_is_tail (sections, node))
0963       {
0964         sect = (rtems_rtl_obj_sect*) node;
0965         if ((sect->flags & mask) == mask)
0966         {
0967           if (sect->section == section)
0968             return order;
0969           ++order;
0970         }
0971         node = rtems_chain_next (node);
0972       }
0973     }
0974     node = rtems_chain_next (node);
0975   }
0976   rtems_rtl_set_error (errno, "section link not found");
0977   return -1;
0978 }
0979 
0980 static void
0981 rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj)
0982 {
0983   rtems_chain_control* sections = &obj->sections;
0984   rtems_chain_node*    node = rtems_chain_first (sections);
0985   int                  order = 0;
0986   while (!rtems_chain_is_tail (sections, node))
0987   {
0988     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
0989     if ((sect->flags & mask) == mask)
0990     {
0991       /*
0992        * If the section is linked in order find the linked-to section's order
0993        * and move the section in the section list to
0994        */
0995       if (sect->link == 0)
0996         sect->load_order = order++;
0997       else
0998       {
0999         sect->load_order =
1000           rtems_rtl_obj_sections_linked_to_order (obj,
1001                                                   sect->link,
1002                                                   mask);
1003       }
1004     }
1005     node = rtems_chain_next (node);
1006   }
1007 }
1008 
1009 static void
1010 rtems_rtl_obj_sections_locate (uint32_t            mask,
1011                                rtems_rtl_alloc_tag tag,
1012                                rtems_rtl_obj*      obj,
1013                                uint8_t*            base)
1014 {
1015   rtems_chain_control* sections = &obj->sections;
1016   rtems_chain_node*    node = rtems_chain_first (sections);
1017   size_t               base_offset = 0;
1018   int                  order = 0;
1019 
1020   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1021     printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
1022 
1023   while (!rtems_chain_is_tail (sections, node))
1024   {
1025     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1026 
1027     if ((sect->size != 0) && ((sect->flags & mask) == mask))
1028     {
1029       if (sect->load_order == order)
1030       {
1031         if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
1032         {
1033           base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
1034           sect->base = base + base_offset;
1035           base_offset += sect->size;
1036         }
1037 
1038         if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1039           printf ("rtl: locating:%2d: %s -> %p (s:%zi f:%04" PRIx32
1040                   " a:%" PRIu32 " l:%02d)\n",
1041                   order, sect->name, sect->base, sect->size,
1042                   sect->flags, sect->alignment, sect->link);
1043 
1044         ++order;
1045 
1046         node = rtems_chain_first (sections);
1047         continue;
1048       }
1049     }
1050 
1051     node = rtems_chain_next (node);
1052   }
1053 }
1054 
1055 static void
1056 rtems_rtl_obj_set_sizes (rtems_rtl_obj* obj)
1057 {
1058   size_t text_size;
1059   size_t tramp_size;
1060   size_t const_size;
1061   size_t eh_size;
1062   size_t data_size;
1063   size_t bss_size;
1064 
1065   /*
1066    * The allocator may not align memory to the required boundary. Add
1067    * the alignment size to the size allocated.
1068    */
1069   text_size  = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_text_alignment (obj);
1070   tramp_size = rtems_rtl_obj_tramp_size (obj);
1071   if (tramp_size != 0)
1072     tramp_size += rtems_rtl_obj_tramp_alignment (obj);
1073   const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_const_alignment (obj);
1074   eh_size    = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_eh_alignment (obj);
1075   data_size  = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_data_alignment (obj);
1076   bss_size   = rtems_rtl_obj_bss_size (obj) + rtems_rtl_obj_bss_alignment (obj);
1077 
1078   /*
1079    * Set the sizes held in the object data. We need this for a fast reference.
1080    */
1081   obj->text_size  = text_size + tramp_size;
1082   obj->tramp_size = tramp_size;
1083   obj->const_size = const_size;
1084   obj->data_size  = data_size;
1085   obj->eh_size    = eh_size;
1086   obj->bss_size   = bss_size;
1087 
1088   obj->exec_size = text_size + const_size + eh_size + data_size + bss_size;
1089 }
1090 
1091 static void
1092 rtems_rtl_obj_print_sizes (rtems_rtl_obj* obj, const char* label)
1093 {
1094   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1095   {
1096     printf ("rtl: %s sect: text  - b:%p s:%zi a:%" PRIu32 "\n",
1097             label, obj->text_base, obj->text_size, rtems_rtl_obj_text_alignment (obj));
1098     printf ("rtl: %s sect: tramp - b:%p s:%zi a:%" PRIu32 "\n",
1099             label, obj->tramp_base, obj->tramp_size, rtems_rtl_obj_tramp_alignment (obj));
1100     printf ("rtl: %s sect: const - b:%p s:%zi a:%" PRIu32 "\n",
1101             label, obj->const_base, obj->const_size, rtems_rtl_obj_const_alignment (obj));
1102     printf ("rtl: %s sect: eh    - b:%p s:%zi a:%" PRIu32 "\n",
1103             label, obj->eh_base, obj->eh_size, rtems_rtl_obj_eh_alignment (obj));
1104     printf ("rtl: %s sect: data  - b:%p s:%zi a:%" PRIu32 "\n",
1105             label, obj->data_base, obj->data_size, rtems_rtl_obj_data_alignment (obj));
1106     printf ("rtl: %s sect: bss   - b:%p s:%zi a:%" PRIu32 "\n",
1107             label, obj->bss_base, obj->bss_size, rtems_rtl_obj_bss_alignment (obj));
1108   }
1109 }
1110 
1111 static void
1112 rtems_rtl_obj_locate (rtems_rtl_obj* obj)
1113 {
1114   /*
1115    * Locate all text, data and bss sections in seperate operations so each type of
1116    * section is grouped together.
1117    */
1118   rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT,
1119                                  rtems_rtl_alloc_text_tag (),
1120                                  obj, obj->text_base);
1121   rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST,
1122                                  rtems_rtl_alloc_const_tag (),
1123                                  obj, obj->const_base);
1124   rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH,
1125                                  rtems_rtl_alloc_eh_tag (),
1126                                  obj, obj->eh_base);
1127   rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA,
1128                                  rtems_rtl_alloc_data_tag (),
1129                                  obj, obj->data_base);
1130   rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS,
1131                                  rtems_rtl_alloc_bss_tag (),
1132                                  obj, obj->bss_base);
1133 }
1134 
1135 bool
1136 rtems_rtl_obj_alloc_sections (rtems_rtl_obj*             obj,
1137                               int                        fd,
1138                               rtems_rtl_obj_sect_handler handler,
1139                               void*                      data)
1140 {
1141   rtems_rtl_obj_set_sizes (obj);
1142 
1143     /*
1144    * Perform any specific allocations for sections.
1145    */
1146   if (handler != NULL)
1147   {
1148     if (!rtems_rtl_obj_section_handler (RTEMS_RTL_OBJ_SECT_TYPES,
1149                                         obj,
1150                                         fd,
1151                                         handler,
1152                                         data))
1153     {
1154       obj->exec_size = 0;
1155       return false;
1156     }
1157   }
1158 
1159   /*
1160    * Let the allocator manage the actual allocation. The user can use the
1161    * standard heap or provide a specific allocator with memory protection.
1162    */
1163   if (!rtems_rtl_alloc_module_new (&obj->text_base, obj->text_size,
1164                                    &obj->const_base, obj->const_size,
1165                                    &obj->eh_base, obj->eh_size,
1166                                    &obj->data_base, obj->data_size,
1167                                    &obj->bss_base, obj->bss_size))
1168   {
1169     obj->exec_size = 0;
1170     rtems_rtl_set_error (ENOMEM, "no memory to load obj");
1171     return false;
1172   }
1173 
1174   /*
1175    * Set the trampoline base if there are trampolines
1176    */
1177   if (obj->tramp_size != 0)
1178   {
1179     obj->tramp_base = obj->tramp_brk =
1180       obj->text_base + obj->text_size - obj->tramp_size;
1181   }
1182 
1183   rtems_rtl_obj_print_sizes (obj, "alloc");
1184 
1185   /*
1186    * Determine the load order.
1187    */
1188   rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_TEXT,  obj);
1189   rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj);
1190   rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH,    obj);
1191   rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA,  obj);
1192   rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS,   obj);
1193 
1194   /*
1195    * Locate the sections to the allocated section bases
1196    */
1197   rtems_rtl_obj_locate (obj);
1198 
1199   return true;
1200 }
1201 
1202 bool
1203 rtems_rtl_obj_resize_sections (rtems_rtl_obj* obj)
1204 {
1205   rtems_rtl_obj_set_sizes (obj);
1206 
1207   /*
1208    * Let the allocator manage the resizing.
1209    */
1210   if (!rtems_rtl_alloc_module_resize (&obj->text_base, obj->text_size,
1211                                       &obj->const_base, obj->const_size,
1212                                       &obj->eh_base, obj->eh_size,
1213                                       &obj->data_base, obj->data_size,
1214                                       &obj->bss_base, obj->bss_size))
1215   {
1216     rtems_rtl_obj_free (obj);
1217     obj->exec_size = 0;
1218     rtems_rtl_set_error (ENOMEM, "no memory resize obj");
1219     return false;
1220   }
1221 
1222   /*
1223    * Set the trampoline base if there are trampolines
1224    */
1225   if (obj->tramp_size != 0)
1226   {
1227     obj->tramp_base = obj->tramp_brk =
1228       obj->text_base + obj->text_size - obj->tramp_size;
1229   }
1230 
1231   rtems_rtl_obj_print_sizes (obj, "resize");
1232 
1233   /*
1234    * Locate the sections to the allocated section bases
1235    */
1236   rtems_rtl_obj_locate (obj);
1237 
1238   return true;
1239 }
1240 
1241 static bool
1242 rtems_rtl_obj_sections_loader (uint32_t                   mask,
1243                                rtems_rtl_alloc_tag        tag,
1244                                rtems_rtl_obj*             obj,
1245                                int                        fd,
1246                                uint8_t*                   base,
1247                                rtems_rtl_obj_sect_handler handler,
1248                                void*                      data)
1249 {
1250   rtems_chain_control* sections = &obj->sections;
1251   rtems_chain_node*    node = rtems_chain_first (sections);
1252   int                  order = 0;
1253 
1254   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1255     printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
1256 
1257   rtems_rtl_alloc_wr_enable (tag, base);
1258 
1259   while (!rtems_chain_is_tail (sections, node))
1260   {
1261     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1262 
1263     if ((sect->size != 0) && ((sect->flags & mask) == mask))
1264     {
1265       if (sect->load_order == order)
1266       {
1267         if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1268           printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
1269                   " a:%" PRIu32 " l:%02d)\n",
1270                   order, sect->name, sect->base, sect->size,
1271                   sect->flags, sect->alignment, sect->link);
1272 
1273         if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
1274         {
1275           if (!handler (obj, fd, sect, data))
1276           {
1277             sect->base = 0;
1278             rtems_rtl_alloc_wr_disable (tag, base);
1279             return false;
1280           }
1281         }
1282         else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
1283         {
1284           memset (sect->base, 0, sect->size);
1285         }
1286         else
1287         {
1288           /*
1289            * This section is not to be loaded, clear the base.
1290            */
1291           sect->base = 0;
1292         }
1293 
1294         ++order;
1295 
1296         node = rtems_chain_first (sections);
1297         continue;
1298       }
1299     }
1300 
1301     node = rtems_chain_next (node);
1302   }
1303 
1304   rtems_rtl_alloc_wr_disable (tag, base);
1305 
1306   return true;
1307 }
1308 
1309 bool
1310 rtems_rtl_obj_load_sections (rtems_rtl_obj*             obj,
1311                              int                        fd,
1312                              rtems_rtl_obj_sect_handler handler,
1313                              void*                      data)
1314 {
1315   /*
1316    * Load all text, data and bsssections in seperate operations so each type of
1317    * section is grouped together. Finish by loading any architecure specific
1318    * sections.
1319    */
1320   if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT,
1321                                       rtems_rtl_alloc_text_tag (),
1322                                       obj, fd, obj->text_base, handler, data) ||
1323       !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST,
1324                                       rtems_rtl_alloc_const_tag (),
1325                                       obj, fd, obj->const_base, handler, data) ||
1326       !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_EH,
1327                                       rtems_rtl_alloc_eh_tag (),
1328                                       obj, fd, obj->eh_base, handler, data) ||
1329       !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA,
1330                                       rtems_rtl_alloc_data_tag (),
1331                                       obj, fd, obj->data_base, handler, data) ||
1332       !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS,
1333                                       rtems_rtl_alloc_bss_tag (),
1334                                       obj, fd, obj->bss_base, handler, data))
1335   {
1336     rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
1337                                 &obj->data_base, &obj->bss_base);
1338     obj->exec_size = 0;
1339     return false;
1340   }
1341 
1342   return true;
1343 }
1344 
1345 static void
1346 rtems_rtl_obj_run_cdtors (rtems_rtl_obj* obj, uint32_t mask)
1347 {
1348   rtems_chain_node* node = rtems_chain_first (&obj->sections);
1349   while (!rtems_chain_is_tail (&obj->sections, node))
1350   {
1351     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1352     if ((sect->flags & mask) == mask)
1353     {
1354       rtems_rtl_cdtor* handler;
1355       size_t           handlers = sect->size / sizeof (rtems_rtl_cdtor);
1356       int              c;
1357       for (c = 0, handler = sect->base; c < handlers; ++c)
1358         if (*handler)
1359           (*handler) ();
1360     }
1361     node = rtems_chain_next (node);
1362   }
1363 }
1364 
1365 static bool
1366 rtems_rtl_obj_cdtors_to_run (rtems_rtl_obj* obj, uint32_t mask)
1367 {
1368   rtems_chain_node* node = rtems_chain_first (&obj->sections);
1369   while (!rtems_chain_is_tail (&obj->sections, node))
1370   {
1371     rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1372     if ((sect->flags & mask) == mask)
1373       return true;
1374     node = rtems_chain_next (node);
1375   }
1376   return false;
1377 }
1378 
1379 bool
1380 rtems_rtl_obj_ctors_to_run (rtems_rtl_obj* obj)
1381 {
1382   return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_CTOR);
1383 }
1384 
1385 void
1386 rtems_rtl_obj_run_ctors (rtems_rtl_obj* obj)
1387 {
1388   rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR);
1389 }
1390 
1391 bool
1392 rtems_rtl_obj_dtors_to_run (rtems_rtl_obj* obj)
1393 {
1394   return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_DTOR);
1395 }
1396 
1397 void
1398 rtems_rtl_obj_run_dtors (rtems_rtl_obj* obj)
1399 {
1400   rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR);
1401 }
1402 
1403 static bool
1404 rtems_rtl_obj_file_load (rtems_rtl_obj* obj, int fd)
1405 {
1406   int l;
1407 
1408   for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table)); ++l)
1409   {
1410     if (loaders[l].check (obj, fd))
1411     {
1412       obj->format = l;
1413       return loaders[l].load (obj, fd);
1414     }
1415   }
1416 
1417   rtems_rtl_set_error (ENOENT, "no format loader found");
1418   return false;
1419 }
1420 
1421 static void
1422 rtems_rtl_obj_set_error (int num, const char* text)
1423 {
1424   rtems_rtl_set_error (num, text);
1425 }
1426 
1427 size_t
1428 rtems_rtl_obj_get_reference (rtems_rtl_obj* obj)
1429 {
1430   return obj->refs;
1431 }
1432 
1433 void
1434 rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj)
1435 {
1436   ++obj->refs;
1437 }
1438 
1439 void
1440 rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj)
1441 {
1442   if (obj->refs)
1443     --obj->refs;
1444 }
1445 
1446 bool
1447 rtems_rtl_obj_orphaned (rtems_rtl_obj* obj)
1448 {
1449   return ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == 0 &&
1450           obj->users == 0 &&
1451           rtems_rtl_obj_get_reference (obj) == 0);
1452 }
1453 
1454 bool
1455 rtems_rtl_obj_load (rtems_rtl_obj* obj)
1456 {
1457   int fd;
1458 
1459   if (!rtems_rtl_obj_fname_valid (obj))
1460   {
1461     rtems_rtl_set_error (ENOMEM, "invalid object file name path");
1462     return false;
1463   }
1464 
1465   fd = open (rtems_rtl_obj_fname (obj), O_RDONLY);
1466   if (fd < 0)
1467   {
1468     rtems_rtl_set_error (errno, "opening for object file");
1469     return false;
1470   }
1471 
1472   /*
1473    * Find the object file in the archive if it is an archive that
1474    * has been opened.
1475    */
1476   if (rtems_rtl_obj_aname_valid (obj))
1477   {
1478     off_t enames = 0;
1479     if (!rtems_rtl_obj_archive_find_obj (fd,
1480                                          obj->fsize,
1481                                          &obj->oname,
1482                                          &obj->ooffset,
1483                                          &obj->fsize,
1484                                          &enames,
1485                                          rtems_rtl_obj_set_error))
1486     {
1487       close (fd);
1488       return false;
1489     }
1490   }
1491 
1492   /*
1493    * Call the format specific loader.
1494    */
1495   if (!rtems_rtl_obj_file_load (obj, fd))
1496   {
1497     close (fd);
1498     return false;
1499   }
1500 
1501    /*
1502     * For GDB
1503     */
1504   if (!_rtld_linkmap_add (obj))
1505   {
1506     close (fd);
1507     return false;
1508   }
1509 
1510   close (fd);
1511 
1512   return true;
1513 }
1514 
1515 bool
1516 rtems_rtl_obj_unload (rtems_rtl_obj* obj)
1517 {
1518   bool ok = false;
1519   if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
1520   {
1521     _rtld_linkmap_delete(obj);
1522     ok = loaders[obj->format].unload (obj);
1523   }
1524   else
1525   {
1526     rtems_rtl_set_error (EINVAL, "invalid object loader format");
1527   }
1528   return ok;
1529 }