Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / system / blaze / ui_elfsym.cc
CommitLineData
920dae64
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: ui_elfsym.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: ui_elfsym.cc
24//
25// Copyright (C) 2005-2007 Sun Microsystems, Inc.
26// All rights reserved.
27//
28
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <ctype.h>
33#include <errno.h>
34#include "types.h"
35#include "blaze_globals.h"
36#include "cpu_interface.h"
37#include "ui_elfsym.h"
38#include "ui.h"
39
40
41// symbol table
42SymTable *g_sym_table = NULL;
43
44extern int load_symbols(char* elf_fname, uint64_t text_base, uint64_t data_base, uint32_t context);
45
46/////////////////////////////////////////////
47//
48// symbol table
49//
50
51static int load_sym (char *file_name, uint32_t context);
52static int load_elf_sym(char* file_name, uint64_t text_base, uint64_t data_base,
53 uint32_t context=Symbol::ANY_CONTEXT, bool elffile=false);
54
55static int print_symtab_usage()
56{
57 ui->output("load symbol table usage (all params are in Hex):\n load_sym -elffile|-elfsym|-vsym -f <file_name> \
58[-x <text start addr>] [-d <data start addr>] [-ctx <contextID>]\n");
59 return 0;
60}
61
62typedef enum { UNK_FILE, ELF_FILE, ELF_SYM, V_SYM } sym_file_t;
63
64int load_sym_ui_cmd (void*, int argc, char **argv)
65{
66 if (ANY_RUNNING_STATE (blaze_run_state))
67 {
68 ui->error("not in stop state, use stop command first\n");
69 return 0;
70 }
71
72 uint64_t text_base = 0;
73 uint64_t data_base = 0;
74 char *file_name;
75 uint32_t context = Symbol::ANY_CONTEXT;
76
77 sym_file_t file_type = UNK_FILE;
78
79
80 // check command options
81 if ( argc < 4 || argc > 10 )
82 return print_symtab_usage();
83
84 for (int i=1; i<argc; i++)
85 {
86 if ((strcmp(argv[i], "-x")==0) && ((i+1)<argc))
87 {
88 // set text base value
89 text_base = int(strtoull(argv[++i], NULL, 16));
90
91 }
92 else if ((strcmp(argv[i], "-d")==0) && ((i+1)<argc))
93 {
94 // set data base value
95 data_base = int(strtoull(argv[++i], NULL, 16));
96
97 }
98 else if ((strcmp(argv[i], "-f")==0) && ((i+1)<argc) )
99 {
100 // elf file name
101 file_name = argv[++i];
102 }
103 else if ((strcmp(argv[i], "-ctx")==0) && ((i+1)<argc) )
104 {
105 // symbols context
106 char *ctx = argv[++i];
107 errno = 0;
108 if (strcmp(ctx, "hv") == 0)
109 {
110 context = Symbol::NO_CONTEXT;
111 }
112 else if (strcmp(ctx, "k") == 0)
113 {
114 context = Symbol::NUCLEUS;
115 }
116 else
117 {
118 context = strtoul(ctx, NULL, 16);
119 }
120
121 if(errno)
122 {
123 ui->error("\n -ctx <contextID> cannot figure out context id, should be 0,k,hv,or a hex number > 0 \n");
124 return 0;
125 }
126 }
127 else if (strcmp(argv[i], "-elffile")==0)
128 {
129 file_type = ELF_FILE;
130 }
131 else if (strcmp(argv[i], "-elfsym")==0)
132 {
133 file_type = ELF_SYM;
134 }
135 else if (strcmp(argv[i], "-vsym")==0)
136 {
137 file_type = V_SYM;
138 }
139 else if (strcmp(argv[i], "?")==0)
140 {
141 return print_symtab_usage();
142 }
143
144 }
145
146
147
148
149 if (!file_name)
150 {
151 ui->error("missing file name \n");
152 return print_symtab_usage();
153 }
154
155 switch ( file_type )
156 {
157 case ELF_FILE: // elf file
158 {
159 // allocate symbol table
160 if (g_sym_table == NULL)
161 {
162 uint32_t idx[4] = {12, 6, 8, 6};
163 g_sym_table = new SymTable(4, idx);
164 }
165
166 load_symbols(file_name, text_base, data_base, context);
167 }
168 //load_elf_sym(file_name, text_base, data_base, true);
169 break;
170
171 case ELF_SYM : // symbol table extracted from elf module
172 load_elf_sym(file_name, text_base, data_base, context);
173 break;
174
175 case V_SYM : // special symbol file
176 load_sym(file_name, context);
177 break;
178
179 default:
180 ui->error("unknown symbol table type, load_sym should have -elffile, -elfsym or -vsym.\n");
181
182 }
183
184 return 1;
185}
186
187
188
189
190/////////////////////////////////////////////////////////////
191// read symbol table file
192static int load_sym (char *file_name, uint32_t context)
193{
194
195 // Open symtab file
196 FILE *file = fopen(file_name,"r");
197 if (file == NULL) { ui->perror (file_name); return 0; }
198
199 char line[512];
200 char delimeter[] = " :\t\n";
201
202 // allocate symbol table
203 if (g_sym_table == NULL)
204 {
205 g_sym_table = new SymTable();
206 }
207
208 ui->output("Loading %s special symbols...", file_name);
209
210 const uint64_t UNKNOWN = ~uint64_t(0);
211
212 while(fgets(line, 512, file) != NULL)
213 {
214 // parse symbol info:
215 // symbolname vaddr raddr paddr
216 char *symbol = strtok(line, delimeter);
217 char *addr = strtok(NULL, delimeter);
218 uint64_t va = strtoull(addr, NULL, 16);
219 if (strcmp(addr, "X") == 0)
220 va = UNKNOWN;
221 addr = strtok(NULL, delimeter);
222 uint64_t ra = strtoull(addr, NULL, 16);
223 if (strcmp(addr, "X") == 0)
224 ra = UNKNOWN;
225 addr = strtok(NULL, delimeter);
226 uint64_t pa = strtoull(addr, NULL, 16);
227 if (strcmp(addr, "X") == 0)
228 pa = UNKNOWN;
229
230 // insert symbol
231 g_sym_table->add(file_name,symbol, va, 4, context);
232
233 }
234 ui->output("Done. \n");
235
236 return 1;
237
238}
239
240
241
242//////////////////////////////////////////////////////////
243static int load_elf_sym
244(
245 char* file_name,
246 uint64_t text_base,
247 uint64_t data_base,
248 uint32_t context,
249 bool elf_file
250)
251{
252 const int bsize = 1024;
253 char sline[1024];
254
255 errno = 0;
256
257 // Open symtab file
258
259 FILE *file = NULL;
260
261 if (elf_file)
262 {
263 sprintf( sline, "nm -xvs %s", file_name);
264 file = popen( sline, "r" );
265 }
266 else
267 {
268 file = fopen( file_name,"r" );
269 }
270
271 if (file == NULL)
272 {
273 ui->perror (file_name);
274 return 0;
275 }
276
277 char delimeter[] = " |\n";
278
279 // allocate symbol table
280 if (g_sym_table == NULL)
281 {
282 uint32_t idx[4] = {12, 6, 8, 6};
283 g_sym_table = new SymTable(4, idx);
284 }
285
286 ui->output("Loading %s elf symbols...", file_name);
287
288 while(fgets(sline, bsize, file) != NULL)
289 {
290 if ((sline[0]=='[') && !isdigit(sline[1]))
291 continue;
292
293 // parse symbol info line
294 // [Index] | Value | Size | Type | Bind | Other | Shname | Name
295 char *idx = strtok(sline, delimeter);
296 if (idx == NULL)
297 continue;
298 char *value = strtok(NULL, delimeter);
299 if (value == NULL)
300 continue;
301 char *size = strtok(NULL, delimeter);
302 if (size == NULL)
303 continue;
304 char *type = strtok(NULL, delimeter);
305 if (type == NULL)
306 continue;
307 char *bind = strtok(NULL, delimeter);
308 if (bind == NULL)
309 continue;
310 char *oth = strtok(NULL, delimeter);
311 if (oth == NULL)
312 continue;
313 char *shname = strtok(NULL, delimeter);
314 if (shname == NULL)
315 continue;
316 char *name = strtok(NULL, delimeter);
317 if (name == NULL)
318 continue;
319
320 errno = 0;
321 uint64_t va = strtoull(value, NULL, 16);
322 uint64_t sz = strtoull(size, NULL, 16);
323
324 if (errno)
325 {
326 ui->perror(name);
327 continue;
328 }
329
330 if (sz == 0) // skip symbols(lebels) with zero size
331 continue;
332
333 if ( strcmp (shname, ".text") == 0)
334 {
335 // text symbol
336 va += text_base;
337
338 }
339 else if (strcmp (type, "OBJT") == 0)
340 {
341 //data symbol
342 if (strcmp (shname, ".data") == 0)
343 {
344 // initialized data
345 va += data_base;
346 }
347 else if (strcmp (shname, ".bss" )==0)
348 {
349 // uninitialized data
350 if (strcmp (bind, "GLOB" ) == 0)
351 va += data_base;
352 else
353 continue;
354 }
355 else
356 continue;
357 }
358 else
359 continue;
360
361
362
363
364 // insert symbol
365 g_sym_table->add(file_name, name, va, sz, context);
366
367
368 }
369
370
371 if ( elf_file )
372 pclose ( file );
373 else
374 fclose ( file );
375
376 ui->output("Done. \n");
377
378 return 1;
379}
380
381
382//////////////////////////////////////////////////////////
383int unload_sym_ui_cmd (void*, int argc, char **argv)
384{
385 // Unload symbol table
386 if (ANY_RUNNING_STATE (blaze_run_state))
387 {
388 ui->error("not in stop state, use stop command first\n");
389 return 0;
390 }
391
392 if ( argc > 1)
393 {
394 ui->error("unload symbol table, usage:\n unload_sym \n");
395 return 0;
396 }
397
398 if (g_sym_table != NULL)
399 {
400 delete(g_sym_table);
401 g_sym_table = NULL;
402 }
403
404 return 1;
405}
406
407
408//////////////////////////////////////////////////////////
409// print symbols
410
411static int print_sym_usage()
412{
413 ui->output("sym command usage:\n sym [-ctx <contextID>] [-o filename]-all|-a <addr>|-s <name>\n");
414 return 0;
415}
416int symbols_ui_cmd (void*, int argc, char **argv)
417{
418 if (g_sym_table == NULL)
419 {
420 ui->error("There is no symbol table allocated \n");
421 return 0;
422 }
423
424 char *file_name = NULL;
425 uint32_t context = Symbol::ANY_CONTEXT;
426
427 // check command options
428 if ( argc < 2 )
429 return print_sym_usage();
430
431 for (int i=1; i<argc; i++)
432 {
433 if (strcmp(argv[i], "-all")==0)
434 {
435 // show all symbols
436 g_sym_table->print(file_name, context);
437 return 1;
438
439 }
440 else if (strcmp(argv[i], "-hash")==0)
441 {
442 g_sym_table->hprint(file_name, context);
443 return 1;
444
445 }
446 else if ((strcmp(argv[i], "-s")==0) && ((i+1)<argc) )
447 {
448 // search for symbol by name
449 char *name = argv[++i];
450 if (!g_sym_table->fputs(name, context, ui->get_output_file()))
451 ui->error("%s not found\n", name);
452 if (ui->get_log_file())
453 g_sym_table->fputs(name, context, ui->get_log_file());
454 return 1;
455 }
456 else if ((strcmp(argv[i], "-a")==0) && ((i+1)<argc))
457 {
458 // addr
459 char *addr = argv[++i];
460 uint64_t vaddr = strtoull(addr, NULL, 16);
461
462 if (g_sym_table->fputs(vaddr, context, ui->get_output_file()))
463 {
464 if (ui->get_log_file())
465 g_sym_table->fputs(vaddr, context, ui->get_log_file());
466 ui->output("at address = 0x%llx\n", vaddr);
467 }
468 else
469 {
470 if (ui->get_log_file())
471 g_sym_table->fputs(vaddr, context, ui->get_log_file());
472 ui->error("address %s not found\n", addr );
473 }
474 return 1;
475 }
476 else if ((strcmp(argv[i], "-ctx")==0) && ((i+1)<argc) )
477 {
478 // symbols context
479 char *ctx = argv[++i];
480 errno = 0;
481 if (strcmp(ctx, "hv") == 0)
482 {
483 context = Symbol::NO_CONTEXT;
484 }
485 else if (strcmp(ctx, "k") == 0)
486 {
487 context = Symbol::NUCLEUS;
488 }
489 else
490 {
491 context = strtoul(ctx, NULL, 16);
492 }
493
494 if(errno)
495 {
496 ui->error("-ctx <contextID> cannot figure out context id, should be 0,k,hv,or a hex number > 0 \n");
497 return 0;
498 }
499 }
500 else if ((strcmp(argv[i], "-o")==0) && ((i+1)<argc) )
501 {
502 file_name = argv[++i];
503 }
504 else if (strcmp(argv[i], "?")==0)
505 {
506 return print_sym_usage();
507 }
508
509 }
510
511 return 1;
512
513}
514
515
516
517//////////////////////////////////////////////////////////////
518//
519// where ui command
520//
521
522static int print_routine_name ( uint64_t pc )
523{
524 if (!g_sym_table->fputs(pc, Symbol::ANY_CONTEXT, ui->get_output_file()))
525 {
526 ui->error("unknown routine \n");
527 return 1;
528 }
529
530 if (ui->get_log_file())
531 g_sym_table->fputs(pc, Symbol::ANY_CONTEXT, ui->get_log_file());
532
533 return 0;
534}
535
536int where_ui_cmd (void*, int argc, char **argv)
537{
538 // Unload symbol table
539 if (ANY_RUNNING_STATE (blaze_run_state))
540 {
541 ui->error("not in stop state, use stop command first\n");
542 return 0;
543 }
544
545 if ( argc > 1)
546 {
547 ui->error("show call stack, usage:\n where \n");
548 return 0;
549 }
550
551
552 for (int i=0; i<=g_vcpu_id_max; i++)
553 {
554 // for each vcpu
555 Vcpu *cpu = get_vcpu(i);
556 if (!cpu)
557 continue;
558
559 // get pc value
560 uint64_t pc = 0;
561 cpu->get_reg(VCPU_ASR_PC, &pc);
562 ui->output("cpu[%i]: pc=0x%llx ",cpu->id(), pc);
563
564 if (g_sym_table != NULL)
565 {
566 print_routine_name(pc);
567
568 // get sp value
569 uint64_t sp = 0;
570 cpu->get_reg(VCPU_IRF_0 + 14, &sp);
571
572 // get fp value
573 uint64_t fp = 0;
574 cpu->get_reg(VCPU_IRF_0 + 30, &fp);
575
576 // get ret address
577 uint64_t ret_addr = 0;
578 cpu->get_reg(VCPU_IRF_0 + 31, &ret_addr);
579
580 ui->output("called from address 0x%llx ", ret_addr);
581 print_routine_name(ret_addr);
582
583
584
585 // check trap level
586 uint64_t tl = 0;
587 cpu->get_reg(VCPU_PR_TL, &tl);
588 uint64_t cur_tl = tl;
589
590 for( ;tl > 0; tl--)
591 {
592 ui->output("Trap Level = %llx ", tl);
593 uint64_t tpc = 0;
594 cpu->set_reg(VCPU_PR_TL, tl);
595 int stat = cpu->get_reg(VCPU_PR_TPC, &tpc);
596
597 if (stat == 0)
598 {
599 print_routine_name(tpc);
600 }
601 }
602 cpu->set_reg(VCPU_PR_TL, cur_tl);
603
604
605 }
606 ui->output("\n");
607 }
608
609
610
611 return 1;
612}
613
614
615
616