source: rtems-tools/rtemstoolkit/rld-symbols.cpp @ 7d3350d

5
Last change on this file since 7d3350d was 6c94148, checked in by Chris Johns <chrisj@…>, on 04/03/16 at 06:26:36

linkers: Demangle the C++ labels in the .ctors/.dtors sections.

Show user friendly labels for the C++ constructors and destructors.

  • Property mode set to 100644
File size: 10.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 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    bool
41    is_cplusplus (const std::string& name)
42    {
43      char* demangled_name = ::cplus_demangle (name.c_str (),
44                                               DMGL_ANSI | DMGL_PARAMS);
45      bool yes = false;
46      if (demangled_name)
47      {
48        yes = true;
49        ::free (demangled_name);
50      }
51      return yes;
52    }
53
54    void
55    demangle_name (std::string& name, std::string& demangled)
56    {
57      char* demangled_name = ::cplus_demangle (name.c_str (),
58                                               DMGL_ANSI | DMGL_PARAMS);
59      if (demangled_name)
60      {
61        demangled = demangled_name;
62        ::free (demangled_name);
63      }
64    }
65
66    symbol::symbol ()
67      : index_ (-1),
68        object_ (0),
69        references_ (0)
70    {
71      memset (&esym_, 0, sizeof (esym_));
72    }
73
74    symbol::symbol (int                 index,
75                    const std::string&  name,
76                    files::object&      object,
77                    const elf::elf_sym& esym)
78      : index_ (index),
79        name_ (name),
80        object_ (&object),
81        esym_ (esym),
82        references_ (0)
83    {
84      if (!object_)
85        throw rld_error_at ("object pointer is 0");
86      if (is_cplusplus ())
87        demangle_name (name_, demangled_);
88    }
89
90    symbol::symbol (int                 index,
91                    const std::string&  name,
92                    const elf::elf_sym& esym)
93      : index_ (index),
94        name_ (name),
95        object_ (0),
96        esym_ (esym),
97        references_ (0)
98    {
99      if (is_cplusplus ())
100        demangle_name (name_, demangled_);
101    }
102
103    symbol::symbol (const std::string&  name,
104                    const elf::elf_addr value)
105      : index_ (-1),
106        name_ (name),
107        object_ (0),
108        references_ (0)
109    {
110      memset (&esym_, 0, sizeof (esym_));
111      esym_.st_value = value;
112    }
113
114    symbol::symbol (const char*         name,
115                    const elf::elf_addr value)
116      : index_ (-1),
117        name_ (name),
118        object_ (0),
119        references_ (0)
120    {
121      memset (&esym_, 0, sizeof (esym_));
122      esym_.st_value = value;
123    }
124
125    int
126    symbol::index () const
127    {
128      return index_;
129    }
130
131    const std::string&
132    symbol::name () const
133    {
134      return name_;
135    }
136
137    const std::string&
138    symbol::demangled () const
139    {
140      return demangled_;
141    }
142
143    bool
144    symbol::is_cplusplus () const
145    {
146      return (name_[0] == '_') && (name_[1] == 'Z');
147    }
148
149    bool
150    symbol::is_local () const
151    {
152      return binding () == STB_LOCAL;
153    }
154
155    bool
156    symbol::is_weak () const
157    {
158      return binding () == STB_WEAK;
159    }
160
161    bool
162    symbol::is_global () const
163    {
164      return binding () == STB_GLOBAL;
165    }
166
167    int
168    symbol::type () const
169    {
170      return GELF_ST_TYPE (esym_.st_info);
171    }
172
173    int
174    symbol::binding () const
175    {
176      return GELF_ST_BIND (esym_.st_info);
177    }
178
179    int
180    symbol::section_index () const
181    {
182      return esym_.st_shndx;
183    }
184
185    elf::elf_addr
186    symbol::value () const
187    {
188      return esym_.st_value;
189    }
190
191    uint32_t
192    symbol::info () const
193    {
194      return esym_.st_info;
195    }
196
197    rld::files::object*
198    symbol::object () const
199    {
200      return object_;
201    }
202
203    void
204    symbol::set_object (rld::files::object& obj)
205    {
206      object_ = &obj;
207    }
208
209    const elf::elf_sym&
210    symbol::esym () const
211    {
212      return esym_;
213    }
214
215    void
216    symbol::referenced ()
217    {
218      ++references_;
219      if (object_)
220        object_->symbol_referenced ();
221    }
222
223    bool
224    symbol::operator< (const symbol& rhs) const
225    {
226      return name_ < rhs.name_;
227    }
228
229    void
230    symbol::output (std::ostream& out) const
231    {
232      const elf::elf_sym& es = esym ();
233
234      std::string binding;
235      int binding_val = GELF_ST_BIND (es.st_info);
236      switch (binding_val)
237      {
238        case STB_LOCAL:
239          binding = "STB_LOCAL ";
240          break;
241        case STB_GLOBAL:
242          binding = "STB_GLOBAL";
243          break;
244        case STB_WEAK:
245          binding = "STB_WEAK  ";
246          break;
247        default:
248          if ((binding_val >= STB_LOPROC) && (binding_val <= STB_HIPROC))
249            binding = "STB_LOPROC(" + rld::to_string (binding_val) + ")";
250          else
251            binding = "STB_INVALID("  + rld::to_string (binding_val) + ")";
252          break;
253      }
254
255      std::string type;
256      int type_val = GELF_ST_TYPE (es.st_info);
257      switch (type_val)
258      {
259        case STT_NOTYPE:
260          type = "STT_NOTYPE ";
261          break;
262        case STT_OBJECT:
263          type = "STT_OBJECT ";
264          break;
265        case STT_FUNC:
266          type = "STT_FUNC   ";
267          break;
268        case STT_SECTION:
269          type = "STT_SECTION";
270          break;
271        case STT_FILE:
272          type = "STT_FILE   ";
273          break;
274        default:
275          if ((type_val >= STT_LOPROC) && (type_val <= STT_HIPROC))
276            type = "STT_LOPROC(" + rld::to_string (type_val) + ")";
277          else
278            type = "STT_INVALID("  + rld::to_string (type_val) + ")";
279          break;
280      }
281
282      out << std::setw (5) << index_
283          << ' ' << binding
284          << ' ' << type
285          << ' ' << std::setw(6) << es.st_shndx
286          << " 0x" << std::setw (8) << std::setfill ('0') << std::hex
287          << es.st_value
288          << std::dec << std::setfill (' ')
289          << ' ' << std::setw (7)  << es.st_size
290          << ' ';
291
292      if (is_cplusplus ())
293        out << demangled ();
294      else
295        out << name ();
296
297      if (object ())
298        out << "   (" << object ()->name ().basename () << ')';
299    }
300
301    table::table ()
302    {
303    }
304
305    table::~table ()
306    {
307    }
308
309    void
310    table::add_global (symbol& sym)
311    {
312      globals_[sym.name ()] = &sym;
313    }
314
315    void
316    table::add_weak (symbol& sym)
317    {
318      weaks_[sym.name ()] = &sym;
319    }
320
321    void
322    table::add_local (symbol& sym)
323    {
324      locals_[sym.name ()] = &sym;
325    }
326
327    symbol*
328    table::find_global (const std::string& name)
329    {
330      symtab::iterator sti = globals_.find (name);
331      if (sti == globals_.end ())
332        return 0;
333      return (*sti).second;
334    }
335
336    symbol*
337    table::find_weak (const std::string& name)
338    {
339      symtab::iterator sti = weaks_.find (name);
340      if (sti == weaks_.end ())
341        return 0;
342      return (*sti).second;
343    }
344
345    symbol*
346    table::find_local (const std::string& name)
347    {
348      symtab::iterator sti = locals_.find (name);
349      if (sti == locals_.end ())
350        return 0;
351      return (*sti).second;
352    }
353
354    size_t
355    table::size () const
356    {
357      return globals_.size () + weaks_.size () + locals_.size ();
358    }
359
360    const symtab&
361    table::globals () const
362    {
363      return globals_;
364    }
365
366    const symtab&
367    table::weaks () const
368    {
369      return weaks_;
370    }
371
372    const symtab&
373    table::locals () const
374    {
375      return locals_;
376    }
377
378    void
379    table::globals (addrtab& addresses)
380    {
381      for (symtab::iterator gi = globals_.begin ();
382           gi != globals_.end ();
383           ++gi)
384      {
385        symbol& sym = *((*gi).second);
386        addresses[sym.value ()] = (*gi).second;
387      }
388    }
389
390    void
391    table::weaks (addrtab& addresses)
392    {
393      for (symtab::iterator wi = weaks_.begin ();
394           wi != weaks_.end ();
395           ++wi)
396      {
397        symbol& sym = *((*wi).second);
398        addresses[sym.value ()] = (*wi).second;
399      }
400    }
401
402    void
403    table::locals (addrtab& addresses)
404    {
405      for (symtab::iterator li = locals_.begin ();
406           li != locals_.end ();
407           ++li)
408      {
409        symbol& sym = *((*li).second);
410        addresses[sym.value ()] = (*li).second;
411      }
412    }
413
414    void
415    load (bucket& bucket_, table& table_)
416    {
417      for (bucket::iterator sbi = bucket_.begin ();
418           sbi != bucket_.end ();
419           ++sbi)
420      {
421        table_.add_global (*sbi);
422      }
423    }
424
425    void
426    load (bucket& bucket_, symtab& table_)
427    {
428      for (bucket::iterator sbi = bucket_.begin ();
429           sbi != bucket_.end ();
430           ++sbi)
431      {
432        symbol& sym = *sbi;
433        table_[sym.name ()] = &sym;
434      }
435    }
436
437    size_t
438    referenced (pointers& symbols)
439    {
440      size_t used = 0;
441      for (pointers::iterator sli = symbols.begin ();
442           sli != symbols.end ();
443           ++sli)
444      {
445        symbol& sym = *(*sli);
446        if (sym.references ())
447          ++used;
448      }
449
450      return used;
451    }
452
453    void
454    output (std::ostream& out, const table& symbols)
455    {
456      out << "Globals:" << std::endl;
457      output (out, symbols.globals ());
458      out << "Weaks:" << std::endl;
459      output (out, symbols.weaks ());
460      out << "Locals:" << std::endl;
461      output (out, symbols.locals ());
462    }
463
464    void
465    output (std::ostream& out, const symtab& symbols)
466    {
467      out << " No.  Index Scope      Type        SHNDX  Address    Size    Name" << std::endl;
468      int index = 0;
469      for (symtab::const_iterator si = symbols.begin ();
470           si != symbols.end ();
471           ++si)
472      {
473        const symbol& sym = *((*si).second);
474        out << std::setw (5) << index << ' ' << sym << std::endl;
475        ++index;
476      }
477    }
478
479  }
480}
Note: See TracBrowser for help on using the repository browser.