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

5
Last change on this file since 3618a62 was 78bbe4c, checked in by Chris Johns <chrisj@…>, on 08/16/17 at 08:09:59

linkers/exe-info Support ARM static constructors.

Note, ARM destructors are registered at runtime and currently not
easly found.

Update libiberty to get a newer demangler.

Closes #3102.

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