source: rtems-tools/linkers/rld-symbols.cpp @ 825a10e

4.104.115
Last change on this file since 825a10e was ea6f8d4, checked in by Chris Johns <chrisj@…>, on 11/29/12 at 08:01:43

Add access to the value and info fields of a symbols.

  • Property mode set to 100644
File size: 6.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      : object_ (0),
54        references_ (0)
55    {
56      memset (&esym_, 0, sizeof (esym_));
57    }
58
59    symbol::symbol (const std::string&  name,
60                    files::object&      object,
61                    const elf::elf_sym& esym)
62      : name_ (name),
63        object_ (&object),
64        esym_ (esym),
65        references_ (0)
66    {
67      if (!object_)
68        throw rld_error_at ("object pointer is 0");
69      if (name_.empty ())
70        throw rld_error_at ("name is empty in " + object.name ().full ());
71      if (is_cplusplus ())
72        denamgle_name (name_, demangled_);
73    }
74
75    symbol::symbol (const std::string& name, const elf::elf_sym& esym)
76      : name_ (name),
77        object_ (0),
78        esym_ (esym),
79        references_ (0)
80    {
81      if (name_.empty ())
82        throw rld_error_at ("name is empty");
83      if (is_cplusplus ())
84        denamgle_name (name_, demangled_);
85    }
86
87    symbol::symbol (const std::string&  name,
88                    const elf::elf_addr value)
89      : name_ (name),
90        object_ (0),
91        references_ (0)
92    {
93      memset (&esym_, 0, sizeof (esym_));
94      esym_.st_value = value;
95    }
96
97    symbol::symbol (const char*         name,
98                    const elf::elf_addr value)
99      : name_ (name),
100        object_ (0),
101        references_ (0)
102    {
103      memset (&esym_, 0, sizeof (esym_));
104      esym_.st_value = value;
105    }
106
107    const std::string&
108    symbol::name () const
109    {
110      return name_;
111    }
112
113    const std::string&
114    symbol::demangled () const
115    {
116      return demangled_;
117    }
118
119    bool
120    symbol::is_cplusplus () const
121    {
122      return (name_[0] == '_') && (name_[1] == 'Z');
123    }
124
125    int
126    symbol::type () const
127    {
128      return GELF_ST_TYPE (esym_.st_info);
129    }
130
131    int
132    symbol::binding () const
133    {
134      return GELF_ST_BIND (esym_.st_info);
135    }
136
137    int
138    symbol::index () const
139    {
140      return esym_.st_shndx;
141    }
142
143    elf::elf_addr
144    symbol::value () const
145    {
146      return esym_.st_value;
147    }
148
149    uint32_t
150    symbol::info () const
151    {
152      return esym_.st_info;
153    }
154
155    rld::files::object*
156    symbol::object () const
157    {
158      return object_;
159    }
160
161    void
162    symbol::set_object (rld::files::object& obj)
163    {
164      object_ = &obj;
165    }
166
167    const elf::elf_sym&
168    symbol::esym () const
169    {
170      return esym_;
171    }
172
173    void
174    symbol::referenced ()
175    {
176      ++references_;
177      if (object_)
178        object_->symbol_referenced ();
179    }
180
181    bool
182    symbol::operator< (const symbol& rhs) const
183    {
184      return name_ < rhs.name_;
185    }
186
187    void
188    symbol::output (std::ostream& out) const
189    {
190      const elf::elf_sym& es = esym ();
191
192      std::string binding;
193      int binding_val = GELF_ST_BIND (es.st_info);
194      switch (binding_val)
195      {
196        case STB_LOCAL:
197          binding = "STB_LOCAL ";
198          break;
199        case STB_GLOBAL:
200          binding = "STB_GLOBAL";
201          break;
202        case STB_WEAK:
203          binding = "STB_WEAK  ";
204          break;
205        default:
206          if ((binding_val >= STB_LOPROC) && (binding_val <= STB_HIPROC))
207            binding = "STB_LOPROC(" + rld::to_string (binding_val) + ")";
208          else
209            binding = "STB_INVALID("  + rld::to_string (binding_val) + ")";
210          break;
211      }
212
213      std::string type;
214      int type_val = GELF_ST_TYPE (es.st_info);
215      switch (type_val)
216      {
217        case STT_NOTYPE:
218          type = "STT_NOTYPE ";
219          break;
220        case STT_OBJECT:
221          type = "STT_OBJECT ";
222          break;
223        case STT_FUNC:
224          type = "STT_FUNC   ";
225          break;
226        case STT_SECTION:
227          type = "STT_SECTION";
228          break;
229        case STT_FILE:
230          type = "STT_FILE   ";
231          break;
232        default:
233          if ((type_val >= STT_LOPROC) && (type_val <= STT_HIPROC))
234            type = "STT_LOPROC(" + rld::to_string (type_val) + ")";
235          else
236            type = "STT_INVALID("  + rld::to_string (type_val) + ")";
237          break;
238      }
239
240      out << binding
241          << ' ' << type
242          << " 0x" << std::setw (8) << std::setfill ('0') << std::hex
243          << es.st_value
244          << std::dec << std::setfill (' ')
245          << ' ' << std::setw (7)  << es.st_size
246          << ' ';
247
248      if (is_cplusplus ())
249        out << demangled ();
250      else
251        out << name ();
252
253      if (object ())
254        out << "   (" << object ()->name ().basename () << ')';
255    }
256
257    void
258    load (bucket& bucket_, table& table_)
259    {
260      for (bucket::iterator sbi = bucket_.begin ();
261           sbi != bucket_.end ();
262           ++sbi)
263      {
264        symbol& sym = *sbi;
265        table_[sym.name ()] = &sym;
266      }
267    }
268
269    size_t
270    referenced (pointers& symbols)
271    {
272      size_t used = 0;
273      for (pointers::iterator sli = symbols.begin ();
274           sli != symbols.end ();
275           ++sli)
276      {
277        symbol& sym = *(*sli);
278        if (sym.references ())
279          ++used;
280      }
281
282      return used;
283    }
284
285    void
286    output (std::ostream& out, const table& symbols)
287    {
288      std::cout << " No.  Scope      Type        Address    Size    Name" << std::endl;
289      int index = 0;
290      for (table::const_iterator si = symbols.begin ();
291           si != symbols.end ();
292           ++si)
293      {
294        const symbol& sym = *((*si).second);
295        out << std::setw (5) << index << ' ' << sym << std::endl;
296        ++index;
297      }
298    }
299
300  }
301}
Note: See TracBrowser for help on using the repository browser.