add debugger function: break point & next step

This commit is contained in:
ValKmjolnir 2021-12-21 15:27:38 +08:00
parent 189d49fa4a
commit e79d1eb8a4
2 changed files with 61 additions and 22 deletions

View File

@ -7,7 +7,7 @@ class nasal_dbg:public nasal_vm
{ {
private: private:
std::vector<std::string> parse(std::string&); std::vector<std::string> parse(std::string&);
uint16_t get_fileindex(std::string); uint16_t get_fileindex(std::string&);
void err(); void err();
void help(); void help();
void interact(); void interact();
@ -37,7 +37,7 @@ std::vector<std::string> nasal_dbg::parse(std::string& cmd)
return res; return res;
} }
uint16_t nasal_dbg::get_fileindex(std::string filename) uint16_t nasal_dbg::get_fileindex(std::string& filename)
{ {
for(uint16_t i=0;i<files_size;++i) for(uint16_t i=0;i<files_size;++i)
if(filename==files[i]) if(filename==files[i])
@ -58,40 +58,47 @@ void nasal_dbg::help()
<<"<option>\n" <<"<option>\n"
<<"\th, help | get help\n" <<"\th, help | get help\n"
<<"\tbt, backtrace | get function call trace\n" <<"\tbt, backtrace | get function call trace\n"
<<"\tr, run | run program until break point or exit\n" <<"\tc, continue | run program until break point or exit\n"
<<"\tg, global | see global values\n" <<"\tg, global | see global values\n"
<<"\tl, local | see local values\n" <<"\tl, local | see local values\n"
<<"\tu, upval | see upvalue\n" <<"\tu, upval | see upvalue\n"
<<"\tquit, exit | exit debugger\n"; <<"\ta, all | show global,local and upvalue\n"
<<"\tn, next | execute next bytecode\n"
<<"\tq, exit | exit debugger\n"
<<"<option> <filename> <line>\n"
<<"\tbk, break | set break point\n";
} }
void nasal_dbg::interact() void nasal_dbg::interact()
{ {
static bool next_step=false;
static uint16_t last_fidx=0; static uint16_t last_fidx=0;
static uint32_t last_line=0; static uint32_t last_line=0;
// special operand
if(bytecode[pc].op==op_intg) if(bytecode[pc].op==op_intg)
{ {
std::cout std::cout
<<"nasal debug mode\n" <<"nasal debug mode\n"
<<"input \'h\' to get help\n"; <<"input \'h\' to get help\n";
} }
else if(bytecode[pc].op==op_exit) else if(bytecode[pc].op==op_nop || bytecode[pc].op==op_exit)
{
std::cout<<"debugger exited successfully\n";
return;
}
else if(bytecode[pc].op==op_nop)
return;
if(bytecode[pc].fidx!=last_fidx || bytecode[pc].line!=last_line)
return; return;
if(
(bytecode[pc].fidx!=last_fidx || bytecode[pc].line!=last_line) && // break point
!next_step // next step
)return;
last_fidx=0; next_step=false;
last_line=0;
std::string cmd; std::string cmd;
bytecodeinfo("->\t",pc); printf("next bytecode:\n");
for(uint32_t i=1;i<5 && bytecode[pc+i].op!=op_exit;++i)
bytecodeinfo(" \t",pc+i); uint32_t begin=(pc>>3)==0?0:((pc>>3)<<3);
uint32_t end=(1+(pc>>3))<<3;
for(uint32_t i=begin;i<end && bytecode[i].op!=op_exit;++i)
bytecodeinfo(i==pc?"->\t":" \t",i);
stackinfo(5);
while(1) while(1)
{ {
printf(">> "); printf(">> ");
@ -104,7 +111,7 @@ void nasal_dbg::interact()
help(); help();
else if(res[0]=="bt" || res[0]=="backtrace") else if(res[0]=="bt" || res[0]=="backtrace")
traceback(); traceback();
else if(res[0]=="r" || res[0]=="run") else if(res[0]=="c" || res[0]=="continue")
return; return;
else if(res[0]=="g" || res[0]=="global") else if(res[0]=="g" || res[0]=="global")
global_state(); global_state();
@ -112,13 +119,39 @@ void nasal_dbg::interact()
local_state(); local_state();
else if(res[0]=="u" || res[0]=="upval") else if(res[0]=="u" || res[0]=="upval")
upval_state(); upval_state();
else if(res[0]=="quit" || res[0]=="exit") else if(res[0]=="a" || res[0]=="all")
{
global_state();
local_state();
upval_state();
}
else if(res[0]=="n" || res[0]=="next")
{
next_step=true;
return;
}
else if(res[0]=="q" || res[0]=="exit")
std::exit(0); std::exit(0);
else else
err(); err();
break; break;
case 3: case 3:
std::cout<<"unfinished\n"; if(res[0]=="bk" || res[0]=="break")
{
last_fidx=get_fileindex(res[1]);
if(last_fidx==65535)
{
printf("cannot find file named \"%s\"\n",res[1].c_str());
last_fidx=0;
}
int tmp=atoi(res[2].c_str());
if(tmp<=0)
printf("incorrect line number \"%s\"\n",res[2].c_str());
else
last_line=tmp;
}
else
err();
break; break;
default:err();break; default:err();break;
} }
@ -173,6 +206,7 @@ vmexit:
die("stack overflow"); die("stack overflow");
gc.clear(); gc.clear();
imm.clear(); imm.clear();
printf("debugger exited\n");
return; return;
#define dbg(op) {interact();op();if(gc.top<canary)goto *code[++pc];goto vmexit;} #define dbg(op) {interact();op();if(gc.top<canary)goto *code[++pc];goto vmexit;}

View File

@ -210,13 +210,18 @@ void nasal_vm::stackinfo(const uint32_t limit=10)
uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg
nasal_ref* top=gc.top; nasal_ref* top=gc.top;
nasal_ref* bottom=gc.stack+global_size; nasal_ref* bottom=gc.stack+global_size;
if(top<bottom)
{
printf("vm stack(limit %d, total 0)\n",limit);
return;
}
printf("vm stack(limit %d, total %ld):\n",limit,top-bottom+1); printf("vm stack(limit %d, total %ld):\n",limit,top-bottom+1);
for(uint32_t i=0;i<limit && top>=bottom;++i,--top) for(uint32_t i=0;i<limit && top>=bottom;++i,--top)
valinfo(top[0]); valinfo(top[0]);
} }
void nasal_vm::global_state() void nasal_vm::global_state()
{ {
if(!bytecode[0].num) // bytecode[0].op is op_intg if(!bytecode[0].num || gc.stack[0].type==vm_none) // bytecode[0].op is op_intg
{ {
printf("no global value exists\n"); printf("no global value exists\n");
return; return;