source: rtems/cpukit/libdl/rtl-obj.c @ b36c5209

Last change on this file since b36c5209 was b36c5209, checked in by Chris Johns <chrisj@…>, on May 3, 2019 at 12:15:20 AM

libdl: Do not access the ELF file while the allocator is locked.

  • Load symbols before allocation.
  • Parse reloc records and place any reloc recs in a cache to use while the allocator is locked.
  • Relocate symbols after section allocation.
  • Split section loading into allocation/locating and loading.
  • Update all arch back-ends with a new reloc interface to control tramp handling.
  • Add -a and -t to the object list shell command.

Closes #3741

  • Property mode set to 100644
File size: 40.9 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 rtl
12 *
13 * @brief RTEMS Run-Time Linker Error
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <errno.h>
21#include <inttypes.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
26#include <rtems/libio_.h>
27
28#include <rtems/rtl/rtl.h>
29#include "rtl-chain-iterator.h"
30#include <rtems/rtl/rtl-obj.h>
31#include "rtl-error.h"
32#include "rtl-find-file.h"
33#include "rtl-string.h"
34#include <rtems/rtl/rtl-trace.h>
35
36#define RTEMS_RTL_ELF_LOADER 1
37#define RTEMS_RTL_RAP_LOADER 1
38
39#if RTEMS_RTL_RAP_LOADER
40#include "rtl-rap.h"
41#define RTEMS_RTL_RAP_LOADER_COUNT 1
42#else
43#define RTEMS_RTL_RAP_LOADER_COUNT 0
44#endif
45
46#if RTEMS_RTL_ELF_LOADER
47#include "rtl-elf.h"
48#define RTEMS_RTL_ELF_LOADER_COUNT 1
49#else
50#define RTEMS_RTL_ELF_LOADER_COUNT 0
51#endif
52
53/**
54 * The table of supported loader formats.
55 */
56#define RTEMS_RTL_LOADERS (RTEMS_RTL_ELF_LOADER_COUNT + RTEMS_RTL_RAP_LOADER_COUNT)
57static const rtems_rtl_loader_table loaders[RTEMS_RTL_LOADERS] =
58{
59#if RTEMS_RTL_RAP_LOADER
60  { .check     = rtems_rtl_rap_file_check,
61    .load      = rtems_rtl_rap_file_load,
62    .unload    = rtems_rtl_rap_file_unload,
63    .unload    = rtems_rtl_rap_file_unload,
64    .signature = rtems_rtl_rap_file_sig },
65#endif
66#if RTEMS_RTL_ELF_LOADER
67  { .check     = rtems_rtl_elf_file_check,
68    .load      = rtems_rtl_elf_file_load,
69    .unload    = rtems_rtl_elf_file_unload,
70    .signature = rtems_rtl_elf_file_sig },
71#endif
72};
73
74rtems_rtl_obj*
75rtems_rtl_obj_alloc (void)
76{
77  rtems_rtl_obj* obj = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
78                                            sizeof (rtems_rtl_obj),
79                                            true);
80  if (obj)
81  {
82    /*
83     * Initialise the chains.
84     */
85    rtems_chain_initialize_empty (&obj->sections);
86    rtems_chain_initialize_empty (&obj->dependents);
87    /*
88     * No valid format.
89     */
90    obj->format = -1;
91  }
92  return obj;
93}
94
95static void
96rtems_rtl_obj_free_names (rtems_rtl_obj* obj)
97{
98  if (rtems_rtl_obj_oname_valid (obj))
99    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->oname);
100  if (rtems_rtl_obj_aname_valid (obj))
101    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->aname);
102  if (rtems_rtl_obj_fname_valid (obj))
103    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->fname);
104}
105
106bool
107rtems_rtl_obj_free (rtems_rtl_obj* obj)
108{
109  if (obj->users > 0 || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0))
110  {
111    rtems_rtl_set_error (EINVAL, "cannot free obj still in use");
112    return false;
113  }
114  if (!rtems_chain_is_node_off_chain (&obj->link))
115    rtems_chain_extract (&obj->link);
116  rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
117                              &obj->data_base, &obj->bss_base);
118  rtems_rtl_obj_erase_sections (obj);
119  rtems_rtl_obj_erase_dependents (obj);
120  rtems_rtl_symbol_obj_erase (obj);
121  rtems_rtl_obj_erase_trampoline (obj);
122  rtems_rtl_obj_free_names (obj);
123  if (obj->sec_num != NULL)
124    free (obj->sec_num);
125  if (obj->linkmap != NULL)
126    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->linkmap);
127  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj);
128  return true;
129}
130
131typedef struct rtems_rtl_obj_unresolved_data
132{
133  bool has_unresolved;
134} rtems_rtl_obj_unresolved_data;
135
136static bool
137rtems_rtl_obj_unresolved_dependent (rtems_rtl_obj* obj,
138                                    rtems_rtl_obj* dependent,
139                                    void*          data)
140{
141  rtems_rtl_obj_unresolved_data* ud;
142  ud = (rtems_rtl_obj_unresolved_data*) data;
143  if ((dependent->flags & RTEMS_RTL_OBJ_DEP_VISITED) == 0)
144  {
145    dependent->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
146    if ((dependent->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0)
147      ud->has_unresolved = true;
148    else
149    {
150      rtems_rtl_obj_iterate_dependents (dependent,
151                                        rtems_rtl_obj_unresolved_dependent,
152                                        ud);
153    }
154    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
155      printf ("rtl: obj: unresolved: dep: %s is %s\n",
156              dependent->oname, ud->has_unresolved ? "unresolved" : "resolved");
157  }
158  return ud->has_unresolved;
159}
160
161static bool
162rtems_rtl_obj_unresolved_object (rtems_chain_node* node, void* data)
163{
164  rtems_rtl_obj*                 obj = (rtems_rtl_obj*) node;
165  rtems_rtl_obj_unresolved_data* ud;
166  ud = (rtems_rtl_obj_unresolved_data*) data;
167  ud->has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0;
168  return !ud->has_unresolved;
169}
170
171bool
172rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
173{
174  rtems_rtl_obj_unresolved_data ud = {
175    .has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0
176  };
177  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
178    printf ("rtl: obj: unresolved: dep: %s is %s\n",
179            obj->oname, ud.has_unresolved ? "unresolved" : "resolved");
180  if (!ud.has_unresolved)
181  {
182    if ((obj->flags & RTEMS_RTL_OBJ_BASE) != 0)
183    {
184      rtems_rtl_data* rtl = rtems_rtl_data_unprotected ();
185      rtems_rtl_chain_iterate (&rtl->objects,
186                               rtems_rtl_obj_unresolved_object,
187                               &ud);
188    }
189    else
190    {
191      rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
192      obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
193      rtems_rtl_obj_iterate_dependents (obj,
194                                        rtems_rtl_obj_unresolved_dependent,
195                                        &ud);
196      rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
197    }
198  }
199  return ud.has_unresolved;
200}
201
202bool
203rtems_rtl_parse_name (const char*  name,
204                      const char** aname,
205                      const char** oname,
206                      off_t*       ooffset)
207{
208  const char* laname = NULL;
209  const char* loname = NULL;
210  const char* colon;
211  const char* end;
212
213  /*
214   * Parse the name to determine if the object file is part of an archive or it
215   * is an object file. If an archive check the name for a '@' to see if the
216   * archive contains an offset.
217   *
218   * Note, if an archive the object file oofset may be know but the
219   *       object file is not. Leave the object name as a NULL.
220   */
221  end = name + strlen (name);
222  colon = strrchr (name, ':');
223  if (colon == NULL || colon < strrchr(name, '/'))
224    colon = end;
225
226  loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, colon - name + 1, true);
227  if (!loname)
228  {
229    rtems_rtl_set_error (ENOMEM, "no memory for object file name");
230    return false;
231  }
232
233  memcpy ((void*) loname, name, colon - name);
234
235  /*
236   * If the pointers match there is no ':' delimiter.
237   */
238  if (colon != end)
239  {
240    const char* at;
241
242    /*
243     * The file name is an archive and the object file name is next after the
244     * delimiter. Move the pointer to the archive name.
245     */
246    laname = loname;
247    ++colon;
248
249    /*
250     * See if there is a '@' to delimit an archive offset for the object in the
251     * archive.
252     */
253    at = strchr (colon, '@');
254
255    if (at == NULL)
256      at = end;
257
258
259    loname = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, at - colon + 1, true);
260    if (!loname)
261    {
262      rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) laname);
263      rtems_rtl_set_error (ENOMEM, "no memory for object file name");
264      return false;
265    }
266
267    memcpy ((void*) loname, colon, at - colon);
268
269    if (at != end)
270    {
271      /*
272       * The object name has an archive offset. If the number
273       * does not parse 0 will be returned and the archive will be
274       * searched.
275       */
276      *ooffset = strtoul (at + 1, 0, 0);
277    }
278  }
279
280  *oname = loname;
281  *aname = laname;
282  return true;
283}
284
285static bool
286rtems_rtl_obj_parse_name (rtems_rtl_obj* obj, const char* name)
287{
288  return rtems_rtl_parse_name (name, &(obj->aname), &(obj->oname), &(obj->ooffset));
289}
290
291/**
292 * Section size summer iterator data.
293 */
294typedef struct
295{
296  uint32_t mask; /**< The selection mask to sum. */
297  size_t   size; /**< The size of all section fragments. */
298} rtems_rtl_obj_sect_summer_data;
299
300static bool
301rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data)
302{
303  rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
304  if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
305  {
306    rtems_rtl_obj_sect_summer_data* summer = data;
307    if ((sect->flags & summer->mask) == summer->mask)
308      summer->size =
309        rtems_rtl_obj_align (summer->size, sect->alignment) + sect->size;
310  }
311  return true;
312}
313
314static size_t
315rtems_rtl_obj_section_size (const rtems_rtl_obj* obj, uint32_t mask)
316{
317  rtems_rtl_obj_sect_summer_data summer;
318  summer.mask = mask;
319  summer.size = 0;
320  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
321                           rtems_rtl_obj_sect_summer,
322                           &summer);
323  return summer.size;
324}
325
326/**
327 * Section alignment iterator data. The first section's alignment sets the
328 * alignment for that type of section.
329 */
330typedef struct
331{
332  uint32_t mask;      /**< The selection mask to look for alignment. */
333  uint32_t alignment; /**< The alignment of the section type. */
334} rtems_rtl_obj_sect_aligner_data;
335
336/**
337 * The section aligner iterator.
338 */
339static bool
340rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data)
341{
342  rtems_rtl_obj_sect*              sect = (rtems_rtl_obj_sect*) node;
343  rtems_rtl_obj_sect_aligner_data* aligner = data;
344  if ((sect->flags & aligner->mask) == aligner->mask)
345  {
346    aligner->alignment = sect->alignment;
347    return false;
348  }
349  return true;
350}
351
352static size_t
353rtems_rtl_obj_section_alignment (const rtems_rtl_obj* obj, uint32_t mask)
354{
355  rtems_rtl_obj_sect_aligner_data aligner;
356  aligner.mask = mask;
357  aligner.alignment = 0;
358  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
359                           rtems_rtl_obj_sect_aligner,
360                           &aligner);
361  return aligner.alignment;
362}
363
364static bool
365rtems_rtl_obj_section_handler (uint32_t                   mask,
366                               rtems_rtl_obj*             obj,
367                               int                        fd,
368                               rtems_rtl_obj_sect_handler handler,
369                               void*                      data)
370{
371  rtems_chain_node* node = rtems_chain_first (&obj->sections);
372  while (!rtems_chain_is_tail (&obj->sections, node))
373  {
374    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
375    if ((sect->flags & mask) != 0)
376    {
377      if (!handler (obj, fd, sect, data))
378        return false;
379    }
380    node = rtems_chain_next (node);
381  }
382  return true;
383}
384
385bool
386rtems_rtl_obj_find_file (rtems_rtl_obj* obj, const char* name)
387{
388  const char*     pname;
389  rtems_rtl_data* rtl;
390
391  /*
392   * Parse the name. The object descriptor will have the archive name and/or
393   * object name fields filled in. A find of the file will result in the file
394   * name (fname) field pointing to the actual file if present on the file
395   * system.
396   */
397  if (!rtems_rtl_obj_parse_name (obj, name))
398    return false;
399
400  /*
401   * If the archive field (aname) is set we use that name else we use the
402   * object field (oname). If selected name is absolute we just point the aname
403   * field to the fname field to that name. If the field is relative we search
404   * the paths set in the RTL for the file.
405   */
406  if (rtems_rtl_obj_aname_valid (obj))
407    pname = rtems_rtl_obj_aname (obj);
408  else
409    pname = rtems_rtl_obj_oname (obj);
410
411  rtl = rtems_rtl_lock ();
412
413  if (!rtems_rtl_find_file (pname, rtl->paths, &obj->fname, &obj->fsize))
414  {
415    rtems_rtl_set_error (ENOENT, "file not found");
416    rtems_rtl_unlock ();
417    return false;
418  }
419
420  rtems_rtl_unlock ();
421
422  return true;
423}
424
425bool
426rtems_rtl_obj_add_section (rtems_rtl_obj* obj,
427                           int            section,
428                           const char*    name,
429                           size_t         size,
430                           off_t          offset,
431                           uint32_t       alignment,
432                           int            link,
433                           int            info,
434                           uint32_t       flags)
435{
436  if (size > 0)
437  {
438    rtems_rtl_obj_sect* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
439                                                    sizeof (rtems_rtl_obj_sect),
440                                                    true);
441    if (!sect)
442    {
443      rtems_rtl_set_error (ENOMEM, "adding allocated section");
444      return false;
445    }
446    sect->section = section;
447    sect->name = rtems_rtl_strdup (name);
448    sect->size = size;
449    sect->offset = offset;
450    sect->alignment = alignment;
451    sect->link = link;
452    sect->info = info;
453    sect->flags = flags;
454    sect->base = NULL;
455    rtems_chain_append (&obj->sections, &sect->node);
456
457    if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION))
458      printf ("rtl: sect: add: %-2d: %s (%zu) 0x%08" PRIu32 "\n",
459              section, name, size, flags);
460  }
461  return true;
462}
463
464void
465rtems_rtl_obj_erase_sections (rtems_rtl_obj* obj)
466{
467  rtems_chain_node* node = rtems_chain_first (&obj->sections);
468  while (!rtems_chain_is_tail (&obj->sections, node))
469  {
470    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
471    rtems_chain_node*   next_node = rtems_chain_next (node);
472    rtems_chain_extract (node);
473    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) sect->name);
474    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, sect);
475    node = next_node;
476  }
477}
478
479/**
480 * Section finder iterator data.
481 */
482typedef struct
483{
484  rtems_rtl_obj_sect*  sect;  /**< The matching section. */
485  const char*          name;  /**< The name to match. */
486  int                  index; /**< The index to match. */
487  uint32_t             mask;  /**< The mask to match. */
488  unsigned int         flags; /**< The flags to use when matching. */
489} rtems_rtl_obj_sect_finder;
490
491static bool
492rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data)
493{
494  rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
495  rtems_rtl_obj_sect_finder* match = data;
496  if (strcmp (sect->name, match->name) == 0)
497  {
498    match->sect = sect;
499    return false;
500  }
501  return true;
502}
503
504rtems_rtl_obj_sect*
505rtems_rtl_obj_find_section (const rtems_rtl_obj* obj,
506                            const char*          name)
507{
508  rtems_rtl_obj_sect_finder match;
509  match.sect = NULL;
510  match.name = name;
511  match.mask = 0;
512  match.flags = 0;
513  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
514                           rtems_rtl_obj_sect_match_name,
515                           &match);
516  return match.sect;
517}
518
519static bool
520rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data)
521{
522  rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
523  rtems_rtl_obj_sect_finder* match = data;
524  if (sect->section == match->index)
525  {
526    match->sect = sect;
527    return false;
528  }
529  return true;
530}
531
532rtems_rtl_obj_sect*
533rtems_rtl_obj_find_section_by_index (const rtems_rtl_obj* obj,
534                                     int                  index)
535{
536  rtems_rtl_obj_sect_finder match;
537  match.sect = NULL;
538  match.index = index;
539  match.mask = 0;
540  match.flags = 0;
541  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
542                           rtems_rtl_obj_sect_match_index,
543                           &match);
544  return match.sect;
545}
546
547static bool
548rtems_rtl_obj_sect_match_mask (rtems_chain_node* node, void* data)
549{
550  rtems_rtl_obj_sect*        sect = (rtems_rtl_obj_sect*) node;
551  rtems_rtl_obj_sect_finder* match = data;
552  if (match->flags == 0)
553  {
554    if (match->index < 0 || sect->section == match->index)
555      match->flags = 1;
556    if (match->index >= 0)
557      return true;
558  }
559  if ((sect->flags & match->mask) != 0)
560  {
561    match->sect = sect;
562    return false;
563  }
564  return true;
565}
566
567rtems_rtl_obj_sect*
568rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
569                                    int                  index,
570                                    uint32_t             mask)
571{
572  rtems_rtl_obj_sect_finder match;
573  match.sect = NULL;
574  match.index = index;
575  match.mask = mask;
576  match.flags = 0;
577  rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections,
578                           rtems_rtl_obj_sect_match_mask,
579                           &match);
580  return match.sect;
581}
582
583bool
584rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
585{
586  if (obj->tramps_size == 0)
587    return true;
588  obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
589                                         obj->tramps_size,
590                                         true);
591  if (obj->trampoline == NULL)
592    rtems_rtl_set_error (ENOMEM, "no memory for the trampoline");
593  obj->tramp_brk = obj->trampoline;
594  return obj->trampoline != NULL;
595}
596
597void
598rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj)
599{
600  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline);
601}
602
603bool
604rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
605{
606  rtems_rtl_obj_depends* depends;
607  size_t                 size;
608
609  size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents;
610
611  depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
612                                 size,
613                                 true);
614  if (depends == NULL)
615  {
616    rtems_rtl_set_error (ENOMEM, "no memory for the dependency");
617  }
618  else
619  {
620    depends->dependents = dependents;
621    rtems_chain_append (&obj->dependents, &depends->node);
622  }
623
624  return depends != NULL;
625}
626
627void
628rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj)
629{
630  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
631  while (!rtems_chain_is_tail (&obj->dependents, node))
632  {
633    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
634    rtems_chain_node*      next_node = rtems_chain_next (node);
635    rtems_chain_extract (node);
636    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends);
637    node = next_node;
638  }
639}
640
641bool
642rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent)
643{
644  rtems_rtl_obj**   free_slot;
645  rtems_chain_node* node;
646
647  if (obj == dependent || dependent == rtems_rtl_baseimage ())
648    return false;
649
650  if (rtems_rtl_trace (RTEMS_RTL_TRACE_DEPENDENCY))
651    printf ("rtl: depend: add: %s -> %s\n", obj->oname, dependent->oname);
652
653  free_slot = NULL;
654
655  node = rtems_chain_first (&obj->dependents);
656  while (!rtems_chain_is_tail (&obj->dependents, node))
657  {
658    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
659    size_t                 d;
660    for (d = 0; d < depends->dependents; ++d)
661    {
662      if (free_slot == NULL && depends->depends[d] == NULL)
663        free_slot = &(depends->depends[d]);
664      if (depends->depends[d] == dependent)
665        return false;
666    }
667    node = rtems_chain_next (node);
668  }
669
670  if (free_slot == NULL)
671  {
672    if (rtems_rtl_obj_alloc_dependents (obj,
673                                        RTEMS_RTL_DEPENDENCY_BLOCK_SIZE))
674    {
675      rtems_rtl_obj_depends* depends;
676      node = rtems_chain_last (&obj->dependents);
677      depends = (rtems_rtl_obj_depends*) node;
678      free_slot = &(depends->depends[0]);
679      if (*free_slot != NULL)
680      {
681        rtems_rtl_set_error (EINVAL, "new dependency node not empty");
682        free_slot = NULL;
683      }
684    }
685  }
686
687  if (free_slot != NULL)
688    *free_slot = dependent;
689
690  return free_slot != NULL;
691}
692
693
694bool
695rtems_rtl_obj_remove_dependencies (rtems_rtl_obj* obj)
696{
697  /*
698   * If there are no references unload the object.
699   */
700  if (obj->refs == 0)
701  {
702    /*
703     * Remove the refences from the object files this file depend on. The
704     * unload happens once the list of objects to be unloaded has been made and
705     * the destructors have been called for all those modules.
706     */
707    rtems_chain_node* node = rtems_chain_first (&obj->dependents);
708    while (!rtems_chain_is_tail (&obj->dependents, node))
709    {
710      rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
711      size_t                 d;
712      for (d = 0; d < depends->dependents; ++d)
713      {
714        if (depends->depends[d] != NULL)
715        {
716          rtems_rtl_obj_dec_reference (depends->depends[d]);
717          depends->depends[d] = NULL;
718        }
719      }
720      node = rtems_chain_next (node);
721    }
722    return true;
723  }
724  return false;
725}
726
727bool
728rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
729                                  rtems_rtl_obj_depends_iterator iterator,
730                                  void*                          data)
731{
732  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
733  while (!rtems_chain_is_tail (&obj->dependents, node))
734  {
735    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
736    size_t                 d;
737    for (d = 0; d < depends->dependents; ++d)
738    {
739      if (depends->depends[d])
740      {
741        if (iterator (obj, depends->depends[d], data))
742          return true;
743      }
744    }
745    node = rtems_chain_next (node);
746  }
747  return false;
748}
749
750size_t
751rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
752{
753  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
754  return rtems_rtl_obj_section_size (obj, flags);
755}
756
757uint32_t
758rtems_rtl_obj_text_alignment (const rtems_rtl_obj* obj)
759{
760  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
761  return rtems_rtl_obj_section_alignment (obj, flags);
762}
763
764size_t
765rtems_rtl_obj_const_size (const rtems_rtl_obj* obj)
766{
767  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
768  return rtems_rtl_obj_section_size (obj, flags);
769}
770
771uint32_t
772rtems_rtl_obj_const_alignment (const rtems_rtl_obj* obj)
773{
774  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
775  return rtems_rtl_obj_section_alignment (obj, flags);
776}
777
778uint32_t
779rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
780{
781  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
782  return rtems_rtl_obj_section_alignment (obj, flags);
783}
784
785size_t
786rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
787{
788  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
789  return rtems_rtl_obj_section_size (obj, flags);
790}
791
792size_t
793rtems_rtl_obj_data_size (const rtems_rtl_obj* obj)
794{
795  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
796  return rtems_rtl_obj_section_size (obj, flags);
797}
798
799uint32_t
800rtems_rtl_obj_data_alignment (const rtems_rtl_obj* obj)
801{
802  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
803  return rtems_rtl_obj_section_alignment (obj, flags);
804}
805
806size_t
807rtems_rtl_obj_bss_size (const rtems_rtl_obj* obj)
808{
809  return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS);
810}
811
812uint32_t
813rtems_rtl_obj_bss_alignment (const rtems_rtl_obj* obj)
814{
815  return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS);
816}
817
818bool
819rtems_rtl_obj_relocate (rtems_rtl_obj*             obj,
820                        int                        fd,
821                        rtems_rtl_obj_sect_handler handler,
822                        void*                      data)
823{
824  const uint32_t flags = (RTEMS_RTL_OBJ_SECT_LOAD |
825                          RTEMS_RTL_OBJ_SECT_REL |
826                          RTEMS_RTL_OBJ_SECT_RELA);
827  bool r = rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
828  rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
829  return r;
830}
831
832/**
833 * Cache synchronization after runtime object load (dlopen)
834 */
835typedef struct
836{
837  uint32_t mask;
838  void     *start_va;
839  void     *end_va;
840  size_t   cache_line_size;
841} rtems_rtl_obj_sect_sync_ctx;
842
843static bool
844rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data)
845{
846  rtems_rtl_obj_sect*          sect = (rtems_rtl_obj_sect*) node;
847  rtems_rtl_obj_sect_sync_ctx* sync_ctx = data;
848  uintptr_t                    old_end;
849  uintptr_t                    new_start;
850
851  if ((sect->flags & sync_ctx->mask) == 0 || sect->size == 0)
852    return true;
853
854  if (sync_ctx->end_va == sync_ctx->start_va)
855  {
856    sync_ctx->start_va = sect->base;
857  }
858  else
859  {
860    old_end = (uintptr_t) sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1);
861    new_start = (uintptr_t) sect->base & ~(sync_ctx->cache_line_size - 1);
862    if ((sect->base <  sync_ctx->start_va) ||
863        (new_start - old_end > sync_ctx->cache_line_size))
864    {
865      rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va,
866                             sync_ctx->end_va - sync_ctx->start_va + 1);
867      sync_ctx->start_va = sect->base;
868    }
869  }
870
871  sync_ctx->end_va = sect->base + sect->size;
872
873  return true;
874}
875
876void
877rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
878{
879  rtems_rtl_obj_sect_sync_ctx sync_ctx;
880
881  if (rtems_cache_get_instruction_line_size() == 0)
882    return;
883
884  sync_ctx.cache_line_size = rtems_cache_get_maximal_line_size();
885
886  sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST |
887                  RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS |
888                  RTEMS_RTL_OBJ_SECT_EH   | RTEMS_RTL_OBJ_SECT_EXEC;
889
890  sync_ctx.start_va = 0;
891  sync_ctx.end_va = sync_ctx.start_va;
892  rtems_rtl_chain_iterate (&obj->sections,
893                           rtems_rtl_obj_sect_sync_handler,
894                           &sync_ctx);
895
896  if (sync_ctx.end_va != sync_ctx.start_va)
897  {
898    size_t size = sync_ctx.end_va - sync_ctx.start_va;
899    rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
900                                                   size);
901  }
902
903  if (obj->trampoline != NULL)
904  {
905    rtems_cache_instruction_sync_after_code_change(obj->trampoline,
906                                                   obj->tramps_size);
907  }
908}
909
910bool
911rtems_rtl_obj_load_symbols (rtems_rtl_obj*             obj,
912                            int                        fd,
913                            rtems_rtl_obj_sect_handler handler,
914                            void*                      data)
915{
916  uint32_t mask = RTEMS_RTL_OBJ_SECT_SYM;
917  return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
918}
919
920static int
921rtems_rtl_obj_sections_linked_to_order (rtems_rtl_obj* obj,
922                                        int            section,
923                                        uint32_t       visited_mask)
924{
925  rtems_chain_control* sections = &obj->sections;
926  rtems_chain_node*    node = rtems_chain_first (sections);
927  /*
928   * Find the section being linked-to. If the linked-to link field is 0 we have
929   * the end and the section's order is the position we are after.
930   */
931  while (!rtems_chain_is_tail (sections, node))
932  {
933    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
934    if (sect->section == section)
935    {
936      const uint32_t mask = sect->flags & RTEMS_RTL_OBJ_SECT_TYPES;
937      int            order = 0;
938      if (sect->link != 0)
939      {
940        /*
941         * Have we already visited this type of section? Avoid nesting for
942         * ever.
943         */
944        if ((sect->flags & visited_mask) != 0)
945        {
946          rtems_rtl_set_error (errno, "section link loop");
947          return -1;
948        }
949        return rtems_rtl_obj_sections_linked_to_order (obj,
950                                                       sect->link,
951                                                       visited_mask | mask);
952      }
953      node = rtems_chain_first (sections);
954      while (!rtems_chain_is_tail (sections, node))
955      {
956        sect = (rtems_rtl_obj_sect*) node;
957        if ((sect->flags & mask) == mask)
958        {
959          if (sect->section == section)
960            return order;
961          ++order;
962        }
963        node = rtems_chain_next (node);
964      }
965    }
966    node = rtems_chain_next (node);
967  }
968  rtems_rtl_set_error (errno, "section link not found");
969  return -1;
970}
971
972static void
973rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj)
974{
975  rtems_chain_control* sections = &obj->sections;
976  rtems_chain_node*    node = rtems_chain_first (sections);
977  int                  order = 0;
978  while (!rtems_chain_is_tail (sections, node))
979  {
980    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
981    if ((sect->flags & mask) == mask)
982    {
983      /*
984       * If the section is linked in order find the linked-to section's order
985       * and move the section in the section list to
986       */
987      if (sect->link == 0)
988        sect->load_order = order++;
989      else
990      {
991        sect->load_order =
992          rtems_rtl_obj_sections_linked_to_order (obj,
993                                                  sect->link,
994                                                  mask);
995      }
996    }
997    node = rtems_chain_next (node);
998  }
999}
1000
1001static void
1002rtems_rtl_obj_sections_locate (uint32_t            mask,
1003                               rtems_rtl_alloc_tag tag,
1004                               rtems_rtl_obj*      obj,
1005                               uint8_t*            base)
1006{
1007  rtems_chain_control* sections = &obj->sections;
1008  rtems_chain_node*    node = rtems_chain_first (sections);
1009  size_t               base_offset = 0;
1010  int                  order = 0;
1011
1012  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1013    printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
1014
1015  while (!rtems_chain_is_tail (sections, node))
1016  {
1017    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1018
1019    if ((sect->size != 0) && ((sect->flags & mask) == mask))
1020    {
1021      if (sect->load_order == order)
1022      {
1023        if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
1024        {
1025          base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
1026          sect->base = base + base_offset;
1027        }
1028
1029        if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1030          printf ("rtl: locating:%2d: %s -> %p (s:%zi f:%04" PRIx32
1031                  " a:%" PRIu32 " l:%02d)\n",
1032                  order, sect->name, sect->base, sect->size,
1033                  sect->flags, sect->alignment, sect->link);
1034
1035        if (sect->base)
1036          base_offset += sect->size;
1037
1038        ++order;
1039
1040        node = rtems_chain_first (sections);
1041        continue;
1042      }
1043    }
1044
1045    node = rtems_chain_next (node);
1046  }
1047}
1048
1049bool
1050rtems_rtl_obj_alloc_sections (rtems_rtl_obj*             obj,
1051                              int                        fd,
1052                              rtems_rtl_obj_sect_handler handler,
1053                              void*                      data)
1054{
1055  size_t text_size;
1056  size_t const_size;
1057  size_t eh_size;
1058  size_t data_size;
1059  size_t bss_size;
1060
1061  text_size  = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj);
1062  const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj);
1063  eh_size    = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj);
1064  data_size  = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj);
1065  bss_size   = rtems_rtl_obj_bss_size (obj);
1066
1067  /*
1068   * Set the sizes held in the object data. We need this for a fast reference.
1069   */
1070  obj->text_size  = text_size;
1071  obj->const_size = const_size;
1072  obj->data_size  = data_size;
1073  obj->eh_size    = eh_size;
1074  obj->bss_size   = bss_size;
1075
1076  /*
1077   * Perform any specific allocations for sections.
1078   */
1079  if (handler != NULL)
1080  {
1081    if (!rtems_rtl_obj_section_handler (RTEMS_RTL_OBJ_SECT_TYPES,
1082                                        obj,
1083                                        fd,
1084                                        handler,
1085                                        data))
1086    {
1087      obj->exec_size = 0;
1088      return false;
1089    }
1090  }
1091
1092  /*
1093   * Let the allocator manage the actual allocation. The user can use the
1094   * standard heap or provide a specific allocator with memory protection.
1095   */
1096  if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size,
1097                                   &obj->const_base, const_size,
1098                                   &obj->eh_base, eh_size,
1099                                   &obj->data_base, data_size,
1100                                   &obj->bss_base, bss_size))
1101  {
1102    obj->exec_size = 0;
1103    rtems_rtl_set_error (ENOMEM, "no memory to load obj");
1104    return false;
1105  }
1106
1107  obj->exec_size = text_size + const_size + eh_size + data_size + bss_size;
1108
1109  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1110  {
1111    printf ("rtl: load sect: text  - b:%p s:%zi a:%" PRIu32 "\n",
1112            obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj));
1113    printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n",
1114            obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj));
1115    printf ("rtl: load sect: eh    - b:%p s:%zi a:%" PRIu32 "\n",
1116            obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj));
1117    printf ("rtl: load sect: data  - b:%p s:%zi a:%" PRIu32 "\n",
1118            obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj));
1119    printf ("rtl: load sect: bss   - b:%p s:%zi a:%" PRIu32 "\n",
1120            obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj));
1121  }
1122
1123  /*
1124   * Determine the load order.
1125   */
1126  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_TEXT,  obj);
1127  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj);
1128  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH,    obj);
1129  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA,  obj);
1130  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS,   obj);
1131
1132  /*
1133   * Locate all text, data and bss sections in seperate operations so each type of
1134   * section is grouped together.
1135   */
1136  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT,
1137                                 rtems_rtl_alloc_text_tag (),
1138                                 obj, obj->text_base);
1139  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST,
1140                                 rtems_rtl_alloc_const_tag (),
1141                                 obj, obj->const_base);
1142  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH,
1143                                 rtems_rtl_alloc_eh_tag (),
1144                                 obj, obj->eh_base);
1145  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA,
1146                                 rtems_rtl_alloc_data_tag (),
1147                                 obj, obj->data_base);
1148  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS,
1149                                 rtems_rtl_alloc_bss_tag (),
1150                                 obj, obj->bss_base);
1151
1152  return true;
1153}
1154
1155static bool
1156rtems_rtl_obj_sections_loader (uint32_t                   mask,
1157                               rtems_rtl_alloc_tag        tag,
1158                               rtems_rtl_obj*             obj,
1159                               int                        fd,
1160                               uint8_t*                   base,
1161                               rtems_rtl_obj_sect_handler handler,
1162                               void*                      data)
1163{
1164  rtems_chain_control* sections = &obj->sections;
1165  rtems_chain_node*    node = rtems_chain_first (sections);
1166  int                  order = 0;
1167
1168  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1169    printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
1170
1171  rtems_rtl_alloc_wr_enable (tag, base);
1172
1173  while (!rtems_chain_is_tail (sections, node))
1174  {
1175    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1176
1177    if ((sect->size != 0) && ((sect->flags & mask) == mask))
1178    {
1179      if (sect->load_order == order)
1180      {
1181        if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
1182          printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
1183                  " a:%" PRIu32 " l:%02d)\n",
1184                  order, sect->name, sect->base, sect->size,
1185                  sect->flags, sect->alignment, sect->link);
1186
1187        if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
1188        {
1189          if (!handler (obj, fd, sect, data))
1190          {
1191            sect->base = 0;
1192            rtems_rtl_alloc_wr_disable (tag, base);
1193            return false;
1194          }
1195        }
1196        else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
1197        {
1198          memset (sect->base, 0, sect->size);
1199        }
1200        else
1201        {
1202          /*
1203           * This section is not to be loaded, clear the base.
1204           */
1205          sect->base = 0;
1206        }
1207
1208        ++order;
1209
1210        node = rtems_chain_first (sections);
1211        continue;
1212      }
1213    }
1214
1215    node = rtems_chain_next (node);
1216  }
1217
1218  rtems_rtl_alloc_wr_disable (tag, base);
1219
1220  return true;
1221}
1222
1223bool
1224rtems_rtl_obj_load_sections (rtems_rtl_obj*             obj,
1225                             int                        fd,
1226                             rtems_rtl_obj_sect_handler handler,
1227                             void*                      data)
1228{
1229  /*
1230   * Load all text, data and bsssections in seperate operations so each type of
1231   * section is grouped together. Finish by loading any architecure specific
1232   * sections.
1233   */
1234  if (!rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_TEXT,
1235                                      rtems_rtl_alloc_text_tag (),
1236                                      obj, fd, obj->text_base, handler, data) ||
1237      !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST,
1238                                      rtems_rtl_alloc_const_tag (),
1239                                      obj, fd, obj->const_base, handler, data) ||
1240      !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_EH,
1241                                      rtems_rtl_alloc_eh_tag (),
1242                                      obj, fd, obj->eh_base, handler, data) ||
1243      !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA,
1244                                      rtems_rtl_alloc_data_tag (),
1245                                      obj, fd, obj->data_base, handler, data) ||
1246      !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS,
1247                                      rtems_rtl_alloc_bss_tag (),
1248                                      obj, fd, obj->bss_base, handler, data))
1249  {
1250    rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
1251                                &obj->data_base, &obj->bss_base);
1252    obj->exec_size = 0;
1253    return false;
1254  }
1255
1256  return true;
1257}
1258
1259static void
1260rtems_rtl_obj_run_cdtors (rtems_rtl_obj* obj, uint32_t mask)
1261{
1262  rtems_chain_node* node = rtems_chain_first (&obj->sections);
1263  while (!rtems_chain_is_tail (&obj->sections, node))
1264  {
1265    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1266    if ((sect->flags & mask) == mask)
1267    {
1268      rtems_rtl_cdtor* handler;
1269      size_t           handlers = sect->size / sizeof (rtems_rtl_cdtor);
1270      int              c;
1271      for (c = 0, handler = sect->base; c < handlers; ++c)
1272        if (*handler)
1273          (*handler) ();
1274    }
1275    node = rtems_chain_next (node);
1276  }
1277}
1278
1279static bool
1280rtems_rtl_obj_cdtors_to_run (rtems_rtl_obj* obj, uint32_t mask)
1281{
1282  rtems_chain_node* node = rtems_chain_first (&obj->sections);
1283  while (!rtems_chain_is_tail (&obj->sections, node))
1284  {
1285    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
1286    if ((sect->flags & mask) == mask)
1287      return true;
1288    node = rtems_chain_next (node);
1289  }
1290  return false;
1291}
1292
1293bool
1294rtems_rtl_obj_ctors_to_run (rtems_rtl_obj* obj)
1295{
1296  return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_CTOR);
1297}
1298
1299void
1300rtems_rtl_obj_run_ctors (rtems_rtl_obj* obj)
1301{
1302  rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR);
1303}
1304
1305bool
1306rtems_rtl_obj_dtors_to_run (rtems_rtl_obj* obj)
1307{
1308  return rtems_rtl_obj_cdtors_to_run (obj, RTEMS_RTL_OBJ_SECT_DTOR);
1309}
1310
1311void
1312rtems_rtl_obj_run_dtors (rtems_rtl_obj* obj)
1313{
1314  rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR);
1315}
1316
1317static bool
1318rtems_rtl_obj_file_load (rtems_rtl_obj* obj, int fd)
1319{
1320  int l;
1321
1322  for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table)); ++l)
1323  {
1324    if (loaders[l].check (obj, fd))
1325    {
1326      obj->format = l;
1327      return loaders[l].load (obj, fd);
1328    }
1329  }
1330
1331  rtems_rtl_set_error (ENOENT, "no format loader found");
1332  return false;
1333}
1334
1335static void
1336rtems_rtl_obj_set_error (int num, const char* text)
1337{
1338  rtems_rtl_set_error (num, text);
1339}
1340
1341size_t
1342rtems_rtl_obj_get_reference (rtems_rtl_obj* obj)
1343{
1344  return obj->refs;
1345}
1346
1347void
1348rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj)
1349{
1350  ++obj->refs;
1351}
1352
1353void
1354rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj)
1355{
1356  if (obj->refs)
1357    --obj->refs;
1358}
1359
1360bool
1361rtems_rtl_obj_orphaned (rtems_rtl_obj* obj)
1362{
1363  return ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == 0 &&
1364          obj->users == 0 &&
1365          rtems_rtl_obj_get_reference (obj) == 0);
1366}
1367
1368bool
1369rtems_rtl_obj_load (rtems_rtl_obj* obj)
1370{
1371  int fd;
1372
1373  if (!rtems_rtl_obj_fname_valid (obj))
1374  {
1375    rtems_rtl_set_error (ENOMEM, "invalid object file name path");
1376    return false;
1377  }
1378
1379  fd = open (rtems_rtl_obj_fname (obj), O_RDONLY);
1380  if (fd < 0)
1381  {
1382    rtems_rtl_set_error (errno, "opening for object file");
1383    return false;
1384  }
1385
1386  /*
1387   * Find the object file in the archive if it is an archive that
1388   * has been opened.
1389   */
1390  if (rtems_rtl_obj_aname_valid (obj))
1391  {
1392    off_t enames = 0;
1393    if (!rtems_rtl_obj_archive_find_obj (fd,
1394                                         obj->fsize,
1395                                         &obj->oname,
1396                                         &obj->ooffset,
1397                                         &obj->fsize,
1398                                         &enames,
1399                                         rtems_rtl_obj_set_error))
1400    {
1401      close (fd);
1402      return false;
1403    }
1404  }
1405
1406  /*
1407   * Call the format specific loader.
1408   */
1409  if (!rtems_rtl_obj_file_load (obj, fd))
1410  {
1411    close (fd);
1412    return false;
1413  }
1414
1415   /*
1416    * For GDB
1417    */
1418  if (!_rtld_linkmap_add (obj))
1419  {
1420    close (fd);
1421    return false;
1422  }
1423
1424  close (fd);
1425
1426  return true;
1427}
1428
1429bool
1430rtems_rtl_obj_unload (rtems_rtl_obj* obj)
1431{
1432  bool ok = false;
1433  if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
1434  {
1435    _rtld_linkmap_delete(obj);
1436    ok = loaders[obj->format].unload (obj);
1437  }
1438  else
1439  {
1440    rtems_rtl_set_error (EINVAL, "invalid object loader format");
1441  }
1442  return ok;
1443}
Note: See TracBrowser for help on using the repository browser.