source: rtems-tools/linkers/rld-resolver.cpp @ 39f48c9

4.104.115
Last change on this file since 39f48c9 was 544de91, checked in by Chris Johns <chrisj@…>, on 12/28/12 at 23:20:22

Fix managing weak symbols.

Weak symbols where not being managed correctly. The symbols table
is now a class with externals and weaks as separate symtabs so
the externals can be searched first then the weaks and if not
found an unresolved error is raised. This was found creating
a libbsdport RAP file where the drivers in the all driver table
resolved to the weak symbols and so linking in nothing.

Fixing the weak symbols as found in the libbsdport library
triggered a new resolver bug. The object files now contain the
resolver state and this is used to determine if an object file
has been resolved or is currently being resolved avoiding
rescursive loops with dependent object files.

The resolver trace output is a little easier to read.

  • Property mode set to 100644
File size: 7.1 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 = files::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_external (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_external (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  }
242
243}
Note: See TracBrowser for help on using the repository browser.