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> | |
8 | ||
9 | #include "elfcpp.h" | |
14bfc3f5 | 10 | #include "stringpool.h" |
bae7f79e ILT |
11 | |
12 | #ifndef GOLD_SYMTAB_H | |
13 | #define GOLD_SYMTAB_H | |
14 | ||
15 | namespace gold | |
16 | { | |
17 | ||
14bfc3f5 ILT |
18 | class Object; |
19 | ||
20 | template<int size, bool big_endian> | |
21 | class Sized_object; | |
22 | ||
23 | template<int size, bool big_endian> | |
24 | class Sized_target; | |
25 | ||
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 | ||
14bfc3f5 ILT |
97 | protected: |
98 | // Instances of this class should always be created at a specific | |
99 | // size. | |
100 | Symbol() | |
101 | { } | |
102 | ||
103 | // Initialize fields from an ELF symbol in OBJECT. | |
104 | template<int size, bool big_endian> | |
105 | void | |
106 | init_base(const char *name, const char* version, Object* object, | |
107 | const elfcpp::Sym<size, big_endian>&); | |
bae7f79e | 108 | |
1564db8d ILT |
109 | // Override existing symbol. |
110 | template<int size, bool big_endian> | |
111 | void | |
112 | override_base(const elfcpp::Sym<size, big_endian>&, Object* object); | |
113 | ||
bae7f79e | 114 | private: |
14bfc3f5 ILT |
115 | Symbol(const Symbol&); |
116 | Symbol& operator=(const Symbol&); | |
117 | ||
118 | // Symbol name (expected to point into a Stringpool). | |
119 | const char* name_; | |
120 | // Symbol version (expected to point into a Stringpool). This may | |
121 | // be NULL. | |
bae7f79e | 122 | const char* version_; |
14bfc3f5 | 123 | // Object in which symbol is defined, or in which it was first seen. |
bae7f79e | 124 | Object* object_; |
14bfc3f5 | 125 | // Section number in object_ in which symbol is defined. |
bae7f79e | 126 | unsigned int shnum_; |
14bfc3f5 | 127 | // Symbol type. |
bae7f79e | 128 | elfcpp::STT type_ : 4; |
14bfc3f5 | 129 | // Symbol binding. |
bae7f79e | 130 | elfcpp::STB binding_ : 4; |
14bfc3f5 ILT |
131 | // Symbol visibility. |
132 | elfcpp::STV visibility_ : 2; | |
133 | // Rest of symbol st_other field. | |
bae7f79e | 134 | unsigned int other_ : 6; |
14bfc3f5 ILT |
135 | // True if this symbol always requires special target-specific |
136 | // handling. | |
1564db8d | 137 | bool is_special_ : 1; |
14bfc3f5 | 138 | // True if this is the default version of the symbol. |
1564db8d | 139 | bool is_def_ : 1; |
14bfc3f5 ILT |
140 | // True if this symbol really forwards to another symbol. This is |
141 | // used when we discover after the fact that two different entries | |
142 | // in the hash table really refer to the same symbol. This will | |
143 | // never be set for a symbol found in the hash table, but may be set | |
144 | // for a symbol found in the list of symbols attached to an Object. | |
145 | // It forwards to the symbol found in the forwarders_ map of | |
146 | // Symbol_table. | |
1564db8d ILT |
147 | bool is_forwarder_ : 1; |
148 | // True if we've seen this symbol in a dynamic object. | |
149 | bool in_dyn_ : 1; | |
bae7f79e ILT |
150 | }; |
151 | ||
14bfc3f5 ILT |
152 | // The parts of a symbol which are size specific. Using a template |
153 | // derived class like this helps us use less space on a 32-bit system. | |
bae7f79e ILT |
154 | |
155 | template<int size> | |
14bfc3f5 ILT |
156 | class Sized_symbol : public Symbol |
157 | { | |
158 | public: | |
1564db8d ILT |
159 | typedef typename elfcpp::Elf_types<size>::Elf_Addr Value_type; |
160 | typedef typename elfcpp::Elf_types<size>::Elf_WXword Size_type; | |
161 | ||
14bfc3f5 ILT |
162 | Sized_symbol() |
163 | { } | |
164 | ||
165 | // Initialize fields from an ELF symbol in OBJECT. | |
166 | template<bool big_endian> | |
167 | void | |
168 | init(const char *name, const char* version, Object* object, | |
169 | const elfcpp::Sym<size, big_endian>&); | |
170 | ||
1564db8d ILT |
171 | // Override existing symbol. |
172 | template<bool big_endian> | |
173 | void | |
174 | override(const elfcpp::Sym<size, big_endian>&, Object* object); | |
175 | ||
176 | // Return the symbol's value. | |
177 | Value_type | |
178 | value() const | |
179 | { return this->value_; } | |
180 | ||
181 | // Return the symbol's size (we can't call this 'size' because that | |
182 | // is a template parameter). | |
183 | Size_type | |
184 | symsize() const | |
185 | { return this->size_; } | |
186 | ||
14bfc3f5 ILT |
187 | private: |
188 | Sized_symbol(const Sized_symbol&); | |
189 | Sized_symbol& operator=(const Sized_symbol&); | |
190 | ||
191 | // Symbol value. | |
1564db8d | 192 | Value_type value_; |
14bfc3f5 | 193 | // Symbol size. |
1564db8d | 194 | Size_type size_; |
14bfc3f5 ILT |
195 | }; |
196 | ||
197 | // The main linker symbol table. | |
198 | ||
bae7f79e ILT |
199 | class Symbol_table |
200 | { | |
201 | public: | |
202 | Symbol_table(); | |
203 | ||
1564db8d | 204 | ~Symbol_table(); |
bae7f79e | 205 | |
14bfc3f5 ILT |
206 | // Add COUNT external symbols from OBJECT to the symbol table. SYMS |
207 | // is the symbols, SYM_NAMES is their names, SYM_NAME_SIZE is the | |
208 | // size of SYM_NAMES. This sets SYMPOINTERS to point to the symbols | |
209 | // in the symbol table. | |
210 | template<int size, bool big_endian> | |
211 | void | |
212 | add_from_object(Sized_object<size, big_endian>* object, | |
213 | const elfcpp::Sym<size, big_endian>* syms, | |
214 | size_t count, const char* sym_names, size_t sym_name_size, | |
215 | Symbol** sympointers); | |
216 | ||
217 | // Return the real symbol associated with the forwarder symbol FROM. | |
bae7f79e | 218 | Symbol* |
14bfc3f5 | 219 | resolve_forwards(Symbol* from) const; |
bae7f79e | 220 | |
14bfc3f5 ILT |
221 | // Return the size of the symbols in the table. |
222 | int | |
223 | get_size() const | |
224 | { return this->size_; } | |
bae7f79e | 225 | |
1564db8d ILT |
226 | // Return the sized version of a symbol in this table. |
227 | template<int size> | |
228 | Sized_symbol<size>* | |
229 | get_sized_symbol(Symbol*); | |
230 | ||
231 | template<int size> | |
232 | const Sized_symbol<size>* | |
233 | get_sized_symbol(const Symbol*); | |
234 | ||
bae7f79e ILT |
235 | private: |
236 | Symbol_table(const Symbol_table&); | |
237 | Symbol_table& operator=(const Symbol_table&); | |
238 | ||
14bfc3f5 ILT |
239 | // Set the size of the symbols in the table. |
240 | void | |
241 | set_size(int size) | |
242 | { this->size_ = size; } | |
243 | ||
244 | // Make FROM a forwarder symbol to TO. | |
245 | void | |
246 | make_forwarder(Symbol* from, Symbol* to); | |
247 | ||
248 | // Add a symbol. | |
249 | template<int size, bool big_endian> | |
250 | Symbol* | |
251 | add_from_object(Sized_object<size, big_endian>*, const char *name, | |
252 | const char *version, bool def, | |
253 | const elfcpp::Sym<size, big_endian>& sym); | |
254 | ||
255 | // Resolve symbols. | |
256 | template<int size, bool big_endian> | |
257 | static void | |
1564db8d ILT |
258 | resolve(Sized_symbol<size>* to, |
259 | const elfcpp::Sym<size, big_endian>& sym, | |
260 | Object*); | |
14bfc3f5 | 261 | |
1564db8d | 262 | template<int size, bool big_endian> |
14bfc3f5 | 263 | static void |
1564db8d | 264 | resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from); |
14bfc3f5 ILT |
265 | |
266 | typedef std::pair<const char*, const char*> Symbol_table_key; | |
267 | ||
268 | struct Symbol_table_hash | |
269 | { | |
270 | size_t | |
271 | operator()(const Symbol_table_key&) const; | |
272 | }; | |
273 | ||
274 | struct Symbol_table_eq | |
275 | { | |
276 | bool | |
277 | operator()(const Symbol_table_key&, const Symbol_table_key&) const; | |
278 | }; | |
279 | ||
280 | typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash, | |
281 | Symbol_table_eq> Symbol_table_type; | |
282 | ||
283 | // The size of the symbols in the symbol table (32 or 64). | |
284 | int size_; | |
285 | ||
286 | // The symbol table itself. | |
287 | Symbol_table_type table_; | |
288 | ||
289 | // A pool of symbol names. | |
290 | Stringpool namepool_; | |
bae7f79e | 291 | |
14bfc3f5 ILT |
292 | // Forwarding symbols. |
293 | Unordered_map<Symbol*, Symbol*> forwarders_; | |
bae7f79e ILT |
294 | }; |
295 | ||
1564db8d ILT |
296 | // We inline get_sized_symbol for efficiency. |
297 | ||
298 | template<int size> | |
299 | Sized_symbol<size>* | |
300 | Symbol_table::get_sized_symbol(Symbol* sym) | |
301 | { | |
302 | assert(size == this->get_size()); | |
303 | return static_cast<Sized_symbol<size>*>(sym); | |
304 | } | |
305 | ||
306 | template<int size> | |
307 | const Sized_symbol<size>* | |
308 | Symbol_table::get_sized_symbol(const Symbol* sym) | |
309 | { | |
310 | assert(size == this->get_size()); | |
311 | return static_cast<const Sized_symbol<size>*>(sym); | |
312 | } | |
313 | ||
bae7f79e ILT |
314 | } // End namespace gold. |
315 | ||
316 | #endif // !defined(GOLD_SYMTAB_H) |