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

4.115
Last change on this file since 3feb372 was ae5fe7e6, checked in by Chris Johns <chrisj@…>, on 10/27/14 at 01:09:41

cpukit: Add libdl with the Runtime Loader (RTL) code.

This is a merge of the RTL project.

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