Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / symbols.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: symbols.cc
4// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
6//
7// The above named program is free software; you can redistribute it and/or
8// modify it under the terms of the GNU General Public
9// License version 2 as published by the Free Software Foundation.
10//
11// The above named program is distributed in the hope that it will be
12// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14// General Public License for more details.
15//
16// You should have received a copy of the GNU General Public
17// License along with this work; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19//
20// ========== Copyright Header End ============================================
21////////////////////////////////////////////////////////////
22//
23// File: symbols.cc
24//
25// Symbol table submodule
26//
27// Copyright (C) 2006 Sun Microsystems, Inc.
28// All rights reserved.
29//
30// Symbol table implementation file
31//
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <ctype.h>
36#include "types.h"
37#include "symbols.h"
38#include "ui.h"
39
40
41#define DEBUG_ON 0
42
43/////////////////////////////////////////////////////////
44//
45// Symbol class
46//
47
48Symbol::Symbol
49(
50 char* mname, // module name
51 char* sname, // symbol name
52 uint64_t vaddr, // starting address
53 uint64_t size, // size of address space taken this symbol
54 uint32_t context // symbol context
55)
56: SymBase(NULL)
57{
58 // add module name
59 if (sname != NULL)
60 {
61 char sym_name[128];
62 sprintf (sym_name, "%s:%s", mname, sname);
63 m_name = strdup(sym_name);
64 m_sname = strdup(sname);
65 }
66 else
67 {
68 m_name = NULL;
69 m_sname = NULL;
70 }
71 m_next = NULL;
72
73 m_vaddr = vaddr;
74 m_size = size;
75
76 m_context = context;
77}
78
79// destructor
80Symbol::~Symbol ()
81{
82 if (m_name ) free(m_name);
83 if (m_sname) free(m_sname);
84}
85
86//////////////////////////////////////////////////////////////
87//
88// Container class for all symbols
89//
90
91// constructor
92SymTable::SymTable
93(
94 uint32_t levels, // total number of table levels +1
95 uint32_t *idx_width // number of bits for table index
96 // on each level, plus last offset
97)
98{
99
100 int i;
101 uint32_t *wd = idx_width;
102
103 const uint32_t default_level = MAX_LEVEL+1; // number of tables + 1
104 uint32_t default_width[default_level] = {12,10,10,10,10,10,2};
105
106
107 if ((idx_width == NULL) || (levels > default_level ))
108 {
109 levels = default_level;
110 wd = default_width;
111 }
112
113 m_lev = levels-2;
114 int max_lev = m_lev + 1;
115
116 for (i=max_lev; i>=0; i--)
117 {
118 m_width[i] = wd[i];
119 m_size [i] = 1<<m_width[i];
120 m_mask [i] = m_size[i] -1;
121
122 m_sft [i] = (i==max_lev) ? 0 : m_width[i+1];
123 if ( i < max_lev)
124 m_sft [i] += m_sft[i+1];
125 #if(DEBUG_ON)
126 ui->verbose("\n symbol tbl level=%d, sft=%d, width=%d, size=0x%x, mask=0x%llx\n",
127 i, m_sft[i],m_width[i],m_size[i],m_mask[i]);
128 #endif
129
130 }
131
132 m_tbl = (void **) calloc(m_size[0], sizeof(void*));
133
134 for (int j=0; j<SYM_TBL_SIZE; j++)
135 m_bucket[j] = NULL;
136
137 m_empty = true;
138}
139
140// destructor
141SymTable::~SymTable ()
142{
143 for (int j=0; j<SYM_TBL_SIZE; j++)
144 {
145 if (m_bucket[j] != NULL)
146 delete m_bucket[j];
147 }
148
149 delete_tbl ( m_tbl, 0 );
150}
151
152// get a pointer in multi level addr tables;
153// nested tables are allocated if needed
154void ** SymTable::alloc( uint64_t addr )
155{
156 void ** tbl = m_tbl;
157 void ** ptr = NULL;
158
159
160 for ( int i=0; i<m_lev; i++)
161 {
162 ptr = tbl + ((addr>>m_sft[i]) & m_mask[i]);
163 void **next = (void**)(*ptr);
164 if (next == NULL)
165 {
166 // allocate a new table
167 next = (void **) calloc ( m_size[i+1], sizeof(void*));
168
169 // insert a pointer
170 *ptr = next;
171 }
172 tbl = next;
173 }
174
175 // get a pointer to the leaf table entry
176 return (tbl + ((addr>>m_sft[m_lev]) & m_mask[m_lev]));
177}
178
179// recursively delete all tables on deeper levels
180void SymTable::delete_tbl ( void ** tbl, uint32_t level)
181{
182 if ( level == m_lev )
183 {
184 // leaf table
185 for ( int i=0; i<m_size[level]; i++ )
186 {
187 // remove all links
188 SymBase *s = (SymBase *)tbl[i];
189
190 while (s)
191 {
192 SymBase *r = s;
193 s = s->m_link;
194 if (r->m_origin)
195 delete (r);
196 else
197 {
198 delete ( (Symbol*)r);
199 }
200 }
201
202 }
203 free ( tbl );
204 }
205 else
206 {
207 for ( int i=0; i<m_size[level]; i++ )
208 {
209 if (tbl[i]) // nested table
210 delete_tbl ( (void **)tbl[i], level+1 );
211 free ( tbl[i] );
212 }
213 }
214}
215
216
217// search for symbols specified by symbol name;
218// return pointer to symbol if found; 0 otherwise
219Symbol* SymTable::find
220(
221 char* name, // symbol name
222 Symbol* start // start search from this one
223)
224{
225 if ( this->is_empty() )
226 return NULL;
227
228 Symbol *sym = start ? start->m_next : NULL;
229
230 if (start == NULL)
231 {
232 // hash index for the bucket
233 sym = m_bucket[sym_hash(name)];
234 }
235
236
237 while (sym) // possibly iterate through the list
238 {
239 // check if name match
240 if ( strcmp (sym->m_sname, name) == 0 )
241 {
242 return sym;
243 }
244 // traverse the list for this bucket
245 sym = sym->m_next;
246 }
247
248 return NULL;
249}
250
251// find symbol specified by address ;
252// return 1 if found, 0 otherwise;
253SymBase* SymTable::find
254(
255 uint64_t addr, // address used to lookup the symbol
256 SymBase* start // start from this symbol
257)
258{
259 SymBase* res = NULL;
260
261
262 SymBase* s = start ? start->m_link : NULL;
263
264 if(start==NULL)
265 s = find ( addr );
266
267 if ( s == NULL )
268 return 0; // not found
269
270 while (s)
271 {
272 Symbol *sym = (s->m_origin) ? (Symbol*)(s->m_origin) : (Symbol*)s;
273
274 // check the range
275 if ( (addr >= sym->m_vaddr) &&
276 (addr < (sym->m_vaddr+ sym->m_size)) )
277 {
278 // symbol is in the range
279 res = (SymBase*)sym;
280 return res;
281 }
282
283 s = s->m_link;
284 }
285 return res;
286}
287
288// find and output address for all symbols specified by name;
289// return 1 if found, 0 otherwise;
290int SymTable::fputs
291(
292 char *name, // name used to lookup the symbol
293 uint32_t context, // symbol context
294 FILE * fp // output symbol name to stream if found
295)
296{
297 int res = 0;
298
299 if ( this->is_empty() )
300 return 0;
301
302 // hash index for the bucket
303 int hindex = sym_hash ( name );
304
305 Symbol *sym = m_bucket[hindex];
306
307 while (sym) // possibly iterate over the list
308 {
309 // check if name match
310 if (
311 (context == Symbol::ANY_CONTEXT || context == sym->m_context) &&
312 (strcmp (sym->m_sname, name) == 0)
313 )
314 {
315 fprintf(fp,"\n%s at address=0x%llx, size=0x%llx \n", sym->m_name, sym->m_vaddr, sym->m_size);
316 res = 1;
317 }
318
319 // traverse the list for this bucket
320 sym = sym->m_next;
321 }
322
323 return res;
324}
325
326
327// find and output full symbol name by specified address ;
328// return 1 if found, 0 otherwise;
329int SymTable::fputs
330(
331 uint64_t addr, // address used to lookup the symbol
332 uint32_t context, // symbol context
333 FILE * fp // output symbol name to stream if found
334)
335{
336 int res = 0;
337 SymBase *s = find ( addr );
338
339
340 if ( s == NULL )
341 return 0; // not found
342
343 while (s)
344 {
345 Symbol *sym = (s->m_origin) ? (Symbol*)(s->m_origin) : (Symbol*)s;
346
347 // check the range
348 if (
349 (context == Symbol::ANY_CONTEXT || context == sym->m_context) &&
350 (addr >= sym->m_vaddr) &&
351 (addr < (sym->m_vaddr+ sym->m_size))
352 )
353 {
354 // symbol is in the range
355 fprintf (fp, "%s+0x%llx ", sym->m_name, addr - sym->m_vaddr);
356 res = 1;
357 }
358
359 #if(DEBUG_ON)
360 // debug print out
361 if (s->m_origin) fprintf (fp, "\nredirected to ->");
362 fprintf(fp, "0x%016llx : 0x%016llx : %s , sp=0x%llx \n",
363 sym->m_vaddr, sym->m_size, sym->m_name, s);
364 #endif
365
366 s = s->m_link;
367 }
368 return res;
369}
370
371// add a new symbol to the symbol table
372// return 1 if added, 0 otherwise
373int SymTable::add
374(
375 char * mname, // module name
376 char * name, // symbol name
377 uint64_t vaddr, // starting address
378 uint64_t size, // range covered
379 uint32_t context // symbol context
380)
381{
382 if ((vaddr == ~uint64_t(0)) || (size == 0))
383 return 0;
384
385 uint32_t awidth = m_width[0] + m_sft[0];
386 uint64_t max_addr = awidth < 64 ? (uint64_t(1)<<awidth) - 1 : ~uint64_t(0);
387
388
389 if ( ~max_addr && (vaddr & ~max_addr) )
390 {
391 ui->warning( "Symbol: %s ingnored, address 0x%llx exceeds max addr 0x%llx for the sym table. \n",
392 name, vaddr, max_addr);
393 return 0;
394 }
395
396 // create a new symbol
397 Symbol *sym = new Symbol(mname, name, vaddr, size, context);
398
399 uint64_t addr = vaddr;
400
401 // block size
402 uint32_t bsize = m_size[m_lev+1];
403
404 // cover all range
405 for (uint64_t offset = 0; ((vaddr+offset) & ~m_mask[m_lev+1]) <= (vaddr+size); offset += bsize)
406 {
407 SymBase *new_sym = (SymBase *)sym;
408
409 if (offset !=0 ) // not first symbol in the range
410 {
411 new_sym = sym->dup();
412 }
413
414 // find a spot in address tables
415 SymBase **p_sym = (SymBase **)this->alloc(addr);
416
417
418 if (*p_sym==NULL) // table slot is empty
419 {
420 // insert new symbol
421 *p_sym = new_sym;
422 }
423 else // something is already there
424 {
425 // overlap with another symbol
426 (*p_sym)->attach ( new_sym );
427 #if(DEBUG_ON)
428 ui->verbose("\nnew_sym=0x%llx: %s+0x%llx was attached to p_sym=0x%llx(0x%llx) \n",
429 new_sym, sym->m_name, offset, *p_sym, p_sym);
430 #endif
431 }
432
433 addr += bsize;
434 }
435
436
437
438 // insert symbol into hash list
439 int hindex = sym_hash (name); // hash index
440 sym->m_next = m_bucket[hindex];
441 m_bucket[hindex] = sym;
442
443 m_empty = false;
444
445 return 1;
446}
447
448// print all symbols
449// from low to upper addresses
450void SymTable::print ( char *filename, uint32_t context )
451{
452 uint64_t total = 0;
453
454
455 if(filename)
456 {
457 FILE* fp = fopen (filename, "w");
458
459 if ( fp == NULL )
460 {
461 ui->error("cannot open %s\n", filename);
462 return;
463 }
464 else
465 {
466 ui->verbose("Collect symbols to %s file\n", filename);
467 }
468
469 if (print_tbl ( fp, m_tbl, 0, total, context )==0)
470 fprintf(fp, "Total number of symbols: %i \n", total);
471
472 fclose(fp);
473 }
474 else
475 {
476 if (print_tbl ( ui->get_output_file(), m_tbl, 0, total, context )==0)
477 fprintf(ui->get_output_file(), "Total number of symbols: %i \n", total);
478
479 // When logging is enabled we replicate output to log file.
480 if (ui->get_log_file()
481 && (print_tbl ( ui->get_log_file(), m_tbl, 0, total, context )==0))
482 fprintf(ui->get_log_file(), "Total number of symbols: %i \n", total);
483 }
484}
485
486// print one symbol
487int print_sym ( FILE *fp, Symbol *s, uint32_t context )
488{
489 if (context != Symbol::ANY_CONTEXT && context != s->context())
490 return 0;
491
492 fprintf(fp, "0x%016llx : 0x%016llx ",
493 s->vaddr(), s->size());
494
495 if (s->context() < Symbol::NO_CONTEXT)
496 fprintf(fp, ": 0x%08lx : %s \n", s->context(), s->name());
497 else
498 fprintf(fp, ": %s \n", s->name());
499
500 return 1;
501}
502
503// recursively print symbols for all tables on deeper levels
504int SymTable::print_tbl
505(
506 FILE *fp, // output to the stream
507 void ** tbl, // table pointer
508 uint32_t level, // table level
509 uint64_t &total, // symbol counter
510 uint32_t context
511)
512{
513 if ( level == m_lev )
514 {
515 // leaf table
516 for ( int j=0; j<m_size[level]; j++ )
517 {
518 SymBase *sym = (Symbol *)tbl[j];
519
520 while (sym)
521 {
522 if (sym->m_origin) // range mark - skip it
523 {
524 sym = sym->m_link;
525 continue;
526 }
527
528 Symbol *s = (Symbol *)sym;
529
530 if (print_sym (fp, s, context))
531 {
532 total++;
533 if ((fp == ui->get_output_file()) && ((total % 40) == 0))
534 {
535 fprintf ( fp, "more? space, n - next page, q - quit\n");
536 char c;
537 scanf("%c", &c);
538 if (c == 'q')
539 return 1;
540 }
541 }
542 sym = sym->m_link;
543 }
544 }
545 return 0;
546
547 }
548 else
549 {
550 for ( int i=0; i<m_size[level]; i++ )
551 {
552 if (tbl[i]) // nested table
553 if (print_tbl ( fp, (void **)tbl[i], level+1, total, context ) != 0)
554 return 1; // quit
555 }
556 }
557 return 0;
558}
559
560// print all symbols without any order -
561// hash table order
562int SymTable::hprint ( char *filename, uint32_t context )
563{
564 int index_max = 0;
565 int icount_max = 0;
566 int total = 0;
567 int cont = 0;
568
569 FILE *fp = ui->get_output_file();
570
571 if(filename)
572 {
573 fp = fopen (filename, "w");
574 if ( fp == NULL )
575 {
576 ui->error("cannot open %s\n", filename);
577 return 1;
578 }
579 else
580 {
581 ui->verbose("Collect symbols to %s file\n", filename);
582 }
583 }
584 fprintf(fp, "Symbol table: \n");
585
586 for ( int j = 0; j<SYM_TBL_SIZE; j++)
587 {
588 Symbol *sym = m_bucket[j];
589 Symbol *prev = NULL;
590
591 int count = 0;
592
593 while (sym) // possibly iterate through the list
594 {
595 if (print_sym (fp, sym, context))
596 {
597 count +=1;
598 total +=1;
599 if ((cont == 0) && (fp == ui->get_output_file()) &&
600 ((total % 40) == 0))
601 {
602 fprintf ( fp, "more? space, n - next page, q - quit\n");
603 char c;
604 scanf("%c", &c);
605 if (c == 'q')
606 goto quiting;
607 else if ( c == 'c' )
608 cont = 1;
609 }
610 }
611 sym = sym->m_next;
612 }
613
614 if (icount_max < count)
615 {
616 icount_max = count;
617 index_max = j;
618 }
619
620
621
622 } //for j
623
624quiting:
625 fprintf(fp, "Total number of symbols: %i \n", total);
626
627 fprintf(fp, "max list size = %i at idx = %i \n", icount_max, index_max);
628
629
630 return 0;
631}
632
633