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

Last change on this file since d8c70ba6 was d8c70ba6, checked in by Chris Johns <chrisj@…>, on Jan 15, 2019 at 6:47:41 AM

libdl: Add support for trampolines

  • Trampolines or fixups for veneers provide long jump support for instruciton sets that implement short relative address branches. The linker provides trampolines when creating a static image. This patch adds trampoline support to libdl and the ARM architecture.
  • The dl09 test requires enough memory so modules are outside the relative branch instruction ranges for the architecture.

Updates #3685

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