source: rtems-tools/rtemstoolkit/rld-symbols.cpp @ 2e97351

4.10
Last change on this file since 2e97351 was 2e97351, checked in by Chris Johns <chrisj@…>, on Apr 3, 2016 at 5:38:14 AM

rtemstoolkit: Add an address table of symbols key by the symbol address.

This is useful if you need to look up a symbol based on its address.

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