source: rtems-tools/rtemstoolkit/rld-symbols.cpp @ 3fd45d3

4.104.11
Last change on this file since 3fd45d3 was 3fd45d3, checked in by Chris Johns <chrisj@…>, on Oct 28, 2014 at 8:13:47 AM

toolkit: Fix the map formatting.

  • Property mode set to 100644
File size: 8.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    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 (5) << 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      out << " No.  Index Scope      Type        SHNDX  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.