]> Git Repo - binutils.git/blob - gold/symtab.cc
More symbol resolution code.
[binutils.git] / gold / symtab.cc
1 // symtab.cc -- the gold symbol table
2
3 #include "gold.h"
4
5 #include <cassert>
6 #include <stdint.h>
7 #include <string>
8 #include <utility>
9
10 #include "object.h"
11 #include "symtab.h"
12
13 namespace gold
14 {
15
16 // Class Symbol.
17
18 // Initialize the fields in the base class Symbol.
19
20 template<int size, bool big_endian>
21 void
22 Symbol::init_base(const char* name, const char* version, Object* object,
23                   const elfcpp::Sym<size, big_endian>& sym)
24 {
25   this->name_ = name;
26   this->version_ = version;
27   this->object_ = object;
28   this->shnum_ = sym.get_st_shndx(); // FIXME: Handle SHN_XINDEX.
29   this->type_ = sym.get_st_type();
30   this->binding_ = sym.get_st_bind();
31   this->visibility_ = sym.get_st_visibility();
32   this->other_ = sym.get_st_nonvis();
33   this->is_special_ = false;
34   this->is_def_ = false;
35   this->is_forwarder_ = false;
36   this->in_dyn_ = object->is_dynamic();
37 }
38
39 // Initialize the fields in Sized_symbol.
40
41 template<int size>
42 template<bool big_endian>
43 void
44 Sized_symbol<size>::init(const char* name, const char* version, Object* object,
45                          const elfcpp::Sym<size, big_endian>& sym)
46 {
47   this->init_base(name, version, object, sym);
48   this->value_ = sym.get_st_value();
49   this->size_ = sym.get_st_size();
50 }
51
52 // Class Symbol_table.
53
54 Symbol_table::Symbol_table()
55   : size_(0), table_(), namepool_(), forwarders_()
56 {
57 }
58
59 Symbol_table::~Symbol_table()
60 {
61 }
62
63 // The hash function.  The key is always canonicalized, so we use a
64 // simple combination of the pointers.
65
66 size_t
67 Symbol_table::Symbol_table_hash::operator()(const Symbol_table_key& key) const
68 {
69   return (reinterpret_cast<size_t>(key.first)
70           ^ reinterpret_cast<size_t>(key.second));
71 }
72
73 // The symbol table key equality function.  This is only called with
74 // canonicalized name and version strings, so we can use pointer
75 // comparison.
76
77 bool
78 Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1,
79                                           const Symbol_table_key& k2) const
80 {
81   return k1.first == k2.first && k1.second == k2.second;
82 }
83
84 // Make TO a symbol which forwards to FROM.  
85
86 void
87 Symbol_table::make_forwarder(Symbol* from, Symbol* to)
88 {
89   assert(!from->is_forwarder() && !to->is_forwarder());
90   this->forwarders_[from] = to;
91   from->set_forwarder();
92 }
93
94 Symbol*
95 Symbol_table::resolve_forwards(Symbol* from) const
96 {
97   assert(from->is_forwarder());
98   Unordered_map<Symbol*, Symbol*>::const_iterator p =
99     this->forwarders_.find(from);
100   assert(p != this->forwarders_.end());
101   return p->second;
102 }
103
104 // Resolve a Symbol with another Symbol.  This is only used in the
105 // unusual case where there are references to both an unversioned
106 // symbol and a symbol with a version, and we then discover that that
107 // version is the default version.  Because this is unusual, we do
108 // this the slow way, by converting back to an ELF symbol.
109
110 template<int size, bool big_endian>
111 void
112 Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
113 {
114   unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
115   elfcpp::Sym_write<size, big_endian> esym(buf);
116   // We don't bother to set the st_name field.
117   esym.put_st_value(from->value());
118   esym.put_st_size(from->symsize());
119   esym.put_st_info(from->binding(), from->type());
120   esym.put_st_other(from->visibility(), from->other());
121   esym.put_st_shndx(from->shnum());
122   Symbol_table::resolve(to, esym.sym(), from->object());
123 }
124
125 // Add one symbol from OBJECT to the symbol table.  NAME is symbol
126 // name and VERSION is the version; both are canonicalized.  DEF is
127 // whether this is the default version.
128
129 // If DEF is true, then this is the definition of a default version of
130 // a symbol.  That means that any lookup of NAME/NULL and any lookup
131 // of NAME/VERSION should always return the same symbol.  This is
132 // obvious for references, but in particular we want to do this for
133 // definitions: overriding NAME/NULL should also override
134 // NAME/VERSION.  If we don't do that, it would be very hard to
135 // override functions in a shared library which uses versioning.
136
137 // We implement this by simply making both entries in the hash table
138 // point to the same Symbol structure.  That is easy enough if this is
139 // the first time we see NAME/NULL or NAME/VERSION, but it is possible
140 // that we have seen both already, in which case they will both have
141 // independent entries in the symbol table.  We can't simply change
142 // the symbol table entry, because we have pointers to the entries
143 // attached to the object files.  So we mark the entry attached to the
144 // object file as a forwarder, and record it in the forwarders_ map.
145 // Note that entries in the hash table will never be marked as
146 // forwarders.
147
148 template<int size, bool big_endian>
149 Symbol*
150 Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
151                               const char *name,
152                               const char *version, bool def,
153                               const elfcpp::Sym<size, big_endian>& sym)
154 {
155   Symbol* const snull = NULL;
156   std::pair<typename Symbol_table_type::iterator, bool> ins =
157     this->table_.insert(std::make_pair(std::make_pair(name, version), snull));
158
159   std::pair<typename Symbol_table_type::iterator, bool> insdef =
160     std::make_pair(this->table_.end(), false);
161   if (def)
162     {
163       const char* const vnull = NULL;
164       insdef = this->table_.insert(std::make_pair(std::make_pair(name, vnull),
165                                                   snull));
166     }
167
168   // ins.first: an iterator, which is a pointer to a pair.
169   // ins.first->first: the key (a pair of name and version).
170   // ins.first->second: the value (Symbol*).
171   // ins.second: true if new entry was inserted, false if not.
172
173   Sized_symbol<size>* ret;
174   if (!ins.second)
175     {
176       // We already have an entry for NAME/VERSION.
177       ret = this->get_sized_symbol<size>(ins.first->second);
178       assert(ret != NULL);
179       Symbol_table::resolve(ret, sym, object);
180
181       if (def)
182         {
183           if (insdef.second)
184             {
185               // This is the first time we have seen NAME/NULL.  Make
186               // NAME/NULL point to NAME/VERSION.
187               insdef.first->second = ret;
188             }
189           else
190             {
191               // This is the unfortunate case where we already have
192               // entries for both NAME/VERSION and NAME/NULL.
193               const Sized_symbol<size>* sym2 =
194                 this->get_sized_symbol<size>(insdef.first->second);
195               Symbol_table::resolve<size, big_endian>(ret, sym2);
196               this->make_forwarder(insdef.first->second, ret);
197               insdef.first->second = ret;
198             }
199         }
200     }
201   else
202     {
203       // This is the first time we have seen NAME/VERSION.
204       assert(ins.first->second == NULL);
205       if (def && !insdef.second)
206         {
207           // We already have an entry for NAME/NULL.  Make
208           // NAME/VERSION point to it.
209           ret = this->get_sized_symbol<size>(insdef.first->second);
210           Symbol_table::resolve(ret, sym, object);
211           ins.first->second = ret;
212         }
213       else
214         {
215           Sized_target<size, big_endian>* target = object->sized_target();
216           if (!target->has_make_symbol())
217             ret = new Sized_symbol<size>();
218           else
219             {
220               ret = target->make_symbol();
221               if (ret == NULL)
222                 {
223                   // This means that we don't want a symbol table
224                   // entry after all.
225                   if (!def)
226                     this->table_.erase(ins.first);
227                   else
228                     {
229                       this->table_.erase(insdef.first);
230                       // Inserting insdef invalidated ins.
231                       this->table_.erase(std::make_pair(name, version));
232                     }
233                   return NULL;
234                 }
235             }
236
237           ret->init(name, version, object, sym);
238
239           ins.first->second = ret;
240           if (def)
241             {
242               // This is the first time we have seen NAME/NULL.  Point
243               // it at the new entry for NAME/VERSION.
244               assert(insdef.second);
245               insdef.first->second = ret;
246             }
247         }
248     }
249
250   return ret;
251 }
252
253 // Add all the symbols in an object to the hash table.
254
255 template<int size, bool big_endian>
256 void
257 Symbol_table::add_from_object(
258     Sized_object<size, big_endian>* object,
259     const elfcpp::Sym<size, big_endian>* syms,
260     size_t count,
261     const char* sym_names,
262     size_t sym_name_size,
263     Symbol** sympointers)
264 {
265   // We take the size from the first object we see.
266   if (this->get_size() == 0)
267     this->set_size(size);
268
269   if (size != this->get_size() || size != object->target()->get_size())
270     {
271       fprintf(stderr, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
272               program_name, object->name().c_str());
273       gold_exit(false);
274     }
275
276   const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
277   for (size_t i = 0; i < count; ++i)
278     {
279       elfcpp::Sym<size, big_endian> sym(p);
280
281       unsigned int st_name = sym.get_st_name();
282       if (st_name >= sym_name_size)
283         {
284           fprintf(stderr, _("%s: %s: bad symbol name offset %u at %lu\n"),
285                   program_name, object->name().c_str(), st_name,
286                   static_cast<unsigned long>(i));
287           gold_exit(false);
288         }
289
290       const char* name = sym_names + st_name;
291
292       // In an object file, an '@' in the name separates the symbol
293       // name from the version name.  If there are two '@' characters,
294       // this is the default version.
295       const char* ver = strchr(name, '@');
296
297       Symbol* res;
298       if (ver == NULL)
299         {
300           name = this->namepool_.add(name);
301           res = this->add_from_object(object, name, NULL, false, sym);
302         }
303       else
304         {
305           name = this->namepool_.add(name, ver - name);
306           bool def = false;
307           ++ver;
308           if (*ver == '@')
309             {
310               def = true;
311               ++ver;
312             }
313           ver = this->namepool_.add(ver);
314           res = this->add_from_object(object, name, ver, def, sym);
315         }
316
317       *sympointers++ = res;
318
319       p += elfcpp::Elf_sizes<size>::sym_size;
320     }
321 }
322
323 // Instantiate the templates we need.  We could use the configure
324 // script to restrict this to only the ones needed for implemented
325 // targets.
326
327 template
328 void
329 Symbol_table::add_from_object<32, true>(
330     Sized_object<32, true>* object,
331     const elfcpp::Sym<32, true>* syms,
332     size_t count,
333     const char* sym_names,
334     size_t sym_name_size,
335     Symbol** sympointers);
336
337 template
338 void
339 Symbol_table::add_from_object<32, false>(
340     Sized_object<32, false>* object,
341     const elfcpp::Sym<32, false>* syms,
342     size_t count,
343     const char* sym_names,
344     size_t sym_name_size,
345     Symbol** sympointers);
346
347 template
348 void
349 Symbol_table::add_from_object<64, true>(
350     Sized_object<64, true>* object,
351     const elfcpp::Sym<64, true>* syms,
352     size_t count,
353     const char* sym_names,
354     size_t sym_name_size,
355     Symbol** sympointers);
356
357 template
358 void
359 Symbol_table::add_from_object<64, false>(
360     Sized_object<64, false>* object,
361     const elfcpp::Sym<64, false>* syms,
362     size_t count,
363     const char* sym_names,
364     size_t sym_name_size,
365     Symbol** sympointers);
366
367 } // End namespace gold.
This page took 0.044769 seconds and 4 git commands to generate.