source: rtems-tools/rtemstoolkit/rld-resolver.cpp @ 3618a62

Last change on this file since 3618a62 was efae4ae, checked in by Chris Johns <chrisj@…>, on Nov 8, 2014 at 7:00:28 AM

toolkit: Print dependents in resolver.

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Copyright (c) 2011, Chris Johns <chrisj@rtems.org>
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16/**
17 * @file
18 *
19 * @ingroup rtems_ld
20 *
21 * @brief RTEMS Linker.
22 *
23 */
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <iomanip>
30#include <iostream>
31
32#include <sys/stat.h>
33
34#include <rld.h>
35#include <rld.h>
36
37namespace rld
38{
39  namespace resolver
40  {
41    static files::object*
42    get_object (files::cache&      cache,
43                const std::string& fullname)
44    {
45      files::objects&          objects = cache.get_objects ();
46      files::objects::iterator oi = objects.find (fullname);
47      if (oi == objects.end ())
48        return 0;
49      return (*oi).second;
50    }
51
52    static void
53    resolve_symbols (files::object_list& dependents,
54                     files::cache&       cache,
55                     symbols::table&     base_symbols,
56                     symbols::table&     symbols,
57                     symbols::symtab&    unresolved,
58                     const std::string&  fullname)
59    {
60      const std::string name = path::basename (fullname);
61
62      static int nesting = 0;
63
64      ++nesting;
65
66      /*
67       * Find each unresolved symbol in the symbol table pointing the
68       * unresolved symbol's object file to the file that resolves the
69       * symbol. Record each object file that is found and when all unresolved
70       * symbols in this object file have been found iterate over the found
71       * object files resolving them. The 'urs' is the unresolved symbol and
72       * 'es' is the exported symbol.
73       */
74
75      files::object* object = get_object (cache, fullname);
76
77      if (object)
78      {
79        if (object->resolved () || object->resolving ())
80        {
81          if (rld::verbose () >= RLD_VERBOSE_INFO)
82            std::cout << "resolver:resolving: "
83                      << std::setw (nesting - 1) << ' '
84                      << name
85                      << " is resolved or resolving"
86                      << std::endl;
87          return;
88        }
89        object->resolve_set ();
90      }
91
92      if (rld::verbose () >= RLD_VERBOSE_INFO)
93        std::cout << "resolver:resolving: "
94                  << std::setw (nesting - 1) << ' '
95                  << name
96                  << ", unresolved: "
97                  << unresolved.size ()
98                  << std::endl;
99
100      files::object_list objects;
101
102      for (symbols::symtab::iterator ursi = unresolved.begin ();
103           ursi != unresolved.end ();
104           ++ursi)
105      {
106        symbols::symbol& urs = *((*ursi).second);
107
108        if ((urs.binding () != STB_WEAK) && urs.object ())
109          continue;
110
111        symbols::symbol* es = base_symbols.find_global (urs.name ());
112        bool             base = true;
113
114        if (rld::verbose () >= RLD_VERBOSE_INFO)
115        {
116          std::cout << "resolver:resolve  : "
117                    << std::setw (nesting + 1) << ' '
118                    << " |- " << urs.name () << std::endl;
119        }
120
121        if (!es)
122        {
123          es = symbols.find_global (urs.name ());
124          if (!es)
125          {
126            es = symbols.find_weak (urs.name ());
127            if (!es)
128              throw rld::error ("symbol not found: " + urs.name (), name);
129          }
130          base = false;
131        }
132
133        symbols::symbol& esym = *es;
134
135        if (rld::verbose () >= RLD_VERBOSE_INFO)
136        {
137          std::cout << "resolver:resolved : "
138                    << std::setw (nesting + 1) << ' '
139                    << " |   `--> ";
140          if (esym.object())
141          {
142            std::cout << esym.object()->name ().basename ();
143            if (esym.object()->resolving ())
144              std::cout << " (resolving)";
145            else if (esym.object()->resolved ())
146              std::cout << " (resolved)";
147            else if (base)
148              std::cout << " (base)";
149            else
150              std::cout << " (unresolved: " << objects.size () + 1 << ')';
151          }
152          else
153            std::cout << "null";
154          std::cout << std::endl;
155        }
156
157        if (!base)
158        {
159          files::object& eobj = *esym.object ();
160          urs.set_object (eobj);
161          if (!eobj.resolved () && !eobj.resolving ())
162          {
163            objects.push_back (&eobj);
164            objects.unique ();
165          }
166        }
167
168        esym.referenced ();
169      }
170
171      if (object)
172      {
173        object->resolve_clear ();
174        object->resolved_set ();
175      }
176
177      /*
178       * Recurse into any references object files.
179       */
180
181      if (rld::verbose () >= RLD_VERBOSE_INFO)
182        std::cout << "resolver:resolved : "
183                  << std::setw (nesting + 1) << ' '
184                  << " +-- referenced objects: " << objects.size ()
185                  << std::endl;
186
187      for (files::object_list::iterator oli = objects.begin ();
188           oli != objects.end ();
189           ++oli)
190      {
191        files::object& obj = *(*oli);
192        if (rld::verbose () >= RLD_VERBOSE_INFO)
193          std::cout << "resolver:resolving: "
194                    << std::setw (nesting) << ' '
195                    << "] " << name << " ==> "
196                    << obj.name ().basename () << std::endl;
197        resolve_symbols (dependents, cache, base_symbols, symbols,
198                         obj.unresolved_symbols (),
199                         obj.name ().full ());
200      }
201
202      --nesting;
203
204      dependents.merge (objects);
205      dependents.unique ();
206    }
207
208    void
209    resolve (files::object_list& dependents,
210             files::cache&       cache,
211             symbols::table&     base_symbols,
212             symbols::table&     symbols,
213             symbols::symtab&    undefined)
214    {
215      files::object_list objects;
216      cache.get_objects (objects);
217
218      /*
219       * First resolve any undefined symbols that are forced by the linker or
220       * the user.
221       */
222      resolver::resolve_symbols (dependents, cache, base_symbols, symbols,
223                                 undefined, "undefines");
224
225      /*
226       * Resolve the symbols in the object files.
227       */
228      for (files::object_list::iterator oi = objects.begin ();
229           oi != objects.end ();
230           ++oi)
231      {
232        files::object& object = *(*oi);
233        if (rld::verbose () >= RLD_VERBOSE_INFO)
234          std::cout << "resolver:resolving: top: "
235                    << object.name ().basename () << std::endl;
236        resolver::resolve_symbols (dependents, cache, base_symbols, symbols,
237                                   object.unresolved_symbols (),
238                                   object.name ().full ());
239      }
240
241      if (rld::verbose () >= RLD_VERBOSE_INFO)
242      {
243        std::cout << "resolver:resolving: dependents: "
244                  << dependents.size () << std::endl;
245        int count = 1;
246        for (files::object_list::iterator di = dependents.begin ();
247             di != dependents.end ();
248             ++di)
249        {
250          files::object& obj = *(*di);
251          std::cout << std::setw (3) << count++
252                    << ": " << obj.name ().basename () << std::endl;
253        }
254      }
255    }
256  }
257
258}
Note: See TracBrowser for help on using the repository browser.