Commit | Line | Data |
---|---|---|
bae7f79e ILT |
1 | // symtab.h -- the gold symbol table -*- C++ -*- |
2 | ||
3 | // Symbol_table | |
4 | // The symbol table. | |
5 | ||
bae7f79e ILT |
6 | #include <string> |
7 | #include <utility> | |
54dc6425 | 8 | #include <cassert> |
bae7f79e ILT |
9 | |
10 | #include "elfcpp.h" | |
14bfc3f5 | 11 | #include "stringpool.h" |
bae7f79e ILT |
12 | |
13 | #ifndef GOLD_SYMTAB_H | |
14 | #define GOLD_SYMTAB_H | |
15 | ||
16 | namespace gold | |
17 | { | |
18 | ||
14bfc3f5 | 19 | class Object; |
61ba1cf9 ILT |
20 | class Output_file; |
21 | class Target; | |
14bfc3f5 ILT |
22 | |
23 | template<int size, bool big_endian> | |
24 | class Sized_object; | |
25 | ||
14bfc3f5 ILT |
26 | // The base class of an entry in the symbol table. The symbol table |
27 | // can have a lot of entries, so we don't want this class to big. | |
28 | // Size dependent fields can be found in the template class | |
29 | // Sized_symbol. Targets may support their own derived classes. | |
bae7f79e | 30 | |
bae7f79e ILT |
31 | class Symbol |
32 | { | |
33 | public: | |
14bfc3f5 ILT |
34 | // Return the symbol name. |
35 | const char* | |
36 | name() const | |
37 | { return this->name_; } | |
38 | ||
39 | // Return the symbol version. This will return NULL for an | |
40 | // unversioned symbol. | |
41 | const char* | |
42 | version() const | |
43 | { return this->version_; } | |
44 | ||
14bfc3f5 ILT |
45 | // Return the object with which this symbol is associated. |
46 | Object* | |
47 | object() const | |
48 | { return this->object_; } | |
49 | ||
50 | // Return the symbol binding. | |
51 | elfcpp::STB | |
52 | binding() const | |
53 | { return this->binding_; } | |
54 | ||
1564db8d ILT |
55 | // Return the symbol type. |
56 | elfcpp::STT | |
57 | type() const | |
58 | { return this->type_; } | |
59 | ||
60 | // Return the symbol visibility. | |
61 | elfcpp::STV | |
62 | visibility() const | |
63 | { return this->visibility_; } | |
64 | ||
65 | // Return the non-visibility part of the st_other field. | |
66 | unsigned char | |
67 | other() const | |
68 | { return this->other_; } | |
69 | ||
14bfc3f5 ILT |
70 | // Return the section index. |
71 | unsigned int | |
72 | shnum() const | |
73 | { return this->shnum_; } | |
74 | ||
1564db8d ILT |
75 | // Return whether this symbol is a forwarder. This will never be |
76 | // true of a symbol found in the hash table, but may be true of | |
77 | // symbol pointers attached to object files. | |
78 | bool | |
79 | is_forwarder() const | |
80 | { return this->is_forwarder_; } | |
81 | ||
82 | // Mark this symbol as a forwarder. | |
83 | void | |
84 | set_forwarder() | |
85 | { this->is_forwarder_ = true; } | |
86 | ||
87 | // Return whether this symbol was seen in a dynamic object. | |
88 | bool | |
89 | in_dyn() const | |
90 | { return this->in_dyn_; } | |
91 | ||
92 | // Mark this symbol as seen in a dynamic object. | |
93 | void | |
94 | set_in_dyn() | |
95 | { this->in_dyn_ = true; } | |
96 | ||
92e059d8 ILT |
97 | // Return whether this symbol needs an entry in the dynamic symbol |
98 | // table. FIXME: Needs to be fleshed out. | |
99 | bool | |
100 | in_dynsym() const | |
101 | { return this->in_dyn_; } | |
102 | ||
14bfc3f5 ILT |
103 | protected: |
104 | // Instances of this class should always be created at a specific | |
105 | // size. | |
106 | Symbol() | |
107 | { } | |
108 | ||
109 | // Initialize fields from an ELF symbol in OBJECT. | |
110 | template<int size, bool big_endian> | |
111 | void | |
112 | init_base(const char *name, const char* version, Object* object, | |
113 | const elfcpp::Sym<size, big_endian>&); | |
bae7f79e | 114 | |
1564db8d ILT |
115 | // Override existing symbol. |
116 | template<int size, bool big_endian> | |
117 | void | |
118 | override_base(const elfcpp::Sym<size, big_endian>&, Object* object); | |
119 | ||
bae7f79e | 120 | private: |
14bfc3f5 ILT |
121 | Symbol(const Symbol&); |
122 | Symbol& operator=(const Symbol&); | |
123 | ||
124 | // Symbol name (expected to point into a Stringpool). | |
125 | const char* name_; | |
126 | // Symbol version (expected to point into a Stringpool). This may | |
127 | // be NULL. | |
bae7f79e | 128 | const char* version_; |
14bfc3f5 | 129 | // Object in which symbol is defined, or in which it was first seen. |
bae7f79e | 130 | Object* object_; |
14bfc3f5 | 131 | // Section number in object_ in which symbol is defined. |
bae7f79e | 132 | unsigned int shnum_; |
14bfc3f5 | 133 | // Symbol type. |
bae7f79e | 134 | elfcpp::STT type_ : 4; |
14bfc3f5 | 135 | // Symbol binding. |
bae7f79e | 136 | elfcpp::STB binding_ : 4; |
14bfc3f5 ILT |
137 | // Symbol visibility. |
138 | elfcpp::STV visibility_ : 2; | |
139 | // Rest of symbol st_other field. | |
bae7f79e | 140 | unsigned int other_ : 6; |
14bfc3f5 ILT |
141 | // True if this symbol always requires special target-specific |
142 | // handling. | |
1564db8d | 143 | bool is_special_ : 1; |
14bfc3f5 | 144 | // True if this is the default version of the symbol. |
1564db8d | 145 | bool is_def_ : 1; |
14bfc3f5 ILT |
146 | // True if this symbol really forwards to another symbol. This is |
147 | // used when we discover after the fact that two different entries | |
148 | // in the hash table really refer to the same symbol. This will | |
149 | // never be set for a symbol found in the hash table, but may be set | |
150 | // for a symbol found in the list of symbols attached to an Object. | |
151 | // It forwards to the symbol found in the forwarders_ map of | |
152 | // Symbol_table. | |
1564db8d ILT |
153 | bool is_forwarder_ : 1; |
154 | // True if we've seen this symbol in a dynamic object. | |
155 | bool in_dyn_ : 1; | |
bae7f79e ILT |
156 | }; |
157 | ||
14bfc3f5 ILT |
158 | // The parts of a symbol which are size specific. Using a template |
159 | // derived class like this helps us use less space on a 32-bit system. | |
bae7f79e ILT |
160 | |
161 | template<int size> | |
14bfc3f5 ILT |
162 | class Sized_symbol : public Symbol |
163 | { | |
164 | public: | |
1564db8d ILT |
165 | typedef typename elfcpp::Elf_types<size>::Elf_Addr Value_type; |
166 | typedef typename elfcpp::Elf_types<size>::Elf_WXword Size_type; | |
167 | ||
14bfc3f5 ILT |
168 | Sized_symbol() |
169 | { } | |
170 | ||
171 | // Initialize fields from an ELF symbol in OBJECT. | |
172 | template<bool big_endian> | |
173 | void | |
174 | init(const char *name, const char* version, Object* object, | |
175 | const elfcpp::Sym<size, big_endian>&); | |
176 | ||
1564db8d ILT |
177 | // Override existing symbol. |
178 | template<bool big_endian> | |
179 | void | |
180 | override(const elfcpp::Sym<size, big_endian>&, Object* object); | |
181 | ||
182 | // Return the symbol's value. | |
183 | Value_type | |
184 | value() const | |
185 | { return this->value_; } | |
186 | ||
187 | // Return the symbol's size (we can't call this 'size' because that | |
188 | // is a template parameter). | |
189 | Size_type | |
190 | symsize() const | |
191 | { return this->size_; } | |
192 | ||
75f65a3e ILT |
193 | // Set the symbol value. This is called when we store the final |
194 | // values of the symbols into the symbol table. | |
195 | void | |
196 | set_value(Value_type value) | |
197 | { this->value_ = value; } | |
198 | ||
14bfc3f5 ILT |
199 | private: |
200 | Sized_symbol(const Sized_symbol&); | |
201 | Sized_symbol& operator=(const Sized_symbol&); | |
202 | ||
203 | // Symbol value. | |
1564db8d | 204 | Value_type value_; |
14bfc3f5 | 205 | // Symbol size. |
1564db8d | 206 | Size_type size_; |
14bfc3f5 ILT |
207 | }; |
208 | ||
209 | // The main linker symbol table. | |
210 | ||
bae7f79e ILT |
211 | class Symbol_table |
212 | { | |
213 | public: | |
214 | Symbol_table(); | |
215 | ||
1564db8d | 216 | ~Symbol_table(); |
bae7f79e | 217 | |
14bfc3f5 ILT |
218 | // Add COUNT external symbols from OBJECT to the symbol table. SYMS |
219 | // is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the | |
220 | // size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols | |
221 | // in the symbol table. | |
222 | template<int size, bool big_endian> | |
223 | void | |
224 | add_from_object(Sized_object<size, big_endian>* object, | |
225 | const elfcpp::Sym<size, big_endian>* syms, | |
226 | size_t count, const char* sym_names, size_t sym_name_size, | |
227 | Symbol** sympointers); | |
228 | ||
61ba1cf9 ILT |
229 | // Look up a symbol. |
230 | Symbol* | |
231 | lookup(const char*, const char* version = NULL) const; | |
232 | ||
14bfc3f5 | 233 | // Return the real symbol associated with the forwarder symbol FROM. |
bae7f79e | 234 | Symbol* |
14bfc3f5 | 235 | resolve_forwards(Symbol* from) const; |
bae7f79e | 236 | |
14bfc3f5 ILT |
237 | // Return the size of the symbols in the table. |
238 | int | |
239 | get_size() const | |
240 | { return this->size_; } | |
bae7f79e | 241 | |
1564db8d ILT |
242 | // Return the sized version of a symbol in this table. |
243 | template<int size> | |
244 | Sized_symbol<size>* | |
5482377d | 245 | get_sized_symbol(Symbol* ACCEPT_SIZE) const; |
1564db8d ILT |
246 | |
247 | template<int size> | |
248 | const Sized_symbol<size>* | |
5482377d | 249 | get_sized_symbol(const Symbol* ACCEPT_SIZE) const; |
54dc6425 | 250 | |
75f65a3e ILT |
251 | // Finalize the symbol table after we have set the final addresses |
252 | // of all the input sections. This sets the final symbol values and | |
253 | // adds the names to *POOL. It records the file offset OFF, and | |
254 | // returns the new file offset. | |
255 | off_t | |
256 | finalize(off_t, Stringpool*); | |
1564db8d | 257 | |
61ba1cf9 ILT |
258 | // Write out the global symbols. |
259 | void | |
260 | write_globals(const Target*, const Stringpool*, Output_file*) const; | |
261 | ||
bae7f79e ILT |
262 | private: |
263 | Symbol_table(const Symbol_table&); | |
264 | Symbol_table& operator=(const Symbol_table&); | |
265 | ||
14bfc3f5 ILT |
266 | // Set the size of the symbols in the table. |
267 | void | |
268 | set_size(int size) | |
269 | { this->size_ = size; } | |
270 | ||
271 | // Make FROM a forwarder symbol to TO. | |
272 | void | |
273 | make_forwarder(Symbol* from, Symbol* to); | |
274 | ||
275 | // Add a symbol. | |
276 | template<int size, bool big_endian> | |
277 | Symbol* | |
278 | add_from_object(Sized_object<size, big_endian>*, const char *name, | |
279 | const char *version, bool def, | |
280 | const elfcpp::Sym<size, big_endian>& sym); | |
281 | ||
282 | // Resolve symbols. | |
283 | template<int size, bool big_endian> | |
284 | static void | |
1564db8d ILT |
285 | resolve(Sized_symbol<size>* to, |
286 | const elfcpp::Sym<size, big_endian>& sym, | |
287 | Object*); | |
14bfc3f5 | 288 | |
1564db8d | 289 | template<int size, bool big_endian> |
14bfc3f5 | 290 | static void |
5482377d ILT |
291 | resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from |
292 | ACCEPT_SIZE_ENDIAN); | |
14bfc3f5 | 293 | |
75f65a3e ILT |
294 | // Finalize symbols specialized for size. |
295 | template<int size> | |
296 | off_t | |
297 | sized_finalize(off_t, Stringpool*); | |
298 | ||
61ba1cf9 ILT |
299 | // Write globals specialized for size and endianness. |
300 | template<int size, bool big_endian> | |
301 | void | |
302 | sized_write_globals(const Target*, const Stringpool*, Output_file*) const; | |
303 | ||
54dc6425 ILT |
304 | // The type of the symbol hash table. |
305 | ||
14bfc3f5 ILT |
306 | typedef std::pair<const char*, const char*> Symbol_table_key; |
307 | ||
308 | struct Symbol_table_hash | |
309 | { | |
310 | size_t | |
311 | operator()(const Symbol_table_key&) const; | |
312 | }; | |
313 | ||
314 | struct Symbol_table_eq | |
315 | { | |
316 | bool | |
317 | operator()(const Symbol_table_key&, const Symbol_table_key&) const; | |
318 | }; | |
319 | ||
320 | typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, | |
321 | Symbol_table_eq> Symbol_table_type; | |
322 | ||
323 | // The size of the symbols in the symbol table (32 or 64). | |
324 | int size_; | |
325 | ||
75f65a3e ILT |
326 | // The file offset within the output symtab section where we should |
327 | // write the table. | |
328 | off_t offset_; | |
329 | ||
61ba1cf9 ILT |
330 | // The number of global symbols we want to write out. |
331 | size_t output_count_; | |
332 | ||
54dc6425 | 333 | // The symbol hash table. |
14bfc3f5 ILT |
334 | Symbol_table_type table_; |
335 | ||
54dc6425 ILT |
336 | // A pool of symbol names. This is used for all global symbols. |
337 | // Entries in the hash table point into this pool. | |
14bfc3f5 | 338 | Stringpool namepool_; |
bae7f79e | 339 | |
14bfc3f5 ILT |
340 | // Forwarding symbols. |
341 | Unordered_map<Symbol*, Symbol*> forwarders_; | |
bae7f79e ILT |
342 | }; |
343 | ||
1564db8d ILT |
344 | // We inline get_sized_symbol for efficiency. |
345 | ||
346 | template<int size> | |
347 | Sized_symbol<size>* | |
5482377d | 348 | Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const |
1564db8d ILT |
349 | { |
350 | assert(size == this->get_size()); | |
351 | return static_cast<Sized_symbol<size>*>(sym); | |
352 | } | |
353 | ||
354 | template<int size> | |
355 | const Sized_symbol<size>* | |
5482377d | 356 | Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const |
1564db8d ILT |
357 | { |
358 | assert(size == this->get_size()); | |
359 | return static_cast<const Sized_symbol<size>*>(sym); | |
360 | } | |
361 | ||
bae7f79e ILT |
362 | } // End namespace gold. |
363 | ||
364 | #endif // !defined(GOLD_SYMTAB_H) |