source: rtems/cpukit/libdl/rtl-unresolved.c @ c5615ddc

5
Last change on this file since c5615ddc was c5615ddc, checked in by Chris Johns <chrisj@…>, on 02/18/19 at 02:28:10

libdl/unresolved: Fix return value for rtems_rtl_unresolved_remove

Coverity 1399717

Updates #3686

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