source: rtems/cpukit/libdl/rtl-rap.c @ 4408603

Last change on this file since 4408603 was f59d435d, checked in by Chris Johns <chrisj@…>, on Apr 12, 2018 at 7:46:49 AM

libdl: Remove _t from all structures as this is reserved for the standards

  • Property mode set to 100644
File size: 25.7 KB
Line 
1/*
2 *  COPYRIGHT (c) 2012-2013, 2018 Chris Johns <chrisj@rtems.org>
3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
6 *  http://www.rtems.org/license/LICENSE.
7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtld
12 *
13 * @brief RTEMS Run-Time Link Editor
14 *
15 * This is the RAP format loader support..
16 */
17
18#if HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <errno.h>
23#include <fcntl.h>
24#include <inttypes.h>
25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
28#include <unistd.h>
29
30#include <rtems/rtl/rtl.h>
31#include "rtl-elf.h"
32#include "rtl-error.h"
33#include <rtems/rtl/rtl-obj-comp.h>
34#include "rtl-rap.h"
35#include <rtems/rtl/rtl-trace.h>
36#include <rtems/rtl/rtl-unresolved.h>
37
38/**
39 * The offsets in the unresolved array.
40 */
41#define REL_R_OFFSET (0)
42#define REL_R_INFO   (1)
43#define REL_R_ADDEND (2)
44
45/**
46 * The ELF format signature.
47 */
48static rtems_rtl_loader_format rap_sig =
49{
50  .label = "RAP",
51  .flags = RTEMS_RTL_FMT_COMP
52};
53
54/**
55 * The section definitions found in a RAP file.
56 */
57typedef struct rtems_rtl_rap_sectdef
58{
59  const char*    name;    /**< Name of the section. */
60  const uint32_t flags;   /**< Section flags. */
61} rtems_rtl_rap_sectdef;
62
63/**
64 * The section indexes. These are fixed.
65 */
66#define RTEMS_RTL_RAP_TEXT_SEC  (0)
67#define RTEMS_RTL_RAP_CONST_SEC (1)
68#define RTEMS_RTL_RAP_CTOR_SEC  (2)
69#define RTEMS_RTL_RAP_DTOR_SEC  (3)
70#define RTEMS_RTL_RAP_DATA_SEC  (4)
71#define RTEMS_RTL_RAP_BSS_SEC   (5)
72#define RTEMS_RTL_RAP_SECS      (6)
73
74/**
75 * The sections as loaded from a RAP file.
76 */
77static const rtems_rtl_rap_sectdef rap_sections[RTEMS_RTL_RAP_SECS] =
78{
79  { ".text",  RTEMS_RTL_OBJ_SECT_TEXT  | RTEMS_RTL_OBJ_SECT_LOAD },
80  { ".const", RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD },
81  { ".ctor",  RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CTOR },
82  { ".dtor",  RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DTOR },
83  { ".data",  RTEMS_RTL_OBJ_SECT_DATA  | RTEMS_RTL_OBJ_SECT_LOAD },
84  { ".bss",   RTEMS_RTL_OBJ_SECT_BSS   | RTEMS_RTL_OBJ_SECT_ZERO }
85};
86
87/**
88 * The section definitions found in a RAP file.
89 */
90typedef struct rtems_rtl_rap_section
91{
92  uint32_t size;       /**< The size of the section. */
93  uint32_t alignment;  /**< The alignment of the section. */
94} rtems_rtl_rap_section;
95
96/**
97 * The RAP loader.
98 */
99typedef struct rtems_rtl_rap
100{
101  rtems_rtl_obj_cache*  file;         /**< The file cache for the RAP file. */
102  rtems_rtl_obj_comp*   decomp;       /**< The decompression streamer. */
103  uint32_t              length;       /**< The file length. */
104  uint32_t              version;      /**< The RAP file version. */
105  uint32_t              compression;  /**< The type of compression. */
106  uint32_t              checksum;     /**< The checksum. */
107  uint32_t              machinetype;  /**< The ELF machine type. */
108  uint32_t              datatype;     /**< The ELF data type. */
109  uint32_t              class;        /**< The ELF class. */
110  uint32_t              init;         /**< The initialisation strtab offset. */
111  uint32_t              fini;         /**< The finish strtab offset. */
112  rtems_rtl_rap_section secs[RTEMS_RTL_RAP_SECS]; /**< The sections. */
113  uint32_t              symtab_size;  /**< The symbol table size. */
114  char*                 strtab;       /**< The string table. */
115  uint32_t              strtab_size;  /**< The string table size. */
116  uint32_t              relocs_size;  /**< The relocation table size. */
117  uint32_t              symbols;      /**< The number of symbols. */
118  uint32_t              strtable_size;/**< The size of section names and obj names. */
119  uint32_t              rpathlen;     /**< The length of rpath. */
120  char*                 strtable;     /**< The detail string which resides in obj detail. */
121} rtems_rtl_rap;
122
123/**
124 * Check the machine type.
125 */
126static bool
127rtems_rtl_rap_machine_check (uint32_t machinetype)
128{
129  /*
130   * This code is determined by the machine headers.
131   */
132  switch (machinetype)
133  {
134    ELFDEFNNAME (MACHDEP_ID_CASES)
135    default:
136      return false;
137  }
138  return true;
139}
140
141/**
142 * Check the data type.
143 */
144static bool
145rtems_rtl_rap_datatype_check (uint32_t datatype)
146{
147  /*
148   * This code is determined by the machine headers.
149   */
150  if (datatype != ELFDEFNNAME (MACHDEP_ENDIANNESS))
151    return false;
152  return true;
153}
154
155/**
156 * Check the class of executable.
157 */
158static bool
159rtems_rtl_rap_class_check (uint32_t class)
160{
161  /*
162   * This code is determined by the machine headers.
163   */
164  switch (class)
165  {
166    case ELFCLASS32:
167      if (ARCH_ELFSIZE == 32)
168        return true;
169      break;
170    case ELFCLASS64:
171      if (ARCH_ELFSIZE == 64)
172        return true;
173      break;
174    default:
175      break;
176  }
177  return false;
178}
179
180static uint32_t
181rtems_rtl_rap_get_uint32 (const uint8_t* buffer)
182{
183  uint32_t value = 0;
184  int      b;
185  for (b = 0; b < sizeof (uint32_t); ++b)
186  {
187    value <<= 8;
188    value |= buffer[b];
189  }
190  return value;
191}
192
193static bool
194rtems_rtl_rap_read_uint32 (rtems_rtl_obj_comp* comp, uint32_t* value)
195{
196  uint8_t buffer[sizeof (uint32_t)];
197
198  if (!rtems_rtl_obj_comp_read (comp, buffer, sizeof (uint32_t)))
199    return false;
200
201  *value = rtems_rtl_rap_get_uint32 (buffer);
202
203  return true;
204}
205
206static bool
207rtems_rtl_rap_loader (rtems_rtl_obj*      obj,
208                      int                 fd,
209                      rtems_rtl_obj_sect* sect,
210                      void*               data)
211{
212  rtems_rtl_rap* rap = (rtems_rtl_rap*) data;
213
214  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
215    printf ("rtl: rap: input %s=%" PRIu32 "\n",
216            sect->name, rtems_rtl_obj_comp_input (rap->decomp));
217
218  return rtems_rtl_obj_comp_read (rap->decomp, sect->base, sect->size);
219}
220
221static bool
222rtems_rtl_rap_relocate (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
223{
224  #define SYMNAME_BUFFER_SIZE (1024)
225  char*    symname_buffer = NULL;
226  int      section;
227
228  if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
229    printf ("rtl: relocation\n");
230
231  symname_buffer = malloc (SYMNAME_BUFFER_SIZE);
232  if (!symname_buffer)
233  {
234    rtems_rtl_set_error (ENOMEM, "no memory for local symbol name buffer");
235    return false;
236  }
237
238  for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
239  {
240    rtems_rtl_obj_sect* targetsect;
241    uint32_t            header = 0;
242    int                 relocs;
243    bool                is_rela;
244    int                 r;
245
246    targetsect = rtems_rtl_obj_find_section (obj, rap_sections[section].name);
247
248    if (!targetsect)
249      continue;
250
251    if (!rtems_rtl_rap_read_uint32 (rap->decomp, &header))
252    {
253      free (symname_buffer);
254      return false;
255    }
256
257    /*
258     * Bit 31 of the header indicates if the relocations for this section
259     * have a valid addend field.
260     */
261
262    is_rela = (header & (1 << 31)) != 0 ? true : false;
263    relocs = header & ~(1 << 31);
264
265    if (relocs && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
266      printf ("rtl: relocation: %s: header: %08" PRIx32 " relocs: %d %s\n",
267              rap_sections[section].name,
268              header, relocs, is_rela ? "rela" : "rel");
269
270    for (r = 0; r < relocs; ++r)
271    {
272      uint32_t    info = 0;
273      uint32_t    offset = 0;
274      uint32_t    addend = 0;
275      Elf_Word    type;
276      const char* symname = NULL;
277      uint32_t    symname_size;
278      Elf_Word    symtype = 0;
279      Elf_Word    symvalue = 0;
280
281      if (!rtems_rtl_rap_read_uint32 (rap->decomp, &info))
282      {
283        free (symname_buffer);
284        return false;
285      }
286
287      if (!rtems_rtl_rap_read_uint32 (rap->decomp, &offset))
288      {
289        free (symname_buffer);
290        return false;
291      }
292
293      /*
294       * The types are:
295       *
296       *  0  Section symbol offset in addend.
297       *  1  Symbol appended to the relocation record.
298       *  2  Symbol is in the strtabl.
299       *
300       * If type 2 bits 30:8 is the offset in the strtab. If type 1 the bits
301       * are the size of the string. The lower 8 bits of the info field if the
302       * ELF relocation type field.
303       */
304
305      if (((info & (1 << 31)) == 0) || is_rela)
306      {
307        if (!rtems_rtl_rap_read_uint32 (rap->decomp, &addend))
308        {
309          free (symname_buffer);
310          return false;
311        }
312      }
313
314      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
315        printf (" %2d: info=%08" PRIx32 " offset=%" PRIu32
316                " addend=%" PRIu32 "\n",
317                r, info, offset, addend);
318
319      type = info & 0xff;
320
321      if ((info & (1 << 31)) == 0)
322      {
323        rtems_rtl_obj_sect* symsect;
324
325        symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
326        if (!symsect)
327        {
328          free (symname_buffer);
329          return false;
330        }
331
332        symvalue = (Elf_Addr) symsect->base + addend;
333      }
334      else if (rtems_rtl_elf_rel_resolve_sym (type))
335      {
336        rtems_rtl_obj_sym* symbol;
337
338        symname_size = (info & ~(3 << 30)) >> 8;
339
340        if ((info & (1 << 30)) != 0)
341        {
342          symname = rap->strtab + symname_size;
343        }
344        else
345        {
346          if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
347          {
348            free (symname_buffer);
349            rtems_rtl_set_error (EINVAL, "reloc symbol too big");
350            return false;
351          }
352
353          if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
354          {
355            free (symname_buffer);
356            return false;
357          }
358
359          symname_buffer[symname_size] = '\0';
360          symname = symname_buffer;
361        }
362
363        symbol = rtems_rtl_symbol_obj_find (obj, symname);
364
365        if (!symbol)
366        {
367          rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
368          free (symname_buffer);
369          return false;
370        }
371
372        symvalue = (Elf_Addr) symbol->value;
373      }
374
375      if (is_rela)
376      {
377        Elf_Rela rela;
378
379        rela.r_offset = offset;
380        rela.r_info = type;
381
382        if ((info & (1 << 31)) == 0)
383          rela.r_addend = 0;
384        else rela.r_addend = addend;
385
386        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
387          printf (" %2d: rela: type:%-2d off:%" PRIu32 " addend:%d"
388                  " symname=%s symtype=%ju symvalue=0x%08jx\n",
389                  r, (int) type, offset, (int) addend,
390                  symname, (uintmax_t) symtype, (uintmax_t) symvalue);
391
392        if (!rtems_rtl_elf_relocate_rela (obj, &rela, targetsect,
393                                          symname, symtype, symvalue))
394        {
395          free (symname_buffer);
396          return false;
397        }
398      }
399      else
400      {
401        Elf_Rel rel;
402
403        rel.r_offset = offset;
404        rel.r_info = type;
405
406        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
407          printf (" %2d: rel: type:%-2d off:%" PRIu32
408                  " symname=%s symtype=%ju symvalue=0x%08jx\n",
409                  r, (int) type, offset,
410                  symname, (uintmax_t) symtype, (uintmax_t) symvalue);
411
412        if (!rtems_rtl_elf_relocate_rel (obj, &rel, targetsect,
413                                         symname, symtype, symvalue))
414        {
415          free (symname_buffer);
416          return false;
417        }
418      }
419    }
420  }
421
422  free (symname_buffer);
423
424  return true;
425}
426
427/**
428 * The structure of obj->linkmap is:
429 *
430 * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])|
431 * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num])
432 *
433 */
434static bool
435rtems_rtl_rap_load_linkmap (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
436{
437  void*            detail;
438  struct link_map* tmp1;
439  section_detail*  tmp2;
440  uint32_t         obj_detail_size;
441  uint32_t         pos = 0;
442  int              i;
443  int              j;
444
445  obj_detail_size = sizeof (struct link_map) * obj->obj_num;
446
447  for (i = 0; i < obj->obj_num; ++i)
448  {
449    obj_detail_size += (obj->sec_num[i] * sizeof (section_detail));
450  }
451
452  detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
453                                obj_detail_size + rap->strtable_size, true);
454
455  if (!detail)
456  {
457    rap->strtable_size = 0;
458    rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
459    return false;
460  }
461
462  rap->strtable = detail + obj_detail_size;
463
464  /*
465   *  Read the obj names and section names
466   */
467  if (!rtems_rtl_obj_comp_read (rap->decomp,
468                                rap->strtable,
469                                rap->strtable_size))
470  {
471    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, detail);
472    return false;
473  }
474
475  obj->linkmap = (struct link_map*) detail;
476
477  if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
478  {
479    if (rap->rpathlen > 0)
480      printf ("File rpath:\n");
481  }
482
483  while (pos < rap->rpathlen)
484  {
485    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
486    {
487      printf ("          %s\n", rap->strtable + pos);
488    }
489    pos = pos + strlen (rap->strtable + pos) + 1;
490  }
491
492  if (rap->rpathlen > 0)
493    pos = rap->rpathlen;
494
495  for (i = 0; i < obj->obj_num; ++i)
496  {
497    tmp1 = obj->linkmap + i;
498    tmp1->name = rap->strtable + pos;
499    tmp1->sec_num = obj->sec_num[i];
500    tmp1->rpathlen = rap->rpathlen;
501    tmp1->rpath = (char*) rap->strtable;
502    pos += strlen (tmp1->name) + 1;
503
504    if (!i)
505    {
506      tmp1->l_next = NULL;
507      tmp1->l_prev = NULL;
508    }
509    else
510    {
511      (tmp1 - 1)->l_next = tmp1;
512      tmp1->l_prev = tmp1 - 1;
513      tmp1->l_next = NULL;
514    }
515  }
516
517  tmp2 = (section_detail*) (obj->linkmap + obj->obj_num);
518
519  for (i = 0; i < obj->obj_num; ++i)
520  {
521    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
522    {
523      printf ("File %d: %s\n", i, (obj->linkmap + i)->name);
524      printf ("Section: %d sections\n", (unsigned int) obj->sec_num[i]);
525    }
526
527    obj->linkmap[i].sec_detail = tmp2;
528
529    for (j = 0; j < obj->sec_num[i]; ++j)
530    {
531      uint32_t name;
532      uint32_t rap_id;
533      uint32_t offset;
534      uint32_t size;
535
536      if (!rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
537          !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) ||
538          !rtems_rtl_rap_read_uint32 (rap->decomp, &size))
539      {
540        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->linkmap);
541        obj->linkmap = NULL;
542        return false;
543      }
544
545      rap_id = offset >> 28;
546      offset = offset & 0xfffffff;
547
548      tmp2->name = rap->strtable + name;
549      tmp2->offset = offset;
550      tmp2->rap_id = rap_id;
551      tmp2->size = size;
552      pos += strlen (tmp2->name) + 1;
553
554      if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
555      {
556        printf ("name:%16s offset:0x%08x rap_id:%d size:0x%x\n",
557                tmp2->name, (unsigned int) tmp2->offset,
558                (unsigned int) tmp2->rap_id, (unsigned int) tmp2->size);
559      }
560
561      tmp2 += 1;
562    }
563  }
564  return true;
565}
566
567static bool
568rtems_rtl_rap_load_symbols (rtems_rtl_rap* rap, rtems_rtl_obj* obj)
569{
570  rtems_rtl_obj_sym* gsym;
571  int                sym;
572
573  obj->global_size =
574    rap->symbols * sizeof (rtems_rtl_obj_sym) + rap->strtab_size;
575
576  obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
577                                           obj->global_size, true);
578  if (!obj->global_table)
579  {
580    obj->global_size = 0;
581    rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
582    return false;
583  }
584
585  obj->global_syms = rap->symbols;
586
587  rap->strtab = (((char*) obj->global_table) +
588                 (rap->symbols * sizeof (rtems_rtl_obj_sym)));
589
590  if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtab, rap->strtab_size))
591  {
592    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
593    return false;
594  }
595
596  for (sym = 0, gsym = obj->global_table; sym < rap->symbols; ++sym)
597  {
598    rtems_rtl_obj_sect* symsect;
599    uint32_t            data;
600    uint32_t            name;
601    uint32_t            value;
602
603    if (!rtems_rtl_rap_read_uint32 (rap->decomp, &data) ||
604        !rtems_rtl_rap_read_uint32 (rap->decomp, &name) ||
605        !rtems_rtl_rap_read_uint32 (rap->decomp, &value))
606    {
607      rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
608      obj->global_table = NULL;
609      obj->global_syms = 0;
610      obj->global_size = 0;
611      return false;
612    }
613
614    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
615      printf ("rtl: sym:load: data=0x%08" PRIx32 " name=0x%08" PRIx32
616              " value=0x%08" PRIx32 "\n",
617              data, name, value);
618
619    /*
620     * If there is a globally exported symbol already present and this
621     * symbol is not weak raise an error. If the symbol is weak and present
622     * globally ignore this symbol and use the global one and if it is not
623     * present take this symbol global or weak. We accept the first weak
624     * symbol we find and make it globally exported.
625     */
626    if (rtems_rtl_symbol_global_find (rap->strtab + name) &&
627        (ELF_ST_BIND (data & 0xffff) != STB_WEAK))
628    {
629      rtems_rtl_set_error (EINVAL,
630                           "duplicate global symbol: %s", rap->strtab + name);
631      rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
632      obj->global_table = NULL;
633      obj->global_syms = 0;
634      obj->global_size = 0;
635      return false;
636    }
637
638    symsect = rtems_rtl_obj_find_section_by_index (obj, data >> 16);
639    if (!symsect)
640    {
641      rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
642      obj->global_table = NULL;
643      obj->global_syms = 0;
644      obj->global_size = 0;
645      rtems_rtl_set_error (EINVAL, "section index not found: %" PRIu32, data >> 16);
646      return false;
647    }
648
649    rtems_chain_set_off_chain (&gsym->node);
650    gsym->name = rap->strtab + name;
651    gsym->value = (uint8_t*) (value + symsect->base);
652    gsym->data = data & 0xffff;
653
654    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
655      printf ("rtl: sym:add:%-2d name:%-20s bind:%-2d type:%-2d val:%8p sect:%d\n",
656              sym, gsym->name,
657              (int) ELF_ST_BIND (data & 0xffff),
658              (int) ELF_ST_TYPE (data & 0xffff),
659              gsym->value, (int) (data >> 16));
660
661    ++gsym;
662  }
663
664  if (obj->global_syms)
665    rtems_rtl_symbol_obj_add (obj);
666
667  return true;
668}
669
670static bool
671rtems_rtl_rap_parse_header (uint8_t*  rhdr,
672                            size_t*   rhdr_len,
673                            uint32_t* length,
674                            uint32_t* version,
675                            uint32_t* compression,
676                            uint32_t* checksum)
677{
678  char* sptr = (char*) rhdr;
679  char* eptr;
680
681  *rhdr_len = 0;
682
683  /*
684   * "RAP," = 4 bytes, total 4
685   */
686
687  if ((rhdr[0] != 'R') || (rhdr[1] != 'A') || (rhdr[2] != 'P') || (rhdr[3] != ','))
688    return false;
689
690  sptr = sptr + 4;
691
692  /*
693   * "00000000," = 9 bytes, total 13
694   */
695
696  *length = strtoul (sptr, &eptr, 10);
697
698  if (*eptr != ',')
699    return false;
700
701  sptr = eptr + 1;
702
703  /*
704   * "0000," = 5 bytes, total 18
705   */
706
707  *version = strtoul (sptr, &eptr, 10);
708
709  if (*eptr != ',')
710    return false;
711
712  sptr = eptr + 1;
713
714  /*
715   * "NONE," and "LZ77," = 5 bytes, total 23
716   */
717
718  if ((sptr[0] == 'N') &&
719      (sptr[1] == 'O') &&
720      (sptr[2] == 'N') &&
721      (sptr[3] == 'E'))
722  {
723    *compression = RTEMS_RTL_COMP_NONE;
724    eptr = sptr + 4;
725  }
726  else if ((sptr[0] == 'L') &&
727           (sptr[1] == 'Z') &&
728           (sptr[2] == '7') &&
729           (sptr[3] == '7'))
730  {
731    *compression = RTEMS_RTL_COMP_LZ77;
732    eptr = sptr + 4;
733  }
734  else
735    return false;
736
737  if (*eptr != ',')
738    return false;
739
740  sptr = eptr + 1;
741
742  /*
743   * "00000000," = 9 bytes, total 32
744   */
745  *checksum = strtoul (sptr, &eptr, 16);
746
747  /*
748   * "\n" = 1 byte, total 33
749   */
750  if (*eptr != '\n')
751    return false;
752
753  *rhdr_len = ((uint8_t*) eptr) - rhdr + 1;
754
755  return true;
756}
757
758bool
759rtems_rtl_rap_file_check (rtems_rtl_obj* obj, int fd)
760{
761  rtems_rtl_obj_cache* header;
762  uint8_t*             rhdr = NULL;
763  size_t               rlen = 64;
764  uint32_t             length = 0;
765  uint32_t             version = 0;
766  uint32_t             compression = 0;
767  uint32_t             checksum = 0;
768
769  rtems_rtl_obj_caches (&header, NULL, NULL);
770
771  if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
772                                 (void**) &rhdr, &rlen))
773    return false;
774
775  if (!rtems_rtl_rap_parse_header (rhdr,
776                                   &rlen,
777                                   &length,
778                                   &version,
779                                   &compression,
780                                   &checksum))
781    return false;
782
783  return true;
784}
785
786bool
787rtems_rtl_rap_file_load (rtems_rtl_obj* obj, int fd)
788{
789  rtems_rtl_rap rap = { 0 };
790  uint8_t*      rhdr = NULL;
791  size_t        rlen = 64;
792  int           section;
793
794  rtems_rtl_obj_caches (&rap.file, NULL, NULL);
795
796  if (!rtems_rtl_obj_cache_read (rap.file, fd, obj->ooffset,
797                                 (void**) &rhdr, &rlen))
798    return false;
799
800  if (!rtems_rtl_rap_parse_header (rhdr,
801                                   &rlen,
802                                   &rap.length,
803                                   &rap.version,
804                                   &rap.compression,
805                                   &rap.checksum))
806  {
807    rtems_rtl_set_error (EINVAL, "invalid RAP file format");
808    return false;
809  }
810
811  /*
812   * Set up the decompressor.
813   */
814  rtems_rtl_obj_decompress (&rap.decomp, rap.file, fd, rap.compression,
815                            rlen + obj->ooffset);
816
817  /*
818   * uint32_t: machinetype
819   * uint32_t: datatype
820   * uint32_t: class
821   */
822
823  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
824    printf ("rtl: rap: input machine=%" PRIu32 "\n",
825            rtems_rtl_obj_comp_input (rap.decomp));
826
827  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.machinetype))
828    return false;
829
830  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
831    printf ("rtl: rap: machinetype=%" PRIu32 "\n", rap.machinetype);
832
833  if (!rtems_rtl_rap_machine_check (rap.machinetype))
834  {
835    rtems_rtl_set_error (EINVAL, "invalid machinetype");
836    return false;
837  }
838
839  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.datatype))
840    return false;
841
842  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
843    printf ("rtl: rap: datatype=%" PRIu32 "\n", rap.datatype);
844
845  if (!rtems_rtl_rap_datatype_check (rap.datatype))
846  {
847    rtems_rtl_set_error (EINVAL, "invalid datatype");
848    return false;
849  }
850
851  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.class))
852    return false;
853
854  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
855    printf ("rtl: rap: class=%" PRIu32 "\n", rap.class);
856
857  if (!rtems_rtl_rap_class_check (rap.class))
858  {
859    rtems_rtl_set_error (EINVAL, "invalid class");
860    return false;
861  }
862
863  /*
864   * uint32_t: init
865   * uint32_t: fini
866   * uint32_t: symtab_size
867   * uint32_t: strtab_size
868   * uint32_t: relocs_size
869   */
870
871  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
872    printf ("rtl: rap: input header=%" PRIu32 "\n",
873            rtems_rtl_obj_comp_input (rap.decomp));
874
875  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.init))
876    return false;
877
878  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.fini))
879    return false;
880
881  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.symtab_size))
882    return false;
883
884  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtab_size))
885    return false;
886
887  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.relocs_size))
888    return false;
889
890  rap.symbols = rap.symtab_size / (3 * sizeof (uint32_t));
891
892  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
893    printf ("rtl: rap: load: symtab=%" PRIu32 " (%" PRIu32
894            ") strtab=%" PRIu32 " relocs=%" PRIu32 "\n",
895            rap.symtab_size, rap.symbols,
896            rap.strtab_size, rap.relocs_size);
897
898  /*
899   * Load the details
900   */
901  if (!rtems_rtl_rap_read_uint32 (rap.decomp, &obj->obj_num))
902    return false;
903
904  if (obj->obj_num > 0)
905  {
906    obj->sec_num = (uint32_t*) malloc (sizeof (uint32_t) * obj->obj_num);
907
908    if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.rpathlen))
909      return false;
910
911    uint32_t i;
912    for (i = 0; i < obj->obj_num; ++i)
913    {
914      if (!rtems_rtl_rap_read_uint32 (rap.decomp, &(obj->sec_num[i])))
915        return false;
916    }
917
918    if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.strtable_size))
919      return false;
920
921    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
922      printf ("rtl: rap: details: obj_num=%" PRIu32 "\n", obj->obj_num);
923
924    if (!rtems_rtl_rap_load_linkmap (&rap, obj))
925      return false;
926  }
927
928  /*
929   * uint32_t: text_size
930   * uint32_t: text_alignment
931   * uint32_t: const_size
932   * uint32_t: const_alignment
933   * uint32_t: ctor_size
934   * uint32_t: ctor_alignment
935   * uint32_t: dtor_size
936   * uint32_t: dtor_alignment
937   * uint32_t: data_size
938   * uint32_t: data_alignment
939   * uint32_t: bss_size
940   * uint32_t: bss_alignment
941   */
942
943  for (section = 0; section < RTEMS_RTL_RAP_SECS; ++section)
944  {
945    if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].size))
946      return false;
947
948    if (!rtems_rtl_rap_read_uint32 (rap.decomp, &rap.secs[section].alignment))
949      return false;
950
951    if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
952      printf ("rtl: rap: %s: size=%" PRIu32 " align=%" PRIu32 "\n",
953              rap_sections[section].name,
954              rap.secs[section].size,
955              rap.secs[section].alignment);
956
957    if (!rtems_rtl_obj_add_section (obj,
958                                    section,
959                                    rap_sections[section].name,
960                                    rap.secs[section].size,
961                                    0,
962                                    rap.secs[section].alignment,
963                                    0, 0,
964                                    rap_sections[section].flags))
965      return false;
966  }
967
968  /** obj->entry = (void*)(uintptr_t) ehdr.e_entry; */
969
970  if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_rap_loader, &rap))
971    return false;
972
973  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
974    printf ("rtl: rap: input symbols=%" PRIu32 "\n",
975            rtems_rtl_obj_comp_input (rap.decomp));
976
977  if (!rtems_rtl_rap_load_symbols (&rap, obj))
978    return false;
979
980  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
981    printf ("rtl: rap: input relocs=%" PRIu32 "\n",
982            rtems_rtl_obj_comp_input (rap.decomp));
983
984  if (!rtems_rtl_rap_relocate (&rap, obj))
985    return false;
986
987  rtems_rtl_obj_synchronize_cache (obj);
988
989  return true;
990}
991
992bool
993rtems_rtl_rap_file_unload (rtems_rtl_obj* obj)
994{
995  (void) obj;
996  return true;
997}
998
999rtems_rtl_loader_format*
1000rtems_rtl_rap_file_sig (void)
1001{
1002  return &rap_sig;
1003}
Note: See TracBrowser for help on using the repository browser.