// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: ui_elfsym.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
// The above named program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// ========== Copyright Header End ============================================
////////////////////////////////////////////////////////////
// Copyright (C) 2005-2007 Sun Microsystems, Inc.
#include "blaze_globals.h"
#include "cpu_interface.h"
SymTable
*g_sym_table
= NULL
;
extern int load_symbols(char* elf_fname
, uint64_t text_base
, uint64_t data_base
, uint32_t context
);
/////////////////////////////////////////////
static int load_sym (char *file_name
, uint32_t context
);
static int load_elf_sym(char* file_name
, uint64_t text_base
, uint64_t data_base
,
uint32_t context
=Symbol::ANY_CONTEXT
, bool elffile
=false);
static int print_symtab_usage()
ui
->output("load symbol table usage (all params are in Hex):\n load_sym -elffile|-elfsym|-vsym -f <file_name> \
[-x <text start addr>] [-d <data start addr>] [-ctx <contextID>]\n");
typedef enum { UNK_FILE
, ELF_FILE
, ELF_SYM
, V_SYM
} sym_file_t
;
int load_sym_ui_cmd (void*, int argc
, char **argv
)
if (ANY_RUNNING_STATE (blaze_run_state
))
ui
->error("not in stop state, use stop command first\n");
uint32_t context
= Symbol::ANY_CONTEXT
;
sym_file_t file_type
= UNK_FILE
;
if ( argc
< 4 || argc
> 10 )
return print_symtab_usage();
for (int i
=1; i
<argc
; i
++)
if ((strcmp(argv
[i
], "-x")==0) && ((i
+1)<argc
))
text_base
= int(strtoull(argv
[++i
], NULL
, 16));
else if ((strcmp(argv
[i
], "-d")==0) && ((i
+1)<argc
))
data_base
= int(strtoull(argv
[++i
], NULL
, 16));
else if ((strcmp(argv
[i
], "-f")==0) && ((i
+1)<argc
) )
else if ((strcmp(argv
[i
], "-ctx")==0) && ((i
+1)<argc
) )
if (strcmp(ctx
, "hv") == 0)
context
= Symbol::NO_CONTEXT
;
else if (strcmp(ctx
, "k") == 0)
context
= Symbol::NUCLEUS
;
context
= strtoul(ctx
, NULL
, 16);
ui
->error("\n -ctx <contextID> cannot figure out context id, should be 0,k,hv,or a hex number > 0 \n");
else if (strcmp(argv
[i
], "-elffile")==0)
else if (strcmp(argv
[i
], "-elfsym")==0)
else if (strcmp(argv
[i
], "-vsym")==0)
else if (strcmp(argv
[i
], "?")==0)
return print_symtab_usage();
ui
->error("missing file name \n");
return print_symtab_usage();
case ELF_FILE
: // elf file
uint32_t idx
[4] = {12, 6, 8, 6};
g_sym_table
= new SymTable(4, idx
);
load_symbols(file_name
, text_base
, data_base
, context
);
//load_elf_sym(file_name, text_base, data_base, true);
case ELF_SYM
: // symbol table extracted from elf module
load_elf_sym(file_name
, text_base
, data_base
, context
);
case V_SYM
: // special symbol file
load_sym(file_name
, context
);
ui
->error("unknown symbol table type, load_sym should have -elffile, -elfsym or -vsym.\n");
/////////////////////////////////////////////////////////////
// read symbol table file
static int load_sym (char *file_name
, uint32_t context
)
FILE *file
= fopen(file_name
,"r");
if (file
== NULL
) { ui
->perror (file_name
); return 0; }
char delimeter
[] = " :\t\n";
g_sym_table
= new SymTable();
ui
->output("Loading %s special symbols...", file_name
);
const uint64_t UNKNOWN
= ~uint64_t(0);
while(fgets(line
, 512, file
) != NULL
)
// symbolname vaddr raddr paddr
char *symbol
= strtok(line
, delimeter
);
char *addr
= strtok(NULL
, delimeter
);
uint64_t va
= strtoull(addr
, NULL
, 16);
if (strcmp(addr
, "X") == 0)
addr
= strtok(NULL
, delimeter
);
uint64_t ra
= strtoull(addr
, NULL
, 16);
if (strcmp(addr
, "X") == 0)
addr
= strtok(NULL
, delimeter
);
uint64_t pa
= strtoull(addr
, NULL
, 16);
if (strcmp(addr
, "X") == 0)
g_sym_table
->add(file_name
,symbol
, va
, 4, context
);
//////////////////////////////////////////////////////////
sprintf( sline
, "nm -xvs %s", file_name
);
file
= popen( sline
, "r" );
file
= fopen( file_name
,"r" );
char delimeter
[] = " |\n";
uint32_t idx
[4] = {12, 6, 8, 6};
g_sym_table
= new SymTable(4, idx
);
ui
->output("Loading %s elf symbols...", file_name
);
while(fgets(sline
, bsize
, file
) != NULL
)
if ((sline
[0]=='[') && !isdigit(sline
[1]))
// parse symbol info line
// [Index] | Value | Size | Type | Bind | Other | Shname | Name
char *idx
= strtok(sline
, delimeter
);
char *value
= strtok(NULL
, delimeter
);
char *size
= strtok(NULL
, delimeter
);
char *type
= strtok(NULL
, delimeter
);
char *bind
= strtok(NULL
, delimeter
);
char *oth
= strtok(NULL
, delimeter
);
char *shname
= strtok(NULL
, delimeter
);
char *name
= strtok(NULL
, delimeter
);
uint64_t va
= strtoull(value
, NULL
, 16);
uint64_t sz
= strtoull(size
, NULL
, 16);
if (sz
== 0) // skip symbols(lebels) with zero size
if ( strcmp (shname
, ".text") == 0)
else if (strcmp (type
, "OBJT") == 0)
if (strcmp (shname
, ".data") == 0)
else if (strcmp (shname
, ".bss" )==0)
if (strcmp (bind
, "GLOB" ) == 0)
g_sym_table
->add(file_name
, name
, va
, sz
, context
);
//////////////////////////////////////////////////////////
int unload_sym_ui_cmd (void*, int argc
, char **argv
)
if (ANY_RUNNING_STATE (blaze_run_state
))
ui
->error("not in stop state, use stop command first\n");
ui
->error("unload symbol table, usage:\n unload_sym \n");
//////////////////////////////////////////////////////////
static int print_sym_usage()
ui
->output("sym command usage:\n sym [-ctx <contextID>] [-o filename]-all|-a <addr>|-s <name>\n");
int symbols_ui_cmd (void*, int argc
, char **argv
)
ui
->error("There is no symbol table allocated \n");
uint32_t context
= Symbol::ANY_CONTEXT
;
return print_sym_usage();
for (int i
=1; i
<argc
; i
++)
if (strcmp(argv
[i
], "-all")==0)
g_sym_table
->print(file_name
, context
);
else if (strcmp(argv
[i
], "-hash")==0)
g_sym_table
->hprint(file_name
, context
);
else if ((strcmp(argv
[i
], "-s")==0) && ((i
+1)<argc
) )
// search for symbol by name
if (!g_sym_table
->fputs(name
, context
, ui
->get_output_file()))
ui
->error("%s not found\n", name
);
g_sym_table
->fputs(name
, context
, ui
->get_log_file());
else if ((strcmp(argv
[i
], "-a")==0) && ((i
+1)<argc
))
uint64_t vaddr
= strtoull(addr
, NULL
, 16);
if (g_sym_table
->fputs(vaddr
, context
, ui
->get_output_file()))
g_sym_table
->fputs(vaddr
, context
, ui
->get_log_file());
ui
->output("at address = 0x%llx\n", vaddr
);
g_sym_table
->fputs(vaddr
, context
, ui
->get_log_file());
ui
->error("address %s not found\n", addr
);
else if ((strcmp(argv
[i
], "-ctx")==0) && ((i
+1)<argc
) )
if (strcmp(ctx
, "hv") == 0)
context
= Symbol::NO_CONTEXT
;
else if (strcmp(ctx
, "k") == 0)
context
= Symbol::NUCLEUS
;
context
= strtoul(ctx
, NULL
, 16);
ui
->error("-ctx <contextID> cannot figure out context id, should be 0,k,hv,or a hex number > 0 \n");
else if ((strcmp(argv
[i
], "-o")==0) && ((i
+1)<argc
) )
else if (strcmp(argv
[i
], "?")==0)
return print_sym_usage();
//////////////////////////////////////////////////////////////
static int print_routine_name ( uint64_t pc
)
if (!g_sym_table
->fputs(pc
, Symbol::ANY_CONTEXT
, ui
->get_output_file()))
ui
->error("unknown routine \n");
g_sym_table
->fputs(pc
, Symbol::ANY_CONTEXT
, ui
->get_log_file());
int where_ui_cmd (void*, int argc
, char **argv
)
if (ANY_RUNNING_STATE (blaze_run_state
))
ui
->error("not in stop state, use stop command first\n");
ui
->error("show call stack, usage:\n where \n");
for (int i
=0; i
<=g_vcpu_id_max
; i
++)
cpu
->get_reg(VCPU_ASR_PC
, &pc
);
ui
->output("cpu[%i]: pc=0x%llx ",cpu
->id(), pc
);
cpu
->get_reg(VCPU_IRF_0
+ 14, &sp
);
cpu
->get_reg(VCPU_IRF_0
+ 30, &fp
);
cpu
->get_reg(VCPU_IRF_0
+ 31, &ret_addr
);
ui
->output("called from address 0x%llx ", ret_addr
);
print_routine_name(ret_addr
);
cpu
->get_reg(VCPU_PR_TL
, &tl
);
ui
->output("Trap Level = %llx ", tl
);
cpu
->set_reg(VCPU_PR_TL
, tl
);
int stat
= cpu
->get_reg(VCPU_PR_TPC
, &tpc
);
cpu
->set_reg(VCPU_PR_TL
, cur_tl
);