Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: symbols.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | //////////////////////////////////////////////////////////// | |
24 | // | |
25 | // File: symbols.h | |
26 | // | |
27 | // Symbol table submodule | |
28 | // | |
29 | // Copyright (C) 2006 Sun Microsystems, Inc. | |
30 | // All rights reserved. | |
31 | // | |
32 | // | |
33 | // Symbol table support. | |
34 | // | |
35 | // 1. maps address range to a symbol, | |
36 | // lookup methods need to detect that address resides inside the range. | |
37 | // more then one symbol could correspond to a particular address - | |
38 | // a label inside a routine or structure inside another structure. | |
39 | // | |
40 | // 2. elf modules could be loaded at very low and very high virtual addresses; | |
41 | // the size of address space coverage impacts the algorithm choice. | |
42 | // | |
43 | // 3. needs to provide a resonable performance for both searches : | |
44 | // by symbols name and by address. | |
45 | // | |
46 | // 4. kernel modules could have static symbols with the same name; | |
47 | // | |
48 | ||
49 | ||
50 | #ifndef _SYMBOLS_H | |
51 | #define _SYMBOLS_H | |
52 | ||
53 | #include "types.h" | |
54 | ||
55 | ||
56 | ///////////////////////////////////////////////////////// | |
57 | // | |
58 | // Symbol class | |
59 | // | |
60 | ||
61 | class Symbol; | |
62 | ||
63 | // For each symbol there is only one Symbol object, | |
64 | // but if that symbol cover a few pages - SymBase marker is used | |
65 | // for each page this symbol belongs to. | |
66 | // SymBase object points to original symbol object, | |
67 | // is is used to save some mem space when marking the range. | |
68 | // | |
69 | class SymBase | |
70 | { | |
71 | protected: | |
72 | SymBase *m_origin; // prt to origin symbol | |
73 | ||
74 | // symbols that have overlapped address range | |
75 | // are kept in a link list | |
76 | SymBase *m_link; // prt to symbol if range overlaps | |
77 | ||
78 | ||
79 | // duplicate symbol reference for address range | |
80 | SymBase *dup() | |
81 | { | |
82 | SymBase *s = new SymBase (this); | |
83 | return s; | |
84 | } | |
85 | ||
86 | // attach symbol to list tail | |
87 | void attach ( SymBase *sym ) | |
88 | { | |
89 | SymBase* tail = this; | |
90 | while(tail->m_link) | |
91 | tail = tail->m_link; | |
92 | tail->m_link = sym; | |
93 | } | |
94 | ||
95 | ||
96 | SymBase (SymBase *o=NULL) { m_origin = o; m_link = NULL;} | |
97 | ||
98 | // base class better have a virtual destructor but | |
99 | // virtual table takes additional mem space | |
100 | ~SymBase() {} | |
101 | ||
102 | public: | |
103 | SymBase* link() { return m_link; } | |
104 | ||
105 | }; | |
106 | ||
107 | ||
108 | ||
109 | // Symbol class - maintain symbol information; | |
110 | // Each symbol is defined by name, starting address, | |
111 | // and size - number of bytes in address space covered by this symbol, | |
112 | // e.g. routine, data structure and etc. | |
113 | // Only container object could add a new symbol objects to the table. | |
114 | class Symbol : public SymBase | |
115 | { | |
116 | friend class SymTable; | |
117 | ||
118 | public: | |
119 | ||
120 | enum | |
121 | { | |
122 | NUCLEUS = 0, | |
123 | NO_CONTEXT = ~uint32_t(1), | |
124 | ANY_CONTEXT = ~uint32_t(0) | |
125 | }; | |
126 | ||
127 | private : | |
128 | ||
129 | char* m_name; // symbol full name | |
130 | char* m_sname; // symbol name | |
131 | ||
132 | uint64_t m_vaddr; // virtual address for the the object | |
133 | uint64_t m_size; // object size in bytes | |
134 | ||
135 | Symbol *m_next; // ptr to the next symbol in the hash table | |
136 | ||
137 | uint32_t m_context; // 0 - kernel, -2 - hypervisor, <contextID> for user | |
138 | ||
139 | // private constructor - only container class can construct/destruct the symbol | |
140 | Symbol (char* mname=NULL, char* sname=NULL, uint64_t vaddr=~uint64_t(0), | |
141 | uint64_t size =0, uint32_t context = NO_CONTEXT); | |
142 | ||
143 | // destructor | |
144 | ~Symbol (); | |
145 | ||
146 | ||
147 | public: // member functions | |
148 | ||
149 | char * name () { return m_name; } | |
150 | uint64_t vaddr () { return m_vaddr; } | |
151 | uint64_t size () { return m_size; } | |
152 | Symbol* next () { return m_next; } | |
153 | uint32_t context() { return m_context; } | |
154 | ||
155 | }; | |
156 | ||
157 | ////////////////////////////////////////////////////////////// | |
158 | // | |
159 | // Container class for all symbols | |
160 | // | |
161 | // - symbol addresses are mapped using nested address tables; | |
162 | // - number of used address bits control how much of address space symbol table | |
163 | // will cover, if number of address bits for all tables sum up to 64 - | |
164 | // cover all address space. | |
165 | // - table size also control how much "meta data" space you are willing to | |
166 | // spend for address mapping; | |
167 | // - for smaller number of table levels address search is faster but middle tables | |
168 | // are bigger - a lot of memory is waisted to provide a faster search | |
169 | // - if symbols are loaded in a relatively small address range - | |
170 | // it requires a small number of middle tables. | |
171 | // - the number of levels and size of tables on each level is fixed | |
172 | // after construction phase. | |
173 | ||
174 | // table indexes | |
175 | //---------------------------------------------- | |
176 | // level 0 | level 1 |...|level n | offset n+1 | | |
177 | //---------------------------------------------- | |
178 | // | |
179 | ||
180 | class SymTable | |
181 | { | |
182 | public: | |
183 | ||
184 | enum | |
185 | { | |
186 | // hash table size - should be power of 2 | |
187 | SYM_TBL_SIZE = 1<<10, | |
188 | MAX_LEVEL = 6 | |
189 | }; | |
190 | ||
191 | ||
192 | private: | |
193 | ||
194 | // hash table - quick search by name | |
195 | Symbol *m_bucket [SYM_TBL_SIZE]; | |
196 | ||
197 | // address tables - quick search by address; | |
198 | // total number of tables is m_lev+1 | |
199 | void** m_tbl; | |
200 | uint32_t m_lev; // number of table levels minus one | |
201 | ||
202 | // arrays for each table level | |
203 | uint32_t m_width[MAX_LEVEL+1]; // index width (number of bits) | |
204 | uint32_t m_size [MAX_LEVEL+1]; // table size | |
205 | uint32_t m_sft [MAX_LEVEL+1]; // index shift amount | |
206 | uint64_t m_mask [MAX_LEVEL+1]; // index mask | |
207 | ||
208 | bool m_empty; // true if there is no symbols | |
209 | ||
210 | ||
211 | private: // internal methods | |
212 | ||
213 | int sym_hash ( char *s) | |
214 | { | |
215 | uint64_t hash = 0; | |
216 | ||
217 | for(int i=0; i<strlen(s); i++) | |
218 | { | |
219 | hash = ( hash << 5 ) ^ s[i] ^ hash; | |
220 | } | |
221 | return hash % SYM_TBL_SIZE; | |
222 | } | |
223 | ||
224 | // recursively delete all tables on deeper levels | |
225 | void delete_tbl ( void ** tbl, uint32_t level); | |
226 | ||
227 | ||
228 | // search symbol by specified address | |
229 | // return symbol poiner or NULL if not found | |
230 | SymBase* find ( uint64_t addr) | |
231 | { | |
232 | if ( this->is_empty() ) | |
233 | return NULL; | |
234 | ||
235 | void ** tbl = m_tbl; | |
236 | void ** ptr = NULL; | |
237 | ||
238 | ||
239 | for ( int i=0; i<m_lev; i++) | |
240 | { | |
241 | ptr = tbl + ((addr>>m_sft[i]) & m_mask[i]); | |
242 | void **next = (void **)(*ptr); | |
243 | if (next == NULL) | |
244 | { | |
245 | return NULL; | |
246 | } | |
247 | tbl = next; | |
248 | } | |
249 | ||
250 | // get a pointer from the leaf table | |
251 | return (SymBase *)tbl[(addr>>m_sft[m_lev]) & m_mask[m_lev]]; | |
252 | } | |
253 | ||
254 | // get a pointer in multi level addr tables; | |
255 | // nested tables are allocated if needed | |
256 | void **alloc( uint64_t addr ); | |
257 | ||
258 | // recursively print symbols for all tables on deeper levels | |
259 | int print_tbl | |
260 | ( | |
261 | FILE *fp, // output to the stream | |
262 | void ** tbl, // table pointer | |
263 | uint32_t level, // table level | |
264 | uint64_t &total, // symbol counter | |
265 | uint32_t context // symbol context | |
266 | ); | |
267 | ||
268 | public: | |
269 | ||
270 | // constructor/destructor | |
271 | SymTable ( uint32_t levels = MAX_LEVEL+1, uint32_t *idx_width=NULL ); | |
272 | ~SymTable (); | |
273 | ||
274 | // Member functions | |
275 | ||
276 | // check if container is empty | |
277 | bool is_empty () { return m_empty; } | |
278 | ||
279 | // find() methods combines functionality of search and iterator | |
280 | // - use it with start=NULL to find a head of the list; | |
281 | // to traverse the list call find() method again using start | |
282 | // pointing to the previous symbol. | |
283 | ||
284 | // search for address of symbol specified by symbol name; | |
285 | // return pointer to symbol if found; 0 otherwise; | |
286 | // | |
287 | // different modules could have static variables (symbols) with | |
288 | // the same name - you will get a list of the symbols with | |
289 | // same name that reside in different modules, | |
290 | // you need to traverse the list to get the symbols; | |
291 | Symbol * find | |
292 | ( | |
293 | char* name, // symbol name | |
294 | Symbol* start=NULL // start search from this one | |
295 | ); | |
296 | ||
297 | // find symbol specified by address ; | |
298 | // return 1 if found, 0 otherwise; | |
299 | // if you make a search by address - it return a list of symbols | |
300 | // that resides at that address. Symbols address ranges could overlap. | |
301 | // You need to traverse that list and extract symbol names. | |
302 | SymBase* find | |
303 | ( | |
304 | uint64_t addr, // address used to lookup the symbol | |
305 | SymBase* start // start from this symbol | |
306 | ); | |
307 | ||
308 | // find and output address for all symbols specified by name; | |
309 | // return 1 if found, 0 otherwise; | |
310 | int fputs | |
311 | ( | |
312 | char *name, // name used to lookup the symbol | |
313 | uint32_t context, // symbol context | |
314 | FILE *fp // output symbol name to stream if found | |
315 | ); | |
316 | ||
317 | ||
318 | // find and output full symbol name by specified address ; | |
319 | // return 1 if found, 0 otherwise; | |
320 | int fputs | |
321 | ( | |
322 | uint64_t addr, // address used to lookup the symbol | |
323 | uint32_t context, // symbol context | |
324 | FILE *fp // output symbol name to stream if found | |
325 | ); | |
326 | ||
327 | ||
328 | // add a new symbol to the symbol table | |
329 | // return 1 if added, 0 otherwise | |
330 | int add | |
331 | ( | |
332 | char * mname, // module name | |
333 | char * name, // symbol name | |
334 | uint64_t vaddr, // starting address | |
335 | uint64_t size=0, // range covered | |
336 | uint32_t context=Symbol::NUCLEUS // symbol context | |
337 | ); | |
338 | ||
339 | // print all symbols | |
340 | // from low to upper addresses | |
341 | void print ( char *filename, uint32_t context ); | |
342 | ||
343 | // print all symbols without any order - | |
344 | // hash table order | |
345 | int hprint ( char *filename, uint32_t context ); | |
346 | ||
347 | }; | |
348 | ||
349 | ||
350 | ||
351 | ||
352 | ||
353 | ||
354 | ||
355 | ||
356 | ||
357 | ||
358 | #endif // _SYMBOLS_H |