source: rtems/cpukit/libdl/rtl-unresolved.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: 23.5 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_rtl
12 *
13 * @brief RTEMS Run-Time Linker Object File Unresolved Relocations Table.
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/rtl/rtl.h>
27#include "rtl-error.h"
28#include <rtems/rtl/rtl-unresolved.h>
29#include <rtems/rtl/rtl-trace.h>
30#include "rtl-trampoline.h"
31
32static rtems_rtl_unresolv_block*
33rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
34{
35  /*
36   * The block header contains a record.
37   */
38  size_t size =
39    (sizeof(rtems_rtl_unresolv_block) +
40     (sizeof(rtems_rtl_unresolv_rec) * unresolved->block_recs));
41  rtems_rtl_unresolv_block* block =
42    rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
43  if (block)
44  {
45    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
46      printf ("rtl: unresolv: block-alloc %p (%p)\n", block, block + size);
47    rtems_chain_append (&unresolved->blocks, &block->link);
48  }
49  else
50    rtems_rtl_set_error (ENOMEM, "no memory for unresolved block");
51  return block;
52}
53
54static size_t
55rtems_rtl_unresolved_symbol_rec_count (size_t length)
56{
57  const size_t rec_size = sizeof(rtems_rtl_unresolv_rec);
58  const size_t rec_name_header = offsetof(rtems_rtl_unresolv_rec, rec.name.name);
59  /*
60   * Add on the nul and rmeove 1 to be inside a record.
61   */
62  return ((length + rec_name_header - 1) / rec_size) + 1;
63}
64
65static size_t
66rtems_rtl_unresolved_symbol_recs (const char* name)
67{
68  return rtems_rtl_unresolved_symbol_rec_count (strlen (name) + 1);
69}
70
71static int
72rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
73                                rtems_rtl_unresolv_rec*   rec)
74{
75  return rec - &block->rec[0];
76}
77
78static rtems_rtl_unresolv_rec*
79rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block* block)
80{
81  return &block->rec[0];
82}
83
84static rtems_rtl_unresolv_rec*
85rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
86{
87  switch (rec->type)
88  {
89    case rtems_rtl_unresolved_empty:
90    default:
91      /*
92       * Empty returns NULL. The end of the records in the block.
93       */
94      rec = NULL;
95      break;
96
97    case rtems_rtl_unresolved_symbol:
98      /*
99       * Determine how many records the name occupies. Round up.
100       */
101      rec += rtems_rtl_unresolved_symbol_rec_count (rec->rec.name.length);
102      break;
103
104    case rtems_rtl_unresolved_reloc:
105    case rtems_rtl_trampoline_reloc:
106      ++rec;
107      break;
108  }
109
110  return rec;
111}
112
113static bool
114rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block* block,
115                                  rtems_rtl_unresolv_rec*   rec)
116{
117  int index = rtems_rtl_unresolved_rec_index (block, rec);
118  return (rec == NULL ||
119          (index < 0) ||
120          (index >= block->recs) ||
121          (rec->type == rtems_rtl_unresolved_empty));
122}
123
124static rtems_rtl_unresolv_rec*
125rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block* block)
126{
127  return &block->rec[0] + block->recs;
128}
129
130/**
131 * Name management iterator data.
132 */
133typedef struct
134{
135  const char*             name;   /**< The name being searched for. */
136  size_t                  length; /**< The length of the name. */
137  rtems_rtl_unresolv_rec* rec;    /**< The record being searched for. */
138  int                     index;  /**< The name's index. */
139  int                     offset; /**< The offset to move the index. */
140} rtl_unresolved_name_data;
141
142static bool
143rtems_rtl_unresolved_find_name_iterator (rtems_rtl_unresolv_rec* rec,
144                                         void*                   data)
145{
146  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
147  if (rec->type == rtems_rtl_unresolved_symbol)
148  {
149    if ((rec->rec.name.length == nd->length)
150        && (strcmp (rec->rec.name.name, nd->name) == 0))
151    {
152      ++rec->rec.name.refs;
153      return true;
154    }
155    ++nd->index;
156  }
157  return false;
158}
159
160static int
161rtems_rtl_unresolved_find_name (const char* name)
162{
163  rtl_unresolved_name_data nd = {
164    .name = name,
165    .length = strlen (name) + 1,
166    .rec = NULL,
167    .index = 1,
168    .offset = 0
169  };
170  if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_name_iterator,
171                                    &nd))
172    return nd.index;
173  return -1;
174}
175
176static bool
177rtems_rtl_unresolved_find_index_iterator (rtems_rtl_unresolv_rec* rec,
178                                          void*                   data)
179{
180  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
181  if (rec == nd->rec)
182    return true;
183  if (rec->type == rtems_rtl_unresolved_symbol)
184    ++nd->index;
185  return false;
186}
187
188static int
189rtems_rtl_unresolved_find_index (rtems_rtl_unresolv_rec* rec)
190{
191  rtl_unresolved_name_data nd = {
192    .name = NULL,
193    .length = 0,
194    .rec = rec,
195    .index = 1,
196    .offset = 0
197  };
198  if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_index_iterator,
199                                    &nd))
200    return nd.index;
201  return -1;
202}
203
204static bool
205rtems_rtl_unresolved_reindex_iterator (rtems_rtl_unresolv_rec* rec,
206                                       void*                   data)
207{
208  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
209  /*
210   * Reindexing only effects the reloc records.
211   */
212  if (rec->type == rtems_rtl_unresolved_reloc)
213  {
214    if (rec->rec.reloc.name >= nd->index)
215      rec->rec.reloc.name += nd->offset;
216  }
217  return false;
218}
219
220static void
221rtems_rtl_unresolved_reindex_names (uint16_t index, int offset)
222{
223  rtl_unresolved_name_data nd = {
224    .name = NULL,
225    .length = 0,
226    .rec = NULL,
227    .index = index,
228    .offset = offset
229  };
230  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_reindex_iterator,
231                                &nd);
232}
233
234/**
235 * Struct to pass relocation data in the iterator.
236 */
237typedef struct rtems_rtl_unresolved_reloc_data
238{
239  uint16_t                name;     /**< Name index. */
240  rtems_rtl_unresolv_rec* name_rec; /**< Name record. */
241  rtems_rtl_obj_sym*      sym;      /**< The symbol record. */
242} rtems_rtl_unresolved_reloc_data;
243
244static bool
245rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
246                                    void*                   data)
247{
248  if (rec->type == rtems_rtl_unresolved_reloc)
249  {
250    rtems_chain_control*             pending;
251    rtems_rtl_unresolved_reloc_data* rd;
252
253    rd = (rtems_rtl_unresolved_reloc_data*) data;
254
255    if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL)
256    {
257      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
258        printf ("rtl: unresolv: resolve reloc: %s\n",
259                rd->name_rec->rec.name.name);
260
261      if (rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym))
262      {
263        /*
264         * If all unresolved externals are resolved add the obj module
265         * to the pending queue. This will flush the object module's
266         * data from the cache and call it's constructors.
267         */
268        if (rec->rec.reloc.obj->unresolved == 0)
269        {
270          pending = rtems_rtl_pending_unprotected ();
271          rtems_chain_extract (&rec->rec.reloc.obj->link);
272          rtems_chain_append (pending, &rec->rec.reloc.obj->link);
273        }
274
275        /*
276         * Set the object pointer to NULL to indicate the record is
277         * not used anymore. Update the reference count of the name so
278         * it can garbage collected if not referenced. The sweep after
279         * relocating will remove the reloc records with obj set to
280         * NULL and names with a reference count of 0.
281         */
282        rec->rec.reloc.obj = NULL;
283        if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
284          --rd->name_rec->rec.name.refs;
285      }
286    }
287  }
288  return false;
289}
290
291static bool
292rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec* rec,
293                                       void*                   data)
294{
295  if (rec->type == rtems_rtl_unresolved_symbol)
296  {
297    rtems_rtl_unresolved_reloc_data* rd;
298    rd = (rtems_rtl_unresolved_reloc_data*) data;
299
300    ++rd->name;
301
302    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
303      printf ("rtl: unresolv: lookup: %d: %s\n", rd->name, rec->rec.name.name);
304
305    rd->sym = rtems_rtl_symbol_global_find (rec->rec.name.name);
306
307    if (rd->sym)
308    {
309      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
310        printf ("rtl: unresolv: found: %s\n", rec->rec.name.name);
311
312      rd->name_rec = rec;
313
314      rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_resolve_reloc, rd);
315
316      rd->name_rec = NULL;
317      rd->sym = NULL;
318    }
319  }
320
321  return false;
322}
323
324/**
325 * Struct to pass archive relocation data in the iterator.
326 */
327typedef struct rtems_rtl_unresolved_archive_reloc_data
328{
329  uint16_t                 name;     /**< Name index. */
330  rtems_rtl_archive_search result;   /**< The result of the load. */
331  rtems_rtl_archives*      archives; /**< The archives to search. */
332} rtems_rtl_unresolved_archive_reloc_data;
333
334static bool
335rtems_rtl_unresolved_archive_iterator (rtems_rtl_unresolv_rec* rec,
336                                       void*                   data)
337{
338  if (rec->type == rtems_rtl_unresolved_symbol)
339  {
340    rtems_rtl_unresolved_archive_reloc_data* ard;
341    ard = (rtems_rtl_unresolved_archive_reloc_data*) data;
342
343    ++ard->name;
344
345    if ((rec->rec.name.flags & RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE) != 0)
346    {
347      rtems_rtl_archive_search result;
348
349      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
350        printf ("rtl: unresolv: archive lookup: %d: %s\n",
351                ard->name, rec->rec.name.name);
352
353      result = rtems_rtl_archive_obj_load (ard->archives,
354                                           rec->rec.name.name, true);
355      if (result != rtems_rtl_archive_search_not_found)
356      {
357        rec->rec.name.flags &= ~RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
358        ard->result = result;
359        return true;
360      }
361    }
362  }
363
364  return false;
365}
366
367static bool
368rtems_rtl_unresolved_archive_search_iterator (rtems_rtl_unresolv_rec* rec,
369                                              void*                   data)
370{
371  if (rec->type == rtems_rtl_unresolved_symbol)
372    rec->rec.name.flags |= RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
373  return false;
374}
375
376static rtems_rtl_unresolv_block*
377rtems_rtl_unresolved_alloc_recs (rtems_rtl_unresolved* unresolved,
378                                 size_t                count)
379{
380  rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
381  while (!rtems_chain_is_tail (&unresolved->blocks, node))
382  {
383    rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
384
385    if (block->recs + count <= unresolved->block_recs)
386      return block;
387    node = rtems_chain_next (node);
388  }
389  return NULL;
390}
391
392static void
393rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
394                                  rtems_rtl_unresolv_rec*   rec,
395                                  size_t                    count,
396                                  size_t                    recs_per_block)
397{
398  size_t index = rtems_rtl_unresolved_rec_index (block, rec);
399  size_t bytes =
400    (block->recs - index - count) * sizeof (rtems_rtl_unresolv_rec);
401  if (bytes)
402    memmove (rec, rec + count, bytes);
403  block->recs -= count;
404  bytes = count * sizeof (rtems_rtl_unresolv_rec);
405  memset (&block->rec[block->recs], 0, bytes);
406}
407
408static rtems_chain_node*
409rtems_rtl_unresolved_delete_block_if_empty (rtems_chain_control*      blocks,
410                                            rtems_rtl_unresolv_block* block)
411{
412  rtems_chain_node* node = &block->link;
413  rtems_chain_node* next_node = rtems_chain_next (node);
414  /*
415   * Always leave a single block allocated. Eases possible heap fragmentation.
416   */
417  if (block->recs == 0 && !rtems_chain_has_only_one_node (blocks))
418  {
419    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
420      printf ("rtl: unresolv: block-del %p\n", block);
421    rtems_chain_extract (node);
422    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
423  }
424  return next_node;
425}
426
427static void
428rtems_rtl_unresolved_compact (void)
429{
430  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
431  if (unresolved)
432  {
433    /*
434     * Iterate over the blocks removing any empty strings. If a string is
435     * removed update the indexes of all strings above this level.
436     */
437    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
438    uint16_t          index = 0;
439    while (!rtems_chain_is_tail (&unresolved->blocks, node))
440    {
441      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
442      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
443      while (!rtems_rtl_unresolved_rec_is_last (block, rec))
444      {
445        bool next_rec = true;
446
447        if (rec->type == rtems_rtl_unresolved_symbol)
448        {
449          ++index;
450          if (rec->rec.name.refs == 0)
451          {
452            size_t name_recs;
453            if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
454              printf ("rtl: unresolv: remove name: %s\n", rec->rec.name.name);
455            rtems_rtl_unresolved_reindex_names (index, -1);
456            /*
457             * Compact the block removing the name record.
458             */
459            name_recs = rtems_rtl_unresolved_symbol_recs (rec->rec.name.name);
460            rtems_rtl_unresolved_clean_block (block, rec, name_recs,
461                                              unresolved->block_recs);
462            --index;
463            next_rec = false;
464          }
465        }
466        else if (rec->type == rtems_rtl_unresolved_reloc)
467        {
468          if (rec->rec.reloc.obj == NULL)
469          {
470            rtems_rtl_unresolved_clean_block (block, rec, 1,
471                                              unresolved->block_recs);
472            next_rec = false;
473          }
474        }
475
476        if (next_rec)
477          rec = rtems_rtl_unresolved_rec_next (rec);
478      }
479
480      node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
481                                                         block);
482    }
483  }
484}
485
486bool
487rtems_rtl_unresolved_table_open (rtems_rtl_unresolved* unresolved,
488                                 size_t                block_recs)
489{
490  unresolved->marker = 0xdeadf00d;
491  unresolved->block_recs = block_recs;
492  rtems_chain_initialize_empty (&unresolved->blocks);
493  return rtems_rtl_unresolved_block_alloc (unresolved);
494}
495
496void
497rtems_rtl_unresolved_table_close (rtems_rtl_unresolved* unresolved)
498{
499  rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
500  while (!rtems_chain_is_tail (&unresolved->blocks, node))
501  {
502    rtems_chain_node* next = rtems_chain_next (node);
503    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, node);
504    node = next;
505  }
506}
507
508bool
509rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_iterator iterator,
510                              void*                         data)
511{
512  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
513  if (unresolved)
514  {
515    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
516    while (!rtems_chain_is_tail (&unresolved->blocks, node))
517    {
518      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
519      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
520
521      while (!rtems_rtl_unresolved_rec_is_last (block, rec))
522      {
523        if (iterator (rec, data))
524          return true;
525        rec = rtems_rtl_unresolved_rec_next (rec);
526      }
527
528      node = rtems_chain_next (node);
529    }
530  }
531  return false;
532}
533
534bool
535rtems_rtl_unresolved_add (rtems_rtl_obj*        obj,
536                          const uint16_t        flags,
537                          const char*           name,
538                          const uint16_t        sect,
539                          const rtems_rtl_word* rel)
540{
541  rtems_rtl_unresolved*     unresolved;
542  rtems_rtl_unresolv_block* block;
543  rtems_rtl_unresolv_rec*   rec;
544  int                       name_index;
545
546  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
547    printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
548            rtems_rtl_obj_oname (obj), sect, name);
549
550  unresolved = rtems_rtl_unresolved_unprotected ();
551  if (!unresolved)
552    return false;
553
554  /*
555   * Is the name present?
556   */
557  name_index = rtems_rtl_unresolved_find_name (name);
558
559  /*
560   * An index less than 0 means the name was not found.
561   */
562  if (name_index < 0)
563  {
564    size_t name_recs;
565
566    name_recs = rtems_rtl_unresolved_symbol_recs (name);
567
568    /*
569     * Is there enough room to fit the name ? It not add a new block.
570     */
571    block = rtems_rtl_unresolved_alloc_recs (unresolved, name_recs);
572    if (block == NULL)
573    {
574      block = rtems_rtl_unresolved_block_alloc (unresolved);
575      if (!block)
576        return false;
577    }
578
579    /*
580     * Find the record in the block.
581     */
582    rec = rtems_rtl_unresolved_rec_first_free (block);
583
584    /*
585     * Enter the new record before reindexing so the iterator can see
586     * it and the iterator is called.
587     */
588    rec->type = rtems_rtl_unresolved_symbol;
589    rec->rec.name.refs = 1;
590    rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
591    rec->rec.name.length = strlen (name) + 1;
592    memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length);
593    block->recs += name_recs;
594
595    /*
596     * Find the name index for the name and then reindex the names which
597     * are moved up because of the insertion.
598     */
599    name_index = rtems_rtl_unresolved_find_index (rec);
600    if (name_index < 0)
601    {
602      rtems_rtl_set_error (ENOMEM, "internal unresolved block error");
603      return false;
604    }
605
606    rtems_rtl_unresolved_reindex_names (name_index, 1);
607  }
608
609  /*
610   * Find the first block with a spare record.
611   */
612  block = rtems_rtl_unresolved_alloc_recs (unresolved, 1);
613  if (block == NULL)
614  {
615    block = rtems_rtl_unresolved_block_alloc (unresolved);
616    if (!block)
617      return false;
618  }
619
620  rec = rtems_rtl_unresolved_rec_first_free (block);
621  rec->type = rtems_rtl_unresolved_reloc;
622  rec->rec.reloc.obj = obj;
623  rec->rec.reloc.flags = flags;
624  rec->rec.reloc.name = name_index;
625  rec->rec.reloc.sect = sect;
626  rec->rec.reloc.rel[0] = rel[0];
627  rec->rec.reloc.rel[1] = rel[1];
628  rec->rec.reloc.rel[2] = rel[2];
629
630  ++block->recs;
631
632  return true;
633}
634
635void
636rtems_rtl_unresolved_resolve (void)
637{
638  bool resolving = true;
639
640  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
641    printf ("rtl: unresolv: global resolve\n");
642
643  /*
644   * The resolving process is two separate stages, The first stage is to
645   * iterate over the unresolved symbols searching the global symbol table. If
646   * a symbol is found iterate over the unresolved relocation records for the
647   * symbol fixing up the relocations. The second stage is to search the
648   * archives for symbols we have not searched before and if a symbol is found
649   * in an archve load the object file. Loading an object file stops the
650   * search of the archives for symbols and stage one is performed again. The
651   * process repeats until no more symbols are resolved or there is an error.
652   */
653  while (resolving)
654  {
655    rtems_rtl_unresolved_reloc_data rd = {
656      .name = 0,
657      .name_rec = NULL,
658      .sym = NULL
659    };
660    rtems_rtl_unresolved_archive_reloc_data ard = {
661      .name = 0,
662      .result = rtems_rtl_archive_search_not_found,
663      .archives = rtems_rtl_archives_unprotected ()
664    };
665
666    rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_resolve_iterator, &rd);
667    rtems_rtl_unresolved_compact ();
668    rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_iterator, &ard);
669
670    resolving = ard.result == rtems_rtl_archive_search_loaded;
671  }
672
673  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
674    rtems_rtl_unresolved_dump ();
675}
676
677bool
678rtems_rtl_trampoline_add (rtems_rtl_obj*        obj,
679                          const uint16_t        flags,
680                          const uint16_t        sect,
681                          const rtems_rtl_word  symvalue,
682                          const rtems_rtl_word* rel)
683{
684  rtems_rtl_unresolved*     unresolved;
685  rtems_rtl_unresolv_block* block;
686  rtems_rtl_unresolv_rec*   rec;
687
688  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
689    printf ("rtl: tramp: add: %s sect:%d flags:%04x\n",
690            rtems_rtl_obj_oname (obj), sect, flags);
691
692  unresolved = rtems_rtl_unresolved_unprotected ();
693  if (!unresolved)
694    return false;
695
696  block = rtems_rtl_unresolved_alloc_recs (unresolved, 1);
697  if (block == NULL)
698  {
699    block = rtems_rtl_unresolved_block_alloc (unresolved);
700    if (!block)
701      return false;
702  }
703
704  rec = rtems_rtl_unresolved_rec_first_free (block);
705  rec->type = rtems_rtl_trampoline_reloc;
706  rec->rec.tramp.obj = obj;
707  rec->rec.tramp.flags = flags;
708  rec->rec.tramp.sect = sect;
709  rec->rec.tramp.symvalue = symvalue;
710  rec->rec.tramp.rel[0] = rel[0];
711  rec->rec.tramp.rel[1] = rel[1];
712  rec->rec.tramp.rel[2] = rel[2];
713
714  ++block->recs;
715
716  return true;
717}
718
719void
720rtems_rtl_trampoline_remove (rtems_rtl_obj* obj)
721{
722  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
723  if (unresolved)
724  {
725    /*
726     * Iterate over the blocks clearing any trampoline records.
727     */
728    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
729    while (!rtems_chain_is_tail (&unresolved->blocks, node))
730    {
731      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
732      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
733
734      /*
735       * Search the table for a trampoline record and if found clean the
736       * record moving the remaining records down the block.
737       */
738      while (!rtems_rtl_unresolved_rec_is_last (block, rec))
739      {
740        bool next_rec = true;
741
742        if (rec->type == rtems_rtl_trampoline_reloc && rec->rec.tramp.obj == obj)
743        {
744            rtems_rtl_unresolved_clean_block (block, rec, 1,
745                                              unresolved->block_recs);
746            next_rec = false;
747        }
748
749        if (next_rec)
750          rec = rtems_rtl_unresolved_rec_next (rec);
751      }
752
753      node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
754                                                         block);
755    }
756  }
757}
758
759/**
760 * Struct to pass relocation data in the iterator.
761 */
762typedef struct rtems_rtl_unresolved_dump_data
763{
764  size_t rec;
765  size_t names;
766  bool   show_relocs;
767} rtems_rtl_unresolved_dump_data;
768
769static bool
770rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
771                                    void*                   data)
772{
773  rtems_rtl_unresolved_dump_data* dd;
774  dd = (rtems_rtl_unresolved_dump_data*) data;
775  switch (rec->type)
776  {
777  case rtems_rtl_unresolved_empty:
778    printf (" %03zu: 0: empty\n", dd->rec);
779    break;
780  case rtems_rtl_unresolved_symbol:
781    ++dd->names;
782    printf (" %3zu: 1:  name: %3zu refs:%4d: flags:%04x %s (%d)\n",
783            dd->rec, dd->names,
784            rec->rec.name.refs,
785            rec->rec.name.flags,
786            rec->rec.name.name,
787            rec->rec.name.length);
788    break;
789  case rtems_rtl_unresolved_reloc:
790  case rtems_rtl_trampoline_reloc:
791    if (dd->show_relocs)
792      printf (" %3zu: 2:reloc%c: obj:%s name:%2d: sect:%d\n",
793              rec->type == rtems_rtl_unresolved_reloc ? 'R' : 'T',
794              dd->rec,
795              rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
796              rec->rec.reloc.name,
797              rec->rec.reloc.sect);
798    break;
799  default:
800    printf (" %03zu: %d: unknown\n", dd->rec, rec->type);
801    break;
802  }
803  ++dd->rec;
804  return false;
805}
806
807void
808rtems_rtl_unresolved_dump (void)
809{
810  rtems_rtl_unresolved_dump_data dd = { 0 };
811  printf ("RTL Unresolved data:\n");
812  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_dump_iterator, &dd);
813}
814
815void
816rtems_rtl_unresolved_set_archive_search (void)
817{
818  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
819                                NULL);
820}
Note: See TracBrowser for help on using the repository browser.