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 RAP format loader support..
0011  */
0012 
0013 /*
0014  *  COPYRIGHT (c) 2012-2013, 2018 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-obj-comp.h>
0054 #include "rtl-rap.h"
0055 #include <rtems/rtl/rtl-trace.h>
0056 #include <rtems/rtl/rtl-unresolved.h>
0057 
0058 /**
0059  * The offsets in the unresolved array.
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 rap_sig =
0069 {
0070   .label = "RAP",
0071   .flags = RTEMS_RTL_FMT_COMP
0072 };
0073 
0074 /**
0075  * The section definitions found in a RAP file.
0076  */
0077 typedef struct rtems_rtl_rap_sectdef
0078 {
0079   const char*    name;    /**< Name of the section. */
0080   const uint32_t flags;   /**< Section flags. */
0081 } rtems_rtl_rap_sectdef;
0082 
0083 /**
0084  * The section indexes. These are fixed.
0085  */
0086 #define RTEMS_RTL_RAP_TEXT_SEC  (0)
0087 #define RTEMS_RTL_RAP_CONST_SEC (1)
0088 #define RTEMS_RTL_RAP_CTOR_SEC  (2)
0089 #define RTEMS_RTL_RAP_DTOR_SEC  (3)
0090 #define RTEMS_RTL_RAP_DATA_SEC  (4)
0091 #define RTEMS_RTL_RAP_BSS_SEC   (5)
0092 #define RTEMS_RTL_RAP_SECS      (6)
0093 
0094 /**
0095  * The sections as loaded from a RAP file.
0096  */
0097 static const rtems_rtl_rap_sectdef rap_sections[RTEMS_RTL_RAP_SECS] =
0098 {
0099   { ".text",  RTEMS_RTL_OBJ_SECT_TEXT  | RTEMS_RTL_OBJ_SECT_LOAD },
0100   { ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD },
0101   { ".ctor",  RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR },
0102   { ".dtor",  RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR },
0103   { ".data",  RTEMS_RTL_OBJ_SECT_DATA  | RTEMS_RTL_OBJ_SECT_LOAD },
0104   { ".bss",   RTEMS_RTL_OBJ_SECT_BSS   | RTEMS_RTL_OBJ_SECT_ZERO }
0105 };
0106 
0107 /**
0108  * The section definitions found in a RAP file.
0109  */
0110 typedef struct rtems_rtl_rap_section
0111 {
0112   uint32_t size;       /**< The size of the section. */
0113   uint32_t alignment;  /**< The alignment of the section. */
0114 } rtems_rtl_rap_section;
0115 
0116 /**
0117  * The RAP loader.
0118  */
0119 typedef struct rtems_rtl_rap
0120 {
0121   rtems_rtl_obj_cache*  file;         /**< The file cache for the RAP file. */
0122   rtems_rtl_obj_comp*   decomp;       /**< The decompression streamer. */
0123   uint32_t              length;       /**< The file length. */
0124   uint32_t              version;      /**< The RAP file version. */
0125   uint32_t              compression;  /**< The type of compression. */
0126   uint32_t              checksum;     /**< The checksum. */
0127   uint32_t              machinetype;  /**< The ELF machine type. */
0128   uint32_t              datatype;     /**< The ELF data type. */
0129   uint32_t              class;        /**< The ELF class. */
0130   uint32_t              init;         /**< The initialisation strtab offset. */
0131   uint32_t              fini;         /**< The finish strtab offset. */
0132   rtems_rtl_rap_section secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */
0133   uint32_t              symtab_size;  /**< The symbol table size. */
0134   char*                 strtab;       /**< The string table. */
0135   uint32_t              strtab_size;  /**< The string table size. */
0136   uint32_t              relocs_size;  /**< The relocation table size. */
0137   uint32_t              symbols;      /**< The number of symbols. */
0138   uint32_t              strtable_size;/**< The size of section names and obj names. */
0139   uint32_t              rpathlen;     /**< The length of rpath. */
0140   char*                 strtable;     /**< The detail string which resides in obj detail. */
0141 } rtems_rtl_rap;
0142 
0143 /**
0144  * Check the machine type.
0145  */
0146 static bool
0147 rtems_rtl_rap_machine_check (uint32_t machinetype)
0148 {
0149   /*
0150    * This code is determined by the machine headers.
0151    */
0152   switch (machinetype)
0153   {
0154     ELFDEFNNAME (MACHDEP_ID_CASES)
0155     default:
0156       return false;
0157   }
0158   return true;
0159 }
0160 
0161 /**
0162  * Check the data type.
0163  */
0164 static bool
0165 rtems_rtl_rap_datatype_check (uint32_t datatype)
0166 {
0167   /*
0168    * This code is determined by the machine headers.
0169    */
0170   if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS))
0171     return false;
0172   return true;
0173 }
0174 
0175 /**
0176  * Check the class of executable.
0177  */
0178 static bool
0179 rtems_rtl_rap_class_check (uint32_t class)
0180 {
0181   /*
0182    * This code is determined by the machine headers.
0183    */
0184   switch (class)
0185   {
0186     case ELFCLASS32:
0187       if (ARCH_ELFSIZE == 32)
0188         return true;
0189       break;
0190     case ELFCLASS64:
0191       if (ARCH_ELFSIZE == 64)
0192         return true;
0193       break;
0194     default:
0195       break;
0196   }
0197   return false;
0198 }
0199 
0200 static uint32_t
0201 rtems_rtl_rap_get_uint32 (const uint8_t* buffer)
0202 {
0203   uint32_t value = 0;
0204   int      b;
0205   for (b = 0; b < sizeof (uint32_t); ++b)
0206   {
0207     value <<= 8;
0208     value |= buffer[b];
0209   }
0210   return value;
0211 }
0212 
0213 static bool
0214 rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp* comp, uint32_t* value)
0215 {
0216   uint8_t buffer[sizeof (uint32_t)];
0217 
0218   if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t)))
0219     return false;
0220 
0221   *value = rtems_rtl_rap_get_uint32 (buffer);
0222 
0223   return true;
0224 }
0225 
0226 static bool
0227 rtems_rtl_rap_loader (rtems_rtl_obj*      obj,
0228                       int                 fd,
0229                       rtems_rtl_obj_sect* sect,
0230                       void*               data)
0231 {
0232   rtems_rtl_rap* rap = (rtems_rtl_rap*) data;
0233 
0234   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0235     printf ("rtl: rap: input %s=%" PRIu32 "\n",
0236             sect->name, rtems_rtl_obj_comp_input (rap->decomp));
0237 
0238   return rtems_rtl_obj_comp_read (rap->decomp, sect->base, sect->size);
0239 }
0240 
0241 static bool
0242 rtems_rtl_rap_relocate (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
0243 {
0244   #define SYMNAME_BUFFER_SIZE (1024)
0245   char*    symname_buffer = NULL;
0246   int      section;
0247 
0248   if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0249     printf ("rtl: relocation\n");
0250 
0251   symname_buffer = malloc (SYMNAME_BUFFER_SIZE);
0252   if (!symname_buffer)
0253   {
0254     rtems_rtl_set_error (ENOMEM, "no memory for local symbol name buffer");
0255     return false;
0256   }
0257 
0258   for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
0259   {
0260     rtems_rtl_obj_sect* targetsect;
0261     uint32_t            header = 0;
0262     int                 relocs;
0263     bool                is_rela;
0264     int                 r;
0265 
0266     targetsect = rtems_rtl_obj_find_section (obj, rap_sections[section].name);
0267 
0268     if (!targetsect)
0269       continue;
0270 
0271     if (!rtems_rtl_rap_read_uint32 (rap->decomp, &header))
0272     {
0273       free (symname_buffer);
0274       return false;
0275     }
0276 
0277     /*
0278      * Bit 31 of the header indicates if the relocations for this section
0279      * have a valid addend field.
0280      */
0281 
0282     is_rela = (header & (1 << 31)) != 0 ? true : false;
0283     relocs = header & ~(1 << 31);
0284 
0285     if (relocs && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0286       printf ("rtl: relocation: %s: header: %08" PRIx32 " relocs: %d %s\n",
0287               rap_sections[section].name,
0288               header, relocs, is_rela ? "rela" : "rel");
0289 
0290     for (r = 0; r < relocs; ++r)
0291     {
0292       uint32_t    info = 0;
0293       uint32_t    offset = 0;
0294       uint32_t    addend = 0;
0295       Elf_Word    type;
0296       const char* symname = NULL;
0297       uint32_t    symname_size;
0298       Elf_Word    symtype = 0;
0299       Elf_Word    symvalue = 0;
0300 
0301       if (!rtems_rtl_rap_read_uint32 (rap->decomp, &info))
0302       {
0303         free (symname_buffer);
0304         return false;
0305       }
0306 
0307       if (!rtems_rtl_rap_read_uint32 (rap->decomp, &offset))
0308       {
0309         free (symname_buffer);
0310         return false;
0311       }
0312 
0313       /*
0314        * The types are:
0315        *
0316        *  0  Section symbol offset in addend.
0317        *  1  Symbol appended to the relocation record.
0318        *  2  Symbol is in the strtabl.
0319        *
0320        * If type 2 bits 30:8 is the offset in the strtab. If type 1 the bits
0321        * are the size of the string. The lower 8 bits of the info field if the
0322        * ELF relocation type field.
0323        */
0324 
0325       if (((info & (1 << 31)) == 0) || is_rela)
0326       {
0327         if (!rtems_rtl_rap_read_uint32 (rap->decomp, &addend))
0328         {
0329           free (symname_buffer);
0330           return false;
0331         }
0332       }
0333 
0334       if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0335         printf (" %2d: info=%08" PRIx32 " offset=%" PRIu32
0336                 " addend=%" PRIu32 "\n",
0337                 r, info, offset, addend);
0338 
0339       type = ELF_R_TYPE(info);
0340 
0341       if ((info & (1 << 31)) == 0)
0342       {
0343         rtems_rtl_obj_sect* symsect;
0344 
0345         symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
0346         if (!symsect)
0347         {
0348           free (symname_buffer);
0349           rtems_rtl_set_error (EINVAL, "symsect not found: %d", info >> 8);
0350           return false;
0351         }
0352 
0353         symvalue = (Elf_Addr)(uintptr_t) symsect->base + addend;
0354       }
0355       else if (rtems_rtl_elf_rel_resolve_sym (type))
0356       {
0357         rtems_rtl_obj_sym* symbol;
0358 
0359         symname_size = (info & ~(3 << 30)) >> 8;
0360 
0361         if ((info & (1 << 30)) != 0)
0362         {
0363           symname = rap->strtab + symname_size;
0364         }
0365         else
0366         {
0367           if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
0368           {
0369             free (symname_buffer);
0370             rtems_rtl_set_error (EINVAL, "reloc symbol too big");
0371             return false;
0372           }
0373 
0374           if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
0375           {
0376             free (symname_buffer);
0377             return false;
0378           }
0379 
0380           symname_buffer[symname_size] = '\0';
0381           symname = symname_buffer;
0382         }
0383 
0384         symbol = rtems_rtl_symbol_obj_find (obj, symname);
0385 
0386         if (!symbol)
0387         {
0388           rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
0389           free (symname_buffer);
0390           return false;
0391         }
0392 
0393         symvalue = (Elf_Addr)(uintptr_t) symbol->value;
0394       }
0395 
0396       if (is_rela)
0397       {
0398         Elf_Rela rela;
0399 
0400         rela.r_offset = offset;
0401         rela.r_info = type;
0402 
0403         if ((info & (1 << 31)) == 0)
0404           rela.r_addend = 0;
0405         else rela.r_addend = addend;
0406 
0407         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0408           printf (" %2d: rela: type:%-2d off:%" PRIu32 " addend:%d"
0409                   " symname=%s symtype=%ju symvalue=0x%08jx\n",
0410                   r, (int) type, offset, (int) addend,
0411                   symname, (uintmax_t) symtype, (uintmax_t) symvalue);
0412 
0413         if (rtems_rtl_elf_relocate_rela (obj,
0414                                          &rela,
0415                                          targetsect,
0416                                          symname,
0417                                          symtype,
0418                                          symvalue) == rtems_rtl_elf_rel_failure)
0419         {
0420           free (symname_buffer);
0421           return false;
0422         }
0423       }
0424       else
0425       {
0426         Elf_Rel rel;
0427 
0428         rel.r_offset = offset;
0429         rel.r_info = type;
0430 
0431         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
0432           printf (" %2d: rel: type:%-2d off:%" PRIu32
0433                   " symname=%s symtype=%ju symvalue=0x%08jx\n",
0434                   r, (int) type, offset,
0435                   symname, (uintmax_t) symtype, (uintmax_t) symvalue);
0436 
0437         if (rtems_rtl_elf_relocate_rel (obj,
0438                                         &rel,
0439                                         targetsect,
0440                                         symname,
0441                                         symtype,
0442                                         symvalue) == rtems_rtl_elf_rel_failure)
0443         {
0444           free (symname_buffer);
0445           return false;
0446         }
0447       }
0448     }
0449   }
0450 
0451   free (symname_buffer);
0452 
0453   return true;
0454 }
0455 
0456 /**
0457  * The structure of obj->linkmap is:
0458  *
0459  * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])|
0460  * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num])
0461  *
0462  */
0463 static bool
0464 rtems_rtl_rap_load_linkmap (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
0465 {
0466   void*            detail;
0467   struct link_map* tmp1;
0468   section_detail*  tmp2;
0469   uint32_t         obj_detail_size;
0470   uint32_t         pos = 0;
0471   int              i;
0472   int              j;
0473 
0474   obj_detail_size = sizeof (struct link_map) * obj->obj_num;
0475 
0476   for (i = 0; i < obj->obj_num; ++i)
0477   {
0478     obj_detail_size += (obj->sec_num[i] * sizeof (section_detail));
0479   }
0480 
0481   detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
0482                                 obj_detail_size + rap->strtable_size, true);
0483 
0484   if (!detail)
0485   {
0486     rap->strtable_size = 0;
0487     rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
0488     return false;
0489   }
0490 
0491   rap->strtable = detail + obj_detail_size;
0492 
0493   /*
0494    *  Read the obj names and section names
0495    */
0496   if (!rtems_rtl_obj_comp_read (rap->decomp,
0497                                 rap->strtable,
0498                                 rap->strtable_size))
0499   {
0500     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, detail);
0501     return false;
0502   }
0503 
0504   obj->linkmap = (struct link_map*) detail;
0505 
0506   if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
0507   {
0508     if (rap->rpathlen > 0)
0509       printf ("File rpath:\n");
0510   }
0511 
0512   while (pos < rap->rpathlen)
0513   {
0514     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
0515     {
0516       printf ("          %s\n", rap->strtable + pos);
0517     }
0518     pos = pos + strlen (rap->strtable + pos) + 1;
0519   }
0520 
0521   if (rap->rpathlen > 0)
0522     pos = rap->rpathlen;
0523 
0524   for (i = 0; i < obj->obj_num; ++i)
0525   {
0526     tmp1 = obj->linkmap + i;
0527     tmp1->name = rap->strtable + pos;
0528     tmp1->sec_num = obj->sec_num[i];
0529     tmp1->rpathlen = rap->rpathlen;
0530     tmp1->rpath = (char*) rap->strtable;
0531     pos += strlen (tmp1->name) + 1;
0532 
0533     if (!i)
0534     {
0535       tmp1->l_next = NULL;
0536       tmp1->l_prev = NULL;
0537     }
0538     else
0539     {
0540       (tmp1 - 1)->l_next = tmp1;
0541       tmp1->l_prev = tmp1 - 1;
0542       tmp1->l_next = NULL;
0543     }
0544   }
0545 
0546   tmp2 = (section_detail*) (obj->linkmap + obj->obj_num);
0547 
0548   for (i = 0; i < obj->obj_num; ++i)
0549   {
0550     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
0551     {
0552       printf ("File %d: %s\n", i, (obj->linkmap + i)->name);
0553       printf ("Section: %d sections\n", (unsigned int) obj->sec_num[i]);
0554     }
0555 
0556     obj->linkmap[i].sec_detail = tmp2;
0557 
0558     for (j = 0; j < obj->sec_num[i]; ++j)
0559     {
0560       uint32_t name;
0561       uint32_t rap_id;
0562       uint32_t offset;
0563       uint32_t size;
0564 
0565       if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
0566           !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) ||
0567           !rtems_rtl_rap_read_uint32 (rap->decomp, &size))
0568       {
0569         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->linkmap);
0570         obj->linkmap = NULL;
0571         return false;
0572       }
0573 
0574       rap_id = offset >> 28;
0575       offset = offset & 0xfffffff;
0576 
0577       tmp2->name = rap->strtable + name;
0578       tmp2->offset = offset;
0579       tmp2->rap_id = rap_id;
0580       tmp2->size = size;
0581       pos += strlen (tmp2->name) + 1;
0582 
0583       if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
0584       {
0585         printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n",
0586                 tmp2->name, (unsigned int) tmp2->offset,
0587                 (unsigned int) tmp2->rap_id, (unsigned int) tmp2->size);
0588       }
0589 
0590       tmp2 += 1;
0591     }
0592   }
0593   return true;
0594 }
0595 
0596 static bool
0597 rtems_rtl_rap_load_symbols (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
0598 {
0599   rtems_rtl_obj_sym* gsym;
0600   int                sym;
0601 
0602   obj->global_size =
0603     rap->symbols * sizeof (rtems_rtl_obj_sym) + rap->strtab_size;
0604 
0605   obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
0606                                            obj->global_size, true);
0607   if (!obj->global_table)
0608   {
0609     obj->global_size = 0;
0610     rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
0611     return false;
0612   }
0613 
0614   obj->global_syms = rap->symbols;
0615 
0616   rap->strtab = (((char*) obj->global_table) +
0617                  (rap->symbols * sizeof (rtems_rtl_obj_sym)));
0618 
0619   if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtab, rap->strtab_size))
0620   {
0621     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
0622     return false;
0623   }
0624 
0625   for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym)
0626   {
0627     rtems_rtl_obj_sect* symsect;
0628     uint32_t            data;
0629     uint32_t            name;
0630     uint32_t            value;
0631 
0632     if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) ||
0633         !rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
0634         !rtems_rtl_rap_read_uint32 (rap->decomp, &value))
0635     {
0636       rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
0637       obj->global_table = NULL;
0638       obj->global_syms = 0;
0639       obj->global_size = 0;
0640       return false;
0641     }
0642 
0643     if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0644       printf ("rtl: sym:load: data=0x%08" PRIx32 " name=0x%08" PRIx32
0645               " value=0x%08" PRIx32 "\n",
0646               data, name, value);
0647 
0648     /*
0649      * If there is a globally exported symbol already present and this
0650      * symbol is not weak raise an error. If the symbol is weak and present
0651      * globally ignore this symbol and use the global one and if it is not
0652      * present take this symbol global or weak. We accept the first weak
0653      * symbol we find and make it globally exported.
0654      */
0655     if (rtems_rtl_symbol_global_find (rap->strtab + name) &&
0656         (ELF_ST_BIND (data & 0xffff) != STB_WEAK))
0657     {
0658       rtems_rtl_set_error (EINVAL,
0659                            "duplicate global symbol: %s", rap->strtab + name);
0660       rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
0661       obj->global_table = NULL;
0662       obj->global_syms = 0;
0663       obj->global_size = 0;
0664       return false;
0665     }
0666 
0667     symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
0668     if (!symsect)
0669     {
0670       rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
0671       obj->global_table = NULL;
0672       obj->global_syms = 0;
0673       obj->global_size = 0;
0674       rtems_rtl_set_error (EINVAL, "section index not found: %" PRIu32, data >> 16);
0675       return false;
0676     }
0677 
0678     rtems_chain_set_off_chain (&gsym->node);
0679     gsym->name = rap->strtab + name;
0680     gsym->value = (uint8_t*) (value + symsect->base);
0681     gsym->data = data & 0xffff;
0682 
0683     if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
0684       printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n",
0685               sym, gsym->name,
0686               (int) ELF_ST_BIND (data & 0xffff),
0687               (int) ELF_ST_TYPE (data & 0xffff),
0688               gsym->value, (int) (data >> 16));
0689 
0690     ++gsym;
0691   }
0692 
0693   if (obj->global_syms)
0694     rtems_rtl_symbol_obj_add (obj);
0695 
0696   return true;
0697 }
0698 
0699 static bool
0700 rtems_rtl_rap_parse_header (uint8_t*  rhdr,
0701                             size_t*   rhdr_len,
0702                             uint32_t* length,
0703                             uint32_t* version,
0704                             uint32_t* compression,
0705                             uint32_t* checksum)
0706 {
0707   char* sptr = (char*) rhdr;
0708   char* eptr;
0709 
0710   *rhdr_len = 0;
0711 
0712   /*
0713    * "RAP," = 4 bytes, total 4
0714    */
0715 
0716   if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
0717     return false;
0718 
0719   sptr = sptr + 4;
0720 
0721   /*
0722    * "00000000," = 9 bytes, total 13
0723    */
0724 
0725   *length = strtoul (sptr, &eptr, 10);
0726 
0727   if (*eptr != ',')
0728     return false;
0729 
0730   sptr = eptr + 1;
0731 
0732   /*
0733    * "0000," = 5 bytes, total 18
0734    */
0735 
0736   *version = strtoul (sptr, &eptr, 10);
0737 
0738   if (*eptr != ',')
0739     return false;
0740 
0741   sptr = eptr + 1;
0742 
0743   /*
0744    * "NONE," and "LZ77," = 5 bytes, total 23
0745    */
0746 
0747   if ((sptr[0] == 'N') &&
0748       (sptr[1] == 'O') &&
0749       (sptr[2] == 'N') &&
0750       (sptr[3] == 'E'))
0751   {
0752     *compression = RTEMS_RTL_COMP_NONE;
0753     eptr = sptr + 4;
0754   }
0755   else if ((sptr[0] == 'L') &&
0756            (sptr[1] == 'Z') &&
0757            (sptr[2] == '7') &&
0758            (sptr[3] == '7'))
0759   {
0760     *compression = RTEMS_RTL_COMP_LZ77;
0761     eptr = sptr + 4;
0762   }
0763   else
0764     return false;
0765 
0766   if (*eptr != ',')
0767     return false;
0768 
0769   sptr = eptr + 1;
0770 
0771   /*
0772    * "00000000," = 9 bytes, total 32
0773    */
0774   *checksum = strtoul (sptr, &eptr, 16);
0775 
0776   /*
0777    * "\n" = 1 byte, total 33
0778    */
0779   if (*eptr != '\n')
0780     return false;
0781 
0782   *rhdr_len = ((uint8_t*) eptr) - rhdr + 1;
0783 
0784   return true;
0785 }
0786 
0787 bool
0788 rtems_rtl_rap_file_check (rtems_rtl_obj* obj, int fd)
0789 {
0790   rtems_rtl_obj_cache* header;
0791   uint8_t*             rhdr = NULL;
0792   size_t               rlen = 64;
0793   uint32_t             length = 0;
0794   uint32_t             version = 0;
0795   uint32_t             compression = 0;
0796   uint32_t             checksum = 0;
0797 
0798   rtems_rtl_obj_caches (&header, NULL, NULL);
0799 
0800   if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
0801                                  (void**) &rhdr, &rlen))
0802     return false;
0803 
0804   if (!rtems_rtl_rap_parse_header (rhdr,
0805                                    &rlen,
0806                                    &length,
0807                                    &version,
0808                                    &compression,
0809                                    &checksum))
0810     return false;
0811 
0812   return true;
0813 }
0814 
0815 bool
0816 rtems_rtl_rap_file_load (rtems_rtl_obj* obj, int fd)
0817 {
0818   rtems_rtl_rap rap = { 0 };
0819   uint8_t*      rhdr = NULL;
0820   size_t        rlen = 64;
0821   int           section;
0822 
0823   rtems_rtl_obj_caches (&rap.file, NULL, NULL);
0824 
0825   if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset,
0826                                  (void**) &rhdr, &rlen))
0827     return false;
0828 
0829   if (!rtems_rtl_rap_parse_header (rhdr,
0830                                    &rlen,
0831                                    &rap.length,
0832                                    &rap.version,
0833                                    &rap.compression,
0834                                    &rap.checksum))
0835   {
0836     rtems_rtl_set_error (EINVAL, "invalid RAP file format");
0837     return false;
0838   }
0839 
0840   /*
0841    * Set up the decompressor.
0842    */
0843   rtems_rtl_obj_decompress (&rap.decomp, rap.file, fd, rap.compression,
0844                             rlen + obj->ooffset);
0845 
0846   /*
0847    * uint32_t: machinetype
0848    * uint32_t: datatype
0849    * uint32_t: class
0850    */
0851 
0852   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0853     printf ("rtl: rap: input machine=%" PRIu32 "\n",
0854             rtems_rtl_obj_comp_input (rap.decomp));
0855 
0856   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype))
0857     return false;
0858 
0859   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0860     printf ("rtl: rap: machinetype=%" PRIu32 "\n", rap.machinetype);
0861 
0862   if (!rtems_rtl_rap_machine_check (rap.machinetype))
0863   {
0864     rtems_rtl_set_error (EINVAL, "invalid machinetype");
0865     return false;
0866   }
0867 
0868   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype))
0869     return false;
0870 
0871   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0872     printf ("rtl: rap: datatype=%" PRIu32 "\n", rap.datatype);
0873 
0874   if (!rtems_rtl_rap_datatype_check (rap.datatype))
0875   {
0876     rtems_rtl_set_error (EINVAL, "invalid datatype");
0877     return false;
0878   }
0879 
0880   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class))
0881     return false;
0882 
0883   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0884     printf ("rtl: rap: class=%" PRIu32 "\n", rap.class);
0885 
0886   if (!rtems_rtl_rap_class_check (rap.class))
0887   {
0888     rtems_rtl_set_error (EINVAL, "invalid class");
0889     return false;
0890   }
0891 
0892   /*
0893    * uint32_t: init
0894    * uint32_t: fini
0895    * uint32_t: symtab_size
0896    * uint32_t: strtab_size
0897    * uint32_t: relocs_size
0898    */
0899 
0900   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0901     printf ("rtl: rap: input header=%" PRIu32 "\n",
0902             rtems_rtl_obj_comp_input (rap.decomp));
0903 
0904   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.init))
0905     return false;
0906 
0907   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.fini))
0908     return false;
0909 
0910   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.symtab_size))
0911     return false;
0912 
0913   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtab_size))
0914     return false;
0915 
0916   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size))
0917     return false;
0918 
0919   rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t));
0920 
0921   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
0922     printf ("rtl: rap: load: symtab=%" PRIu32 " (%" PRIu32
0923             ") strtab=%" PRIu32 " relocs=%" PRIu32 "\n",
0924             rap.symtab_size, rap.symbols,
0925             rap.strtab_size, rap.relocs_size);
0926 
0927   /*
0928    * Load the details
0929    */
0930   if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num))
0931     return false;
0932 
0933   if (obj->obj_num > 0)
0934   {
0935     obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num);
0936 
0937     if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.rpathlen))
0938       return false;
0939 
0940     uint32_t i;
0941     for (i = 0; i < obj->obj_num; ++i)
0942     {
0943       if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i])))
0944         return false;
0945     }
0946 
0947     if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size))
0948       return false;
0949 
0950     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
0951       printf ("rtl: rap: details: obj_num=%" PRIu32 "\n", obj->obj_num);
0952 
0953     if (!rtems_rtl_rap_load_linkmap (&rap, obj))
0954       return false;
0955   }
0956 
0957   /*
0958    * uint32_t: text_size
0959    * uint32_t: text_alignment
0960    * uint32_t: const_size
0961    * uint32_t: const_alignment
0962    * uint32_t: ctor_size
0963    * uint32_t: ctor_alignment
0964    * uint32_t: dtor_size
0965    * uint32_t: dtor_alignment
0966    * uint32_t: data_size
0967    * uint32_t: data_alignment
0968    * uint32_t: bss_size
0969    * uint32_t: bss_alignment
0970    */
0971 
0972   for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
0973   {
0974     if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size))
0975       return false;
0976 
0977     if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment))
0978       return false;
0979 
0980     if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
0981       printf ("rtl: rap: %s: size=%" PRIu32 " align=%" PRIu32 "\n",
0982               rap_sections[section].name,
0983               rap.secs[section].size,
0984               rap.secs[section].alignment);
0985 
0986     if (!rtems_rtl_obj_add_section (obj,
0987                                     section,
0988                                     rap_sections[section].name,
0989                                     rap.secs[section].size,
0990                                     0,
0991                                     rap.secs[section].alignment,
0992                                     0, 0,
0993                                     rap_sections[section].flags))
0994       return false;
0995   }
0996 
0997   /** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
0998 
0999   /*
1000    * Allocate the sections.
1001    */
1002   if (!rtems_rtl_obj_alloc_sections (obj, fd, NULL, &rap))
1003     return false;
1004 
1005   if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap))
1006     return false;
1007 
1008   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
1009     printf ("rtl: rap: input symbols=%" PRIu32 "\n",
1010             rtems_rtl_obj_comp_input (rap.decomp));
1011 
1012   if (!rtems_rtl_rap_load_symbols (&rap, obj))
1013     return false;
1014 
1015   if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
1016     printf ("rtl: rap: input relocs=%" PRIu32 "\n",
1017             rtems_rtl_obj_comp_input (rap.decomp));
1018 
1019   if (!rtems_rtl_rap_relocate (&rap, obj))
1020     return false;
1021 
1022   rtems_rtl_obj_synchronize_cache (obj);
1023 
1024   return true;
1025 }
1026 
1027 bool
1028 rtems_rtl_rap_file_unload (rtems_rtl_obj* obj)
1029 {
1030   (void) obj;
1031   return true;
1032 }
1033 
1034 rtems_rtl_loader_format*
1035 rtems_rtl_rap_file_sig (void)
1036 {
1037   return &rap_sig;
1038 }