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

Last change on this file since c5615ddc was c5615ddc, checked in by Chris Johns <chrisj@…>, on Feb 18, 2019 at 2:28:10 AM

libdl/unresolved: Fix return value for rtems_rtl_unresolved_remove

Coverity 1399717

Updates #3686

  • Property mode set to 100644
File size: 20.8 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
31static rtems_rtl_unresolv_block*
32rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
33{
34  /*
35   * The block header contains a record.
36   */
37  size_t size =
38    (sizeof(rtems_rtl_unresolv_block) +
39     (sizeof(rtems_rtl_unresolv_rec) * unresolved->block_recs));
40  rtems_rtl_unresolv_block* block =
41    rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
42  if (block)
43  {
44    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
45      printf ("rtl: unresolv: block-alloc %p (%p)\n", block, block + size);
46    rtems_chain_append (&unresolved->blocks, &block->link);
47  }
48  else
49    rtems_rtl_set_error (ENOMEM, "no memory for unresolved block");
50  return block;
51}
52
53static size_t
54rtems_rtl_unresolved_symbol_rec_count (size_t length)
55{
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;
62}
63
64static size_t
65rtems_rtl_unresolved_symbol_recs (const char* name)
66{
67  return rtems_rtl_unresolved_symbol_rec_count (strlen (name) + 1);
68}
69
70static int
71rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
72                                rtems_rtl_unresolv_rec* rec)
73{
74  return rec - &block->rec[0];
75}
76
77static rtems_rtl_unresolv_rec*
78rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block* block)
79{
80  return &block->rec[0];
81}
82
83static rtems_rtl_unresolv_rec*
84rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
85{
86  switch (rec->type)
87  {
88    case rtems_rtl_unresolved_empty:
89    default:
90      /*
91       * Empty returns NULL. The end of the records in the block.
92       */
93      rec = NULL;
94      break;
95
96    case rtems_rtl_unresolved_symbol:
97      /*
98       * Determine how many records the name occupies. Round up.
99       */
100      rec += rtems_rtl_unresolved_symbol_rec_count (rec->rec.name.length);
101      break;
102
103    case rtems_rtl_unresolved_reloc:
104      ++rec;
105      break;
106  }
107
108  return rec;
109}
110
111static bool
112rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block* block,
113                                  rtems_rtl_unresolv_rec*   rec)
114{
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));
120}
121
122static rtems_rtl_unresolv_rec*
123rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block* block)
124{
125  return &block->rec[0] + block->recs;
126}
127
128/**
129 * Name management iterator data.
130 */
131typedef struct
132{
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;
139
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)
146  {
147    if ((rec->rec.name.length == nd->length)
148        && (strcmp (rec->rec.name.name, nd->name) == 0))
149    {
150      ++rec->rec.name.refs;
151      return true;
152    }
153    ++nd->index;
154  }
155  return false;
156}
157
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;
214  }
215  return false;
216}
217
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);
230}
231
232/**
233 * Struct to pass relocation data in the iterator.
234 */
235typedef struct rtems_rtl_unresolved_reloc_data
236{
237  uint16_t                name;     /**< Name index. */
238  rtems_rtl_unresolv_rec* name_rec; /**< Name record. */
239  rtems_rtl_obj_sym*      sym;      /**< The symbol record. */
240} rtems_rtl_unresolved_reloc_data;
241
242static bool
243rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
244                                    void*                   data)
245{
246  if (rec->type == rtems_rtl_unresolved_reloc)
247  {
248    rtems_chain_control*             pending;
249    rtems_rtl_unresolved_reloc_data* rd;
250
251    rd = (rtems_rtl_unresolved_reloc_data*) data;
252
253    if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL)
254    {
255      if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
256        printf ("rtl: unresolv: resolve reloc: %s\n",
257                rd->name_rec->rec.name.name);
258
259      if (rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym))
260      {
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        }
272
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      }
284    }
285  }
286  return false;
287}
288
289static bool
290rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec* rec,
291                                       void*                   data)
292{
293  if (rec->type == rtems_rtl_unresolved_symbol)
294  {
295    rtems_rtl_unresolved_reloc_data* rd;
296    rd = (rtems_rtl_unresolved_reloc_data*) data;
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
312      rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_resolve_reloc, rd);
313
314      rd->name_rec = NULL;
315      rd->sym = NULL;
316    }
317  }
318
319  return false;
320}
321
322/**
323 * Struct to pass archive relocation data in the iterator.
324 */
325typedef struct rtems_rtl_unresolved_archive_reloc_data
326{
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. */
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    {
345      rtems_rtl_archive_search result;
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
351      result = rtems_rtl_archive_obj_load (ard->archives,
352                                           rec->rec.name.name, true);
353      if (result != rtems_rtl_archive_search_not_found)
354      {
355        rec->rec.name.flags &= ~RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
356        ard->result = result;
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)
370    rec->rec.name.flags |= RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
371  return false;
372}
373
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
390static void
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)
395{
396  size_t index = rtems_rtl_unresolved_rec_index (block, rec);
397  size_t bytes =
398    (block->recs - index - count) * sizeof (rtems_rtl_unresolv_rec);
399  if (bytes)
400    memmove (rec, rec + count, bytes);
401  block->recs -= count;
402  bytes = count * sizeof (rtems_rtl_unresolv_rec);
403  memset (&block->rec[block->recs], 0, bytes);
404}
405
406static void
407rtems_rtl_unresolved_compact (void)
408{
409  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
410  if (unresolved)
411  {
412    /*
413     * Iterate over the blocks removing any empty strings. If a string is
414     * removed update the indexes of all strings above this level.
415     */
416    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
417    uint16_t          index = 0;
418    while (!rtems_chain_is_tail (&unresolved->blocks, node))
419    {
420      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
421      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
422      while (!rtems_rtl_unresolved_rec_is_last (block, rec))
423      {
424        bool next_rec = true;
425
426        if (rec->type == rtems_rtl_unresolved_symbol)
427        {
428          ++index;
429          if (rec->rec.name.refs == 0)
430          {
431            size_t name_recs;
432            if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
433              printf ("rtl: unresolv: remove name: %s\n", rec->rec.name.name);
434            rtems_rtl_unresolved_reindex_names (index, -1);
435            /*
436             * Compact the block removing the name record.
437             */
438            name_recs = rtems_rtl_unresolved_symbol_recs (rec->rec.name.name);
439            rtems_rtl_unresolved_clean_block (block, rec, name_recs,
440                                              unresolved->block_recs);
441            --index;
442            next_rec = false;
443          }
444        }
445        else if (rec->type == rtems_rtl_unresolved_reloc)
446        {
447          if (rec->rec.reloc.obj == NULL)
448          {
449            rtems_rtl_unresolved_clean_block (block, rec, 1,
450                                              unresolved->block_recs);
451            next_rec = false;
452          }
453        }
454
455        if (next_rec)
456          rec = rtems_rtl_unresolved_rec_next (rec);
457      }
458
459      if (block->recs == 0)
460      {
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);
464        rtems_chain_extract (node);
465        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
466        node = next_node;
467      }
468      else
469      {
470        node = rtems_chain_next (node);
471      }
472    }
473  }
474}
475
476bool
477rtems_rtl_unresolved_table_open (rtems_rtl_unresolved* unresolved,
478                                 size_t                block_recs)
479{
480  unresolved->marker = 0xdeadf00d;
481  unresolved->block_recs = block_recs;
482  rtems_chain_initialize_empty (&unresolved->blocks);
483  return true;
484}
485
486void
487rtems_rtl_unresolved_table_close (rtems_rtl_unresolved* unresolved)
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);
493    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, node);
494    node = next;
495  }
496}
497
498bool
499rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_iterator iterator,
500                              void*                         data)
501{
502  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
503  if (unresolved)
504  {
505    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
506    while (!rtems_chain_is_tail (&unresolved->blocks, node))
507    {
508      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
509      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
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
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)
530{
531  rtems_rtl_unresolved*     unresolved;
532  rtems_rtl_unresolv_block* block;
533  rtems_rtl_unresolv_rec*   rec;
534  int                       name_index;
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
540  unresolved = rtems_rtl_unresolved_unprotected ();
541  if (!unresolved)
542    return false;
543
544  /*
545   * Is the name present?
546   */
547  name_index = rtems_rtl_unresolved_find_name (name);
548
549  /*
550   * An index less than 0 means the name was not found.
551   */
552  if (name_index < 0)
553  {
554    size_t name_recs;
555
556    name_recs = rtems_rtl_unresolved_symbol_recs (name);
557
558    /*
559     * Is there enough room to fit the name ? It not add a new block.
560     */
561    block = rtems_rtl_unresolved_alloc_recs (unresolved, name_recs);
562    if (block == NULL)
563    {
564      block = rtems_rtl_unresolved_block_alloc (unresolved);
565      if (!block)
566        return false;
567    }
568
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     */
578    rec->type = rtems_rtl_unresolved_symbol;
579    rec->rec.name.refs = 1;
580    rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
581    rec->rec.name.length = strlen (name) + 1;
582    memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length);
583    block->recs += name_recs;
584
585    /*
586     * Find the name index for the name and then reindex the names which
587     * are moved up because of the insertion.
588     */
589    name_index = rtems_rtl_unresolved_find_index (rec);
590    if (name_index < 0)
591    {
592      rtems_rtl_set_error (ENOMEM, "internal unresolved block error");
593      return false;
594    }
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;
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{
628  bool resolving = true;
629
630  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
631    printf ("rtl: unresolv: global resolve\n");
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,
652      .result = rtems_rtl_archive_search_not_found,
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
660    resolving = ard.result == rtems_rtl_archive_search_loaded;
661  }
662
663  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
664    rtems_rtl_unresolved_dump ();
665}
666
667bool
668rtems_rtl_unresolved_remove (rtems_rtl_obj*        obj,
669                             const char*           name,
670                             const uint16_t        sect,
671                             const rtems_rtl_word* rel)
672{
673  rtems_rtl_unresolved* unresolved;
674  unresolved = rtems_rtl_unresolved_unprotected ();
675  if (unresolved == NULL)
676    return false;
677  return true;
678}
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;
687  bool   show_relocs;
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;
701  case rtems_rtl_unresolved_symbol:
702    ++dd->names;
703    printf (" %3zu: 1:  name: %3zu refs:%4d: flags:%04x %s (%d)\n",
704            dd->rec, dd->names,
705            rec->rec.name.refs,
706            rec->rec.name.flags,
707            rec->rec.name.name,
708            rec->rec.name.length);
709    break;
710  case rtems_rtl_unresolved_reloc:
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);
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");
731  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_dump_iterator, &dd);
732}
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.