/**
|
/**
|
* @file
|
* @file
|
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
* @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved.
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* @author Sergey Khabarov - sergeykhbr@gmail.com
|
* @brief Disassemble data block command.
|
* @brief Disassemble data block command.
|
*/
|
*/
|
|
|
#include <string>
|
#include <string>
|
#include "cmd_disas.h"
|
#include "cmd_disas.h"
|
|
|
namespace debugger {
|
namespace debugger {
|
|
|
CmdDisas::CmdDisas(ITap *tap, ISocInfo *info)
|
CmdDisas::CmdDisas(ITap *tap, ISocInfo *info)
|
: ICommand ("disas", tap, info) {
|
: ICommand ("disas", tap, info) {
|
|
|
briefDescr_.make_string("Disassemble block of data.");
|
briefDescr_.make_string("Disassemble block of data.");
|
detailedDescr_.make_string(
|
detailedDescr_.make_string(
|
"Description:\n"
|
"Description:\n"
|
" Disassemble memory range or a block of data. Convert result\n"
|
" Disassemble memory range or a block of data. Convert result\n"
|
" to a list of assembler items where each of them has\n"
|
" to a list of assembler items where each of them has\n"
|
" ASM_Total sub-items. You can add 'str' flag to receive\n"
|
" ASM_Total sub-items. You can add 'str' flag to receive\n"
|
" formatted text output.\n"
|
" formatted text output.\n"
|
"Usage:\n"
|
"Usage:\n"
|
" disas <addr> <byte> [str]\n"
|
" disas <addr> <byte> [str]\n"
|
" disas <addr> <data> [str]\n"
|
" disas <addr> <data> [str]\n"
|
"Example:\n"
|
"Example:\n"
|
" data 0x40000000 100\n"
|
" data 0x40000000 100\n"
|
" data 0x40000000 100 str\n"
|
" data 0x40000000 100 str\n"
|
" data 0x1000 (73,00,10,00)\n"
|
" data 0x1000 (73,00,10,00)\n"
|
" ['data',0x1000,(73,00,10,00)]\n");
|
" ['data',0x1000,(73,00,10,00)]\n");
|
|
|
AttributeType lstServ;
|
AttributeType lstServ;
|
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
|
RISCV_get_services_with_iface(IFACE_SOURCE_CODE, &lstServ);
|
isrc_ = 0;
|
isrc_ = 0;
|
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());
|
isrc_ = static_cast<ISourceCode *>(
|
isrc_ = static_cast<ISourceCode *>(
|
iserv->getInterface(IFACE_SOURCE_CODE));
|
iserv->getInterface(IFACE_SOURCE_CODE));
|
}
|
}
|
}
|
}
|
|
|
bool CmdDisas::isValid(AttributeType *args) {
|
bool CmdDisas::isValid(AttributeType *args) {
|
if ((*args)[0u].is_equal(cmdName_.to_string())
|
if ((*args)[0u].is_equal(cmdName_.to_string())
|
&& args->size() >= 3 && (*args)[1].is_integer()
|
&& args->size() >= 3 && (*args)[1].is_integer()
|
&& ((*args)[2].is_data() || (*args)[2].is_integer())
|
&& ((*args)[2].is_data() || (*args)[2].is_integer())
|
) {
|
) {
|
return CMD_VALID;
|
return CMD_VALID;
|
}
|
}
|
return CMD_INVALID;
|
return CMD_INVALID;
|
}
|
}
|
|
|
void CmdDisas::exec(AttributeType *args, AttributeType *res) {
|
void CmdDisas::exec(AttributeType *args, AttributeType *res) {
|
res->make_nil();
|
res->make_nil();
|
if (!isrc_ || !isValid(args)) {
|
if (!isrc_ || !isValid(args)) {
|
generateError(res, "Wrong argument list");
|
generateError(res, "Wrong argument list");
|
return;
|
return;
|
}
|
}
|
res->make_list(0);
|
res->make_list(0);
|
|
|
uint64_t addr = (*args)[1].to_uint64();
|
uint64_t addr = (*args)[1].to_uint64();
|
AttributeType *mem_data, *asm_data;
|
AttributeType *mem_data, *asm_data;
|
AttributeType membuf, asmbuf;
|
AttributeType membuf, asmbuf;
|
if ((*args)[2].is_integer()) {
|
if ((*args)[2].is_integer()) {
|
// 4-bytes alignment
|
// 4-bytes alignment
|
uint32_t sz = ((*args)[2].to_uint32() + 3) & ~0x3;
|
uint32_t sz = ((*args)[2].to_uint32() + 3) & ~0x3;
|
membuf.make_data(sz);
|
membuf.make_data(sz);
|
mem_data = &membuf;
|
mem_data = &membuf;
|
if (tap_->read(addr, sz, membuf.data()) == TAP_ERROR) {
|
if (tap_->read(addr, sz, membuf.data()) == TAP_ERROR) {
|
res->make_nil();
|
res->make_nil();
|
return;
|
return;
|
}
|
}
|
} else {
|
} else {
|
mem_data = &(*args)[2];
|
mem_data = &(*args)[2];
|
}
|
}
|
|
|
asm_data = res;
|
asm_data = res;
|
bool do_format = false;
|
bool do_format = false;
|
if (args->size() == 4 && (*args)[3].is_equal("str")) {
|
if (args->size() == 4 && (*args)[3].is_equal("str")) {
|
asm_data = &asmbuf;
|
asm_data = &asmbuf;
|
do_format = true;
|
do_format = true;
|
}
|
}
|
|
|
isrc_->disasm(addr, mem_data, asm_data);
|
isrc_->disasm(addr, mem_data, asm_data);
|
|
|
if (do_format) {
|
if (do_format) {
|
format(asm_data, res);
|
format(asm_data, res);
|
}
|
}
|
}
|
}
|
|
|
void CmdDisas::format(AttributeType *asmbuf, AttributeType *fmtstr) {
|
void CmdDisas::format(AttributeType *asmbuf, AttributeType *fmtstr) {
|
char tstr[128];
|
char tstr[128];
|
std::string tout;
|
std::string tout;
|
for (unsigned i = 0; i < asmbuf->size(); i++) {
|
for (unsigned i = 0; i < asmbuf->size(); i++) {
|
const AttributeType &line = (*asmbuf)[i];
|
const AttributeType &line = (*asmbuf)[i];
|
if (line[ASM_list_type].to_int() != AsmList_disasm) {
|
if (line[ASM_list_type].to_int() != AsmList_disasm) {
|
continue;
|
continue;
|
}
|
}
|
RISCV_sprintf(tstr, sizeof(tstr), "%016" RV_PRI64 "x: %08x %s\n",
|
RISCV_sprintf(tstr, sizeof(tstr), "%016" RV_PRI64 "x: %08x %s\n",
|
line[ASM_addrline].to_uint64(),
|
line[ASM_addrline].to_uint64(),
|
line[ASM_code].to_uint32(),
|
line[ASM_code].to_uint32(),
|
line[ASM_mnemonic].to_string()
|
line[ASM_mnemonic].to_string()
|
);
|
);
|
tout += tstr;
|
tout += tstr;
|
}
|
}
|
fmtstr->make_string(tout.c_str());
|
fmtstr->make_string(tout.c_str());
|
}
|
}
|
|
|
} // namespace debugger
|
} // namespace debugger
|
|
|