source: rtems/cpukit/libdl/rtl.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: 19.4 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 <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 <rtems/rtl/rtl-allocator.h>
30#include <rtems/rtl/rtl-trace.h>
31#include "rtl-chain-iterator.h"
32#include "rtl-error.h"
33#include "rtl-string.h"
34
35/**
36 * Symbol table cache size. They can be big so the cache needs space to work.
37 */
38#define RTEMS_RTL_ELF_SYMBOL_CACHE (2048)
39
40/**
41 * String table cache size.
42 */
43#define RTEMS_RTL_ELF_STRING_CACHE (2048)
44
45/**
46 * Relocations table cache size.
47 */
48#define RTEMS_RTL_ELF_RELOC_CACHE (2048)
49
50/**
51 * Decompression output buffer.
52 */
53#define RTEMS_RTL_COMP_OUTPUT (2048)
54
55/**
56 * Static RTL data is returned to the user when the linker is locked.
57 */
58static rtems_rtl_data* rtl;
59static bool            rtl_data_init;
60
61/**
62 * Define a default base global symbol loader function that is weak
63 * so a real table can be linked in when the user wants one.
64 */
65void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
66void
67rtems_rtl_base_global_syms_init (void)
68{
69  /*
70   * Do nothing.
71   */
72}
73
74static bool
75rtems_rtl_data_init (void)
76{
77  /*
78   * Lock the RTL. We only create a lock if a call is made. First we test if a
79   * lock is present. If one is present we lock it. If not the libio lock is
80   * locked and we then test the lock again. If not present we create the lock
81   * then release libio lock.
82   */
83  if (!rtl)
84  {
85    rtems_libio_lock ();
86
87    if (!rtl)
88    {
89      /*
90       * We cannot set an error in this code because there is no RTL data to
91       * hold it.
92       */
93
94      if (rtl_data_init)
95      {
96        rtems_libio_unlock ();
97        return false;
98      }
99
100      rtl_data_init = true;
101
102      /*
103       * Always in the heap.
104       */
105      rtl = malloc (sizeof (rtems_rtl_data));
106      if (!rtl)
107      {
108        rtems_libio_unlock ();
109        errno = ENOMEM;
110        return false;
111      }
112
113      *rtl = (rtems_rtl_data) { 0 };
114
115      /*
116       * The initialise the allocator data.
117       */
118      rtems_rtl_alloc_initialise (&rtl->allocator);
119
120      /*
121       * Create the RTL lock.
122       */
123      rtems_recursive_mutex_init (&rtl->lock, "Run-Time Linker");
124      rtems_recursive_mutex_lock (&rtl->lock);
125
126      /*
127       * Initialise the objects and pending list.
128       */
129      rtems_chain_initialize_empty (&rtl->objects);
130      rtems_chain_initialize_empty (&rtl->pending);
131
132      /*
133       * Open the global symbol table.
134       */
135      if (!rtems_rtl_symbol_table_open (&rtl->globals,
136                                        RTEMS_RTL_SYMS_GLOBAL_BUCKETS))
137      {
138        rtems_recursive_mutex_destroy (&rtl->lock);
139        free (rtl);
140        rtems_libio_unlock ();
141        return false;
142      }
143
144      /*
145       * Open the archives.
146       */
147      rtems_rtl_archives_open (&rtl->archives, "/etc/libdl.conf");
148
149      /*
150       * Open the unresolved table.
151       */
152      if (!rtems_rtl_unresolved_table_open (&rtl->unresolved,
153                                            RTEMS_RTL_UNRESOLVED_BLOCK_SIZE))
154      {
155        rtems_rtl_symbol_table_close (&rtl->globals);
156        rtems_recursive_mutex_destroy (&rtl->lock);
157        free (rtl);
158        rtems_libio_unlock ();
159        return false;
160      }
161
162      if (!rtems_rtl_obj_cache_open (&rtl->symbols,
163                                     RTEMS_RTL_ELF_SYMBOL_CACHE))
164      {
165        rtems_rtl_symbol_table_close (&rtl->globals);
166        rtems_rtl_unresolved_table_close (&rtl->unresolved);
167        rtems_recursive_mutex_destroy (&rtl->lock);
168        free (rtl);
169        rtems_libio_unlock ();
170        return false;
171      }
172
173      if (!rtems_rtl_obj_cache_open (&rtl->strings,
174                                     RTEMS_RTL_ELF_STRING_CACHE))
175      {
176        rtems_rtl_obj_cache_close (&rtl->symbols);
177        rtems_rtl_unresolved_table_close (&rtl->unresolved);
178        rtems_rtl_symbol_table_close (&rtl->globals);
179        rtems_recursive_mutex_destroy (&rtl->lock);
180        free (rtl);
181        rtems_libio_unlock ();
182        return false;
183      }
184
185      if (!rtems_rtl_obj_cache_open (&rtl->relocs,
186                                     RTEMS_RTL_ELF_RELOC_CACHE))
187      {
188        rtems_rtl_obj_cache_close (&rtl->strings);
189        rtems_rtl_obj_cache_close (&rtl->symbols);
190        rtems_rtl_unresolved_table_close (&rtl->unresolved);
191        rtems_rtl_symbol_table_close (&rtl->globals);
192        rtems_recursive_mutex_destroy (&rtl->lock);
193        free (rtl);
194        rtems_libio_unlock ();
195        return false;
196      }
197
198      if (!rtems_rtl_obj_comp_open (&rtl->decomp,
199                                    RTEMS_RTL_COMP_OUTPUT))
200      {
201        rtems_rtl_obj_cache_close (&rtl->relocs);
202        rtems_rtl_obj_cache_close (&rtl->strings);
203        rtems_rtl_obj_cache_close (&rtl->symbols);
204        rtems_rtl_unresolved_table_close (&rtl->unresolved);
205        rtems_rtl_symbol_table_close (&rtl->globals);
206        rtems_recursive_mutex_destroy (&rtl->lock);
207        free (rtl);
208        rtems_libio_unlock ();
209        return false;
210      }
211
212      rtl->base = rtems_rtl_obj_alloc ();
213      if (!rtl->base)
214      {
215        rtems_rtl_obj_comp_close (&rtl->decomp);
216        rtems_rtl_obj_cache_close (&rtl->relocs);
217        rtems_rtl_obj_cache_close (&rtl->strings);
218        rtems_rtl_obj_cache_close (&rtl->symbols);
219        rtems_rtl_unresolved_table_close (&rtl->unresolved);
220        rtems_rtl_symbol_table_close (&rtl->globals);
221        rtems_recursive_mutex_destroy (&rtl->lock);
222        free (rtl);
223        rtems_libio_unlock ();
224        return false;
225      }
226
227      /*
228       * Need to malloc the memory so the free does not complain.
229       */
230      rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
231
232      /*
233       * Lock the base image and flag it as the base image.
234       */
235      rtl->base->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_BASE;
236
237      rtems_chain_append (&rtl->objects, &rtl->base->link);
238    }
239
240    rtems_libio_unlock ();
241
242    rtems_rtl_path_append (".");
243
244    rtems_rtl_base_global_syms_init ();
245
246    rtems_rtl_unlock ();
247  }
248  return true;
249}
250
251rtems_rtl_data*
252rtems_rtl_data_unprotected (void)
253{
254  return rtl;
255}
256
257rtems_rtl_symbols*
258rtems_rtl_global_symbols (void)
259{
260  if (!rtl)
261  {
262    rtems_rtl_set_error (ENOENT, "no rtl");
263    return NULL;
264  }
265  return &rtl->globals;
266}
267
268const char*
269rtems_rtl_last_error_unprotected (void)
270{
271  if (!rtl)
272    return NULL;
273  return rtl->last_error;
274}
275
276rtems_chain_control*
277rtems_rtl_objects_unprotected (void)
278{
279  if (!rtl)
280  {
281    rtems_rtl_set_error (ENOENT, "no rtl");
282    return NULL;
283  }
284  return &rtl->objects;
285}
286
287rtems_chain_control*
288rtems_rtl_pending_unprotected (void)
289{
290  if (!rtl)
291  {
292    rtems_rtl_set_error (ENOENT, "no rtl");
293    return NULL;
294  }
295  return &rtl->pending;
296}
297
298rtems_rtl_unresolved*
299rtems_rtl_unresolved_unprotected (void)
300{
301  if (!rtl)
302  {
303    rtems_rtl_set_error (ENOENT, "no rtl");
304    return NULL;
305  }
306  return &rtl->unresolved;
307}
308
309rtems_rtl_archives*
310rtems_rtl_archives_unprotected (void)
311{
312  if (!rtl)
313  {
314    rtems_rtl_set_error (ENOENT, "no rtl");
315    return NULL;
316  }
317  return &rtl->archives;
318}
319
320void
321rtems_rtl_obj_caches (rtems_rtl_obj_cache** symbols,
322                      rtems_rtl_obj_cache** strings,
323                      rtems_rtl_obj_cache** relocs)
324{
325  if (!rtl)
326  {
327    if (symbols)
328       *symbols = NULL;
329    if (strings)
330      *strings = NULL;
331    if (relocs)
332      *relocs = NULL;
333  }
334  else
335  {
336    if (symbols)
337      *symbols = &rtl->symbols;
338    if (strings)
339      *strings = &rtl->strings;
340    if (relocs)
341      *relocs = &rtl->relocs;
342  }
343}
344
345void
346rtems_rtl_obj_caches_flush (void)
347{
348  if (rtl)
349  {
350    rtems_rtl_obj_cache_flush (&rtl->symbols);
351    rtems_rtl_obj_cache_flush (&rtl->strings);
352    rtems_rtl_obj_cache_flush (&rtl->relocs);
353  }
354}
355
356void
357rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp,
358                          rtems_rtl_obj_cache* cache,
359                          int                  fd,
360                          int                  compression,
361                          off_t                offset)
362{
363  if (!rtl)
364  {
365    *decomp = NULL;
366  }
367  else
368  {
369    *decomp = &rtl->decomp;
370    rtems_rtl_obj_comp_set (*decomp, cache, fd, compression, offset);
371  }
372}
373
374typedef struct rtems_rtl_obj_flags_data
375{
376  uint32_t clear;   /**< Flags to clear, do not invert. */
377  uint32_t set;     /**< Flags to set, applied after clearing. */
378} rtems_rtl_obj_flags_data;
379
380static bool
381rtems_rtl_obj_flags_iterator (rtems_chain_node* node, void* data)
382{
383  rtems_rtl_obj* obj              = (rtems_rtl_obj*) node;
384  rtems_rtl_obj_flags_data* flags = (rtems_rtl_obj_flags_data*) data;
385  if (flags->clear != 0)
386    obj->flags &= ~flags->clear;
387  if (flags->set != 0)
388    obj->flags |= flags->set;
389  return true;
390}
391
392void
393rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set)
394{
395  rtems_rtl_obj_flags_data flags = {
396    .clear = clear,
397    .set   = set
398  };
399  rtems_rtl_chain_iterate (&rtl->objects,
400                           rtems_rtl_obj_flags_iterator,
401                           &flags);
402}
403
404rtems_rtl_data*
405rtems_rtl_lock (void)
406{
407  if (!rtems_rtl_data_init ())
408    return NULL;
409
410  rtems_recursive_mutex_lock (&rtl->lock);
411
412  return rtl;
413}
414
415void
416rtems_rtl_unlock (void)
417{
418  rtems_recursive_mutex_unlock (&rtl->lock);
419}
420
421rtems_rtl_obj*
422rtems_rtl_check_handle (void* handle)
423{
424  rtems_rtl_obj*    obj;
425  rtems_chain_node* node;
426
427  obj = handle;
428  node = rtems_chain_first (&rtl->objects);
429
430  while (!rtems_chain_is_tail (&rtl->objects, node))
431  {
432    rtems_rtl_obj* check = (rtems_rtl_obj*) node;
433    if (check == obj)
434      return obj;
435    node = rtems_chain_next (node);
436  }
437
438  return NULL;
439}
440
441rtems_rtl_obj*
442rtems_rtl_find_obj (const char* name)
443{
444  rtems_chain_node* node;
445  rtems_rtl_obj*    found = NULL;
446  const char*       aname = NULL;
447  const char*       oname = NULL;
448  off_t             ooffset;
449
450  if (!rtems_rtl_parse_name (name, &aname, &oname, &ooffset))
451    return NULL;
452
453  node = rtems_chain_first (&rtl->objects);
454
455  while (!rtems_chain_is_tail (&rtl->objects, node))
456  {
457    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
458    if ((aname == NULL && strcmp (obj->oname, oname) == 0) ||
459        (aname != NULL &&
460         strcmp (obj->aname, aname) == 0 && strcmp (obj->oname, oname) == 0))
461    {
462      found = obj;
463      break;
464    }
465    node = rtems_chain_next (node);
466  }
467
468  if (aname != NULL)
469    rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) aname);
470
471  if (oname != NULL)
472    rtems_rtl_alloc_del(RTEMS_RTL_ALLOC_OBJECT, (void*) oname);
473
474  return found;
475}
476
477rtems_rtl_obj*
478rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
479{
480  if (sym != NULL)
481  {
482    rtems_chain_node* node = rtems_chain_first (&rtl->objects);
483    while (!rtems_chain_is_tail (&rtl->objects, node))
484    {
485      rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
486      if (rtems_rtl_obj_has_symbol (obj, sym))
487        return obj;
488      node = rtems_chain_next (node);
489    }
490    node = rtems_chain_first (&rtl->pending);
491    while (!rtems_chain_is_tail (&rtl->pending, node))
492    {
493      rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
494      if (rtems_rtl_obj_has_symbol (obj, sym))
495        return obj;
496      node = rtems_chain_next (node);
497    }
498  }
499  return NULL;
500}
501
502rtems_rtl_obj*
503rtems_rtl_load_object (const char* name, int mode)
504{
505  rtems_rtl_obj* obj;
506
507  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD))
508    printf ("rtl: loading '%s'\n", name);
509
510  /*
511   * See if the object module has already been loaded.
512   */
513  obj = rtems_rtl_find_obj (name);
514  if (!obj)
515  {
516    /*
517     * Allocate a new object file descriptor and attempt to load it.
518     */
519    obj = rtems_rtl_obj_alloc ();
520    if (obj == NULL)
521    {
522      rtems_rtl_set_error (ENOMEM, "no memory for object descriptor");
523      return NULL;
524    }
525
526    rtems_chain_append (&rtl->pending, &obj->link);
527
528    /*
529     * Find the file in the file system using the search path. The fname field
530     * will point to a valid file name if found.
531     */
532    if (!rtems_rtl_obj_find_file (obj, name))
533    {
534      rtems_rtl_obj_free (obj);
535      rtems_rtl_obj_caches_flush ();
536      return NULL;
537    }
538
539    if (!rtems_rtl_obj_load (obj))
540    {
541      rtems_chain_extract (&obj->link);
542      rtems_rtl_obj_free (obj);
543      rtems_rtl_obj_caches_flush ();
544      return NULL;
545    }
546
547    /*
548     * If there are unresolved externals remove from the pending queue and place
549     * on the objects list until the symbols are resolved.
550     */
551    if (obj->unresolved != 0)
552    {
553      rtems_chain_extract (&obj->link);
554      rtems_chain_append (&rtl->objects, &obj->link);
555    }
556
557    rtems_rtl_obj_caches_flush ();
558  }
559
560  /*
561   * Increase the number of users.
562   */
563  ++obj->users;
564
565  return obj;
566}
567
568rtems_rtl_obj*
569rtems_rtl_load (const char* name, int mode)
570{
571  rtems_rtl_obj* obj;
572
573  /*
574   * Refesh the archives.
575   */
576  rtems_rtl_archives_refresh (&rtl->archives);
577
578  /*
579   * Collect the loaded object files.
580   */
581  rtems_chain_initialize_empty (&rtl->pending);
582
583  obj = rtems_rtl_load_object (name, mode);
584  if (obj != NULL)
585  {
586    rtems_chain_node* node;
587
588    rtems_rtl_unresolved_resolve ();
589
590    /*
591     * Iterator over the pending list of object files that have been loaded.
592     */
593    node = rtems_chain_first (&rtl->pending);
594    while (!rtems_chain_is_tail (&rtl->pending, node))
595    {
596      rtems_rtl_obj* pobj = (rtems_rtl_obj*) node;
597
598      /*
599       * Move to the next pending object file and place this object file on the
600       * RTL's objects list.
601       */
602      node = rtems_chain_next (&pobj->link);
603      rtems_chain_extract (&pobj->link);
604      rtems_chain_append (&rtl->objects, &pobj->link);
605
606      /*
607       * Make sure the object file and cache is synchronized.
608       */
609      rtems_rtl_obj_synchronize_cache (pobj);
610
611      /*
612       * Run any local constructors if they have not been run. Unlock the linker
613       * to avoid any dead locks if the object file needs to load files or
614       * update the symbol table. We also do not want a constructor to unload
615       * this object file.
616       */
617      if ((pobj->flags & RTEMS_RTL_OBJ_CTOR_RUN) == 0)
618      {
619        pobj->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_CTOR_RUN;
620        rtems_rtl_unlock ();
621        rtems_rtl_obj_run_ctors (pobj);
622        rtems_rtl_lock ();
623        pobj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
624      }
625    }
626  }
627
628  return obj;
629}
630
631bool
632rtems_rtl_unload_object (rtems_rtl_obj* obj)
633{
634  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
635    printf ("rtl: unload object '%s'\n", rtems_rtl_obj_fname (obj));
636
637  /*
638   * If the object is locked it cannot be unloaded and the unload fails.
639   */
640  if ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == RTEMS_RTL_OBJ_LOCKED)
641  {
642    rtems_rtl_set_error (EINVAL, "object file is locked");
643    return false;
644  }
645
646  /*
647   * The object file cannot be unloaded if it is referenced.
648   */
649  if (rtems_rtl_obj_get_reference (obj) > 0)
650  {
651    rtems_rtl_set_error (EINVAL, "object file has references to it");
652    return false;
653  }
654
655  /*
656   * Check the number of users in a safe manner. If this is the last user unload
657   * the object file from memory.
658   */
659  if (obj->users > 0)
660    --obj->users;
661
662  return true;
663}
664
665bool
666rtems_rtl_unload (rtems_rtl_obj* obj)
667{
668  bool ok = rtems_rtl_unload_object (obj);
669  if (ok && obj->users == 0)
670  {
671    rtems_chain_control unloading;
672    rtems_chain_node*   node;
673    bool                orphaned_found = true;
674    int                 loop = 0;
675
676    /*
677     * Remove the orphaned object files from the objects list. The unloading is
678     * private so any changes in any desctructors will not effect the list as it
679     * is being iterated over.
680     *
681     * To avoid maintaining a complex tree loop while oprhans are still be found.
682     */
683
684    rtems_chain_initialize_empty (&unloading);
685
686    while (orphaned_found)
687    {
688      orphaned_found = false;
689      ++loop;
690      node = rtems_chain_first (&rtl->objects);
691      while (!rtems_chain_is_tail (&rtl->objects, node))
692      {
693        rtems_chain_node* next_node = rtems_chain_next (node);
694        rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
695        if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
696          printf ("rtl: unload object: %3i: %9s: %s\n",
697                  loop,
698                  rtems_rtl_obj_orphaned (uobj) ? "orphaned" : "inuse",
699                  rtems_rtl_obj_oname (uobj));
700        if (rtems_rtl_obj_orphaned (uobj))
701        {
702          orphaned_found = true;
703          rtems_rtl_obj_remove_dependencies (uobj);
704          rtems_chain_extract (&uobj->link);
705          rtems_chain_append (&unloading, &uobj->link);
706          uobj->flags |= RTEMS_RTL_OBJ_LOCKED;
707        }
708        node = next_node;
709      }
710    }
711
712    /*
713     * Call the desctructors unlocked. An RTL call will not deadlock.
714     */
715    rtems_rtl_unlock ();
716
717    node = rtems_chain_first (&unloading);
718    while (!rtems_chain_is_tail (&unloading, node))
719    {
720      rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
721      if ((uobj->flags & RTEMS_RTL_OBJ_CTOR_RUN) != 0)
722      {
723        rtems_rtl_obj_run_dtors (uobj);
724        uobj->flags &= ~RTEMS_RTL_OBJ_CTOR_RUN;
725      }
726      node = rtems_chain_next (node);
727    }
728
729    rtems_rtl_lock ();
730
731    /*
732     * Unload the object files.
733     */
734    node = rtems_chain_first (&unloading);
735    while (!rtems_chain_is_tail (&unloading, node))
736    {
737      rtems_chain_node* next_node = rtems_chain_next (node);
738      rtems_rtl_obj*    uobj = (rtems_rtl_obj*) node;
739      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
740        printf ("rtl: unloading '%s'\n", rtems_rtl_obj_oname (uobj));
741      uobj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
742      if (!rtems_rtl_obj_unload (uobj))
743        ok = false;
744      rtems_rtl_obj_free (uobj);
745      rtems_rtl_obj_caches_flush ();
746      node = next_node;
747    }
748  }
749  return ok;
750}
751
752static bool
753rtems_rtl_path_update (bool prepend, const char* path)
754{
755  char*       paths;
756  const char* src = NULL;
757  char*       dst;
758  int         len;
759
760  if (!rtems_rtl_lock ())
761    return false;
762
763  len = strlen (path);
764
765  if (rtl->paths)
766    len += strlen (rtl->paths) + 1;
767  else
768    prepend = true;
769
770  paths = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, len + 1, false);
771
772  if (!paths)
773  {
774    rtems_rtl_unlock ();
775    return false;
776  }
777
778  dst = paths;
779
780  if (prepend)
781  {
782    len = strlen (path);
783    src = path;
784  }
785  else if (rtl->paths)
786  {
787    len = strlen (rtl->paths);
788    src = rtl->paths;
789  }
790
791  memcpy (dst, src, len);
792
793  dst += len;
794
795  if (rtl->paths)
796  {
797    *dst = ':';
798    ++dst;
799  }
800
801  if (prepend)
802  {
803    src = rtl->paths;
804    if (src)
805      len = strlen (src);
806  }
807  else
808  {
809    len = strlen (path);
810    src = path;
811  }
812
813  if (src)
814  {
815    memcpy (dst, src, len);
816    dst += len;
817  }
818
819  *dst = '\0';
820
821  rtl->paths = paths;
822
823  rtems_rtl_unlock ();
824  return false;
825}
826
827bool
828rtems_rtl_path_append (const char* path)
829{
830  return rtems_rtl_path_update (false, path);
831}
832
833bool
834rtems_rtl_path_prepend (const char* path)
835{
836  return rtems_rtl_path_update (true, path);
837}
838
839void
840rtems_rtl_base_sym_global_add (const unsigned char* esyms,
841                               unsigned int         size)
842{
843  if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
844    printf ("rtl: adding global symbols, table size %u\n", size);
845
846  if (!rtems_rtl_lock ())
847  {
848    rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
849    return;
850  }
851
852  rtems_rtl_symbol_global_add (rtl->base, esyms, size);
853
854  rtems_rtl_unlock ();
855}
856
857rtems_rtl_obj*
858rtems_rtl_baseimage (void)
859{
860  rtems_rtl_obj* base = NULL;
861  if (rtems_rtl_lock ())
862  {
863    base = rtl->base;
864    rtems_rtl_unlock ();
865  }
866  return base;
867}
Note: See TracBrowser for help on using the repository browser.