]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gold/symtab.cc
2006-09-27 Dave Brolley <brolley@redhat.com>
[thirdparty/binutils-gdb.git] / gold / symtab.cc
CommitLineData
14bfc3f5
ILT
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
13namespace gold
14{
15
16// Class Symbol.
17
14bfc3f5
ILT
18// Initialize the fields in the base class Symbol.
19
20template<int size, bool big_endian>
21void
22Symbol::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();
1564db8d
ILT
33 this->is_special_ = false;
34 this->is_def_ = false;
35 this->is_forwarder_ = false;
36 this->in_dyn_ = object->is_dynamic();
14bfc3f5
ILT
37}
38
39// Initialize the fields in Sized_symbol.
40
41template<int size>
42template<bool big_endian>
43void
44Sized_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
54Symbol_table::Symbol_table()
54dc6425 55 : size_(0), table_(), namepool_(), output_pool_(), forwarders_()
14bfc3f5
ILT
56{
57}
58
59Symbol_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
66size_t
67Symbol_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
77bool
78Symbol_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
86void
87Symbol_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
94Symbol*
95Symbol_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
1564db8d
ILT
107// version is the default version. Because this is unusual, we do
108// this the slow way, by converting back to an ELF symbol.
14bfc3f5 109
274e99f9
ILT
110#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
111
1564db8d 112template<int size, bool big_endian>
14bfc3f5 113void
1564db8d 114Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
14bfc3f5 115{
1564db8d
ILT
116 unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
117 elfcpp::Sym_write<size, big_endian> esym(buf);
118 // We don't bother to set the st_name field.
119 esym.put_st_value(from->value());
120 esym.put_st_size(from->symsize());
121 esym.put_st_info(from->binding(), from->type());
122 esym.put_st_other(from->visibility(), from->other());
123 esym.put_st_shndx(from->shnum());
124 Symbol_table::resolve(to, esym.sym(), from->object());
14bfc3f5
ILT
125}
126
274e99f9
ILT
127#else
128
129template<int size>
130void
131Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from,
132 bool big_endian)
133{
134 unsigned char buf[elfcpp::Elf_sizes<size>::sym_size];
135 if (big_endian)
136 {
137 elfcpp::Sym_write<size, true> esym(buf);
138 // We don't bother to set the st_name field.
139 esym.put_st_value(from->value());
140 esym.put_st_size(from->symsize());
141 esym.put_st_info(from->binding(), from->type());
142 esym.put_st_other(from->visibility(), from->other());
143 esym.put_st_shndx(from->shnum());
144 Symbol_table::resolve(to, esym.sym(), from->object());
145 }
146 else
147 {
148 elfcpp::Sym_write<size, false> esym(buf);
149 // We don't bother to set the st_name field.
150 esym.put_st_value(from->value());
151 esym.put_st_size(from->symsize());
152 esym.put_st_info(from->binding(), from->type());
153 esym.put_st_other(from->visibility(), from->other());
154 esym.put_st_shndx(from->shnum());
155 Symbol_table::resolve(to, esym.sym(), from->object());
156 }
157}
158
159#endif
160
14bfc3f5
ILT
161// Add one symbol from OBJECT to the symbol table. NAME is symbol
162// name and VERSION is the version; both are canonicalized. DEF is
163// whether this is the default version.
164
165// If DEF is true, then this is the definition of a default version of
166// a symbol. That means that any lookup of NAME/NULL and any lookup
167// of NAME/VERSION should always return the same symbol. This is
168// obvious for references, but in particular we want to do this for
169// definitions: overriding NAME/NULL should also override
170// NAME/VERSION. If we don't do that, it would be very hard to
171// override functions in a shared library which uses versioning.
172
173// We implement this by simply making both entries in the hash table
174// point to the same Symbol structure. That is easy enough if this is
175// the first time we see NAME/NULL or NAME/VERSION, but it is possible
176// that we have seen both already, in which case they will both have
177// independent entries in the symbol table. We can't simply change
178// the symbol table entry, because we have pointers to the entries
179// attached to the object files. So we mark the entry attached to the
180// object file as a forwarder, and record it in the forwarders_ map.
181// Note that entries in the hash table will never be marked as
182// forwarders.
183
184template<int size, bool big_endian>
185Symbol*
186Symbol_table::add_from_object(Sized_object<size, big_endian>* object,
187 const char *name,
188 const char *version, bool def,
189 const elfcpp::Sym<size, big_endian>& sym)
190{
191 Symbol* const snull = NULL;
192 std::pair<typename Symbol_table_type::iterator, bool> ins =
193 this->table_.insert(std::make_pair(std::make_pair(name, version), snull));
194
195 std::pair<typename Symbol_table_type::iterator, bool> insdef =
196 std::make_pair(this->table_.end(), false);
197 if (def)
198 {
199 const char* const vnull = NULL;
200 insdef = this->table_.insert(std::make_pair(std::make_pair(name, vnull),
201 snull));
202 }
203
204 // ins.first: an iterator, which is a pointer to a pair.
205 // ins.first->first: the key (a pair of name and version).
206 // ins.first->second: the value (Symbol*).
207 // ins.second: true if new entry was inserted, false if not.
208
1564db8d 209 Sized_symbol<size>* ret;
14bfc3f5
ILT
210 if (!ins.second)
211 {
212 // We already have an entry for NAME/VERSION.
274e99f9 213#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
1564db8d 214 ret = this->get_sized_symbol<size>(ins.first->second);
274e99f9
ILT
215#else
216 assert(size == this->get_size());
217 ret = static_cast<Sized_symbol<size>*>(ins.first->second);
218#endif
14bfc3f5
ILT
219 assert(ret != NULL);
220 Symbol_table::resolve(ret, sym, object);
221
222 if (def)
223 {
224 if (insdef.second)
225 {
226 // This is the first time we have seen NAME/NULL. Make
227 // NAME/NULL point to NAME/VERSION.
228 insdef.first->second = ret;
229 }
230 else
231 {
232 // This is the unfortunate case where we already have
233 // entries for both NAME/VERSION and NAME/NULL.
274e99f9
ILT
234 const Sized_symbol<size>* sym2;
235#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
236 sym2 = this->get_sized_symbol<size>(insdef.first->second);
1564db8d 237 Symbol_table::resolve<size, big_endian>(ret, sym2);
274e99f9
ILT
238#else
239 sym2 = static_cast<Sized_symbol<size>*>(insdef.first->second);
240 Symbol_table::resolve(ret, sym2, big_endian);
241#endif
14bfc3f5
ILT
242 this->make_forwarder(insdef.first->second, ret);
243 insdef.first->second = ret;
244 }
245 }
246 }
247 else
248 {
249 // This is the first time we have seen NAME/VERSION.
250 assert(ins.first->second == NULL);
251 if (def && !insdef.second)
252 {
253 // We already have an entry for NAME/NULL. Make
254 // NAME/VERSION point to it.
274e99f9 255#ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
1564db8d 256 ret = this->get_sized_symbol<size>(insdef.first->second);
274e99f9
ILT
257#else
258 ret = static_cast<Sized_symbol<size>*>(insdef.first->second);
259#endif
14bfc3f5
ILT
260 Symbol_table::resolve(ret, sym, object);
261 ins.first->second = ret;
262 }
263 else
264 {
14bfc3f5 265 Sized_target<size, big_endian>* target = object->sized_target();
1564db8d
ILT
266 if (!target->has_make_symbol())
267 ret = new Sized_symbol<size>();
268 else
14bfc3f5 269 {
1564db8d
ILT
270 ret = target->make_symbol();
271 if (ret == NULL)
14bfc3f5
ILT
272 {
273 // This means that we don't want a symbol table
274 // entry after all.
275 if (!def)
276 this->table_.erase(ins.first);
277 else
278 {
279 this->table_.erase(insdef.first);
280 // Inserting insdef invalidated ins.
281 this->table_.erase(std::make_pair(name, version));
282 }
283 return NULL;
284 }
285 }
14bfc3f5 286
1564db8d
ILT
287 ret->init(name, version, object, sym);
288
14bfc3f5
ILT
289 ins.first->second = ret;
290 if (def)
291 {
292 // This is the first time we have seen NAME/NULL. Point
293 // it at the new entry for NAME/VERSION.
294 assert(insdef.second);
295 insdef.first->second = ret;
296 }
297 }
298 }
299
300 return ret;
301}
302
303// Add all the symbols in an object to the hash table.
304
305template<int size, bool big_endian>
306void
307Symbol_table::add_from_object(
308 Sized_object<size, big_endian>* object,
309 const elfcpp::Sym<size, big_endian>* syms,
310 size_t count,
311 const char* sym_names,
312 size_t sym_name_size,
313 Symbol** sympointers)
314{
315 // We take the size from the first object we see.
316 if (this->get_size() == 0)
317 this->set_size(size);
318
319 if (size != this->get_size() || size != object->target()->get_size())
320 {
321 fprintf(stderr, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
322 program_name, object->name().c_str());
323 gold_exit(false);
324 }
325
326 const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
327 for (size_t i = 0; i < count; ++i)
328 {
329 elfcpp::Sym<size, big_endian> sym(p);
330
331 unsigned int st_name = sym.get_st_name();
332 if (st_name >= sym_name_size)
333 {
54dc6425
ILT
334 fprintf(stderr,
335 _("%s: %s: bad global symbol name offset %u at %lu\n"),
14bfc3f5
ILT
336 program_name, object->name().c_str(), st_name,
337 static_cast<unsigned long>(i));
338 gold_exit(false);
339 }
340
341 const char* name = sym_names + st_name;
342
343 // In an object file, an '@' in the name separates the symbol
344 // name from the version name. If there are two '@' characters,
345 // this is the default version.
346 const char* ver = strchr(name, '@');
347
348 Symbol* res;
349 if (ver == NULL)
350 {
351 name = this->namepool_.add(name);
352 res = this->add_from_object(object, name, NULL, false, sym);
353 }
354 else
355 {
356 name = this->namepool_.add(name, ver - name);
357 bool def = false;
358 ++ver;
359 if (*ver == '@')
360 {
361 def = true;
362 ++ver;
363 }
364 ver = this->namepool_.add(ver);
365 res = this->add_from_object(object, name, ver, def, sym);
366 }
367
368 *sympointers++ = res;
369
370 p += elfcpp::Elf_sizes<size>::sym_size;
371 }
372}
373
54dc6425
ILT
374// Record the names of the local symbols for an object.
375
376template<int size, bool big_endian>
377void
378Symbol_table::add_local_symbol_names(Sized_object<size, big_endian>* object,
379 const elfcpp::Sym<size, big_endian>* syms,
380 size_t count, const char* sym_names,
381 size_t sym_name_size)
382{
383 const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
384 for (size_t i = 0; i < count; ++i)
385 {
386 elfcpp::Sym<size, big_endian> sym(p);
387
388 unsigned int st_name = sym.get_st_name();
389 if (st_name >= sym_name_size)
390 {
391 fprintf(stderr,
392 _("%s: %s: bad local symbol name offset %u at %lu\n"),
393 program_name, object->name().c_str(), st_name,
394 static_cast<unsigned long>(i));
395 gold_exit(false);
396 }
397
398 this->output_pool_.add(sym_names + st_name);
399 }
400}
401
14bfc3f5
ILT
402// Instantiate the templates we need. We could use the configure
403// script to restrict this to only the ones needed for implemented
404// targets.
405
406template
407void
408Symbol_table::add_from_object<32, true>(
409 Sized_object<32, true>* object,
410 const elfcpp::Sym<32, true>* syms,
411 size_t count,
412 const char* sym_names,
413 size_t sym_name_size,
414 Symbol** sympointers);
415
416template
417void
418Symbol_table::add_from_object<32, false>(
419 Sized_object<32, false>* object,
420 const elfcpp::Sym<32, false>* syms,
421 size_t count,
422 const char* sym_names,
423 size_t sym_name_size,
424 Symbol** sympointers);
425
426template
427void
428Symbol_table::add_from_object<64, true>(
429 Sized_object<64, true>* object,
430 const elfcpp::Sym<64, true>* syms,
431 size_t count,
432 const char* sym_names,
433 size_t sym_name_size,
434 Symbol** sympointers);
435
436template
437void
438Symbol_table::add_from_object<64, false>(
439 Sized_object<64, false>* object,
440 const elfcpp::Sym<64, false>* syms,
441 size_t count,
442 const char* sym_names,
443 size_t sym_name_size,
444 Symbol** sympointers);
445
54dc6425
ILT
446template
447void
448Symbol_table::add_local_symbol_names<32, true>(
449 Sized_object<32, true>* object,
450 const elfcpp::Sym<32, true>* syms,
451 size_t count,
452 const char* sym_names,
453 size_t sym_name_size);
454
455template
456void
457Symbol_table::add_local_symbol_names<32, false>(
458 Sized_object<32, false>* object,
459 const elfcpp::Sym<32, false>* syms,
460 size_t count,
461 const char* sym_names,
462 size_t sym_name_size);
463
464template
465void
466Symbol_table::add_local_symbol_names<64, true>(
467 Sized_object<64, true>* object,
468 const elfcpp::Sym<64, true>* syms,
469 size_t count,
470 const char* sym_names,
471 size_t sym_name_size);
472
473template
474void
475Symbol_table::add_local_symbol_names<64, false>(
476 Sized_object<64, false>* object,
477 const elfcpp::Sym<64, false>* syms,
478 size_t count,
479 const char* sym_names,
480 size_t sym_name_size);
481
14bfc3f5 482} // End namespace gold.