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 rtems_rtld
0007  *
0008  * @brief RTEMS Run-Time Link Editor
0009  *
0010  * This is the RTL implementation.
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 2012-2019 Chris Johns <chrisj@rtems.org>
0015  *
0016  * Redistribution and use in source and binary forms, with or without
0017  * modification, are permitted provided that the following conditions
0018  * are met:
0019  * 1. Redistributions of source code must retain the above copyright
0020  *    notice, this list of conditions and the following disclaimer.
0021  * 2. Redistributions in binary form must reproduce the above copyright
0022  *    notice, this list of conditions and the following disclaimer in the
0023  *    documentation and/or other materials provided with the distribution.
0024  *
0025  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0026  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0027  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0028  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0029  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0030  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0031  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0032  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0033  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0034  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0035  * POSSIBILITY OF SUCH DAMAGE.
0036  */
0037 
0038 #ifdef HAVE_CONFIG_H
0039 #include "config.h"
0040 #endif
0041 
0042 #include <errno.h>
0043 #include <fcntl.h>
0044 #include <inttypes.h>
0045 #include <stdlib.h>
0046 #include <string.h>
0047 #include <stdio.h>
0048 #include <unistd.h>
0049 
0050 #include <rtems/rtl/rtl.h>
0051 #include "rtl-elf.h"
0052 #include "rtl-error.h"
0053 #include <rtems/rtl/rtl-trace.h>
0054 #include "rtl-trampoline.h"
0055 #include "rtl-unwind.h"
0056 #include <rtems/rtl/rtl-unresolved.h>
0057 
0058 /**
0059  * The offsets in the reloc words.
0060  */
0061 #define REL_R_OFFSET (0)
0062 #define REL_R_INFO   (1)
0063 #define REL_R_ADDEND (2)
0064 
0065 /**
0066  * The ELF format signature.
0067  */
0068 static rtems_rtl_loader_format elf_sig =
0069 {
0070   .label = "ELF",
0071   .flags = RTEMS_RTL_FMT_ELF
0072 };
0073 
0074 static const char*
0075 rtems_rtl_elf_sym_type_label (Elf_Byte st_info)
0076 {
0077   const char* label;
0078   switch (ELF_ST_TYPE (st_info))
0079   {
0080     case STT_NOTYPE:
0081       label = "STT_NOTYPE";
0082       break;
0083     case STT_OBJECT:
0084       label = "STT_OBJECT";
0085       break;
0086     case STT_FUNC:
0087       label = "STT_FUNC";
0088       break;
0089     case STT_SECTION:
0090       label = "STT_SECTION";
0091       break;
0092     case STT_FILE:
0093       label = "STT_FILE";
0094       break;
0095     case STT_COMMON:
0096       label = "STT_COMMON";
0097       break;
0098     case STT_TLS:
0099       label = "STT_TLS";
0100       break;
0101     default:
0102       label = "unknown";
0103       break;
0104   }
0105   return label;
0106 }
0107 
0108 static const char*
0109 rtems_rtl_elf_sym_bind_label (Elf_Byte st_info)
0110 {
0111   const char* label;
0112   switch (ELF_ST_BIND (st_info))
0113   {
0114     case STB_LOCAL:
0115       label = "STB_LOCAL";
0116       break;
0117     case STB_GLOBAL:
0118       label = "STB_GLOBAL";
0119       break;
0120     case STB_WEAK:
0121       label = "STB_WEAK";
0122       break;
0123     default:
0124       label = "unknown";
0125       break;
0126   }
0127   return label;
0128 }
0129 
0130 static bool
0131 rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
0132 {
0133   /*
0134    * This code is determined by the NetBSD machine headers.
0135    */
0136   switch (ehdr->e_machine)
0137   {
0138     ELFDEFNNAME (MACHDEP_ID_CASES)
0139     default:
0140       return false;
0141   }
0142   return true;
0143 }
0144 
0145 static const char*
0146 rtems_rtl_elf_separated_section (const char* name)
0147 {
0148   struct {
0149     const char* label;
0150     size_t      len;
0151   } prefix[] = {
0152     #define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 }
0153     SEPARATED_PREFIX (".text."),
0154     SEPARATED_PREFIX (".rel.text."),
0155     SEPARATED_PREFIX (".data."),
0156     SEPARATED_PREFIX (".rel.data."),
0157     SEPARATED_PREFIX (".rodata."),
0158     SEPARATED_PREFIX (".rel.rodata.")
0159   };
0160   const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]);
0161   size_t       p;
0162   for (p = 0; p < prefixes; ++p)
0163   {
0164     if (strncmp (name, prefix[p].label, prefix[p].len) == 0)
0165       return name + prefix[p].len;
0166   }
0167   return NULL;
0168 }
0169 
0170 static bool
0171 rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
0172                            const Elf_Sym*      sym,
0173                            const char*         symname,
0174                            rtems_rtl_obj_sym** symbol,
0175                            Elf_Word*           value)
0176 {
0177   rtems_rtl_obj_sect* sect;
0178 
0179   /*
0180    * If the symbol bind is STB_GLOBAL the symbol references a global
0181    * symbol. The global symbol table is searched to find it and that value
0182    * returned. If the symbol is local to the object module the section for the
0183    * symbol is located and it's base added to the symbol's value giving an
0184    * absolute location.
0185    *
0186    * If the symbols type of TLS return the symbols value. It is the
0187    * offset from the thread's TLS area base. The offset is set by the
0188    * linker for the base image and by the TLS allocator for loaded
0189    * modules. There is no section and no absolute base.
0190    */
0191   if (ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0192       sym->st_shndx == SHN_COMMON ||
0193       ELF_ST_TYPE (sym->st_info) == STT_TLS)
0194   {
0195     /*
0196      * Search the object file then the global table for the symbol.
0197      */
0198     *symbol = rtems_rtl_symbol_obj_find (obj, symname);
0199     if (!*symbol)
0200       return false;
0201 
0202     *value = (Elf_Addr)(uintptr_t) (*symbol)->value;
0203     return true;
0204   }
0205 
0206   *symbol = NULL;
0207 
0208   sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
0209   if (!sect)
0210     return false;
0211 
0212   *value = sym->st_value + (Elf_Addr)(uintptr_t) sect->base;
0213 
0214   return true;
0215 }
0216 
0217 /**
0218  * Relocation worker routine.
0219  */
0220 typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj*      obj,
0221                                             bool                is_rela,
0222                                             void*               relbuf,
0223                                             rtems_rtl_obj_sect* targetsect,
0224                                             rtems_rtl_obj_sym*  symbol,
0225                                             Elf_Sym*            sym,
0226                                             const char*         symname,
0227                                             Elf_Word            symvalue,
0228                                             bool                resolved,
0229                                             void*               data);
0230 
0231 /**
0232  * Relocation parser data.
0233  */
0234 typedef struct
0235 {
0236   size_t dependents; /**< The number of dependent object files. */
0237   size_t unresolved; /**< The number of unresolved symbols. */
0238 } rtems_rtl_elf_reloc_data;
0239 
0240 static bool
0241 rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
0242                             bool                is_rela,
0243                             void*               relbuf,
0244                             rtems_rtl_obj_sect* targetsect,
0245                             rtems_rtl_obj_sym*  symbol,
0246                             Elf_Sym*            sym,
0247                             const char*         symname,
0248                             Elf_Word            symvalue,
0249                             bool                resolved,
0250                             void*               data)
0251 {
0252   rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
0253   rtems_rtl_word            rel_words[3];
0254   rtems_rtl_elf_rel_status  rs;
0255 
0256   /*
0257    * TLS are not parsed.
0258    */
0259   if (ELF_ST_TYPE (sym->st_info) == STT_TLS) {
0260     return true;
0261   }
0262 
0263   /*
0264    * Check the reloc record to see if a trampoline is needed.
0265    */
0266   if (is_rela)
0267   {
0268     const Elf_Rela* rela = (const Elf_Rela*) relbuf;
0269     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0270       printf ("rtl: rela tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
0271               ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0272               ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
0273               symname, (int) ELF_R_SYM (rela->r_info),
0274               (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
0275               (uintmax_t) rela->r_offset, (int) rela->r_addend);
0276     rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
0277                                             symname, sym->st_info, symvalue);
0278     rel_words[REL_R_OFFSET] = rela->r_offset;
0279     rel_words[REL_R_INFO] = rela->r_info;
0280     rel_words[REL_R_ADDEND] = rela->r_addend;
0281   }
0282   else
0283   {
0284     const Elf_Rel* rel = (const Elf_Rel*) relbuf;
0285     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0286       printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n",
0287               ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
0288               ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
0289               symname, (int) ELF_R_SYM (rel->r_info),
0290               (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
0291               (uintmax_t) rel->r_offset);
0292     rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
0293                                            symname, sym->st_info, symvalue);
0294     rel_words[REL_R_OFFSET] = rel->r_offset;
0295     rel_words[REL_R_INFO] = rel->r_info;
0296     rel_words[REL_R_ADDEND] = 0;
0297   }
0298 
0299   if (rs == rtems_rtl_elf_rel_failure)
0300     return false;
0301 
0302   if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add)
0303   {
0304     uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8);
0305     if (!rtems_rtl_trampoline_add (obj, flags,
0306                                    targetsect->section, symvalue, rel_words))
0307       return false;
0308   }
0309 
0310   /*
0311    * Handle any dependencies if there is a valid symbol.
0312    */
0313   if (symname != NULL)
0314   {
0315     /*
0316      * Find the symbol's object file. It cannot be NULL so ignore that result
0317      * if returned, it means something is corrupted. We are in an iterator.
0318      */
0319     rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
0320     if (sobj != NULL)
0321     {
0322       /*
0323        * A dependency is not the base kernel image or itself. Tag the object as
0324        * having been visited so we count it only once.
0325        */
0326       if (sobj != rtems_rtl_baseimage () && obj != sobj &&
0327           (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
0328       {
0329         sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
0330         ++rd->dependents;
0331       }
0332     }
0333   }
0334 
0335   return true;
0336 }
0337 
0338 static bool
0339 rtems_rtl_elf_reloc_relocator (rtems_rtl_obj*      obj,
0340                                bool                is_rela,
0341                                void*               relbuf,
0342                                rtems_rtl_obj_sect* targetsect,
0343                                rtems_rtl_obj_sym*  symbol,
0344                                Elf_Sym*            sym,
0345                                const char*         symname,
0346                                Elf_Word            symvalue,
0347                                bool                resolved,
0348                                void*               data)
0349 {
0350   const Elf_Rela* rela = (const Elf_Rela*) relbuf;
0351   const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
0352 
0353   if (!resolved)
0354   {
0355     uint16_t       flags = 0;
0356     rtems_rtl_word rel_words[3];
0357 
0358     if (is_rela)
0359     {
0360       flags = 1;
0361       rel_words[REL_R_OFFSET] = rela->r_offset;
0362       rel_words[REL_R_INFO] = rela->r_info;
0363       rel_words[REL_R_ADDEND] = rela->r_addend;
0364     }
0365     else
0366     {
0367       rel_words[REL_R_OFFSET] = rel->r_offset;
0368       rel_words[REL_R_INFO] = rel->r_info;
0369       rel_words[REL_R_ADDEND] = 0;
0370     }
0371 
0372     if (!rtems_rtl_unresolved_add (obj,
0373                                    flags,
0374                                    symname,
0375                                    targetsect->section,
0376                                    rel_words))
0377       return false;
0378 
0379     ++obj->unresolved;
0380   }
0381   else
0382   {
0383     rtems_rtl_obj*           sobj;
0384     rtems_rtl_elf_rel_status rs;
0385 
0386     if (is_rela)
0387     {
0388       if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0389         printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
0390                 symname, (int) ELF_R_SYM (rela->r_info),
0391                 (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
0392                 (uintmax_t) rela->r_offset, (int) rela->r_addend);
0393       rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
0394                                         symname, sym->st_info, symvalue);
0395       if (rs != rtems_rtl_elf_rel_no_error)
0396         return false;
0397     }
0398     else
0399     {
0400       if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0401         printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
0402                 symname, (int) ELF_R_SYM (rel->r_info),
0403                 (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
0404                 (uintmax_t) rel->r_offset);
0405       rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
0406                                        symname, sym->st_info, symvalue);
0407       if (rs != rtems_rtl_elf_rel_no_error)
0408         return false;
0409     }
0410 
0411     sobj = rtems_rtl_find_obj_with_symbol (symbol);
0412 
0413     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
0414       printf ("rtl: depend: %s -> %s:%s\n",
0415               obj->oname,
0416               sobj == NULL ? "not-found" : sobj->oname,
0417               symname);
0418 
0419     if (sobj != NULL)
0420     {
0421       if (rtems_rtl_obj_add_dependent (obj, sobj))
0422         rtems_rtl_obj_inc_reference (sobj);
0423     }
0424   }
0425 
0426   return true;
0427 }
0428 
0429 static bool
0430 rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
0431                                int                         fd,
0432                                rtems_rtl_obj_sect*         sect,
0433                                rtems_rtl_elf_reloc_handler handler,
0434                                void*                       data)
0435 {
0436   rtems_rtl_obj_cache* symbols;
0437   rtems_rtl_obj_cache* strings;
0438   rtems_rtl_obj_cache* relocs;
0439   rtems_rtl_obj_sect*  targetsect;
0440   rtems_rtl_obj_sect*  symsect;
0441   rtems_rtl_obj_sect*  strtab;
0442   bool                 is_rela;
0443   size_t               reloc_size;
0444   int                  reloc;
0445 
0446   /*
0447    * First check if the section the relocations are for exists. If it does not
0448    * exist ignore these relocations. They are most probably debug sections.
0449    */
0450   targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info);
0451   if (!targetsect)
0452     return true;
0453 
0454   /*
0455    * The section muct has been loaded. It could be a separate section in an
0456    * archive and not loaded.
0457    */
0458   if ((targetsect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == 0)
0459     return true;
0460 
0461 
0462   rtems_rtl_obj_caches (&symbols, &strings, &relocs);
0463 
0464   if (!symbols || !strings || !relocs)
0465     return false;
0466 
0467   symsect = rtems_rtl_obj_find_section (obj, ".symtab");
0468   if (!symsect)
0469   {
0470     rtems_rtl_set_error (EINVAL, "no .symtab section");
0471     return false;
0472   }
0473 
0474   strtab = rtems_rtl_obj_find_section (obj, ".strtab");
0475   if (!strtab)
0476   {
0477     rtems_rtl_set_error (EINVAL, "no .strtab section");
0478     return false;
0479   }
0480 
0481   if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0482     printf ("rtl: relocation: %s, syms:%s\n", sect->name, symsect->name);
0483 
0484   /*
0485    * Handle the different relocation record types.
0486    */
0487   is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) ==
0488              RTEMS_RTL_OBJ_SECT_RELA) ? true : false;
0489   reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel);
0490 
0491   for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
0492   {
0493     uint8_t            relbuf[reloc_size];
0494     const Elf_Rela*    rela = (const Elf_Rela*) relbuf;
0495     const Elf_Rel*     rel = (const Elf_Rel*) relbuf;
0496     rtems_rtl_obj_sym* symbol = NULL;
0497     Elf_Sym            sym;
0498     const char*        symname = NULL;
0499     off_t              off;
0500     Elf_Word           rel_type;
0501     Elf_Word           symvalue = 0;
0502     bool               resolved;
0503 
0504     off = obj->ooffset + sect->offset + (reloc * reloc_size);
0505 
0506     if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off,
0507                                          &relbuf[0], reloc_size))
0508       return false;
0509 
0510     /*
0511      * Read the symbol details.
0512      */
0513     if (is_rela)
0514       off = (obj->ooffset + symsect->offset +
0515              (ELF_R_SYM (rela->r_info) * sizeof (sym)));
0516     else
0517       off = (obj->ooffset + symsect->offset +
0518              (ELF_R_SYM (rel->r_info) * sizeof (sym)));
0519 
0520     if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0521                                          &sym, sizeof (sym)))
0522       return false;
0523 
0524     /*
0525      * Only need the name of the symbol if global or a common symbol.
0526      */
0527     if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT ||
0528         ELF_ST_TYPE (sym.st_info) == STT_COMMON ||
0529         ELF_ST_TYPE (sym.st_info) == STT_FUNC ||
0530         ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
0531         ELF_ST_TYPE (sym.st_info) == STT_TLS ||
0532         sym.st_shndx == SHN_COMMON)
0533     {
0534       size_t len;
0535       off = obj->ooffset + strtab->offset + sym.st_name;
0536       len = RTEMS_RTL_ELF_STRING_MAX;
0537 
0538       if (!rtems_rtl_obj_cache_read (strings, fd, off,
0539                                      (void**) &symname, &len))
0540         return false;
0541     }
0542 
0543     /*
0544      * See if the record references an external symbol. If it does find the
0545      * symbol value. If the symbol cannot be found flag the object file as
0546      * having unresolved externals and store the external. The load of an
0547      * object after this one may provide the unresolved externals.
0548      */
0549     if (is_rela)
0550       rel_type = ELF_R_TYPE(rela->r_info);
0551     else
0552       rel_type = ELF_R_TYPE(rel->r_info);
0553 
0554     resolved = true;
0555 
0556     if (rtems_rtl_elf_rel_resolve_sym (rel_type))
0557       resolved = rtems_rtl_elf_find_symbol (obj,
0558                                             &sym, symname,
0559                                             &symbol, &symvalue);
0560 
0561     if (!handler (obj,
0562                   is_rela, relbuf, targetsect,
0563                   symbol, &sym, symname, symvalue, resolved,
0564                   data))
0565       return false;
0566   }
0567 
0568   /*
0569    * Set the unresolved externals status if there are unresolved externals.
0570    */
0571   if (obj->unresolved)
0572     obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED;
0573 
0574   return true;
0575 }
0576 
0577 static bool
0578 rtems_rtl_elf_relocs_parser (rtems_rtl_obj*      obj,
0579                              int                 fd,
0580                              rtems_rtl_obj_sect* sect,
0581                              void*               data)
0582 {
0583   bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
0584                                           rtems_rtl_elf_reloc_parser, data);
0585   return r;
0586 }
0587 
0588 static bool
0589 rtems_rtl_elf_relocs_locator (rtems_rtl_obj*      obj,
0590                               int                 fd,
0591                               rtems_rtl_obj_sect* sect,
0592                               void*               data)
0593 {
0594   return rtems_rtl_elf_relocate_worker (obj, fd, sect,
0595                                         rtems_rtl_elf_reloc_relocator, data);
0596 }
0597 
0598 bool
0599 rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
0600                                    rtems_rtl_obj_sym*        sym)
0601 {
0602   rtems_rtl_obj_sect*      sect;
0603   bool                     is_rela;
0604   Elf_Word                 symvalue;
0605   rtems_rtl_obj*           sobj;
0606   rtems_rtl_elf_rel_status rs;
0607 
0608   is_rela = reloc->flags & 1;
0609 
0610   sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
0611   if (!sect)
0612   {
0613     rtems_rtl_set_error (ENOEXEC, "unresolved sect not found");
0614     return false;
0615   }
0616 
0617   symvalue = (Elf_Word) (intptr_t) sym->value;
0618   if (is_rela)
0619   {
0620     Elf_Rela rela;
0621     rela.r_offset = reloc->rel[REL_R_OFFSET];
0622     rela.r_info = reloc->rel[REL_R_INFO];
0623     rela.r_addend = reloc->rel[REL_R_ADDEND];
0624     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0625           printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n",
0626                   (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
0627                   (uintmax_t) rela.r_offset, (int) rela.r_addend);
0628     rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
0629                                       sym->name, sym->data, symvalue);
0630     if (rs != rtems_rtl_elf_rel_no_error)
0631       return false;
0632   }
0633   else
0634   {
0635     Elf_Rel rel;
0636     rel.r_offset = reloc->rel[REL_R_OFFSET];
0637     rel.r_info = reloc->rel[REL_R_INFO];
0638     if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0639       printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
0640               (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
0641               (uintmax_t) rel.r_offset);
0642     rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
0643                                      sym->name, sym->data, symvalue);
0644     if (rs != rtems_rtl_elf_rel_no_error)
0645       return false;
0646   }
0647 
0648   if (reloc->obj->unresolved > 0)
0649   {
0650     --reloc->obj->unresolved;
0651     if (reloc->obj->unresolved == 0)
0652       reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
0653   }
0654 
0655   sobj = rtems_rtl_find_obj_with_symbol (sym);
0656 
0657   if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
0658     printf ("rtl: depend: %s -> %s:%s\n",
0659             reloc->obj->oname,
0660             sobj == NULL ? "not-found" : sobj->oname,
0661             sym->name);
0662 
0663   if (sobj != NULL)
0664   {
0665     if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
0666       rtems_rtl_obj_inc_reference (sobj);
0667   }
0668 
0669   return true;
0670 }
0671 
0672 /**
0673  * Common symbol iterator data.
0674  */
0675 typedef struct
0676 {
0677   size_t   size;      /**< The size of the common section */
0678   uint32_t alignment; /**< The alignment of the common section. */
0679 } rtems_rtl_elf_common_data;
0680 
0681 static bool
0682 rtems_rtl_elf_common (rtems_rtl_obj*      obj,
0683                       int                 fd,
0684                       rtems_rtl_obj_sect* sect,
0685                       void*               data)
0686 {
0687   rtems_rtl_elf_common_data* common = (rtems_rtl_elf_common_data*) data;
0688   rtems_rtl_obj_cache*       symbols;
0689   int                        sym;
0690 
0691   rtems_rtl_obj_caches (&symbols, NULL, NULL);
0692 
0693   if (!symbols)
0694     return false;
0695 
0696   /*
0697    * Find the number size of the common section by finding all symbols that
0698    * reference the SHN_COMMON section.
0699    */
0700   for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
0701   {
0702     Elf_Sym symbol;
0703     off_t   off;
0704 
0705     off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
0706 
0707     if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0708                                          &symbol, sizeof (symbol)))
0709       return false;
0710 
0711     if ((symbol.st_shndx == SHN_COMMON) &&
0712         ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
0713          (ELF_ST_TYPE (symbol.st_info) == STT_COMMON)))
0714     {
0715       if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0716         printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d name:%d\n",
0717                 sym, (int) ELF_ST_BIND (symbol.st_info),
0718                 (int) ELF_ST_TYPE (symbol.st_info),
0719                 (int) symbol.st_size, (int) symbol.st_value,
0720                 (int) symbol.st_name);
0721       /*
0722        * If the size is zero this is the first entry, it defines the common
0723        * section's aligment. The symbol's value is the alignment.
0724        */
0725       if (common->size == 0)
0726         common->alignment = symbol.st_value;
0727       common->size +=
0728         rtems_rtl_obj_align (common->size, symbol.st_value) + symbol.st_size;
0729     }
0730   }
0731 
0732   return true;
0733 }
0734 
0735 /**
0736  * Struct to handle trampoline reloc recs in the unresolved table.
0737  */
0738 typedef struct rtems_rtl_tramp_data
0739 {
0740   bool           failure;
0741   rtems_rtl_obj* obj;
0742   size_t         count;
0743   size_t         total;
0744 } rtems_rtl_tramp_data;
0745 
0746 static bool
0747 rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
0748                                    void*                   data)
0749 {
0750   rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data;
0751   if (rec->type == rtems_rtl_trampoline_reloc)
0752   {
0753     const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp;
0754 
0755     ++td->total;
0756 
0757     if (tramp->obj == td->obj)
0758     {
0759       const rtems_rtl_obj_sect* targetsect;
0760       Elf_Byte                  st_info;
0761       Elf_Word                  symvalue;
0762       rtems_rtl_elf_rel_status  rs;
0763       bool*                     failure = (bool*) data;
0764       const bool                is_rela = (tramp->flags & 1) == 1;
0765       const bool                unresolved = (tramp->flags & (1 << 1)) != 0;
0766 
0767       ++td->count;
0768 
0769       targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect);
0770       st_info = tramp->flags >> 8;
0771       symvalue = tramp->symvalue;
0772 
0773       if (is_rela)
0774       {
0775         Elf_Rela rela = {
0776           .r_offset = tramp->rel[REL_R_OFFSET],
0777           .r_info   = tramp->rel[REL_R_INFO],
0778           .r_addend = tramp->rel[REL_R_ADDEND]
0779         };
0780         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0781           printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n",
0782                   ELF_ST_BIND (st_info) == STB_GLOBAL ||
0783                   ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
0784                   (int) ELF_R_SYM (rela.r_info),
0785                   (uintmax_t) symvalue, (int) ELF_R_TYPE (rela.r_info),
0786                   (uintmax_t) rela.r_offset, (int) rela.r_addend);
0787         rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect,
0788                                                 NULL, st_info, symvalue);
0789       }
0790       else
0791       {
0792         Elf_Rel rel = {
0793           .r_offset = tramp->rel[REL_R_OFFSET],
0794           .r_info   = tramp->rel[REL_R_INFO],
0795         };
0796         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0797           printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n",
0798                   ELF_ST_BIND (st_info) == STB_GLOBAL ||
0799                   ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
0800                   (int) ELF_R_SYM (rel.r_info),
0801                   (uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info),
0802                   (uintmax_t) rel.r_offset);
0803         rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect,
0804                                                NULL, st_info, symvalue);
0805       }
0806 
0807       if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
0808         ++tramp->obj->tramp_slots;
0809       if (rs == rtems_rtl_elf_rel_failure)
0810       {
0811         *failure = true;
0812         return true;
0813       }
0814     }
0815   }
0816 
0817   return false;
0818 }
0819 
0820 static bool
0821 rtems_rtl_elf_find_trampolines (rtems_rtl_obj* obj, size_t unresolved)
0822 {
0823   rtems_rtl_tramp_data td =  { 0 };
0824   td.obj = obj;
0825   /*
0826    * See which relocs are out of range and need a trampoline.
0827    */
0828   rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td);
0829   if (td.failure)
0830     return false;
0831   rtems_rtl_trampoline_remove (obj);
0832   obj->tramp_relocs = obj->tramp_slots;
0833   if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0834     printf ("rtl: tramp:elf: tramps: slots:%zu count:%zu total:%zu\n",
0835             obj->tramp_relocs, td.count, td.total);
0836   /*
0837    * Add on enough space to handle the unresolved externals that need to be
0838    * resolved at some point in time. They could all require fixups and
0839    * trampolines.
0840    */
0841   obj->tramp_slots += unresolved;
0842   if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0843     printf ("rtl: tramp:elf: slots:%zu (%zu)\n",
0844             obj->tramp_slots, obj->tramp_slots * obj->tramp_slot_size);
0845   return true;
0846 }
0847 
0848 static bool
0849 rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
0850 {
0851   /*
0852    * If there are dependencies and no unresolved externals allocate and size
0853    * the dependency table to the number of dependent object files. If there are
0854    * unresolved externals the number of dependencies is unknown at this point
0855    * in time so use dynamic allocation to allocate the block size number of
0856    * entries when the entries are added.
0857    */
0858   if (reloc->dependents > 0 && reloc->unresolved == 0)
0859   {
0860     if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
0861       return false;
0862   }
0863   return true;
0864 }
0865 
0866 static bool
0867 rtems_rtl_elf_symbols_load (rtems_rtl_obj*      obj,
0868                             int                 fd,
0869                             rtems_rtl_obj_sect* sect,
0870                             void*               data)
0871 {
0872   rtems_rtl_obj_cache* symbols;
0873   rtems_rtl_obj_cache* strings;
0874   rtems_rtl_obj_sect*  strtab;
0875   int                  locals;
0876   int                  local_string_space;
0877   rtems_rtl_obj_sym*   lsym;
0878   char*                lstring;
0879   int                  globals;
0880   int                  global_string_space;
0881   rtems_rtl_obj_sym*   gsym;
0882   char*                gstring;
0883   size_t               common_offset;
0884   int                  sym;
0885 
0886   strtab = rtems_rtl_obj_find_section (obj, ".strtab");
0887   if (!strtab)
0888   {
0889     rtems_rtl_set_error (EINVAL, "no .strtab section");
0890     return false;
0891   }
0892 
0893   rtems_rtl_obj_caches (&symbols, &strings, NULL);
0894 
0895   if (!symbols || !strings)
0896     return false;
0897 
0898   /*
0899    * Find the number of globals and the amount of string space
0900    * needed. Also check for duplicate symbols.
0901    */
0902 
0903   globals             = 0;
0904   global_string_space = 0;
0905   locals              = 0;
0906   local_string_space  = 0;
0907 
0908   for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
0909   {
0910     Elf_Sym     symbol;
0911     off_t       off;
0912     const char* name;
0913     size_t      len;
0914 
0915     off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
0916 
0917     if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
0918                                          &symbol, sizeof (symbol)))
0919       return false;
0920 
0921     off = obj->ooffset + strtab->offset + symbol.st_name;
0922     len = RTEMS_RTL_ELF_STRING_MAX;
0923 
0924     if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
0925       return false;
0926 
0927     /*
0928      * Only keep the functions and global or weak symbols so place them in a
0929      * separate table to local symbols. Local symbols are not needed after the
0930      * object file has been loaded. Undefined symbols are NOTYPE so for locals
0931      * we need to make sure there is a valid seciton.
0932      */
0933     if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0934       printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d:%-12s " \
0935               "type:%-2d:%-10s sect:%-5d size:%-5d value:%d\n",
0936               sym, (int) symbol.st_name, name,
0937               (int) ELF_ST_BIND (symbol.st_info),
0938               rtems_rtl_elf_sym_bind_label (symbol.st_info),
0939               (int) ELF_ST_TYPE (symbol.st_info),
0940               rtems_rtl_elf_sym_type_label (symbol.st_info),
0941               symbol.st_shndx,
0942               (int) symbol.st_size,
0943               (int) symbol.st_value);
0944 
0945     /*
0946      * If a duplicate forget it.
0947      */
0948     if (rtems_rtl_symbol_global_find (name))
0949       continue;
0950 
0951     if ((symbol.st_shndx != 0) &&
0952         ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
0953          (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
0954          (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
0955          (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)))
0956     {
0957       /*
0958        * There needs to be a valid section for the symbol.
0959        */
0960       rtems_rtl_obj_sect* symsect;
0961 
0962       symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
0963       if (symsect != NULL)
0964       {
0965         if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
0966             (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
0967         {
0968           /*
0969            * If there is a globally exported symbol already present and this
0970            * symbol is not weak raise check if the object file being loaded is
0971            * from an archive. If the base image is built with text sections a
0972            * symbol with it's section will be linked into the base image and not
0973            * another symbol. If not an archive rause an error.
0974            *
0975            * If the symbol is weak and present globally ignore this symbol and
0976            * use the global one and if it is not present take this symbol global
0977            * or weak. We accept the first weak symbol we find and make it
0978            * globally exported.
0979            */
0980           if (rtems_rtl_symbol_global_find (name) &&
0981               (ELF_ST_BIND (symbol.st_info) != STB_WEAK))
0982           {
0983             if (!rtems_rtl_obj_aname_valid (obj))
0984             {
0985               rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
0986               return false;
0987             }
0988           }
0989           else
0990           {
0991             if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0992               printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n",
0993                       sym, (int) symbol.st_name, name);
0994             ++globals;
0995             global_string_space += strlen (name) + 1;
0996           }
0997         }
0998         else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
0999         {
1000           if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1001             printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n",
1002                     sym, (int) symbol.st_name, name);
1003           ++locals;
1004           local_string_space += strlen (name) + 1;
1005         }
1006       }
1007     }
1008   }
1009 
1010   if (locals)
1011   {
1012     obj->local_size = locals * sizeof (rtems_rtl_obj_sym) + local_string_space;
1013     obj->local_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
1014                                             obj->local_size, true);
1015     if (!obj->local_table)
1016     {
1017       obj->local_size = 0;
1018       rtems_rtl_set_error (ENOMEM, "no memory for obj local syms");
1019       return false;
1020     }
1021 
1022     obj->local_syms = locals;
1023   }
1024 
1025   if (globals)
1026   {
1027     obj->global_size = globals * sizeof (rtems_rtl_obj_sym) + global_string_space;
1028     obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
1029                                              obj->global_size, true);
1030     if (!obj->global_table)
1031     {
1032       if (locals)
1033       {
1034         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1035         obj->local_size = 0;
1036         obj->local_syms = 0;
1037       }
1038       obj->global_size = 0;
1039       rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
1040       return false;
1041     }
1042 
1043     obj->global_syms = globals;
1044   }
1045 
1046   lsym = obj->local_table;
1047   lstring =
1048     (((char*) obj->local_table) + (locals * sizeof (rtems_rtl_obj_sym)));
1049   gsym = obj->global_table;
1050   gstring =
1051     (((char*) obj->global_table) + (globals * sizeof (rtems_rtl_obj_sym)));
1052 
1053   common_offset = 0;
1054 
1055   for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
1056   {
1057     Elf_Sym symbol;
1058     off_t   off;
1059     size_t  len;
1060 
1061     off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
1062 
1063     if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
1064                                          &symbol, sizeof (symbol)))
1065     {
1066       if (obj->local_syms)
1067       {
1068         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1069         obj->local_table = NULL;
1070         obj->local_size = 0;
1071         obj->local_syms = 0;
1072       }
1073       if (obj->global_syms)
1074       {
1075         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
1076         obj->global_table = NULL;
1077         obj->global_syms = 0;
1078         obj->global_size = 0;
1079       }
1080       return false;
1081     }
1082 
1083     if ((symbol.st_shndx != 0) &&
1084         ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
1085          (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
1086          (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
1087          (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)) &&
1088          ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
1089           (ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
1090           (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
1091     {
1092       rtems_rtl_obj_sect* symsect;
1093 
1094       /*
1095        * There needs to be a valid section for the symbol.
1096        */
1097       symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
1098 
1099       if (symsect != NULL)
1100       {
1101         rtems_rtl_obj_sym*  osym;
1102         char*               string;
1103         Elf_Word            value;
1104         const char*         name;
1105 
1106         off = obj->ooffset + strtab->offset + symbol.st_name;
1107         len = RTEMS_RTL_ELF_STRING_MAX;
1108 
1109         if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
1110           return false;
1111 
1112         /*
1113          * If a duplicate forget it.
1114          */
1115         if (rtems_rtl_symbol_global_find (name))
1116           continue;
1117 
1118         if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
1119             (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
1120         {
1121           size_t slen = strlen (name) + 1;
1122           if ((gstring + slen) > (char*) obj->global_table + obj->global_size)
1123             string = NULL;
1124           else
1125           {
1126             osym = gsym;
1127             string = gstring;
1128             gstring += slen;
1129             ++gsym;
1130           }
1131         }
1132         else
1133         {
1134           size_t slen = strlen (name) + 1;
1135           if ((lstring + slen) > (char*) obj->local_table + obj->local_size)
1136             string = NULL;
1137           else
1138           {
1139             osym = lsym;
1140             string = lstring;
1141             lstring += slen;
1142             ++lsym;
1143           }
1144         }
1145 
1146         /*
1147          * See if the loading has overflowed the allocated tables.
1148          */
1149         if (string == NULL)
1150         {
1151           if (obj->local_syms)
1152           {
1153             rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
1154             obj->local_table = NULL;
1155             obj->local_size = 0;
1156             obj->local_syms = 0;
1157           }
1158           if (obj->global_syms)
1159           {
1160             rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
1161             obj->global_table = NULL;
1162             obj->global_syms = 0;
1163             obj->global_size = 0;
1164           }
1165           rtems_rtl_set_error (ENOMEM, "syms overlow, parsing/loading size mismatch");
1166           return false;
1167         }
1168 
1169         /*
1170          * Allocate any common symbols in the common section.
1171          */
1172         if (symbol.st_shndx == SHN_COMMON)
1173         {
1174           size_t value_off = rtems_rtl_obj_align (common_offset,
1175                                                   symbol.st_value);
1176           common_offset = value_off + symbol.st_size;
1177           value = value_off;
1178         }
1179         else
1180         {
1181           value = symbol.st_value;
1182         }
1183 
1184         rtems_chain_set_off_chain (&osym->node);
1185         memcpy (string, name, strlen (name) + 1);
1186         osym->name = string;
1187         osym->value = (void*) (intptr_t) value;
1188         osym->data = symbol.st_shndx;
1189 
1190         if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1191           printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
1192                   "type:%-2d val:%-8p sect:%-3d size:%d\n",
1193                   sym, (int) symbol.st_name, osym->name,
1194                   (int) ELF_ST_BIND (symbol.st_info),
1195                   (int) ELF_ST_TYPE (symbol.st_info),
1196                   osym->value, symbol.st_shndx,
1197                   (int) symbol.st_size);
1198       }
1199     }
1200   }
1201 
1202   return true;
1203 }
1204 
1205 static bool
1206 rtems_rtl_elf_symbols_locate (rtems_rtl_obj*      obj,
1207                               int                 fd,
1208                               rtems_rtl_obj_sect* sect,
1209                               void*               data)
1210 {
1211   int sym;
1212 
1213   for (sym = 0; sym < obj->local_syms; ++sym)
1214   {
1215       rtems_rtl_obj_sym*  osym = &obj->local_table[sym];
1216       rtems_rtl_obj_sect* symsect;
1217       symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
1218       if (symsect)
1219       {
1220         osym->value += (intptr_t) symsect->base;
1221         if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1222           printf ("rtl: sym:locate:local :%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
1223                   sym, osym->name, osym->value, osym->data,
1224                   symsect->name, symsect->base);
1225       }
1226   }
1227 
1228   for (sym = 0; sym < obj->global_syms; ++sym)
1229   {
1230       rtems_rtl_obj_sym*  osym = &obj->global_table[sym];
1231       rtems_rtl_obj_sect* symsect;
1232       symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
1233       if (symsect)
1234       {
1235         osym->value += (intptr_t) symsect->base;
1236         if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
1237           printf ("rtl: sym:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
1238                   sym, osym->name, osym->value, osym->data,
1239                   symsect->name, symsect->base);
1240       }
1241   }
1242 
1243   if (obj->global_size)
1244     rtems_rtl_symbol_obj_add (obj);
1245 
1246   return true;
1247 }
1248 
1249 static bool
1250 rtems_rtl_elf_arch_alloc (rtems_rtl_obj*      obj,
1251                           int                 fd,
1252                           rtems_rtl_obj_sect* sect,
1253                           void*               data)
1254 {
1255   if (rtems_rtl_obj_sect_is_arch_alloc (sect))
1256     return rtems_rtl_elf_arch_section_alloc (obj, sect);
1257   return true;
1258 }
1259 
1260 static bool
1261 rtems_rtl_elf_arch_free (rtems_rtl_obj* obj)
1262 {
1263   int index = -1;
1264   while (true)
1265   {
1266     rtems_rtl_obj_sect* sect;
1267     sect = rtems_rtl_obj_find_section_by_mask (obj,
1268                                                index,
1269                                                RTEMS_RTL_OBJ_SECT_ARCH_ALLOC);
1270     if (sect == NULL)
1271       break;
1272     if (!rtems_rtl_elf_arch_section_free (obj, sect))
1273       return false;
1274     index = sect->section;
1275   }
1276   return true;
1277 }
1278 
1279 static bool
1280 rtems_rtl_elf_loader (rtems_rtl_obj*      obj,
1281                       int                 fd,
1282                       rtems_rtl_obj_sect* sect,
1283                       void*               data)
1284 {
1285   uint8_t* base_offset;
1286   size_t   len;
1287 
1288   if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
1289   {
1290     rtems_rtl_set_error (errno, "section load seek failed");
1291     return false;
1292   }
1293 
1294   base_offset = sect->base;
1295   len = sect->size;
1296 
1297   while (len)
1298   {
1299     ssize_t r = read (fd, base_offset, len);
1300     if (r <= 0)
1301     {
1302       rtems_rtl_set_error (errno, "section load read failed");
1303       return false;
1304     }
1305     base_offset += r;
1306     len -= r;
1307   }
1308 
1309   return true;
1310 }
1311 
1312 static bool
1313 rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
1314 {
1315   rtems_rtl_obj_cache* sects;
1316   rtems_rtl_obj_cache* strings;
1317   int                  section;
1318   off_t                sectstroff;
1319   off_t                off;
1320   Elf_Shdr             shdr;
1321 
1322   rtems_rtl_obj_caches (&sects, &strings, NULL);
1323 
1324   if (!sects || !strings)
1325     return false;
1326 
1327   /*
1328    * Get the offset to the section string table.
1329    */
1330   off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize);
1331 
1332   if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
1333     return false;
1334 
1335   if (shdr.sh_type != SHT_STRTAB)
1336   {
1337     rtems_rtl_set_error (EINVAL, "bad .sectstr section type");
1338     return false;
1339   }
1340 
1341   sectstroff = obj->ooffset + shdr.sh_offset;
1342 
1343   for (section = 0; section < ehdr->e_shnum; ++section)
1344   {
1345     char*    name;
1346     size_t   len;
1347     uint32_t flags;
1348 
1349     /*
1350      * Make sure section is at least 32bits to avoid 16-bit overflow errors.
1351      */
1352     off = obj->ooffset + ehdr->e_shoff + (((uint32_t) section) * ehdr->e_shentsize);
1353 
1354     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
1355       printf ("rtl: section header: %2d: offset=%d\n", section, (int) off);
1356 
1357     if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
1358       return false;
1359 
1360     len = RTEMS_RTL_ELF_STRING_MAX;
1361     if (!rtems_rtl_obj_cache_read (strings, fd,
1362                                    sectstroff + shdr.sh_name,
1363                                    (void**) &name, &len))
1364       return false;
1365 
1366     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
1367       printf ("rtl: section: %2d: name=%s type=%d flags=%08x link=%d info=%d\n",
1368               section, name, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
1369               (int) shdr.sh_link, (int) shdr.sh_info);
1370 
1371     flags = 0;
1372 
1373     switch (shdr.sh_type)
1374     {
1375       case SHT_NULL:
1376         /*
1377          * Ignore.
1378          */
1379         break;
1380 
1381       case SHT_PROGBITS:
1382         /*
1383          * There are 2 program bits sections. One is the program text and the
1384          * other is the program data. The program text is flagged
1385          * alloc/executable and the program data is flagged alloc/writable.
1386          */
1387         if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
1388         {
1389           if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
1390             flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD;
1391           else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE)
1392             flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD;
1393           else
1394             flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD;
1395         }
1396         break;
1397 
1398       case SHT_NOBITS:
1399         /*
1400          * There is 1 NOBIT section which is the .bss section. There is nothing
1401          * but a definition as the .bss is just a clear region of memory.
1402          */
1403         if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE))
1404           flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO;
1405         break;
1406 
1407       case SHT_RELA:
1408         flags = RTEMS_RTL_OBJ_SECT_RELA | RTEMS_RTL_OBJ_SECT_LOAD;
1409         break;
1410 
1411       case SHT_REL:
1412         /*
1413          * The sh_link holds the section index for the symbol table. The sh_info
1414          * holds the section index the relocations apply to.
1415          */
1416         flags = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_LOAD;
1417         break;
1418 
1419       case SHT_SYMTAB:
1420         flags = RTEMS_RTL_OBJ_SECT_SYM;
1421         break;
1422 
1423       case SHT_STRTAB:
1424         flags = RTEMS_RTL_OBJ_SECT_STR;
1425         break;
1426 
1427       case SHT_INIT_ARRAY:
1428         /*
1429          * Constructors are text and need to be loaded.
1430          */
1431         flags = (RTEMS_RTL_OBJ_SECT_CTOR |
1432                  RTEMS_RTL_OBJ_SECT_TEXT |
1433                  RTEMS_RTL_OBJ_SECT_LOAD);
1434         break;
1435 
1436       case SHT_FINI_ARRAY:
1437         /*
1438          * Destructors are text and need to be loaded.
1439          */
1440         flags = (RTEMS_RTL_OBJ_SECT_DTOR |
1441                  RTEMS_RTL_OBJ_SECT_TEXT |
1442                  RTEMS_RTL_OBJ_SECT_LOAD);
1443         break;
1444 
1445       default:
1446         /*
1447          * See if there are architecture specific flags?
1448          */
1449         flags = rtems_rtl_elf_section_flags (obj, &shdr);
1450         if (flags == 0)
1451         {
1452           if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
1453             printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
1454                     section, (int) shdr.sh_type, (int) shdr.sh_flags);
1455         }
1456         break;
1457     }
1458 
1459     if (flags != 0)
1460     {
1461       /*
1462        * If the object file is part of a library check the section's name. If it
1463        * starts with '.text.*' see if the last part is a global symbol. If a
1464        * global symbol exists we have to assume the symbol in the archive is a
1465        * duplicate can can be ignored.
1466        */
1467       if (rtems_rtl_obj_aname_valid (obj))
1468       {
1469         const char* symname = rtems_rtl_elf_separated_section (name);
1470         if (symname != NULL && rtems_rtl_symbol_global_find (symname))
1471           flags &= ~RTEMS_RTL_OBJ_SECT_LOAD;
1472       }
1473 
1474       /*
1475        * If link ordering this section must appear in the same order in memory
1476        * as the linked-to section relative to the sections it loads with.
1477        */
1478       if ((shdr.sh_flags & SHF_LINK_ORDER) != 0)
1479         flags |= RTEMS_RTL_OBJ_SECT_LINK;
1480 
1481       /*
1482        * Some architexctures have a named PROGBIT section for INIT/FINI.
1483        */
1484       if (strcmp (".ctors", name) == 0)
1485         flags |= RTEMS_RTL_OBJ_SECT_CTOR;
1486       if (strcmp (".dtors", name) == 0)
1487         flags |= RTEMS_RTL_OBJ_SECT_DTOR;
1488 
1489       if (rtems_rtl_elf_unwind_parse (obj, name, flags))
1490       {
1491         flags &= ~(RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST);
1492         flags |= RTEMS_RTL_OBJ_SECT_EH;
1493       }
1494 
1495       /*
1496        * Architecture specific parsing. Modified or extends the flags.
1497        */
1498       flags = rtems_rtl_elf_arch_parse_section (obj, section, name, &shdr, flags);
1499       if (flags == 0)
1500       {
1501         if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
1502           printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
1503                   section, (int) shdr.sh_type, (int) shdr.sh_flags);
1504         rtems_rtl_set_error (ENOMEM, "invalid architecture section: %s", name);
1505         return false;
1506       }
1507 
1508       /*
1509        * Add the section.
1510        */
1511       if (!rtems_rtl_obj_add_section (obj, section, name,
1512                                       shdr.sh_size, shdr.sh_offset,
1513                                       shdr.sh_addralign, shdr.sh_link,
1514                                       shdr.sh_info, flags))
1515         return false;
1516     }
1517   }
1518 
1519   return true;
1520 }
1521 
1522 static bool
1523 rtems_rtl_elf_add_common (rtems_rtl_obj* obj, size_t size, uint32_t alignment)
1524 {
1525   if (size > 0)
1526   {
1527     if (!rtems_rtl_obj_add_section (obj, SHN_COMMON, ".common.rtems.rtl",
1528                                     size, 0, alignment, 0, 0,
1529                                     RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO))
1530       return false;
1531   }
1532   return true;
1533 }
1534 
1535 bool
1536 rtems_rtl_elf_file_check (rtems_rtl_obj* obj, int fd)
1537 {
1538   rtems_rtl_obj_cache* header;
1539   Elf_Ehdr             ehdr;
1540 
1541   rtems_rtl_obj_caches (&header, NULL, NULL);
1542 
1543   if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1544                                        &ehdr, sizeof (ehdr)))
1545     return false;
1546 
1547   /*
1548    * Check we have a valid ELF file.
1549    */
1550   if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1551       || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1552   {
1553     return false;
1554   }
1555 
1556   if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1557       || (ehdr.e_version != EV_CURRENT)
1558       || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1559   {
1560     return false;
1561   }
1562 
1563   return true;
1564 }
1565 
1566 static bool
1567 rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
1568 {
1569   rtems_chain_control* sections = NULL;
1570   rtems_chain_node*    node = NULL;
1571   int                  sec_num = 0;
1572   section_detail*      sd;
1573   int                  i = 0;
1574   size_t               m;
1575 
1576   /*
1577    * The section masks to add to the linkmap.
1578    */
1579   const uint32_t       sect_mask[] = {
1580     RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD,
1581     RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD,
1582     RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD,
1583     RTEMS_RTL_OBJ_SECT_BSS
1584   };
1585   const size_t sect_masks = sizeof (sect_mask) / sizeof (sect_mask[0]);
1586 
1587   /*
1588    * Caculate the size of sections' name.
1589    */
1590   for (m = 0; m < sect_masks; ++m)
1591   {
1592     sections = &obj->sections;
1593     node = rtems_chain_first (sections);
1594     while (!rtems_chain_is_tail (sections, node))
1595     {
1596       rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1597       const uint32_t      mask = sect_mask[m];
1598       if ((sect->size != 0) && ((sect->flags & mask) == mask))
1599       {
1600         ++sec_num;
1601       }
1602       node = rtems_chain_next (node);
1603     }
1604   }
1605 
1606   obj->obj_num = 1;
1607   obj->linkmap = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
1608                                       sizeof(struct link_map) +
1609                                       sec_num * sizeof (section_detail), true);
1610   if (!obj->linkmap)
1611   {
1612     rtems_rtl_set_error (ENOMEM, "no memory for obj linkmap");
1613     return false;
1614   }
1615 
1616   obj->linkmap->name = obj->oname;
1617   obj->linkmap->sec_num = sec_num;
1618   obj->linkmap->sec_detail = (section_detail*) (obj->linkmap + 1);
1619   obj->linkmap->rpathlen = 0;
1620   obj->linkmap->rpath = NULL;
1621   obj->linkmap->l_next = NULL;
1622   obj->linkmap->l_prev = NULL;
1623   obj->linkmap->sec_addr[rap_text] = obj->text_base;
1624   obj->linkmap->sec_addr[rap_const] = obj->const_base;
1625   obj->linkmap->sec_addr[rap_data] = obj->data_base;
1626   obj->linkmap->sec_addr[rap_bss] = obj->bss_base;
1627 
1628   sd = obj->linkmap->sec_detail;
1629 
1630   for (m = 0; m < sect_masks; ++m)
1631   {
1632     sections = &obj->sections;
1633     node = rtems_chain_first (sections);
1634     while (!rtems_chain_is_tail (sections, node))
1635     {
1636       rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1637       const uint32_t      mask = sect_mask[m];
1638 
1639       if ((sect->size != 0) && ((sect->flags & mask) == mask))
1640       {
1641         sd[i].name = sect->name;
1642         sd[i].size = sect->size;
1643         if ((mask & RTEMS_RTL_OBJ_SECT_TEXT) != 0)
1644         {
1645           sd[i].rap_id = rap_text;
1646           sd[i].offset = sect->base - obj->text_base;
1647         }
1648         if ((mask & RTEMS_RTL_OBJ_SECT_CONST) != 0)
1649         {
1650           sd[i].rap_id = rap_const;
1651           sd[i].offset = sect->base - obj->const_base;
1652         }
1653         if ((mask & RTEMS_RTL_OBJ_SECT_DATA) != 0)
1654         {
1655           sd[i].rap_id = rap_data;
1656           sd[i].offset = sect->base - obj->data_base;
1657         }
1658         if ((mask & RTEMS_RTL_OBJ_SECT_BSS) != 0)
1659         {
1660           sd[i].rap_id = rap_bss;
1661           sd[i].offset = sect->base - obj->bss_base;
1662         }
1663 
1664         ++i;
1665       }
1666       node = rtems_chain_next (node);
1667     }
1668   }
1669 
1670   return true;
1671 }
1672 
1673 bool
1674 rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
1675 {
1676   rtems_rtl_obj_cache*      header;
1677   Elf_Ehdr                  ehdr;
1678   rtems_rtl_elf_reloc_data  relocs = { 0 };
1679   rtems_rtl_elf_common_data common = { 0 };
1680 
1681   rtems_rtl_obj_caches (&header, NULL, NULL);
1682 
1683   if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1684                                        &ehdr, sizeof (ehdr)))
1685     return false;
1686 
1687   /*
1688    * Check we have a valid ELF file.
1689    */
1690   if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1691       || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1692   {
1693     rtems_rtl_set_error (EINVAL, "invalid ELF file format");
1694     return false;
1695   }
1696 
1697   if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1698       || (ehdr.e_version != EV_CURRENT)
1699       || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1700   {
1701     rtems_rtl_set_error (EINVAL, "unsupported ELF file version");
1702     return false;
1703   }
1704 
1705   if (!rtems_rtl_elf_machine_check (&ehdr))
1706   {
1707     rtems_rtl_set_error (EINVAL, "unsupported machine type");
1708     return false;
1709   }
1710 
1711   if (ehdr.e_type == ET_DYN)
1712   {
1713     rtems_rtl_set_error (EINVAL, "unsupported ELF file type");
1714     return false;
1715   }
1716 
1717   if (ehdr.e_phentsize != 0)
1718   {
1719     rtems_rtl_set_error (EINVAL, "ELF file contains program headers");
1720     return false;
1721   }
1722 
1723   if (ehdr.e_shentsize != sizeof (Elf_Shdr))
1724   {
1725     rtems_rtl_set_error (EINVAL, "invalid ELF section header size");
1726     return false;
1727   }
1728 
1729   /*
1730    * Set the format's architecture's maximum tramp size.
1731    */
1732   obj->tramp_slot_size = rtems_rtl_elf_relocate_tramp_max_size ();
1733 
1734   /*
1735    * Parse the section information first so we have the memory map of the object
1736    * file and the memory allocated. Any further allocations we make to complete
1737    * the load will not fragment the memory.
1738    */
1739   if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr))
1740     return false;
1741 
1742   /*
1743    * Set the entry point if there is one.
1744    */
1745   obj->entry = (void*)(uintptr_t) ehdr.e_entry;
1746 
1747   /*
1748    * Load the symbol table.
1749    *
1750    * 1. See if there are any common variables and if there are add a
1751    *    common section.
1752    * 2. Add up the common.
1753    * 3. The load the symbols.
1754    */
1755   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
1756     return false;
1757   if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
1758     return false;
1759   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &ehdr))
1760     return false;
1761 
1762   /*
1763    * Parse the relocation records. It lets us know how many dependents
1764    * and fixup trampolines there are.
1765    */
1766   if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
1767     return false;
1768 
1769   /*
1770    * Lock the allocator so the section memory and the trampoline memory are as
1771    * clock as possible.
1772    */
1773   rtems_rtl_alloc_lock ();
1774 
1775   /*
1776    * Allocate the sections.
1777    */
1778   if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
1779     return false;
1780 
1781   if (!rtems_rtl_elf_dependents (obj, &relocs))
1782     return false;
1783 
1784   if (!rtems_rtl_elf_find_trampolines (obj, relocs.unresolved))
1785     return false;
1786 
1787   /*
1788    * Resize the sections to allocate the trampoline memory as part of
1789    * the text section.
1790    */
1791   if (rtems_rtl_obj_has_trampolines (obj))
1792   {
1793     if (!rtems_rtl_obj_resize_sections (obj))
1794       return false;
1795   }
1796 
1797   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
1798     return false;
1799 
1800   /*
1801    * Unlock the allocator.
1802    */
1803   rtems_rtl_alloc_unlock ();
1804 
1805   /*
1806    * Load the sections and symbols and then relocation to the base address.
1807    */
1808   if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
1809     return false;
1810 
1811   /*
1812    * Fix up the relocations.
1813    */
1814   if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
1815     return false;
1816 
1817   rtems_rtl_symbol_obj_erase_local (obj);
1818 
1819   if (!rtems_rtl_elf_load_linkmap (obj))
1820   {
1821     return false;
1822   }
1823 
1824   if (!rtems_rtl_elf_unwind_register (obj))
1825   {
1826     return false;
1827   }
1828 
1829   return true;
1830 }
1831 
1832 bool
1833 rtems_rtl_elf_file_unload (rtems_rtl_obj* obj)
1834 {
1835   rtems_rtl_elf_arch_free (obj);
1836   rtems_rtl_elf_unwind_deregister (obj);
1837   return true;
1838 }
1839 
1840 rtems_rtl_loader_format*
1841 rtems_rtl_elf_file_sig (void)
1842 {
1843   return &elf_sig;
1844 }