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

Last change on this file since 4408603 was 4408603, checked in by Chris Johns <chrisj@…>, on Jan 9, 2019 at 11:14:11 AM

libdl: Fix the support for constructors and desctructors.

  • Fix the handling of pending objects.
  • Add a constructor flags in objects to track then being called.

Closes #2921

  • Property mode set to 100644
File size: 38.5 KB
RevLine 
[ae5fe7e6]1/*
[f59d435d]2 *  COPYRIGHT (c) 2012-2018 Chris Johns <chrisj@rtems.org>
[ae5fe7e6]3 *
4 *  The license and distribution terms for this file may be
5 *  found in the file LICENSE in this distribution or at
[d4edbdbc]6 *  http://www.rtems.org/license/LICENSE.
[ae5fe7e6]7 */
8/**
9 * @file
10 *
11 * @ingroup rtems_rtld
12 *
13 * @brief RTEMS Run-Time Link Editor
14 *
15 * This is the RTL implementation.
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"
[990adc5]32#include <rtems/rtl/rtl-trace.h>
[c6eead1]33#include "rtl-unwind.h"
[990adc5]34#include <rtems/rtl/rtl-unresolved.h>
[ae5fe7e6]35
36/**
37 * The offsets in the unresolved array.
38 */
39#define REL_R_OFFSET (0)
40#define REL_R_INFO   (1)
41#define REL_R_ADDEND (2)
42
43/**
44 * The ELF format signature.
45 */
[f59d435d]46static rtems_rtl_loader_format elf_sig =
[ae5fe7e6]47{
48  .label = "ELF",
49  .flags = RTEMS_RTL_FMT_ELF
50};
51
52static bool
53rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
54{
55  /*
56   * This code is determined by the NetBSD machine headers.
57   */
58  switch (ehdr->e_machine)
59  {
60    ELFDEFNNAME (MACHDEP_ID_CASES)
61    default:
62      return false;
63  }
64  return true;
65}
66
[03139d5b]67static bool
68rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
69                           const Elf_Sym*      sym,
70                           const char*         symname,
71                           rtems_rtl_obj_sym** symbol,
72                           Elf_Word*           value)
[ae5fe7e6]73{
[f59d435d]74  rtems_rtl_obj_sect* sect;
[ae5fe7e6]75
[03139d5b]76  /*
77   * If the symbol type is STT_NOTYPE the symbol references a global
78   * symbol. The gobal symbol table is searched to find it and that value
79   * returned. If the symbol is local to the object module the section for the
80   * symbol is located and it's base added to the symbol's value giving an
81   * absolute location.
82   */
83  if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
[ae5fe7e6]84  {
[a2e1e30d]85    /*
86     * Search the object file then the global table for the symbol.
87     */
[03139d5b]88    *symbol = rtems_rtl_symbol_obj_find (obj, symname);
89    if (!*symbol)
[ae5fe7e6]90    {
91      rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
92      return false;
93    }
94
[03139d5b]95    *value = (Elf_Addr) (*symbol)->value;
[ae5fe7e6]96    return true;
97  }
98
[03139d5b]99  *symbol = NULL;
100
[ae5fe7e6]101  sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
102  if (!sect)
103  {
104    rtems_rtl_set_error (EINVAL, "reloc symbol's section not found");
105    return false;
106  }
107
[8bdbefe]108  *value = sym->st_value + (Elf_Addr) sect->base;
[ae5fe7e6]109  return true;
110}
111
[03139d5b]112/**
113 * Relocation worker routine.
114 */
115typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj*      obj,
116                                            bool                is_rela,
117                                            void*               relbuf,
118                                            rtems_rtl_obj_sect* targetsect,
119                                            rtems_rtl_obj_sym*  symbol,
120                                            Elf_Sym*            sym,
121                                            const char*         symname,
122                                            Elf_Word            symvalue,
123                                            bool                resolved,
124                                            void*               data);
125
126/**
127 * Relocation parser data.
128 */
129typedef struct
130{
131  size_t dependents; /**< The number of dependent object files. */
132  size_t unresolved; /**< The number of unresolved symbols. */
133} rtems_rtl_elf_reloc_data;
134
135static bool
136rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
137                            bool                is_rela,
138                            void*               relbuf,
139                            rtems_rtl_obj_sect* targetsect,
140                            rtems_rtl_obj_sym*  symbol,
141                            Elf_Sym*            sym,
142                            const char*         symname,
143                            Elf_Word            symvalue,
144                            bool                resolved,
145                            void*               data)
146{
147  rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
148  /*
149   * If the symbol has been resolved and there is a symbol name it is a global
150   * symbol and from another object file so add it as a dependency.
151   */
152  if (!resolved)
153  {
154    ++rd->unresolved;
155  }
156  else if (resolved && symname != NULL)
157  {
158    /*
159     * Find the symbol's object file. It cannot be NULL so ignore that result
160     * if returned, it means something is corrupted. We are in an iterator.
161     */
162    rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
163    if (sobj != NULL)
164    {
165      /*
166       * A dependency is not the base kernel image or itself. Tag the object as
167       * having been visited so we count it only once.
168       */
169      if (sobj != rtems_rtl_baseimage () && obj != sobj &&
170          (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
171      {
172        sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
173        ++rd->dependents;
174      }
175    }
176  }
177  return true;
178}
179
180static bool
181rtems_rtl_elf_reloc_relocator (rtems_rtl_obj*      obj,
182                               bool                is_rela,
183                               void*               relbuf,
184                               rtems_rtl_obj_sect* targetsect,
185                               rtems_rtl_obj_sym*  symbol,
186                               Elf_Sym*            sym,
187                               const char*         symname,
188                               Elf_Word            symvalue,
189                               bool                resolved,
190                               void*               data)
191{
192  const Elf_Rela* rela = (const Elf_Rela*) relbuf;
193  const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
194
195  if (!resolved)
196  {
197    uint16_t       flags = 0;
198    rtems_rtl_word rel_words[3];
199
200    if (is_rela)
201    {
202      flags = 1;
203      rel_words[REL_R_OFFSET] = rela->r_offset;
204      rel_words[REL_R_INFO] = rela->r_info;
205      rel_words[REL_R_ADDEND] = rela->r_addend;
206    }
207    else
208    {
209      rel_words[REL_R_OFFSET] = rel->r_offset;
210      rel_words[REL_R_INFO] = rel->r_info;
211      rel_words[REL_R_ADDEND] = 0;
212    }
213
214    if (!rtems_rtl_unresolved_add (obj,
215                                   flags,
216                                   symname,
217                                   targetsect->section,
218                                   rel_words))
219      return false;
220
221    ++obj->unresolved;
222  }
223  else
224  {
225    rtems_rtl_obj* sobj;
226
227    if (is_rela)
228    {
229      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
230        printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
231                symname, (int) ELF_R_SYM (rela->r_info),
232                (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
233                (uintmax_t) rela->r_offset, (int) rela->r_addend);
234      if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
235                                        symname, sym->st_info, symvalue))
236        return false;
237    }
238    else
239    {
240      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
241        printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
242                symname, (int) ELF_R_SYM (rel->r_info),
243                (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
244                (uintmax_t) rel->r_offset);
245      if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
246                                       symname, sym->st_info, symvalue))
247        return false;
248    }
249
250    sobj = rtems_rtl_find_obj_with_symbol (symbol);
[89c59be]251
252    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
253      printf ("rtl: depend: %s -> %s:%s\n",
254              obj->oname,
255              sobj == NULL ? "not-found" : sobj->oname,
256              symname);
257
[03139d5b]258    if (sobj != NULL)
259    {
260      if (rtems_rtl_obj_add_dependent (obj, sobj))
261        rtems_rtl_obj_inc_reference (sobj);
262    }
263  }
264
265  return true;
266}
267
[ae5fe7e6]268static bool
[03139d5b]269rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
270                               int                         fd,
271                               rtems_rtl_obj_sect*         sect,
272                               rtems_rtl_elf_reloc_handler handler,
273                               void*                       data)
[ae5fe7e6]274{
[f59d435d]275  rtems_rtl_obj_cache* symbols;
276  rtems_rtl_obj_cache* strings;
277  rtems_rtl_obj_cache* relocs;
278  rtems_rtl_obj_sect*  targetsect;
279  rtems_rtl_obj_sect*  symsect;
280  rtems_rtl_obj_sect*  strtab;
281  bool                 is_rela;
282  size_t               reloc_size;
283  int                  reloc;
[ae5fe7e6]284
285  /*
286   * First check if the section the relocations are for exists. If it does not
287   * exist ignore these relocations. They are most probably debug sections.
288   */
289  targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info);
290  if (!targetsect)
291    return true;
292
293  rtems_rtl_obj_caches (&symbols, &strings, &relocs);
294
295  if (!symbols || !strings || !relocs)
296    return false;
297
298  symsect = rtems_rtl_obj_find_section (obj, ".symtab");
299  if (!symsect)
300  {
301    rtems_rtl_set_error (EINVAL, "no .symtab section");
302    return false;
303  }
304
305  strtab = rtems_rtl_obj_find_section (obj, ".strtab");
306  if (!strtab)
307  {
308    rtems_rtl_set_error (EINVAL, "no .strtab section");
309    return false;
310  }
311
312  if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
313    printf ("rtl: relocation: %s, syms:%s\n", sect->name, symsect->name);
314
315  /*
316   * Handle the different relocation record types.
317   */
318  is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) ==
319             RTEMS_RTL_OBJ_SECT_RELA) ? true : false;
320  reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel);
321
322  for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
323  {
[03139d5b]324    uint8_t            relbuf[reloc_size];
325    const Elf_Rela*    rela = (const Elf_Rela*) relbuf;
326    const Elf_Rel*     rel = (const Elf_Rel*) relbuf;
327    rtems_rtl_obj_sym* symbol = NULL;
328    Elf_Sym            sym;
329    const char*        symname = NULL;
330    off_t              off;
331    Elf_Word           rel_type;
332    Elf_Word           symvalue = 0;
333    bool               resolved;
[ae5fe7e6]334
335    off = obj->ooffset + sect->offset + (reloc * reloc_size);
336
337    if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off,
338                                         &relbuf[0], reloc_size))
339      return false;
340
[c6eead1]341    /*
342     * Read the symbol details.
343     */
[ae5fe7e6]344    if (is_rela)
345      off = (obj->ooffset + symsect->offset +
346             (ELF_R_SYM (rela->r_info) * sizeof (sym)));
347    else
348      off = (obj->ooffset + symsect->offset +
349             (ELF_R_SYM (rel->r_info) * sizeof (sym)));
350
351    if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
352                                         &sym, sizeof (sym)))
353      return false;
354
355    /*
[803eac9]356     * Only need the name of the symbol if global or a common symbol.
[ae5fe7e6]357     */
[803eac9]358    if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
359        sym.st_shndx == SHN_COMMON)
[ae5fe7e6]360    {
361      size_t len;
362      off = obj->ooffset + strtab->offset + sym.st_name;
363      len = RTEMS_RTL_ELF_STRING_MAX;
364
365      if (!rtems_rtl_obj_cache_read (strings, fd, off,
366                                     (void**) &symname, &len))
367        return false;
368    }
369
370    /*
371     * See if the record references an external symbol. If it does find the
372     * symbol value. If the symbol cannot be found flag the object file as
[03139d5b]373     * having unresolved externals and store the external. The load of an
[ae5fe7e6]374     * object after this one may provide the unresolved externals.
375     */
376    if (is_rela)
[03139d5b]377      rel_type = ELF_R_TYPE(rela->r_info);
[ae5fe7e6]378    else
[03139d5b]379      rel_type = ELF_R_TYPE(rel->r_info);
[ae5fe7e6]380
[03139d5b]381    resolved = true;
[ae5fe7e6]382
[03139d5b]383    if (rtems_rtl_elf_rel_resolve_sym (rel_type))
384      resolved = rtems_rtl_elf_find_symbol (obj,
385                                            &sym, symname,
386                                            &symbol, &symvalue);
[ae5fe7e6]387
[03139d5b]388    if (!handler (obj,
389                  is_rela, relbuf, targetsect,
390                  symbol, &sym, symname, symvalue, resolved,
391                  data))
392      return false;
[ae5fe7e6]393  }
394
395  /*
396   * Set the unresolved externals status if there are unresolved externals.
397   */
398  if (obj->unresolved)
399    obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED;
400
401  return true;
402}
403
[03139d5b]404static bool
405rtems_rtl_elf_relocs_parser (rtems_rtl_obj*      obj,
406                             int                 fd,
407                             rtems_rtl_obj_sect* sect,
408                             void*               data)
409{
410  bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
411                                          rtems_rtl_elf_reloc_parser, data);
412  rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
413  return r;
414}
415
416static bool
417rtems_rtl_elf_relocs_locator (rtems_rtl_obj*      obj,
418                              int                 fd,
419                              rtems_rtl_obj_sect* sect,
420                              void*               data)
421{
422  return rtems_rtl_elf_relocate_worker (obj, fd, sect,
423                                        rtems_rtl_elf_reloc_relocator, data);
424}
425
[ae5fe7e6]426bool
[f59d435d]427rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
428                                   rtems_rtl_obj_sym*        sym)
[ae5fe7e6]429{
[f59d435d]430  rtems_rtl_obj_sect* sect;
431  bool                is_rela;
432  Elf_Word            symvalue;
[03139d5b]433  rtems_rtl_obj*      sobj;
[ae5fe7e6]434
[03139d5b]435  is_rela = reloc->flags & 1;
[ae5fe7e6]436
437  sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
438  if (!sect)
439  {
440    rtems_rtl_set_error (ENOEXEC, "unresolved sect not found");
441    return false;
442  }
443
444  symvalue = (Elf_Word) (intptr_t) sym->value;
445  if (is_rela)
446  {
447    Elf_Rela rela;
448    rela.r_offset = reloc->rel[REL_R_OFFSET];
449    rela.r_info = reloc->rel[REL_R_INFO];
450    rela.r_addend = reloc->rel[REL_R_ADDEND];
451    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
[8bdbefe]452          printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n",
[ae5fe7e6]453                  (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
[8bdbefe]454                  (uintmax_t) rela.r_offset, (int) rela.r_addend);
[ae5fe7e6]455    if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
456                                      sym->name, sym->data, symvalue))
457      return false;
458  }
459  else
460  {
461    Elf_Rel rel;
462    rel.r_offset = reloc->rel[REL_R_OFFSET];
463    rel.r_info = reloc->rel[REL_R_INFO];
464    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
[8bdbefe]465      printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
[ae5fe7e6]466              (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
[8bdbefe]467              (uintmax_t) rel.r_offset);
[ae5fe7e6]468    if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
469                                     sym->name, sym->data, symvalue))
470      return false;
471  }
472
[03139d5b]473  if (reloc->obj->unresolved > 0)
[ae5fe7e6]474  {
475    --reloc->obj->unresolved;
[03139d5b]476    if (reloc->obj->unresolved == 0)
[ae5fe7e6]477      reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
478  }
479
[03139d5b]480  sobj = rtems_rtl_find_obj_with_symbol (sym);
[89c59be]481
482  if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
483    printf ("rtl: depend: %s -> %s:%s\n",
484            reloc->obj->oname,
485            sobj == NULL ? "not-found" : sobj->oname,
486            sym->name);
487
[03139d5b]488  if (sobj != NULL)
489  {
490    if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
491      rtems_rtl_obj_inc_reference (sobj);
492  }
493
[ae5fe7e6]494  return true;
495}
496
[803eac9]497/**
498 * Common symbol iterator data.
499 */
500typedef struct
501{
502  size_t   size;      /**< The size of the common section */
503  uint32_t alignment; /**< The alignment of the common section. */
504} rtems_rtl_elf_common_data;
505
506static bool
507rtems_rtl_elf_common (rtems_rtl_obj*      obj,
508                      int                 fd,
509                      rtems_rtl_obj_sect* sect,
510                      void*               data)
511{
512  rtems_rtl_elf_common_data* common = (rtems_rtl_elf_common_data*) data;
513  rtems_rtl_obj_cache*       symbols;
514  int                        sym;
515
516  rtems_rtl_obj_caches (&symbols, NULL, NULL);
517
518  if (!symbols)
519    return false;
520
521  /*
522   * Find the number size of the common section by finding all symbols that
523   * reference the SHN_COMMON section.
524   */
525  for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
526  {
527    Elf_Sym symbol;
528    off_t   off;
529
530    off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
531
532    if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
533                                         &symbol, sizeof (symbol)))
534      return false;
535
536    if ((symbol.st_shndx == SHN_COMMON) &&
537        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
538         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON)))
539    {
540      if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
541        printf ("rtl: com:elf:%-2d bind:%-2d type:%-2d size:%d value:%d\n",
542                sym, (int) ELF_ST_BIND (symbol.st_info),
543                (int) ELF_ST_TYPE (symbol.st_info),
544                (int) symbol.st_size, (int) symbol.st_value);
545      /*
546       * If the size is zero this is the first entry, it defines the common
547       * section's aligment. The symbol's value is the alignment.
548       */
549      if (common->size == 0)
550        common->alignment = symbol.st_value;
551      common->size +=
552        rtems_rtl_obj_align (common->size, symbol.st_value) + symbol.st_size;
553    }
554  }
555
556  return true;
557}
558
[03139d5b]559static bool
560rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
561{
562  /*
563   * If there are dependencies and no unresolved externals allocate and size
564   * the dependency table to the number of dependent object files. If there are
565   * unresolved externals the number of dependencies is unknown at this point
566   * in time so use dynamic allocation to allocate the block size number of
567   * entries when the entries are added.
568   */
569  if (reloc->dependents > 0 && reloc->unresolved == 0)
570  {
571    if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
572      return false;
573  }
574  return true;
575}
576
[ae5fe7e6]577static bool
[f59d435d]578rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
579                       int                 fd,
580                       rtems_rtl_obj_sect* sect,
581                       void*               data)
[ae5fe7e6]582{
[f59d435d]583  rtems_rtl_obj_cache* symbols;
584  rtems_rtl_obj_cache* strings;
585  rtems_rtl_obj_sect*  strtab;
586  int                  locals;
587  int                  local_string_space;
588  rtems_rtl_obj_sym*   lsym;
589  char*                lstring;
590  int                  globals;
591  int                  global_string_space;
592  rtems_rtl_obj_sym*   gsym;
593  char*                gstring;
[803eac9]594  size_t               common_offset;
[f59d435d]595  int                  sym;
[ae5fe7e6]596
597  strtab = rtems_rtl_obj_find_section (obj, ".strtab");
598  if (!strtab)
599  {
600    rtems_rtl_set_error (EINVAL, "no .strtab section");
601    return false;
602  }
603
604  rtems_rtl_obj_caches (&symbols, &strings, NULL);
605
606  if (!symbols || !strings)
607    return false;
608
609  /*
610   * Find the number of globals and the amount of string space
611   * needed. Also check for duplicate symbols.
612   */
613
[a2e1e30d]614  globals             = 0;
615  global_string_space = 0;
616  locals              = 0;
617  local_string_space  = 0;
[ae5fe7e6]618
619  for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
620  {
621    Elf_Sym     symbol;
622    off_t       off;
623    const char* name;
624    size_t      len;
625
626    off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
627
628    if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
629                                         &symbol, sizeof (symbol)))
630      return false;
631
632    off = obj->ooffset + strtab->offset + symbol.st_name;
633    len = RTEMS_RTL_ELF_STRING_MAX;
634
635    if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
636      return false;
637
638    /*
[a2e1e30d]639     * Only keep the functions and global or weak symbols so place them in a
640     * separate table to local symbols. Local symbols are not needed after the
641     * object file has been loaded. Undefined symbols are NOTYPE so for locals
642     * we need to make sure there is a valid seciton.
[ae5fe7e6]643     */
[803eac9]644    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
645      printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \
646              "type:%-2d sect:%d size:%d\n",
647              sym, (int) symbol.st_name, name,
648              (int) ELF_ST_BIND (symbol.st_info),
649              (int) ELF_ST_TYPE (symbol.st_info),
650              symbol.st_shndx,
651              (int) symbol.st_size);
652
[a2e1e30d]653    if ((symbol.st_shndx != 0) &&
654        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
[803eac9]655         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
[a2e1e30d]656         (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
657         (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)))
[ae5fe7e6]658    {
[803eac9]659      /*
660       * There needs to be a valid section for the symbol.
661       */
[f59d435d]662      rtems_rtl_obj_sect* symsect;
[a2e1e30d]663
664      symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
[803eac9]665      if (symsect != NULL)
[ae5fe7e6]666      {
[a2e1e30d]667        if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
668            (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
[ae5fe7e6]669        {
[a2e1e30d]670          /*
671           * If there is a globally exported symbol already present and this
672           * symbol is not weak raise an error. If the symbol is weak and
673           * present globally ignore this symbol and use the global one and if
674           * it is not present take this symbol global or weak. We accept the
675           * first weak symbol we find and make it globally exported.
676           */
677          if (rtems_rtl_symbol_global_find (name) &&
678              (ELF_ST_BIND (symbol.st_info) != STB_WEAK))
679          {
680            rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
681            return false;
682          }
683          else
684          {
[803eac9]685            if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
686              printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n",
687                      sym, (int) symbol.st_name, name);
[a2e1e30d]688            ++globals;
689            global_string_space += strlen (name) + 1;
690          }
[ae5fe7e6]691        }
[a2e1e30d]692        else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
[ae5fe7e6]693        {
[803eac9]694          if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
695            printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n",
696                    sym, (int) symbol.st_name, name);
[a2e1e30d]697          ++locals;
698          local_string_space += strlen (name) + 1;
[ae5fe7e6]699        }
700      }
701    }
702  }
703
[a2e1e30d]704  if (locals)
[ae5fe7e6]705  {
[f59d435d]706    obj->local_size = locals * sizeof (rtems_rtl_obj_sym) + local_string_space;
[a2e1e30d]707    obj->local_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
708                                            obj->local_size, true);
709    if (!obj->local_table)
710    {
711      obj->local_size = 0;
712      rtems_rtl_set_error (ENOMEM, "no memory for obj local syms");
713      return false;
714    }
715
716    obj->local_syms = locals;
717  }
[ae5fe7e6]718
[a2e1e30d]719  if (globals)
720  {
[f59d435d]721    obj->global_size = globals * sizeof (rtems_rtl_obj_sym) + global_string_space;
[ae5fe7e6]722    obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
723                                             obj->global_size, true);
724    if (!obj->global_table)
725    {
[a2e1e30d]726      if (locals)
727      {
728        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
729        obj->local_size = 0;
730        obj->local_syms = 0;
731      }
[ae5fe7e6]732      obj->global_size = 0;
733      rtems_rtl_set_error (ENOMEM, "no memory for obj global syms");
734      return false;
735    }
736
737    obj->global_syms = globals;
[a2e1e30d]738  }
[ae5fe7e6]739
[a2e1e30d]740  lsym = obj->local_table;
741  lstring =
[f59d435d]742    (((char*) obj->local_table) + (locals * sizeof (rtems_rtl_obj_sym)));
[a2e1e30d]743  gsym = obj->global_table;
744  gstring =
[f59d435d]745    (((char*) obj->global_table) + (globals * sizeof (rtems_rtl_obj_sym)));
[a2e1e30d]746
[803eac9]747  common_offset = 0;
748
[a2e1e30d]749  for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
750  {
751    Elf_Sym     symbol;
752    off_t       off;
753    const char* name;
754    size_t      len;
[ae5fe7e6]755
[a2e1e30d]756    off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
[ae5fe7e6]757
[a2e1e30d]758    if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
759                                         &symbol, sizeof (symbol)))
760    {
761      if (locals)
[ae5fe7e6]762      {
[a2e1e30d]763        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
764        obj->local_table = NULL;
765        obj->local_size = 0;
766        obj->local_syms = 0;
767      }
768      if (globals)
769      {
770        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
[ae5fe7e6]771        obj->global_table = NULL;
772        obj->global_syms = 0;
773        obj->global_size = 0;
774      }
[a2e1e30d]775      return false;
776    }
[ae5fe7e6]777
[a2e1e30d]778    off = obj->ooffset + strtab->offset + symbol.st_name;
779    len = RTEMS_RTL_ELF_STRING_MAX;
[ae5fe7e6]780
[a2e1e30d]781    if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
782      return false;
[ae5fe7e6]783
[a2e1e30d]784    if ((symbol.st_shndx != 0) &&
785        ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
[803eac9]786         (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
[a2e1e30d]787         (ELF_ST_TYPE (symbol.st_info) == STT_FUNC) ||
788         (ELF_ST_TYPE (symbol.st_info) == STT_NOTYPE)) &&
789         ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
790          (ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
791          (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
[ae5fe7e6]792      {
[f59d435d]793        rtems_rtl_obj_sect* symsect;
794        rtems_rtl_obj_sym*  osym;
795        char*               string;
[803eac9]796        Elf_Word            value;
[a2e1e30d]797
[ae5fe7e6]798        symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
[a2e1e30d]799        if (symsect)
[ae5fe7e6]800        {
[a2e1e30d]801          if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
802              (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
803          {
804            osym = gsym;
805            string = gstring;
806            gstring += strlen (name) + 1;
807            ++gsym;
808          }
809          else
810          {
811            osym = lsym;
812            string = lstring;
813            lstring += strlen (name) + 1;
814            ++lsym;
815          }
816
[803eac9]817          /*
818           * Allocate any common symbols in the common section.
819           */
820          if (symbol.st_shndx == SHN_COMMON)
821          {
822            size_t value_off = rtems_rtl_obj_align (common_offset,
823                                                    symbol.st_value);
824            common_offset = value_off + symbol.st_size;
825            value = value_off;
826          }
827          else
828          {
829            value = symbol.st_value;
830          }
831
[a2e1e30d]832          rtems_chain_set_off_chain (&osym->node);
833          memcpy (string, name, strlen (name) + 1);
834          osym->name = string;
[803eac9]835          osym->value = value + (uint8_t*) symsect->base;
[a2e1e30d]836          osym->data = symbol.st_info;
837
838          if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
839            printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \
840                    "type:%-2d val:%8p sect:%d size:%d\n",
841                    sym, (int) symbol.st_name, osym->name,
842                    (int) ELF_ST_BIND (symbol.st_info),
843                    (int) ELF_ST_TYPE (symbol.st_info),
844                    osym->value, symbol.st_shndx,
845                    (int) symbol.st_size);
[ae5fe7e6]846        }
847      }
[a2e1e30d]848  }
[ae5fe7e6]849
[a2e1e30d]850  if (globals)
[ae5fe7e6]851    rtems_rtl_symbol_obj_add (obj);
852
853  return true;
854}
855
856static bool
[f59d435d]857rtems_rtl_elf_loader (rtems_rtl_obj*      obj,
858                      int                 fd,
859                      rtems_rtl_obj_sect* sect,
860                      void*               data)
[ae5fe7e6]861{
862  uint8_t* base_offset;
863  size_t   len;
864
865  if (lseek (fd, obj->ooffset + sect->offset, SEEK_SET) < 0)
866  {
867    rtems_rtl_set_error (errno, "section load seek failed");
868    return false;
869  }
870
871  base_offset = sect->base;
872  len = sect->size;
873
874  while (len)
875  {
876    ssize_t r = read (fd, base_offset, len);
877    if (r <= 0)
878    {
879      rtems_rtl_set_error (errno, "section load read failed");
880      return false;
881    }
882    base_offset += r;
883    len -= r;
884  }
885
886  return true;
887}
888
889static bool
[f59d435d]890rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
[ae5fe7e6]891{
[f59d435d]892  rtems_rtl_obj_cache* sects;
893  rtems_rtl_obj_cache* strings;
894  int                  section;
895  off_t                sectstroff;
896  off_t                off;
897  Elf_Shdr             shdr;
[ae5fe7e6]898
899  rtems_rtl_obj_caches (&sects, &strings, NULL);
900
901  if (!sects || !strings)
902    return false;
903
904  /*
905   * Get the offset to the section string table.
906   */
907  off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize);
908
909  if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
910    return false;
911
912  if (shdr.sh_type != SHT_STRTAB)
913  {
914    rtems_rtl_set_error (EINVAL, "bad .sectstr section type");
915    return false;
916  }
917
918  sectstroff = obj->ooffset + shdr.sh_offset;
919
920  for (section = 0; section < ehdr->e_shnum; ++section)
921  {
922    uint32_t flags;
923
[580466c]924    /*
925     * Make sure section is at least 32bits to avoid 16-bit overflow errors.
926     */
[fc523ac8]927    off = obj->ooffset + ehdr->e_shoff + (((uint32_t) section) * ehdr->e_shentsize);
[ae5fe7e6]928
[75386e1]929    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
930      printf ("rtl: section header: %2d: offset=%d\n", section, (int) off);
931
[ae5fe7e6]932    if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
933      return false;
934
[bba48d9]935    if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
936      printf ("rtl: section: %2d: type=%d flags=%08x link=%d info=%d\n",
937              section, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
938              (int) shdr.sh_link, (int) shdr.sh_info);
939
[803eac9]940    flags = 0;
941
[ae5fe7e6]942    switch (shdr.sh_type)
943    {
944      case SHT_NULL:
945        /*
946         * Ignore.
947         */
948        break;
949
950      case SHT_PROGBITS:
951        /*
952         * There are 2 program bits sections. One is the program text and the
953         * other is the program data. The program text is flagged
954         * alloc/executable and the program data is flagged alloc/writable.
955         */
956        if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
957        {
958          if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR)
959            flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD;
960          else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE)
961            flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD;
962          else
963            flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD;
964        }
965        break;
966
967      case SHT_NOBITS:
968        /*
969         * There is 1 NOBIT section which is the .bss section. There is nothing
970         * but a definition as the .bss is just a clear region of memory.
971         */
972        if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE))
973          flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO;
974        break;
975
976      case SHT_RELA:
977        flags = RTEMS_RTL_OBJ_SECT_RELA;
978        break;
979
980      case SHT_REL:
981        /*
982         * The sh_link holds the section index for the symbol table. The sh_info
983         * holds the section index the relocations apply to.
984         */
985        flags = RTEMS_RTL_OBJ_SECT_REL;
986        break;
987
988      case SHT_SYMTAB:
989        flags = RTEMS_RTL_OBJ_SECT_SYM;
990        break;
991
992      case SHT_STRTAB:
993        flags = RTEMS_RTL_OBJ_SECT_STR;
994        break;
995
[4408603]996      case SHT_INIT_ARRAY:
997        /*
998         * Constructors are text and need to be loaded.
999         */
1000        flags = (RTEMS_RTL_OBJ_SECT_CTOR |
1001                 RTEMS_RTL_OBJ_SECT_TEXT |
1002                 RTEMS_RTL_OBJ_SECT_LOAD);
1003        break;
1004
1005      case SHT_FINI_ARRAY:
1006        /*
1007         * Destructors are text and need to be loaded.
1008         */
1009        flags = (RTEMS_RTL_OBJ_SECT_DTOR |
1010                 RTEMS_RTL_OBJ_SECT_TEXT |
1011                 RTEMS_RTL_OBJ_SECT_LOAD);
1012        break;
1013
[ae5fe7e6]1014      default:
[c6eead1]1015        /*
[bba48d9]1016         * See if there are architecture specific flags?
[c6eead1]1017         */
1018        flags = rtems_rtl_elf_section_flags (obj, &shdr);
1019        if (flags == 0)
1020        {
1021          if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING))
1022            printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n",
1023                    section, (int) shdr.sh_type, (int) shdr.sh_flags);
1024        }
[ae5fe7e6]1025        break;
1026    }
1027
1028    if (flags != 0)
1029    {
1030      char*  name;
1031      size_t len;
1032
[bba48d9]1033      /*
1034       * If link ordering this section must appear in the same order in memory
1035       * as the linked-to section relative to the sections it loads with.
1036       */
1037      if ((shdr.sh_flags & SHF_LINK_ORDER) != 0)
1038        flags |= RTEMS_RTL_OBJ_SECT_LINK;
1039
[4408603]1040      /*
1041       * Some architexctures support a named PROGBIT section for INIT/FINI.
1042       */
[ae5fe7e6]1043      len = RTEMS_RTL_ELF_STRING_MAX;
1044      if (!rtems_rtl_obj_cache_read (strings, fd,
1045                                     sectstroff + shdr.sh_name,
1046                                     (void**) &name, &len))
1047        return false;
1048
1049      if (strcmp (".ctors", name) == 0)
1050        flags |= RTEMS_RTL_OBJ_SECT_CTOR;
1051      if (strcmp (".dtors", name) == 0)
1052        flags |= RTEMS_RTL_OBJ_SECT_DTOR;
1053
[c6eead1]1054      if (rtems_rtl_elf_unwind_parse (obj, name, flags))
1055      {
1056        flags &= ~(RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST);
1057        flags |= RTEMS_RTL_OBJ_SECT_EH;
1058      }
1059
[ae5fe7e6]1060      if (!rtems_rtl_obj_add_section (obj, section, name,
1061                                      shdr.sh_size, shdr.sh_offset,
1062                                      shdr.sh_addralign, shdr.sh_link,
1063                                      shdr.sh_info, flags))
1064        return false;
1065    }
1066  }
1067
1068  return true;
1069}
1070
[803eac9]1071static bool
1072rtems_rtl_elf_add_common (rtems_rtl_obj* obj, size_t size, uint32_t alignment)
1073{
1074  if (size > 0)
1075  {
1076    if (!rtems_rtl_obj_add_section (obj, SHN_COMMON, ".common.rtems.rtl",
1077                                    size, 0, alignment, 0, 0,
1078                                    RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO))
1079      return false;
1080  }
1081  return true;
1082}
1083
[ae5fe7e6]1084bool
[f59d435d]1085rtems_rtl_elf_file_check (rtems_rtl_obj* obj, int fd)
[ae5fe7e6]1086{
[f59d435d]1087  rtems_rtl_obj_cache* header;
1088  Elf_Ehdr             ehdr;
[ae5fe7e6]1089
1090  rtems_rtl_obj_caches (&header, NULL, NULL);
1091
1092  if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1093                                       &ehdr, sizeof (ehdr)))
1094    return false;
1095
1096  /*
1097   * Check we have a valid ELF file.
1098   */
1099  if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1100      || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1101  {
1102    return false;
1103  }
1104
1105  if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1106      || (ehdr.e_version != EV_CURRENT)
1107      || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1108  {
1109    return false;
1110  }
1111
1112  return true;
1113}
1114
[c6eead1]1115static bool
[f59d435d]1116rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
[ae5fe7e6]1117{
1118  rtems_chain_control* sections = NULL;
1119  rtems_chain_node*    node = NULL;
1120  size_t               mask = 0;
1121  int                  sec_num = 0;
[c6eead1]1122  section_detail*      sd;
[ae5fe7e6]1123  int                  i = 0;
1124
[c6eead1]1125  /*
1126   * Caculate the size of sections' name.
1127   */
[ae5fe7e6]1128
1129  for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
1130       mask <= RTEMS_RTL_OBJ_SECT_BSS;
1131       mask <<= 1)
1132  {
1133    sections = &obj->sections;
1134    node = rtems_chain_first (sections);
1135    while (!rtems_chain_is_tail (sections, node))
1136    {
[f59d435d]1137      rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
[ae5fe7e6]1138      if ((sect->size != 0) && ((sect->flags & mask) != 0))
1139      {
1140        ++sec_num;
1141      }
1142      node = rtems_chain_next (node);
1143    }
1144  }
1145
1146  obj->obj_num = 1;
[c6eead1]1147  obj->linkmap = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
1148                                      sizeof(struct link_map) +
1149                                      sec_num * sizeof (section_detail), true);
1150  if (!obj->linkmap)
[ae5fe7e6]1151  {
[c6eead1]1152    rtems_rtl_set_error (ENOMEM, "no memory for obj linkmap");
[ae5fe7e6]1153    return false;
1154  }
1155
[c6eead1]1156  obj->linkmap->name = obj->oname;
1157  obj->linkmap->sec_num = sec_num;
1158  obj->linkmap->sec_detail = (section_detail*) (obj->linkmap + 1);
1159  obj->linkmap->rpathlen = 0;
1160  obj->linkmap->rpath = NULL;
1161  obj->linkmap->l_next = NULL;
1162  obj->linkmap->l_prev = NULL;
1163  obj->linkmap->sec_addr[rap_text] = obj->text_base;
1164  obj->linkmap->sec_addr[rap_const] = obj->const_base;
1165  obj->linkmap->sec_addr[rap_data] = obj->data_base;
1166  obj->linkmap->sec_addr[rap_bss] = obj->bss_base;
1167
1168  sd = obj->linkmap->sec_detail;
[ae5fe7e6]1169  sections = &obj->sections;
1170  node = rtems_chain_first (sections);
[c6eead1]1171
[ae5fe7e6]1172  for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
1173       mask <= RTEMS_RTL_OBJ_SECT_BSS;
1174       mask <<= 1)
1175  {
1176    sections = &obj->sections;
1177    node = rtems_chain_first (sections);
1178    while (!rtems_chain_is_tail (sections, node))
1179    {
[f59d435d]1180      rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
[ae5fe7e6]1181
1182      if ((sect->size != 0) && ((sect->flags & mask) != 0))
1183      {
1184        sd[i].name = sect->name;
1185        sd[i].size = sect->size;
1186        if (mask == RTEMS_RTL_OBJ_SECT_TEXT)
1187        {
1188          sd[i].rap_id = rap_text;
1189          sd[i].offset = sect->base - obj->text_base;
1190        }
1191        if (mask == RTEMS_RTL_OBJ_SECT_CONST)
1192        {
1193          sd[i].rap_id = rap_const;
1194          sd[i].offset = sect->base - obj->const_base;
1195        }
1196        if (mask == RTEMS_RTL_OBJ_SECT_DATA)
1197        {
1198          sd[i].rap_id = rap_data;
1199          sd[i].offset = sect->base - obj->data_base;
1200        }
1201        if (mask == RTEMS_RTL_OBJ_SECT_BSS)
1202        {
1203          sd[i].rap_id = rap_bss;
1204          sd[i].offset = sect->base - obj->bss_base;
1205        }
1206
1207        ++i;
1208      }
1209      node = rtems_chain_next (node);
1210    }
1211  }
1212
1213  return true;
1214}
1215
1216bool
[f59d435d]1217rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
[ae5fe7e6]1218{
[803eac9]1219  rtems_rtl_obj_cache*      header;
1220  Elf_Ehdr                  ehdr;
[03139d5b]1221  rtems_rtl_elf_reloc_data  relocs = { 0 };
1222  rtems_rtl_elf_common_data common = { 0 };
[ae5fe7e6]1223
1224  rtems_rtl_obj_caches (&header, NULL, NULL);
1225
1226  if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset,
1227                                       &ehdr, sizeof (ehdr)))
1228    return false;
1229
1230  /*
1231   * Check we have a valid ELF file.
1232   */
1233  if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0)
1234      || ehdr.e_ident[EI_CLASS] != ELFCLASS)
1235  {
1236    rtems_rtl_set_error (EINVAL, "invalid ELF file format");
1237    return false;
1238  }
1239
1240  if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT)
1241      || (ehdr.e_version != EV_CURRENT)
1242      || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS)))
1243  {
1244    rtems_rtl_set_error (EINVAL, "unsupported ELF file version");
1245    return false;
1246  }
1247
1248  if (!rtems_rtl_elf_machine_check (&ehdr))
1249  {
1250    rtems_rtl_set_error (EINVAL, "unsupported machine type");
1251    return false;
1252  }
1253
1254  if (ehdr.e_type == ET_DYN)
1255  {
1256    rtems_rtl_set_error (EINVAL, "unsupported ELF file type");
1257    return false;
1258  }
1259
1260  if (ehdr.e_phentsize != 0)
1261  {
1262    rtems_rtl_set_error (EINVAL, "ELF file contains program headers");
1263    return false;
1264  }
1265
1266  if (ehdr.e_shentsize != sizeof (Elf_Shdr))
1267  {
1268    rtems_rtl_set_error (EINVAL, "invalid ELF section header size");
1269    return false;
1270  }
1271
1272  /*
1273   * Parse the section information first so we have the memory map of the object
1274   * file and the memory allocated. Any further allocations we make to complete
1275   * the load will not fragment the memory.
1276   */
1277  if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr))
1278    return false;
1279
[803eac9]1280  /*
1281   * See if there are any common variables and if there are add a common
1282   * section.
1283   */
1284  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
1285    return false;
1286  if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
1287    return false;
1288
1289  /*
1290   * Set the entry point if there is one.
1291   */
[ae5fe7e6]1292  obj->entry = (void*)(uintptr_t) ehdr.e_entry;
1293
[803eac9]1294  /*
1295   * Load the sections and symbols and then relocation to the base address.
1296   */
[ae5fe7e6]1297  if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
1298    return false;
1299
[03139d5b]1300  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
1301    return false;
1302
1303  if (!rtems_rtl_elf_dependents (obj, &relocs))
1304    return false;
1305
[ae5fe7e6]1306  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
1307    return false;
1308
[03139d5b]1309  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
[ae5fe7e6]1310    return false;
1311
[a2e1e30d]1312  rtems_rtl_symbol_obj_erase_local (obj);
1313
[c6eead1]1314  if (!rtems_rtl_elf_load_linkmap (obj))
1315  {
1316    return false;
1317  }
1318
1319  if (!rtems_rtl_elf_unwind_register (obj))
[ae5fe7e6]1320  {
1321    return false;
1322  }
1323
1324  return true;
1325}
1326
[c6eead1]1327bool
[f59d435d]1328rtems_rtl_elf_file_unload (rtems_rtl_obj* obj)
[c6eead1]1329{
1330  rtems_rtl_elf_unwind_deregister (obj);
1331  return true;
1332}
1333
[f59d435d]1334rtems_rtl_loader_format*
[ae5fe7e6]1335rtems_rtl_elf_file_sig (void)
1336{
1337  return &elf_sig;
1338}
Note: See TracBrowser for help on using the repository browser.