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

5
Last change on this file since 22afb034 was 22afb034, checked in by Chris Johns <chrisj@…>, on 02/18/19 at 00:46:22

libdl/alloc: Add a locking interface to the allocator.

  • Allow an allocator to lock the allocations. This is needed to lock the heap allocator so the text and trampoline table are as close together as possible to allow for the largest possible object file size.
  • Update the default heap allocator to lock the heap allocator.
  • Update ELF loading to lock the allocator.

Updates #3685

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