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

4.104.115
Last change on this file since fe19d06 was 977c3de, checked in by Chris Johns <chrisj@…>, on 11/17/12 at 06:34:33

Refactor the ELF support to allow ELF write suppport.

The refactoring allows better reuse of the ELF support and cleans up
some hacks from the generic file and archive handling improving the
separation of the file handling from the file format, ie ELF. The
handling of ELF object files and ELF object files inside archives
is cleaner.

The refactor cleaned up the symbol handling where the symbols now
reside in the ELF file object and references are take in symbol
pointer containers and symbol table containers.

The main purpose of the refactor is to allow support for creating
and writing ELF files.

Also added an rtems-syms command where special symbol support
can be added.

  • Property mode set to 100644
File size: 6.6 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    rld::files::object*
144    symbol::object () const
145    {
146      return object_;
147    }
148
149    void
150    symbol::set_object (rld::files::object& obj)
151    {
152      object_ = &obj;
153    }
154
155    const elf::elf_sym&
156    symbol::esym () const
157    {
158      return esym_;
159    }
160
161    void
162    symbol::referenced ()
163    {
164      ++references_;
165      if (object_)
166        object_->symbol_referenced ();
167    }
168
169    bool
170    symbol::operator< (const symbol& rhs) const
171    {
172      return name_ < rhs.name_;
173    }
174
175    void
176    symbol::output (std::ostream& out) const
177    {
178      const elf::elf_sym& es = esym ();
179
180      std::string binding;
181      int binding_val = GELF_ST_BIND (es.st_info);
182      switch (binding_val)
183      {
184        case STB_LOCAL:
185          binding = "STB_LOCAL ";
186          break;
187        case STB_GLOBAL:
188          binding = "STB_GLOBAL";
189          break;
190        case STB_WEAK:
191          binding = "STB_WEAK  ";
192          break;
193        default:
194          if ((binding_val >= STB_LOPROC) && (binding_val <= STB_HIPROC))
195            binding = "STB_LOPROC(" + rld::to_string (binding_val) + ")";
196          else
197            binding = "STB_INVALID("  + rld::to_string (binding_val) + ")";
198          break;
199      }
200
201      std::string type;
202      int type_val = GELF_ST_TYPE (es.st_info);
203      switch (type_val)
204      {
205        case STT_NOTYPE:
206          type = "STT_NOTYPE ";
207          break;
208        case STT_OBJECT:
209          type = "STT_OBJECT ";
210          break;
211        case STT_FUNC:
212          type = "STT_FUNC   ";
213          break;
214        case STT_SECTION:
215          type = "STT_SECTION";
216          break;
217        case STT_FILE:
218          type = "STT_FILE   ";
219          break;
220        default:
221          if ((type_val >= STT_LOPROC) && (type_val <= STT_HIPROC))
222            type = "STT_LOPROC(" + rld::to_string (type_val) + ")";
223          else
224            type = "STT_INVALID("  + rld::to_string (type_val) + ")";
225          break;
226      }
227
228      out << binding
229          << ' ' << type
230          << " 0x" << std::setw (8) << std::setfill ('0') << std::hex
231          << es.st_value
232          << std::dec << std::setfill (' ')
233          << ' ' << std::setw (7)  << es.st_size
234          << ' ';
235
236      if (is_cplusplus ())
237        out << demangled ();
238      else
239        out << name ();
240
241      if (object ())
242        out << "   (" << object ()->name ().basename () << ')';
243    }
244
245    void
246    load (bucket& bucket_, table& table_)
247    {
248      for (bucket::iterator sbi = bucket_.begin ();
249           sbi != bucket_.end ();
250           ++sbi)
251      {
252        symbol& sym = *sbi;
253        table_[sym.name ()] = &sym;
254      }
255    }
256
257    size_t
258    referenced (pointers& symbols)
259    {
260      size_t used = 0;
261      for (pointers::iterator sli = symbols.begin ();
262           sli != symbols.end ();
263           ++sli)
264      {
265        symbol& sym = *(*sli);
266        if (sym.references ())
267          ++used;
268      }
269
270      return used;
271    }
272
273    void
274    output (std::ostream& out, const table& symbols)
275    {
276      std::cout << " No.  Scope      Type        Address    Size    Name" << std::endl;
277      int index = 0;
278      for (table::const_iterator si = symbols.begin ();
279           si != symbols.end ();
280           ++si)
281      {
282        const symbol& sym = *((*si).second);
283        out << std::setw (5) << index << ' ' << sym << std::endl;
284        ++index;
285      }
286    }
287
288  }
289}
Note: See TracBrowser for help on using the repository browser.