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> | |
ead1e424 | 8 | #include <vector> |
54dc6425 | 9 | #include <cassert> |
bae7f79e ILT |
10 | |
11 | #include "elfcpp.h" | |
14bfc3f5 | 12 | #include "stringpool.h" |
bae7f79e ILT |
13 | |
14 | #ifndef GOLD_SYMTAB_H | |
15 | #define GOLD_SYMTAB_H | |
16 | ||
17 | namespace gold | |
18 | { | |
19 | ||
14bfc3f5 | 20 | class Object; |
ead1e424 ILT |
21 | class Output_data; |
22 | class Output_segment; | |
61ba1cf9 ILT |
23 | class Output_file; |
24 | class Target; | |
14bfc3f5 ILT |
25 | |
26 | template<int size, bool big_endian> | |
27 | class Sized_object; | |
28 | ||
14bfc3f5 ILT |
29 | // The base class of an entry in the symbol table. The symbol table |
30 | // can have a lot of entries, so we don't want this class to big. | |
31 | // Size dependent fields can be found in the template class | |
32 | // Sized_symbol. Targets may support their own derived classes. | |
bae7f79e | 33 | |
bae7f79e ILT |
34 | class Symbol |
35 | { | |
36 | public: | |
ead1e424 ILT |
37 | // Because we want the class to be small, we don't use any virtual |
38 | // functions. But because symbols can be defined in different | |
39 | // places, we need to classify them. This enum is the different | |
40 | // sources of symbols we support. | |
41 | enum Source | |
42 | { | |
43 | // Symbol defined in an input file--this is the most common case. | |
44 | FROM_OBJECT, | |
45 | // Symbol defined in an Output_data, a special section created by | |
46 | // the target. | |
47 | IN_OUTPUT_DATA, | |
48 | // Symbol defined in an Output_segment, with no associated | |
49 | // section. | |
50 | IN_OUTPUT_SEGMENT, | |
51 | // Symbol value is constant. | |
52 | CONSTANT | |
53 | }; | |
54 | ||
55 | // When the source is IN_OUTPUT_SEGMENT, we need to describe what | |
56 | // the offset means. | |
57 | enum Segment_offset_base | |
58 | { | |
59 | // From the start of the segment. | |
60 | SEGMENT_START, | |
61 | // From the end of the segment. | |
62 | SEGMENT_END, | |
63 | // From the filesz of the segment--i.e., after the loaded bytes | |
64 | // but before the bytes which are allocated but zeroed. | |
65 | SEGMENT_BSS | |
66 | }; | |
67 | ||
14bfc3f5 ILT |
68 | // Return the symbol name. |
69 | const char* | |
70 | name() const | |
71 | { return this->name_; } | |
72 | ||
73 | // Return the symbol version. This will return NULL for an | |
74 | // unversioned symbol. | |
75 | const char* | |
76 | version() const | |
77 | { return this->version_; } | |
78 | ||
ead1e424 ILT |
79 | // Return the symbol source. |
80 | Source | |
81 | source() const | |
82 | { return this->source_; } | |
83 | ||
14bfc3f5 ILT |
84 | // Return the object with which this symbol is associated. |
85 | Object* | |
86 | object() const | |
ead1e424 ILT |
87 | { |
88 | assert(this->source_ == FROM_OBJECT); | |
89 | return this->u_.from_object.object; | |
90 | } | |
91 | ||
92 | // Return the index of the section in the input object file. | |
93 | unsigned int | |
94 | shnum() const | |
95 | { | |
96 | assert(this->source_ == FROM_OBJECT); | |
97 | return this->u_.from_object.shnum; | |
98 | } | |
99 | ||
100 | // Return the output data section with which this symbol is | |
101 | // associated, if the symbol was specially defined with respect to | |
102 | // an output data section. | |
103 | Output_data* | |
104 | output_data() const | |
105 | { | |
106 | assert(this->source_ == IN_OUTPUT_DATA); | |
107 | return this->u_.in_output_data.output_data; | |
108 | } | |
109 | ||
110 | // If this symbol was defined with respect to an output data | |
111 | // section, return whether the value is an offset from end. | |
112 | bool | |
113 | offset_is_from_end() const | |
114 | { | |
115 | assert(this->source_ == IN_OUTPUT_DATA); | |
116 | return this->u_.in_output_data.offset_is_from_end; | |
117 | } | |
118 | ||
119 | // Return the output segment with which this symbol is associated, | |
120 | // if the symbol was specially defined with respect to an output | |
121 | // segment. | |
122 | Output_segment* | |
123 | output_segment() const | |
124 | { | |
125 | assert(this->source_ == IN_OUTPUT_SEGMENT); | |
126 | return this->u_.in_output_segment.output_segment; | |
127 | } | |
128 | ||
129 | // If this symbol was defined with respect to an output segment, | |
130 | // return the offset base. | |
131 | Segment_offset_base | |
132 | offset_base() const | |
133 | { | |
134 | assert(this->source_ == IN_OUTPUT_SEGMENT); | |
135 | return this->u_.in_output_segment.offset_base; | |
136 | } | |
14bfc3f5 ILT |
137 | |
138 | // Return the symbol binding. | |
139 | elfcpp::STB | |
140 | binding() const | |
141 | { return this->binding_; } | |
142 | ||
1564db8d ILT |
143 | // Return the symbol type. |
144 | elfcpp::STT | |
145 | type() const | |
146 | { return this->type_; } | |
147 | ||
148 | // Return the symbol visibility. | |
149 | elfcpp::STV | |
150 | visibility() const | |
151 | { return this->visibility_; } | |
152 | ||
153 | // Return the non-visibility part of the st_other field. | |
154 | unsigned char | |
ead1e424 ILT |
155 | nonvis() const |
156 | { return this->nonvis_; } | |
14bfc3f5 | 157 | |
1564db8d ILT |
158 | // Return whether this symbol is a forwarder. This will never be |
159 | // true of a symbol found in the hash table, but may be true of | |
160 | // symbol pointers attached to object files. | |
161 | bool | |
162 | is_forwarder() const | |
163 | { return this->is_forwarder_; } | |
164 | ||
165 | // Mark this symbol as a forwarder. | |
166 | void | |
167 | set_forwarder() | |
168 | { this->is_forwarder_ = true; } | |
169 | ||
170 | // Return whether this symbol was seen in a dynamic object. | |
171 | bool | |
172 | in_dyn() const | |
173 | { return this->in_dyn_; } | |
174 | ||
175 | // Mark this symbol as seen in a dynamic object. | |
176 | void | |
177 | set_in_dyn() | |
178 | { this->in_dyn_ = true; } | |
179 | ||
ead1e424 | 180 | // Return whether this symbol has an entry in the GOT section. |
92e059d8 | 181 | bool |
ead1e424 ILT |
182 | has_got_offset() const |
183 | { return this->has_got_offset_; } | |
184 | ||
185 | // Return the offset into the GOT section of this symbol. | |
186 | unsigned int | |
187 | got_offset() const | |
188 | { | |
189 | assert(this->has_got_offset()); | |
190 | return this->got_offset_; | |
191 | } | |
192 | ||
193 | // Set the GOT offset of this symbol. | |
194 | void | |
195 | set_got_offset(unsigned int got_offset) | |
196 | { | |
197 | this->has_got_offset_ = true; | |
198 | this->got_offset_ = got_offset; | |
199 | } | |
200 | ||
201 | // Return whether this symbol is resolved locally. This is always | |
202 | // true when linking statically. It is true for a symbol defined in | |
203 | // this object when using -Bsymbolic. It is true for a symbol | |
204 | // marked local in a version file. FIXME: This needs to be | |
205 | // completed. | |
206 | bool | |
207 | is_resolved_locally() const | |
208 | { return !this->in_dyn_; } | |
209 | ||
210 | // Return whether this is an undefined symbol. | |
211 | bool | |
212 | is_undefined() const | |
213 | { | |
214 | return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_UNDEF; | |
215 | } | |
216 | ||
217 | // Return whether this is a common symbol. | |
218 | bool | |
219 | is_common() const | |
220 | { | |
221 | return this->source_ == FROM_OBJECT && this->shnum() == elfcpp::SHN_COMMON; | |
222 | } | |
92e059d8 | 223 | |
14bfc3f5 ILT |
224 | protected: |
225 | // Instances of this class should always be created at a specific | |
226 | // size. | |
227 | Symbol() | |
228 | { } | |
229 | ||
ead1e424 ILT |
230 | // Initialize the general fields. |
231 | void | |
232 | init_fields(const char* name, const char* version, | |
233 | elfcpp::STT type, elfcpp::STB binding, | |
234 | elfcpp::STV visibility, unsigned char nonvis); | |
235 | ||
14bfc3f5 ILT |
236 | // Initialize fields from an ELF symbol in OBJECT. |
237 | template<int size, bool big_endian> | |
238 | void | |
239 | init_base(const char *name, const char* version, Object* object, | |
240 | const elfcpp::Sym<size, big_endian>&); | |
bae7f79e | 241 | |
ead1e424 ILT |
242 | // Initialize fields for an Output_data. |
243 | void | |
244 | init_base(const char* name, Output_data*, elfcpp::STT, elfcpp::STB, | |
245 | elfcpp::STV, unsigned char nonvis, bool offset_is_from_end); | |
246 | ||
247 | // Initialize fields for an Output_segment. | |
248 | void | |
249 | init_base(const char* name, Output_segment* os, elfcpp::STT type, | |
250 | elfcpp::STB binding, elfcpp::STV visibility, | |
251 | unsigned char nonvis, Segment_offset_base offset_base); | |
252 | ||
253 | // Initialize fields for a constant. | |
254 | void | |
255 | init_base(const char* name, elfcpp::STT type, elfcpp::STB binding, | |
256 | elfcpp::STV visibility, unsigned char nonvis); | |
257 | ||
1564db8d ILT |
258 | // Override existing symbol. |
259 | template<int size, bool big_endian> | |
260 | void | |
261 | override_base(const elfcpp::Sym<size, big_endian>&, Object* object); | |
262 | ||
bae7f79e | 263 | private: |
14bfc3f5 ILT |
264 | Symbol(const Symbol&); |
265 | Symbol& operator=(const Symbol&); | |
266 | ||
267 | // Symbol name (expected to point into a Stringpool). | |
268 | const char* name_; | |
269 | // Symbol version (expected to point into a Stringpool). This may | |
270 | // be NULL. | |
bae7f79e | 271 | const char* version_; |
ead1e424 ILT |
272 | |
273 | union | |
274 | { | |
275 | // This struct is used if SOURCE_ == FROM_OBJECT. | |
276 | struct | |
277 | { | |
278 | // Object in which symbol is defined, or in which it was first | |
279 | // seen. | |
280 | Object* object; | |
281 | // Section number in object_ in which symbol is defined. | |
282 | unsigned int shnum; | |
283 | } from_object; | |
284 | ||
285 | // This struct is used if SOURCE_ == IN_OUTPUT_DATA. | |
286 | struct | |
287 | { | |
288 | // Output_data in which symbol is defined. Before | |
289 | // Layout::finalize the symbol's value is an offset within the | |
290 | // Output_data. | |
291 | Output_data* output_data; | |
292 | // True if the offset is from the end, false if the offset is | |
293 | // from the beginning. | |
294 | bool offset_is_from_end; | |
295 | } in_output_data; | |
296 | ||
297 | // This struct is used if SOURCE_ == IN_OUTPUT_SEGMENT. | |
298 | struct | |
299 | { | |
300 | // Output_segment in which the symbol is defined. Before | |
301 | // Layout::finalize the symbol's value is an offset. | |
302 | Output_segment* output_segment; | |
303 | // The base to use for the offset before Layout::finalize. | |
304 | Segment_offset_base offset_base; | |
305 | } in_output_segment; | |
306 | } u_; | |
307 | ||
308 | // If this symbol has an entry in the GOT section (has_got_offset_ | |
309 | // is true), this is the offset. | |
310 | unsigned int got_offset_; | |
14bfc3f5 | 311 | // Symbol type. |
bae7f79e | 312 | elfcpp::STT type_ : 4; |
14bfc3f5 | 313 | // Symbol binding. |
bae7f79e | 314 | elfcpp::STB binding_ : 4; |
14bfc3f5 ILT |
315 | // Symbol visibility. |
316 | elfcpp::STV visibility_ : 2; | |
317 | // Rest of symbol st_other field. | |
ead1e424 ILT |
318 | unsigned int nonvis_ : 6; |
319 | // The type of symbol. | |
320 | Source source_ : 2; | |
14bfc3f5 ILT |
321 | // True if this symbol always requires special target-specific |
322 | // handling. | |
ead1e424 | 323 | bool is_target_special_ : 1; |
14bfc3f5 | 324 | // True if this is the default version of the symbol. |
1564db8d | 325 | bool is_def_ : 1; |
14bfc3f5 ILT |
326 | // True if this symbol really forwards to another symbol. This is |
327 | // used when we discover after the fact that two different entries | |
328 | // in the hash table really refer to the same symbol. This will | |
329 | // never be set for a symbol found in the hash table, but may be set | |
330 | // for a symbol found in the list of symbols attached to an Object. | |
331 | // It forwards to the symbol found in the forwarders_ map of | |
332 | // Symbol_table. | |
1564db8d ILT |
333 | bool is_forwarder_ : 1; |
334 | // True if we've seen this symbol in a dynamic object. | |
335 | bool in_dyn_ : 1; | |
ead1e424 ILT |
336 | // True if the symbol has an entry in the GOT section. |
337 | bool has_got_offset_ : 1; | |
bae7f79e ILT |
338 | }; |
339 | ||
14bfc3f5 ILT |
340 | // The parts of a symbol which are size specific. Using a template |
341 | // derived class like this helps us use less space on a 32-bit system. | |
bae7f79e ILT |
342 | |
343 | template<int size> | |
14bfc3f5 ILT |
344 | class Sized_symbol : public Symbol |
345 | { | |
346 | public: | |
1564db8d ILT |
347 | typedef typename elfcpp::Elf_types<size>::Elf_Addr Value_type; |
348 | typedef typename elfcpp::Elf_types<size>::Elf_WXword Size_type; | |
349 | ||
14bfc3f5 ILT |
350 | Sized_symbol() |
351 | { } | |
352 | ||
353 | // Initialize fields from an ELF symbol in OBJECT. | |
354 | template<bool big_endian> | |
355 | void | |
356 | init(const char *name, const char* version, Object* object, | |
357 | const elfcpp::Sym<size, big_endian>&); | |
358 | ||
ead1e424 ILT |
359 | // Initialize fields for an Output_data. |
360 | void | |
361 | init(const char* name, Output_data*, Value_type value, Size_type symsize, | |
362 | elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis, | |
363 | bool offset_is_from_end); | |
364 | ||
365 | // Initialize fields for an Output_segment. | |
366 | void | |
367 | init(const char* name, Output_segment*, Value_type value, Size_type symsize, | |
368 | elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis, | |
369 | Segment_offset_base offset_base); | |
370 | ||
371 | // Initialize fields for a constant. | |
372 | void | |
373 | init(const char* name, Value_type value, Size_type symsize, | |
374 | elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis); | |
375 | ||
1564db8d ILT |
376 | // Override existing symbol. |
377 | template<bool big_endian> | |
378 | void | |
379 | override(const elfcpp::Sym<size, big_endian>&, Object* object); | |
380 | ||
381 | // Return the symbol's value. | |
382 | Value_type | |
383 | value() const | |
384 | { return this->value_; } | |
385 | ||
386 | // Return the symbol's size (we can't call this 'size' because that | |
387 | // is a template parameter). | |
388 | Size_type | |
389 | symsize() const | |
ead1e424 ILT |
390 | { return this->symsize_; } |
391 | ||
392 | // Set the symbol size. This is used when resolving common symbols. | |
393 | void | |
394 | set_symsize(Size_type symsize) | |
395 | { this->symsize_ = symsize; } | |
1564db8d | 396 | |
75f65a3e ILT |
397 | // Set the symbol value. This is called when we store the final |
398 | // values of the symbols into the symbol table. | |
399 | void | |
400 | set_value(Value_type value) | |
401 | { this->value_ = value; } | |
402 | ||
14bfc3f5 ILT |
403 | private: |
404 | Sized_symbol(const Sized_symbol&); | |
405 | Sized_symbol& operator=(const Sized_symbol&); | |
406 | ||
ead1e424 ILT |
407 | // Symbol value. Before Layout::finalize this is the offset in the |
408 | // input section. This is set to the final value during | |
409 | // Layout::finalize. | |
1564db8d | 410 | Value_type value_; |
14bfc3f5 | 411 | // Symbol size. |
ead1e424 ILT |
412 | Size_type symsize_; |
413 | }; | |
414 | ||
415 | // A struct describing a symbol defined by the linker, where the value | |
416 | // of the symbol is defined based on an output section. This is used | |
417 | // for symbols defined by the linker, like "_init_array_start". | |
418 | ||
419 | struct Define_symbol_in_section | |
420 | { | |
421 | // The symbol name. | |
422 | const char* name; | |
423 | // The name of the output section with which this symbol should be | |
424 | // associated. If there is no output section with that name, the | |
425 | // symbol will be defined as zero. | |
426 | const char* output_section; | |
427 | // The offset of the symbol within the output section. This is an | |
428 | // offset from the start of the output section, unless start_at_end | |
429 | // is true, in which case this is an offset from the end of the | |
430 | // output section. | |
431 | uint64_t value; | |
432 | // The size of the symbol. | |
433 | uint64_t size; | |
434 | // The symbol type. | |
435 | elfcpp::STT type; | |
436 | // The symbol binding. | |
437 | elfcpp::STB binding; | |
438 | // The symbol visibility. | |
439 | elfcpp::STV visibility; | |
440 | // The rest of the st_other field. | |
441 | unsigned char nonvis; | |
442 | // If true, the value field is an offset from the end of the output | |
443 | // section. | |
444 | bool offset_is_from_end; | |
445 | // If true, this symbol is defined only if we see a reference to it. | |
446 | bool only_if_ref; | |
447 | }; | |
448 | ||
449 | // A struct describing a symbol defined by the linker, where the value | |
450 | // of the symbol is defined based on a segment. This is used for | |
451 | // symbols defined by the linker, like "_end". We describe the | |
452 | // segment with which the symbol should be associated by its | |
453 | // characteristics. If no segment meets these characteristics, the | |
454 | // symbol will be defined as zero. If there is more than one segment | |
455 | // which meets these characteristics, we will use the first one. | |
456 | ||
457 | struct Define_symbol_in_segment | |
458 | { | |
459 | // The symbol name. | |
460 | const char* name; | |
461 | // The segment type where the symbol should be defined, typically | |
462 | // PT_LOAD. | |
463 | elfcpp::PT segment_type; | |
464 | // Bitmask of segment flags which must be set. | |
465 | elfcpp::PF segment_flags_set; | |
466 | // Bitmask of segment flags which must be clear. | |
467 | elfcpp::PF segment_flags_clear; | |
468 | // The offset of the symbol within the segment. The offset is | |
469 | // calculated from the position set by offset_base. | |
470 | uint64_t value; | |
471 | // The size of the symbol. | |
472 | uint64_t size; | |
473 | // The symbol type. | |
474 | elfcpp::STT type; | |
475 | // The symbol binding. | |
476 | elfcpp::STB binding; | |
477 | // The symbol visibility. | |
478 | elfcpp::STV visibility; | |
479 | // The rest of the st_other field. | |
480 | unsigned char nonvis; | |
481 | // The base from which we compute the offset. | |
482 | Symbol::Segment_offset_base offset_base; | |
483 | // If true, this symbol is defined only if we see a reference to it. | |
484 | bool only_if_ref; | |
14bfc3f5 ILT |
485 | }; |
486 | ||
487 | // The main linker symbol table. | |
488 | ||
bae7f79e ILT |
489 | class Symbol_table |
490 | { | |
491 | public: | |
492 | Symbol_table(); | |
493 | ||
1564db8d | 494 | ~Symbol_table(); |
bae7f79e | 495 | |
14bfc3f5 ILT |
496 | // Add COUNT external symbols from OBJECT to the symbol table. SYMS |
497 | // is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the | |
498 | // size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols | |
499 | // in the symbol table. | |
500 | template<int size, bool big_endian> | |
501 | void | |
502 | add_from_object(Sized_object<size, big_endian>* object, | |
503 | const elfcpp::Sym<size, big_endian>* syms, | |
504 | size_t count, const char* sym_names, size_t sym_name_size, | |
505 | Symbol** sympointers); | |
506 | ||
ead1e424 ILT |
507 | // Define a special symbol. |
508 | template<int size, bool big_endian> | |
509 | Sized_symbol<size>* | |
593f47df ILT |
510 | define_special_symbol(Target* target, const char* name, bool only_if_ref |
511 | ACCEPT_SIZE_ENDIAN); | |
ead1e424 ILT |
512 | |
513 | // Define a special symbol based on an Output_data. It is a | |
514 | // multiple definition error if this symbol is already defined. | |
515 | void | |
516 | define_in_output_data(Target*, const char* name, Output_data*, | |
517 | uint64_t value, uint64_t symsize, | |
518 | elfcpp::STT type, elfcpp::STB binding, | |
519 | elfcpp::STV visibility, unsigned char nonvis, | |
520 | bool offset_is_from_end, bool only_if_ref); | |
521 | ||
522 | // Define a special symbol based on an Output_segment. It is a | |
523 | // multiple definition error if this symbol is already defined. | |
524 | void | |
525 | define_in_output_segment(Target*, const char* name, Output_segment*, | |
526 | uint64_t value, uint64_t symsize, | |
527 | elfcpp::STT type, elfcpp::STB binding, | |
528 | elfcpp::STV visibility, unsigned char nonvis, | |
529 | Symbol::Segment_offset_base, bool only_if_ref); | |
530 | ||
531 | // Define a special symbol with a constant value. It is a multiple | |
532 | // definition error if this symbol is already defined. | |
533 | void | |
534 | define_as_constant(Target*, const char* name, uint64_t value, | |
535 | uint64_t symsize, elfcpp::STT type, elfcpp::STB binding, | |
536 | elfcpp::STV visibility, unsigned char nonvis, | |
537 | bool only_if_ref); | |
538 | ||
539 | // Define a set of symbols in output sections. | |
540 | void | |
541 | define_symbols(const Layout*, Target*, int count, | |
542 | const Define_symbol_in_section*); | |
543 | ||
544 | // Define a set of symbols in output segments. | |
545 | void | |
546 | define_symbols(const Layout*, Target*, int count, | |
547 | const Define_symbol_in_segment*); | |
548 | ||
61ba1cf9 ILT |
549 | // Look up a symbol. |
550 | Symbol* | |
551 | lookup(const char*, const char* version = NULL) const; | |
552 | ||
14bfc3f5 | 553 | // Return the real symbol associated with the forwarder symbol FROM. |
bae7f79e | 554 | Symbol* |
14bfc3f5 | 555 | resolve_forwards(Symbol* from) const; |
bae7f79e | 556 | |
14bfc3f5 ILT |
557 | // Return the size of the symbols in the table. |
558 | int | |
559 | get_size() const | |
560 | { return this->size_; } | |
bae7f79e | 561 | |
1564db8d ILT |
562 | // Return the sized version of a symbol in this table. |
563 | template<int size> | |
564 | Sized_symbol<size>* | |
5482377d | 565 | get_sized_symbol(Symbol* ACCEPT_SIZE) const; |
1564db8d ILT |
566 | |
567 | template<int size> | |
568 | const Sized_symbol<size>* | |
5482377d | 569 | get_sized_symbol(const Symbol* ACCEPT_SIZE) const; |
54dc6425 | 570 | |
ead1e424 ILT |
571 | // Return the count of undefined symbols seen. |
572 | int | |
573 | saw_undefined() const | |
574 | { return this->saw_undefined_; } | |
575 | ||
576 | // Allocate the common symbols | |
577 | void | |
578 | allocate_commons(const General_options&, Layout*); | |
579 | ||
75f65a3e ILT |
580 | // Finalize the symbol table after we have set the final addresses |
581 | // of all the input sections. This sets the final symbol values and | |
582 | // adds the names to *POOL. It records the file offset OFF, and | |
583 | // returns the new file offset. | |
584 | off_t | |
585 | finalize(off_t, Stringpool*); | |
1564db8d | 586 | |
61ba1cf9 ILT |
587 | // Write out the global symbols. |
588 | void | |
589 | write_globals(const Target*, const Stringpool*, Output_file*) const; | |
590 | ||
bae7f79e ILT |
591 | private: |
592 | Symbol_table(const Symbol_table&); | |
593 | Symbol_table& operator=(const Symbol_table&); | |
594 | ||
14bfc3f5 ILT |
595 | // Set the size of the symbols in the table. |
596 | void | |
597 | set_size(int size) | |
598 | { this->size_ = size; } | |
599 | ||
600 | // Make FROM a forwarder symbol to TO. | |
601 | void | |
602 | make_forwarder(Symbol* from, Symbol* to); | |
603 | ||
604 | // Add a symbol. | |
605 | template<int size, bool big_endian> | |
606 | Symbol* | |
607 | add_from_object(Sized_object<size, big_endian>*, const char *name, | |
608 | const char *version, bool def, | |
609 | const elfcpp::Sym<size, big_endian>& sym); | |
610 | ||
611 | // Resolve symbols. | |
612 | template<int size, bool big_endian> | |
613 | static void | |
1564db8d ILT |
614 | resolve(Sized_symbol<size>* to, |
615 | const elfcpp::Sym<size, big_endian>& sym, | |
616 | Object*); | |
14bfc3f5 | 617 | |
1564db8d | 618 | template<int size, bool big_endian> |
14bfc3f5 | 619 | static void |
5482377d ILT |
620 | resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from |
621 | ACCEPT_SIZE_ENDIAN); | |
14bfc3f5 | 622 | |
ead1e424 ILT |
623 | // Define a symbol in an Output_data, sized version. |
624 | template<int size> | |
625 | void | |
626 | do_define_in_output_data(Target*, const char* name, Output_data*, | |
627 | typename elfcpp::Elf_types<size>::Elf_Addr value, | |
628 | typename elfcpp::Elf_types<size>::Elf_WXword ssize, | |
629 | elfcpp::STT type, elfcpp::STB binding, | |
630 | elfcpp::STV visibility, unsigned char nonvis, | |
631 | bool offset_is_from_end, bool only_if_ref); | |
632 | ||
633 | // Define a symbol in an Output_segment, sized version. | |
634 | template<int size> | |
635 | void | |
636 | do_define_in_output_segment( | |
637 | Target*, const char* name, Output_segment* os, | |
638 | typename elfcpp::Elf_types<size>::Elf_Addr value, | |
639 | typename elfcpp::Elf_types<size>::Elf_WXword ssize, | |
640 | elfcpp::STT type, elfcpp::STB binding, | |
641 | elfcpp::STV visibility, unsigned char nonvis, | |
642 | Symbol::Segment_offset_base offset_base, bool only_if_ref); | |
643 | ||
644 | // Define a symbol as a constant, sized version. | |
645 | template<int size> | |
646 | void | |
647 | do_define_as_constant( | |
648 | Target*, const char* name, | |
649 | typename elfcpp::Elf_types<size>::Elf_Addr value, | |
650 | typename elfcpp::Elf_types<size>::Elf_WXword ssize, | |
651 | elfcpp::STT type, elfcpp::STB binding, | |
652 | elfcpp::STV visibility, unsigned char nonvis, | |
653 | bool only_if_ref); | |
654 | ||
655 | // Allocate the common symbols, sized version. | |
656 | template<int size> | |
657 | void | |
658 | do_allocate_commons(const General_options&, Layout*); | |
659 | ||
75f65a3e ILT |
660 | // Finalize symbols specialized for size. |
661 | template<int size> | |
662 | off_t | |
663 | sized_finalize(off_t, Stringpool*); | |
664 | ||
61ba1cf9 ILT |
665 | // Write globals specialized for size and endianness. |
666 | template<int size, bool big_endian> | |
667 | void | |
668 | sized_write_globals(const Target*, const Stringpool*, Output_file*) const; | |
669 | ||
54dc6425 ILT |
670 | // The type of the symbol hash table. |
671 | ||
14bfc3f5 ILT |
672 | typedef std::pair<const char*, const char*> Symbol_table_key; |
673 | ||
674 | struct Symbol_table_hash | |
675 | { | |
676 | size_t | |
677 | operator()(const Symbol_table_key&) const; | |
678 | }; | |
679 | ||
680 | struct Symbol_table_eq | |
681 | { | |
682 | bool | |
683 | operator()(const Symbol_table_key&, const Symbol_table_key&) const; | |
684 | }; | |
685 | ||
686 | typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, | |
687 | Symbol_table_eq> Symbol_table_type; | |
688 | ||
ead1e424 ILT |
689 | // The type of the list of common symbols. |
690 | ||
691 | typedef std::vector<Symbol*> Commons_type; | |
692 | ||
14bfc3f5 ILT |
693 | // The size of the symbols in the symbol table (32 or 64). |
694 | int size_; | |
695 | ||
ead1e424 ILT |
696 | // We increment this every time we see a new undefined symbol, for |
697 | // use in archive groups. | |
698 | int saw_undefined_; | |
699 | ||
75f65a3e ILT |
700 | // The file offset within the output symtab section where we should |
701 | // write the table. | |
702 | off_t offset_; | |
703 | ||
61ba1cf9 ILT |
704 | // The number of global symbols we want to write out. |
705 | size_t output_count_; | |
706 | ||
54dc6425 | 707 | // The symbol hash table. |
14bfc3f5 ILT |
708 | Symbol_table_type table_; |
709 | ||
54dc6425 ILT |
710 | // A pool of symbol names. This is used for all global symbols. |
711 | // Entries in the hash table point into this pool. | |
14bfc3f5 | 712 | Stringpool namepool_; |
bae7f79e | 713 | |
14bfc3f5 ILT |
714 | // Forwarding symbols. |
715 | Unordered_map<Symbol*, Symbol*> forwarders_; | |
ead1e424 ILT |
716 | |
717 | // We don't expect there to be very many common symbols, so we keep | |
718 | // a list of them. When we find a common symbol we add it to this | |
719 | // list. It is possible that by the time we process the list the | |
720 | // symbol is no longer a common symbol. It may also have become a | |
721 | // forwarder. | |
722 | Commons_type commons_; | |
bae7f79e ILT |
723 | }; |
724 | ||
1564db8d ILT |
725 | // We inline get_sized_symbol for efficiency. |
726 | ||
727 | template<int size> | |
728 | Sized_symbol<size>* | |
5482377d | 729 | Symbol_table::get_sized_symbol(Symbol* sym ACCEPT_SIZE) const |
1564db8d ILT |
730 | { |
731 | assert(size == this->get_size()); | |
732 | return static_cast<Sized_symbol<size>*>(sym); | |
733 | } | |
734 | ||
735 | template<int size> | |
736 | const Sized_symbol<size>* | |
5482377d | 737 | Symbol_table::get_sized_symbol(const Symbol* sym ACCEPT_SIZE) const |
1564db8d ILT |
738 | { |
739 | assert(size == this->get_size()); | |
740 | return static_cast<const Sized_symbol<size>*>(sym); | |
741 | } | |
742 | ||
bae7f79e ILT |
743 | } // End namespace gold. |
744 | ||
745 | #endif // !defined(GOLD_SYMTAB_H) |