source: rtems-tools/rtemstoolkit/rld-symbols.cpp

Last change on this file was c1e3887, checked in by Chris Johns <chrisj@…>, on Sep 2, 2019 at 12:10:05 AM

rtemstoolkit/dwarf: Fix some C++ handling issues.

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