1 // symtab.cc -- the gold symbol table
18 // Initialize the fields in the base class Symbol.
20 template<int size
, bool big_endian
>
22 Symbol::init_base(const char* name
, const char* version
, Object
* object
,
23 const elfcpp::Sym
<size
, big_endian
>& sym
)
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();
39 // Initialize the fields in Sized_symbol.
42 template<bool big_endian
>
44 Sized_symbol
<size
>::init(const char* name
, const char* version
, Object
* object
,
45 const elfcpp::Sym
<size
, big_endian
>& sym
)
47 this->init_base(name
, version
, object
, sym
);
48 this->value_
= sym
.get_st_value();
49 this->size_
= sym
.get_st_size();
52 // Class Symbol_table.
54 Symbol_table::Symbol_table()
55 : size_(0), table_(), namepool_(), output_pool_(), forwarders_()
59 Symbol_table::~Symbol_table()
63 // The hash function. The key is always canonicalized, so we use a
64 // simple combination of the pointers.
67 Symbol_table::Symbol_table_hash::operator()(const Symbol_table_key
& key
) const
69 return (reinterpret_cast<size_t>(key
.first
)
70 ^ reinterpret_cast<size_t>(key
.second
));
73 // The symbol table key equality function. This is only called with
74 // canonicalized name and version strings, so we can use pointer
78 Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key
& k1
,
79 const Symbol_table_key
& k2
) const
81 return k1
.first
== k2
.first
&& k1
.second
== k2
.second
;
84 // Make TO a symbol which forwards to FROM.
87 Symbol_table::make_forwarder(Symbol
* from
, Symbol
* to
)
89 assert(!from
->is_forwarder() && !to
->is_forwarder());
90 this->forwarders_
[from
] = to
;
91 from
->set_forwarder();
95 Symbol_table::resolve_forwards(Symbol
* from
) const
97 assert(from
->is_forwarder());
98 Unordered_map
<Symbol
*, Symbol
*>::const_iterator p
=
99 this->forwarders_
.find(from
);
100 assert(p
!= this->forwarders_
.end());
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.
110 #ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
112 template<int size
, bool big_endian
>
114 Symbol_table::resolve(Sized_symbol
<size
>* to
, const Sized_symbol
<size
>* from
)
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());
131 Symbol_table::resolve(Sized_symbol
<size
>* to
, const Sized_symbol
<size
>* from
,
134 unsigned char buf
[elfcpp::Elf_sizes
<size
>::sym_size
];
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());
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());
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.
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.
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
184 template<int size
, bool big_endian
>
186 Symbol_table::add_from_object(Sized_object
<size
, big_endian
>* object
,
188 const char *version
, bool def
,
189 const elfcpp::Sym
<size
, big_endian
>& sym
)
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
));
195 std::pair
<typename
Symbol_table_type::iterator
, bool> insdef
=
196 std::make_pair(this->table_
.end(), false);
199 const char* const vnull
= NULL
;
200 insdef
= this->table_
.insert(std::make_pair(std::make_pair(name
, vnull
),
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.
209 Sized_symbol
<size
>* ret
;
212 // We already have an entry for NAME/VERSION.
213 #ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
214 ret
= this->get_sized_symbol
<size
>(ins
.first
->second
);
216 assert(size
== this->get_size());
217 ret
= static_cast<Sized_symbol
<size
>*>(ins
.first
->second
);
220 Symbol_table::resolve(ret
, sym
, object
);
226 // This is the first time we have seen NAME/NULL. Make
227 // NAME/NULL point to NAME/VERSION.
228 insdef
.first
->second
= ret
;
232 // This is the unfortunate case where we already have
233 // entries for both NAME/VERSION and NAME/NULL.
234 const Sized_symbol
<size
>* sym2
;
235 #ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
236 sym2
= this->get_sized_symbol
<size
>(insdef
.first
->second
);
237 Symbol_table::resolve
<size
, big_endian
>(ret
, sym2
);
239 sym2
= static_cast<Sized_symbol
<size
>*>(insdef
.first
->second
);
240 Symbol_table::resolve(ret
, sym2
, big_endian
);
242 this->make_forwarder(insdef
.first
->second
, ret
);
243 insdef
.first
->second
= ret
;
249 // This is the first time we have seen NAME/VERSION.
250 assert(ins
.first
->second
== NULL
);
251 if (def
&& !insdef
.second
)
253 // We already have an entry for NAME/NULL. Make
254 // NAME/VERSION point to it.
255 #ifdef HAVE_MEMBER_TEMPLATE_SPECIFICATIONS
256 ret
= this->get_sized_symbol
<size
>(insdef
.first
->second
);
258 ret
= static_cast<Sized_symbol
<size
>*>(insdef
.first
->second
);
260 Symbol_table::resolve(ret
, sym
, object
);
261 ins
.first
->second
= ret
;
265 Sized_target
<size
, big_endian
>* target
= object
->sized_target();
266 if (!target
->has_make_symbol())
267 ret
= new Sized_symbol
<size
>();
270 ret
= target
->make_symbol();
273 // This means that we don't want a symbol table
276 this->table_
.erase(ins
.first
);
279 this->table_
.erase(insdef
.first
);
280 // Inserting insdef invalidated ins.
281 this->table_
.erase(std::make_pair(name
, version
));
287 ret
->init(name
, version
, object
, sym
);
289 ins
.first
->second
= ret
;
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
;
303 // Add all the symbols in an object to the hash table.
305 template<int size
, bool big_endian
>
307 Symbol_table::add_from_object(
308 Sized_object
<size
, big_endian
>* object
,
309 const elfcpp::Sym
<size
, big_endian
>* syms
,
311 const char* sym_names
,
312 size_t sym_name_size
,
313 Symbol
** sympointers
)
315 // We take the size from the first object we see.
316 if (this->get_size() == 0)
317 this->set_size(size
);
319 if (size
!= this->get_size() || size
!= object
->target()->get_size())
321 fprintf(stderr
, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
322 program_name
, object
->name().c_str());
326 const unsigned char* p
= reinterpret_cast<const unsigned char*>(syms
);
327 for (size_t i
= 0; i
< count
; ++i
)
329 elfcpp::Sym
<size
, big_endian
> sym(p
);
331 unsigned int st_name
= sym
.get_st_name();
332 if (st_name
>= sym_name_size
)
335 _("%s: %s: bad global symbol name offset %u at %lu\n"),
336 program_name
, object
->name().c_str(), st_name
,
337 static_cast<unsigned long>(i
));
341 const char* name
= sym_names
+ st_name
;
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
, '@');
351 name
= this->namepool_
.add(name
);
352 res
= this->add_from_object(object
, name
, NULL
, false, sym
);
356 name
= this->namepool_
.add(name
, ver
- name
);
364 ver
= this->namepool_
.add(ver
);
365 res
= this->add_from_object(object
, name
, ver
, def
, sym
);
368 *sympointers
++ = res
;
370 p
+= elfcpp::Elf_sizes
<size
>::sym_size
;
374 // Record the names of the local symbols for an object.
376 template<int size
, bool big_endian
>
378 Symbol_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
)
383 const unsigned char* p
= reinterpret_cast<const unsigned char*>(syms
);
384 for (size_t i
= 0; i
< count
; ++i
)
386 elfcpp::Sym
<size
, big_endian
> sym(p
);
388 unsigned int st_name
= sym
.get_st_name();
389 if (st_name
>= sym_name_size
)
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
));
398 this->output_pool_
.add(sym_names
+ st_name
);
402 // Instantiate the templates we need. We could use the configure
403 // script to restrict this to only the ones needed for implemented
408 Symbol_table::add_from_object
<32, true>(
409 Sized_object
<32, true>* object
,
410 const elfcpp::Sym
<32, true>* syms
,
412 const char* sym_names
,
413 size_t sym_name_size
,
414 Symbol
** sympointers
);
418 Symbol_table::add_from_object
<32, false>(
419 Sized_object
<32, false>* object
,
420 const elfcpp::Sym
<32, false>* syms
,
422 const char* sym_names
,
423 size_t sym_name_size
,
424 Symbol
** sympointers
);
428 Symbol_table::add_from_object
<64, true>(
429 Sized_object
<64, true>* object
,
430 const elfcpp::Sym
<64, true>* syms
,
432 const char* sym_names
,
433 size_t sym_name_size
,
434 Symbol
** sympointers
);
438 Symbol_table::add_from_object
<64, false>(
439 Sized_object
<64, false>* object
,
440 const elfcpp::Sym
<64, false>* syms
,
442 const char* sym_names
,
443 size_t sym_name_size
,
444 Symbol
** sympointers
);
448 Symbol_table::add_local_symbol_names
<32, true>(
449 Sized_object
<32, true>* object
,
450 const elfcpp::Sym
<32, true>* syms
,
452 const char* sym_names
,
453 size_t sym_name_size
);
457 Symbol_table::add_local_symbol_names
<32, false>(
458 Sized_object
<32, false>* object
,
459 const elfcpp::Sym
<32, false>* syms
,
461 const char* sym_names
,
462 size_t sym_name_size
);
466 Symbol_table::add_local_symbol_names
<64, true>(
467 Sized_object
<64, true>* object
,
468 const elfcpp::Sym
<64, true>* syms
,
470 const char* sym_names
,
471 size_t sym_name_size
);
475 Symbol_table::add_local_symbol_names
<64, false>(
476 Sized_object
<64, false>* object
,
477 const elfcpp::Sym
<64, false>* syms
,
479 const char* sym_names
,
480 size_t sym_name_size
);
482 } // End namespace gold.
This page took 0.039363 seconds and 4 git commands to generate.