/**
|
/**
|
* @file
|
* @file
|
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
|
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* @brief Read CPU stack trace buffer.
|
* @brief Read CPU stack trace buffer.
|
*/
|
*/
|
|
|
#include "cmd_stack.h"
|
#include "cmd_stack.h"
|
#include "iservice.h"
|
#include "iservice.h"
|
#include "coreservices/ielfreader.h"
|
#include "coreservices/ielfreader.h"
|
|
|
namespace debugger {
|
namespace debugger {
|
|
|
CmdStack::CmdStack(ITap *tap, ISocInfo *info)
|
CmdStack::CmdStack(ITap *tap, ISocInfo *info)
|
: ICommand ("stack", tap, info) {
|
: ICommand ("stack", tap, info) {
|
|
|
briefDescr_.make_string("Read CPU Stack Trace buffer");
|
briefDescr_.make_string("Read CPU Stack Trace buffer");
|
detailedDescr_.make_string(
|
detailedDescr_.make_string(
|
"Description:\n"
|
"Description:\n"
|
" Read CPU stack trace buffer. Buffer's size is defined\n"
|
" Read CPU stack trace buffer. Buffer's size is defined\n"
|
" by VHDL configuration parameter:\n"
|
" by VHDL configuration parameter:\n"
|
"Usage:\n"
|
"Usage:\n"
|
" stack <depth>\n"
|
" stack <depth>\n"
|
"Example:\n"
|
"Example:\n"
|
" stack\n"
|
" stack\n"
|
" stack 3\n");
|
" stack 3\n");
|
}
|
}
|
|
|
bool CmdStack::isValid(AttributeType *args) {
|
bool CmdStack::isValid(AttributeType *args) {
|
if ((*args)[0u].is_equal(cmdName_.to_string()) && (args->size() == 1
|
if ((*args)[0u].is_equal(cmdName_.to_string()) && (args->size() == 1
|
|| (args->size() == 2 && (*args)[1].is_integer()))) {
|
|| (args->size() == 2 && (*args)[1].is_integer()))) {
|
return CMD_VALID;
|
return CMD_VALID;
|
}
|
}
|
return CMD_INVALID;
|
return CMD_INVALID;
|
}
|
}
|
|
|
void CmdStack::exec(AttributeType *args, AttributeType *res) {
|
void CmdStack::exec(AttributeType *args, AttributeType *res) {
|
res->make_list(0);
|
res->make_list(0);
|
if (!isValid(args)) {
|
if (!isValid(args)) {
|
generateError(res, "Wrong argument list");
|
generateError(res, "Wrong argument list");
|
return;
|
return;
|
}
|
}
|
|
|
Reg64Type t1;
|
Reg64Type t1;
|
DsuMapType *pdsu = info_->getpDsu();
|
DsuMapType *pdsu = info_->getpDsu();
|
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_cnt);
|
uint64_t addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_cnt);
|
t1.val = 0;
|
t1.val = 0;
|
tap_->read(addr, 8, t1.buf);
|
tap_->read(addr, 8, t1.buf);
|
|
|
addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_buf[0]);
|
addr = reinterpret_cast<uint64_t>(&pdsu->ureg.v.stack_trace_buf[0]);
|
unsigned trace_sz = t1.buf32[0];
|
unsigned trace_sz = t1.buf32[0];
|
if (args->size() == 2 && args[1].to_uint64() < trace_sz) {
|
if (args->size() == 2 && args[1].to_uint64() < trace_sz) {
|
addr += 8 * (trace_sz - args[1].to_uint32());
|
addr += 8 * (trace_sz - args[1].to_uint32());
|
trace_sz = args[1].to_uint32();
|
trace_sz = args[1].to_uint32();
|
}
|
}
|
|
|
if (trace_sz == 0) {
|
if (trace_sz == 0) {
|
return;
|
return;
|
}
|
}
|
|
|
AttributeType tbuf, lstServ;
|
AttributeType tbuf, lstServ;
|
uint64_t *p_data;
|
uint64_t *p_data;
|
IElfReader *elf = 0;
|
IElfReader *elf = 0;
|
uint64_t from_addr, to_addr;
|
uint64_t from_addr, to_addr;
|
tbuf.make_data(16*trace_sz);
|
tbuf.make_data(16*trace_sz);
|
tap_->read(addr, tbuf.size(), tbuf.data());
|
tap_->read(addr, tbuf.size(), tbuf.data());
|
|
|
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
|
RISCV_get_services_with_iface(IFACE_ELFREADER, &lstServ);
|
if (lstServ.size() >= 0) {
|
if (lstServ.size() >= 0) {
|
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
|
IService *iserv = static_cast<IService *>(lstServ[0u].to_iface());
|
elf = static_cast<IElfReader *>(iserv->getInterface(IFACE_ELFREADER));
|
elf = static_cast<IElfReader *>(iserv->getInterface(IFACE_ELFREADER));
|
}
|
}
|
|
|
res->make_list(t1.buf32[0]);
|
res->make_list(t1.buf32[0]);
|
p_data = reinterpret_cast<uint64_t *>(tbuf.data());
|
p_data = reinterpret_cast<uint64_t *>(tbuf.data());
|
for (unsigned i = 0; i < trace_sz; i++) {
|
for (unsigned i = 0; i < trace_sz; i++) {
|
AttributeType &item = (*res)[i];
|
AttributeType &item = (*res)[i];
|
from_addr = p_data[2*(trace_sz - i) - 2];
|
from_addr = p_data[2*(trace_sz - i) - 2];
|
to_addr = p_data[2*(trace_sz - i) - 1];
|
to_addr = p_data[2*(trace_sz - i) - 1];
|
// [from, ['symb_name',symb_offset], to, ['symb_name',symb_offset]]
|
// [from, ['symb_name',symb_offset], to, ['symb_name',symb_offset]]
|
item.make_list(4);
|
item.make_list(4);
|
item[0u].make_uint64(from_addr);
|
item[0u].make_uint64(from_addr);
|
item[2].make_uint64(to_addr);
|
item[2].make_uint64(to_addr);
|
if (elf) {
|
if (elf) {
|
elf->addressToSymbol(from_addr, &item[1]);
|
elf->addressToSymbol(from_addr, &item[1]);
|
elf->addressToSymbol(to_addr, &item[3]);
|
elf->addressToSymbol(to_addr, &item[3]);
|
}
|
}
|
}
|
}
|
}
|
}
|
|
|
} // namespace debugger
|
} // namespace debugger
|
|
|