1 // symtab.cc -- the gold symbol table
22 // Initialize the fields in the base class Symbol.
24 template<int size
, bool big_endian
>
26 Symbol::init_base(const char* name
, const char* version
, Object
* object
,
27 const elfcpp::Sym
<size
, big_endian
>& sym
)
30 this->version_
= version
;
31 this->object_
= object
;
32 this->shnum_
= sym
.get_st_shndx(); // FIXME: Handle SHN_XINDEX.
33 this->type_
= sym
.get_st_type();
34 this->binding_
= sym
.get_st_bind();
35 this->visibility_
= sym
.get_st_visibility();
36 this->other_
= sym
.get_st_nonvis();
37 this->special_
= false;
39 this->forwarder_
= false;
42 // Initialize the fields in Sized_symbol.
45 template<bool big_endian
>
47 Sized_symbol
<size
>::init(const char* name
, const char* version
, Object
* object
,
48 const elfcpp::Sym
<size
, big_endian
>& sym
)
50 this->init_base(name
, version
, object
, sym
);
51 this->value_
= sym
.get_st_value();
52 this->size_
= sym
.get_st_size();
55 // Class Symbol_table.
57 Symbol_table::Symbol_table()
58 : size_(0), table_(), namepool_(), forwarders_()
62 Symbol_table::~Symbol_table()
66 // The hash function. The key is always canonicalized, so we use a
67 // simple combination of the pointers.
70 Symbol_table::Symbol_table_hash::operator()(const Symbol_table_key
& key
) const
72 return (reinterpret_cast<size_t>(key
.first
)
73 ^ reinterpret_cast<size_t>(key
.second
));
76 // The symbol table key equality function. This is only called with
77 // canonicalized name and version strings, so we can use pointer
81 Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key
& k1
,
82 const Symbol_table_key
& k2
) const
84 return k1
.first
== k2
.first
&& k1
.second
== k2
.second
;
87 // Make TO a symbol which forwards to FROM.
90 Symbol_table::make_forwarder(Symbol
* from
, Symbol
* to
)
92 assert(!from
->is_forwarder() && !to
->is_forwarder());
93 this->forwarders_
[from
] = to
;
94 from
->set_forwarder();
98 Symbol_table::resolve_forwards(Symbol
* from
) const
100 assert(from
->is_forwarder());
101 Unordered_map
<Symbol
*, Symbol
*>::const_iterator p
=
102 this->forwarders_
.find(from
);
103 assert(p
!= this->forwarders_
.end());
107 // Resolve a Symbol with another Symbol. This is only used in the
108 // unusual case where there are references to both an unversioned
109 // symbol and a symbol with a version, and we then discover that that
110 // version is the default version.
113 Symbol_table::resolve(Symbol
*, const Symbol
*)
117 // Add one symbol from OBJECT to the symbol table. NAME is symbol
118 // name and VERSION is the version; both are canonicalized. DEF is
119 // whether this is the default version.
121 // If DEF is true, then this is the definition of a default version of
122 // a symbol. That means that any lookup of NAME/NULL and any lookup
123 // of NAME/VERSION should always return the same symbol. This is
124 // obvious for references, but in particular we want to do this for
125 // definitions: overriding NAME/NULL should also override
126 // NAME/VERSION. If we don't do that, it would be very hard to
127 // override functions in a shared library which uses versioning.
129 // We implement this by simply making both entries in the hash table
130 // point to the same Symbol structure. That is easy enough if this is
131 // the first time we see NAME/NULL or NAME/VERSION, but it is possible
132 // that we have seen both already, in which case they will both have
133 // independent entries in the symbol table. We can't simply change
134 // the symbol table entry, because we have pointers to the entries
135 // attached to the object files. So we mark the entry attached to the
136 // object file as a forwarder, and record it in the forwarders_ map.
137 // Note that entries in the hash table will never be marked as
140 template<int size
, bool big_endian
>
142 Symbol_table::add_from_object(Sized_object
<size
, big_endian
>* object
,
144 const char *version
, bool def
,
145 const elfcpp::Sym
<size
, big_endian
>& sym
)
147 Symbol
* const snull
= NULL
;
148 std::pair
<typename
Symbol_table_type::iterator
, bool> ins
=
149 this->table_
.insert(std::make_pair(std::make_pair(name
, version
), snull
));
151 std::pair
<typename
Symbol_table_type::iterator
, bool> insdef
=
152 std::make_pair(this->table_
.end(), false);
155 const char* const vnull
= NULL
;
156 insdef
= this->table_
.insert(std::make_pair(std::make_pair(name
, vnull
),
160 // ins.first: an iterator, which is a pointer to a pair.
161 // ins.first->first: the key (a pair of name and version).
162 // ins.first->second: the value (Symbol*).
163 // ins.second: true if new entry was inserted, false if not.
168 // We already have an entry for NAME/VERSION.
169 ret
= ins
.first
->second
;
171 Symbol_table::resolve(ret
, sym
, object
);
177 // This is the first time we have seen NAME/NULL. Make
178 // NAME/NULL point to NAME/VERSION.
179 insdef
.first
->second
= ret
;
183 // This is the unfortunate case where we already have
184 // entries for both NAME/VERSION and NAME/NULL.
185 Symbol_table::resolve(ret
, insdef
.first
->second
);
186 this->make_forwarder(insdef
.first
->second
, ret
);
187 insdef
.first
->second
= ret
;
193 // This is the first time we have seen NAME/VERSION.
194 assert(ins
.first
->second
== NULL
);
195 if (def
&& !insdef
.second
)
197 // We already have an entry for NAME/NULL. Make
198 // NAME/VERSION point to it.
199 ret
= insdef
.first
->second
;
200 Symbol_table::resolve(ret
, sym
, object
);
201 ins
.first
->second
= ret
;
205 Sized_symbol
<size
>* rs
;
206 Sized_target
<size
, big_endian
>* target
= object
->sized_target();
207 if (target
->has_make_symbol())
209 rs
= target
->make_symbol();
212 // This means that we don't want a symbol table
215 this->table_
.erase(ins
.first
);
218 this->table_
.erase(insdef
.first
);
219 // Inserting insdef invalidated ins.
220 this->table_
.erase(std::make_pair(name
, version
));
226 rs
= new Sized_symbol
<size
>();
227 rs
->init(name
, version
, object
, sym
);
230 ins
.first
->second
= ret
;
233 // This is the first time we have seen NAME/NULL. Point
234 // it at the new entry for NAME/VERSION.
235 assert(insdef
.second
);
236 insdef
.first
->second
= ret
;
244 // Add all the symbols in an object to the hash table.
246 template<int size
, bool big_endian
>
248 Symbol_table::add_from_object(
249 Sized_object
<size
, big_endian
>* object
,
250 const elfcpp::Sym
<size
, big_endian
>* syms
,
252 const char* sym_names
,
253 size_t sym_name_size
,
254 Symbol
** sympointers
)
256 // We take the size from the first object we see.
257 if (this->get_size() == 0)
258 this->set_size(size
);
260 if (size
!= this->get_size() || size
!= object
->target()->get_size())
262 fprintf(stderr
, _("%s: %s: mixing 32-bit and 64-bit ELF objects\n"),
263 program_name
, object
->name().c_str());
267 const unsigned char* p
= reinterpret_cast<const unsigned char*>(syms
);
268 for (size_t i
= 0; i
< count
; ++i
)
270 elfcpp::Sym
<size
, big_endian
> sym(p
);
272 unsigned int st_name
= sym
.get_st_name();
273 if (st_name
>= sym_name_size
)
275 fprintf(stderr
, _("%s: %s: bad symbol name offset %u at %lu\n"),
276 program_name
, object
->name().c_str(), st_name
,
277 static_cast<unsigned long>(i
));
281 const char* name
= sym_names
+ st_name
;
283 // In an object file, an '@' in the name separates the symbol
284 // name from the version name. If there are two '@' characters,
285 // this is the default version.
286 const char* ver
= strchr(name
, '@');
291 name
= this->namepool_
.add(name
);
292 res
= this->add_from_object(object
, name
, NULL
, false, sym
);
296 name
= this->namepool_
.add(name
, ver
- name
);
304 ver
= this->namepool_
.add(ver
);
305 res
= this->add_from_object(object
, name
, ver
, def
, sym
);
308 *sympointers
++ = res
;
310 p
+= elfcpp::Elf_sizes
<size
>::sym_size
;
314 // Instantiate the templates we need. We could use the configure
315 // script to restrict this to only the ones needed for implemented
320 Symbol_table::add_from_object
<32, true>(
321 Sized_object
<32, true>* object
,
322 const elfcpp::Sym
<32, true>* syms
,
324 const char* sym_names
,
325 size_t sym_name_size
,
326 Symbol
** sympointers
);
330 Symbol_table::add_from_object
<32, false>(
331 Sized_object
<32, false>* object
,
332 const elfcpp::Sym
<32, false>* syms
,
334 const char* sym_names
,
335 size_t sym_name_size
,
336 Symbol
** sympointers
);
340 Symbol_table::add_from_object
<64, true>(
341 Sized_object
<64, true>* object
,
342 const elfcpp::Sym
<64, true>* syms
,
344 const char* sym_names
,
345 size_t sym_name_size
,
346 Symbol
** sympointers
);
350 Symbol_table::add_from_object
<64, false>(
351 Sized_object
<64, false>* object
,
352 const elfcpp::Sym
<64, false>* syms
,
354 const char* sym_names
,
355 size_t sym_name_size
,
356 Symbol
** sympointers
);
358 } // End namespace gold.
This page took 0.036609 seconds and 4 git commands to generate.