source: rtems-tools/linkers/rld-symbols.cpp @ 26b46b1

4.104.115
Last change on this file since 26b46b1 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: 8.3 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 symbols manages the symbols from all the object files.
22 *
23 */
24
25#include <string.h>
26
27#include <iomanip>
28
29#include <rld.h>
30
31#include <libiberty/demangle.h>
32
33namespace rld
34{
35  namespace symbols
36  {
37    /**
38     * Get the demangled name.
39     */
40    static void
41    denamgle_name (std::string& name, std::string& demangled)
42    {
43      char* demangled_name = ::cplus_demangle (name.c_str (),
44                                               DMGL_ANSI | DMGL_PARAMS);
45      if (demangled_name)
46      {
47        demangled = demangled_name;
48        ::free (demangled_name);
49      }
50    }
51
52    symbol::symbol ()
53      : index_ (-1),
54        object_ (0),
55        references_ (0)
56    {
57      memset (&esym_, 0, sizeof (esym_));
58    }
59
60    symbol::symbol (int                 index,
61                    const std::string&  name,
62                    files::object&      object,
63                    const elf::elf_sym& esym)
64      : index_ (index),
65        name_ (name),
66        object_ (&object),
67        esym_ (esym),
68        references_ (0)
69    {
70      if (!object_)
71        throw rld_error_at ("object pointer is 0");
72      if (is_cplusplus ())
73        denamgle_name (name_, demangled_);
74    }
75
76    symbol::symbol (int                 index,
77                    const std::string&  name,
78                    const elf::elf_sym& esym)
79      : index_ (index),
80        name_ (name),
81        object_ (0),
82        esym_ (esym),
83        references_ (0)
84    {
85      if (is_cplusplus ())
86        denamgle_name (name_, demangled_);
87    }
88
89    symbol::symbol (const std::string&  name,
90                    const elf::elf_addr value)
91      : index_ (-1),
92        name_ (name),
93        object_ (0),
94        references_ (0)
95    {
96      memset (&esym_, 0, sizeof (esym_));
97      esym_.st_value = value;
98    }
99
100    symbol::symbol (const char*         name,
101                    const elf::elf_addr value)
102      : index_ (-1),
103        name_ (name),
104        object_ (0),
105        references_ (0)
106    {
107      memset (&esym_, 0, sizeof (esym_));
108      esym_.st_value = value;
109    }
110
111    int
112    symbol::index () const
113    {
114      return index_;
115    }
116
117    const std::string&
118    symbol::name () const
119    {
120      return name_;
121    }
122
123    const std::string&
124    symbol::demangled () const
125    {
126      return demangled_;
127    }
128
129    bool
130    symbol::is_cplusplus () const
131    {
132      return (name_[0] == '_') && (name_[1] == 'Z');
133    }
134
135    int
136    symbol::type () const
137    {
138      return GELF_ST_TYPE (esym_.st_info);
139    }
140
141    int
142    symbol::binding () const
143    {
144      return GELF_ST_BIND (esym_.st_info);
145    }
146
147    int
148    symbol::section_index () const
149    {
150      return esym_.st_shndx;
151    }
152
153    elf::elf_addr
154    symbol::value () const
155    {
156      return esym_.st_value;
157    }
158
159    uint32_t
160    symbol::info () const
161    {
162      return esym_.st_info;
163    }
164
165    rld::files::object*
166    symbol::object () const
167    {
168      return object_;
169    }
170
171    void
172    symbol::set_object (rld::files::object& obj)
173    {
174      object_ = &obj;
175    }
176
177    const elf::elf_sym&
178    symbol::esym () const
179    {
180      return esym_;
181    }
182
183    void
184    symbol::referenced ()
185    {
186      ++references_;
187      if (object_)
188        object_->symbol_referenced ();
189    }
190
191    bool
192    symbol::operator< (const symbol& rhs) const
193    {
194      return name_ < rhs.name_;
195    }
196
197    void
198    symbol::output (std::ostream& out) const
199    {
200      const elf::elf_sym& es = esym ();
201
202      std::string binding;
203      int binding_val = GELF_ST_BIND (es.st_info);
204      switch (binding_val)
205      {
206        case STB_LOCAL:
207          binding = "STB_LOCAL ";
208          break;
209        case STB_GLOBAL:
210          binding = "STB_GLOBAL";
211          break;
212        case STB_WEAK:
213          binding = "STB_WEAK  ";
214          break;
215        default:
216          if ((binding_val >= STB_LOPROC) && (binding_val <= STB_HIPROC))
217            binding = "STB_LOPROC(" + rld::to_string (binding_val) + ")";
218          else
219            binding = "STB_INVALID("  + rld::to_string (binding_val) + ")";
220          break;
221      }
222
223      std::string type;
224      int type_val = GELF_ST_TYPE (es.st_info);
225      switch (type_val)
226      {
227        case STT_NOTYPE:
228          type = "STT_NOTYPE ";
229          break;
230        case STT_OBJECT:
231          type = "STT_OBJECT ";
232          break;
233        case STT_FUNC:
234          type = "STT_FUNC   ";
235          break;
236        case STT_SECTION:
237          type = "STT_SECTION";
238          break;
239        case STT_FILE:
240          type = "STT_FILE   ";
241          break;
242        default:
243          if ((type_val >= STT_LOPROC) && (type_val <= STT_HIPROC))
244            type = "STT_LOPROC(" + rld::to_string (type_val) + ")";
245          else
246            type = "STT_INVALID("  + rld::to_string (type_val) + ")";
247          break;
248      }
249
250      out << std::setw (4) << index_
251          << ' ' << binding
252          << ' ' << type
253          << ' ' << std::setw(6) << es.st_shndx
254          << " 0x" << std::setw (8) << std::setfill ('0') << std::hex
255          << es.st_value
256          << std::dec << std::setfill (' ')
257          << ' ' << std::setw (7)  << es.st_size
258          << ' ';
259
260      if (is_cplusplus ())
261        out << demangled ();
262      else
263        out << name ();
264
265      if (object ())
266        out << "   (" << object ()->name ().basename () << ')';
267    }
268
269    table::table ()
270    {
271    }
272
273    table::~table ()
274    {
275    }
276
277    void
278    table::add_external (symbol& sym)
279    {
280      _externals[sym.name ()] = &sym;
281    }
282
283    void
284    table::add_weak (symbol& sym)
285    {
286      _weaks[sym.name ()] = &sym;
287    }
288
289    symbol*
290    table::find_external (const std::string& name)
291    {
292      symtab::iterator sti = _externals.find (name);
293      if (sti == _externals.end ())
294        return 0;
295      return (*sti).second;
296    }
297
298    symbol*
299    table::find_weak (const std::string& name)
300    {
301      symtab::iterator sti = _weaks.find (name);
302      if (sti == _weaks.end ())
303        return 0;
304      return (*sti).second;
305    }
306
307    size_t
308    table::size () const
309    {
310      return _externals.size () + _weaks.size ();
311    }
312
313    const symtab&
314    table::externals () const
315    {
316      return _externals;
317    }
318
319    const symtab&
320    table::weaks () const
321    {
322      return _weaks;
323    }
324
325    void
326    load (bucket& bucket_, table& table_)
327    {
328      for (bucket::iterator sbi = bucket_.begin ();
329           sbi != bucket_.end ();
330           ++sbi)
331      {
332        table_.add_external (*sbi);
333      }
334    }
335
336    void
337    load (bucket& bucket_, symtab& table_)
338    {
339      for (bucket::iterator sbi = bucket_.begin ();
340           sbi != bucket_.end ();
341           ++sbi)
342      {
343        symbol& sym = *sbi;
344        table_[sym.name ()] = &sym;
345      }
346    }
347
348    size_t
349    referenced (pointers& symbols)
350    {
351      size_t used = 0;
352      for (pointers::iterator sli = symbols.begin ();
353           sli != symbols.end ();
354           ++sli)
355      {
356        symbol& sym = *(*sli);
357        if (sym.references ())
358          ++used;
359      }
360
361      return used;
362    }
363
364    void
365    output (std::ostream& out, const table& symbols)
366    {
367      out << "Externals:" << std::endl;
368      output (out, symbols.externals ());
369      out << "Weaks:" << std::endl;
370      output (out, symbols.weaks ());
371    }
372
373    void
374    output (std::ostream& out, const symtab& symbols)
375    {
376      std::cout << " No.  Scope      Type        Address    Size    Name" << std::endl;
377      int index = 0;
378      for (symtab::const_iterator si = symbols.begin ();
379           si != symbols.end ();
380           ++si)
381      {
382        const symbol& sym = *((*si).second);
383        out << std::setw (5) << index << ' ' << sym << std::endl;
384        ++index;
385      }
386    }
387
388  }
389}
Note: See TracBrowser for help on using the repository browser.