Files
TempleOS-Rijn/SparrowOS/OSMain/Dbg1a.CPP
T
2018-09-08 21:45:28 +02:00

559 lines
12 KiB
C++

Bool IsDbgTask()
{
CTask *task=Fs->parent_task;
if (TaskValidate(task) && task->dbg_task==Fs)
return TRUE;
else
return FALSE;
}
Bool ChkPtr(U8 *ptr)
{
if (sys_heap_base<=ptr<=MAPPED_MEM_SPACE) {
if (*MemPtAtPageTableEntry(ptr)&1)
return TRUE;
else
return FALSE;
} else if (ptr<sys_boot_base)
return FALSE;
else if (ptr<VGA_GRAPHIC_MEM_BASE)
return TRUE;
else
return FALSE;
}
Bool ChkOnStk(U8 *ptr,CTask *task=NULL)
{
Bool result=FALSE;
PushFD;
Cli;
if (task) {
if (&task->stk->stk_base<=ptr<=(&task->stk->stk_base)(U8 *)+task->stk->stk_size)
result=TRUE;
} else if (sys_heap_base<=ptr<=sys_heap_limit)
result=TRUE;
PopFD;
return result;
}
I64 UnusedStk(CTask *task=NULL)
{
I64 result;
if (!task) task=Fs;
PushFD;
Cli;
if (task==Fs)
result=GetStkPtr()(U8 *)-(&task->stk->stk_base)(U8 *);
else
result=task->rsp(U8 *)-(&task->stk->stk_base)(U8 *);
PopFD;
return result;
}
U8 *Caller(I64 num=1)
//Returns the addr of the fun
//which called this one, or the caller
//of the caller, etc.
{
U8 **rbp=GetBasePtr,**ptr;
while (num--) {
if (rbp>=*rbp)
return NULL;
rbp=*rbp;
if (!ChkOnStk(rbp,Fs))
return NULL;
}
ptr=rbp+1;
return *ptr;
}
U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE)
{
U8 **ptr,**rbp,**rsp;
if (!task) task=Fs;
if (!saved_context && task==Fs)
return Caller(num+1);
if (!TaskValidate(task))
return NULL;
rbp=task->rbp;
rsp=task->rsp;
if (num) {
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
if (! --num)
return *ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
return NULL;
} else {
if (task->rip==SYS_IDLE_PT)
return *rsp;
else
return task->rip;
}
}
#define STK_REP_LEN 32
U0 StkRep(CTask *task=NULL)
//Reports whats on the stk
{
I64 i,j,add,
**rbp,**rsp,*my_rsp[STK_REP_LEN];
CHashTable *old_hash=Fs->hash_table;
if (!task) task=Fs;
if (!TaskValidate(task))
return;
PushFD;
Cli;
if (task==Fs) {
rbp=GetBasePtr;
rsp=rbp+3;
rbp=*rbp;
} else {
rsp=task->rsp;
rbp=task->rbp;
}
if (task->rip==SYS_IDLE_PT)
add=*rsp;
else
add=task->rip;
MemCpy(my_rsp,rsp,STK_REP_LEN*sizeof(U8 *));
PopFD;
Fs->hash_table=task->hash_table;
for (i=0;i<STK_REP_LEN;i++) {
"%08X [RSP+%04X]: %016X ",rsp+i,
i*sizeof(U8 *),my_rsp[i];
while (TRUE) {
if (!(&task->stk->stk_base<=rbp<(&task->stk->stk_base)(U8 *)+task->stk->stk_size))
break;
j=rbp-rsp;
if (j>=i)
break;
add=my_rsp[j+1];
if (rbp>=my_rsp[j])
break;
rbp=my_rsp[j];
}
if (my_rsp[i]==add)
"$$FG,RED$$";
"%P$$FG$$\n",my_rsp[i];
}
NewLine;
Fs->hash_table=old_hash;
}
U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL)
//Prints a report of calling routines
{
I64 **ptr;
if (!task) task=Fs;
if (!rbp) rbp=GetBasePtr;
"CallerRep:\n";
while (ChkOnStk(rbp,task)) {
ptr=rbp+1;
"%08X:%08tX:%P\n",ptr,*ptr,*ptr;
if (rbp>=*rbp)
break;
rbp=*rbp;
}
}
U0 DbgStr(U8 *st,I64 mS=100)
//Shows a string using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgStr(";
"" st;
')';
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgNum(I64 num,I64 mS=100)
//Shows a hex num using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgNum(%016X)",num;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgF(F64 d,I64 mS=100)
//Shows a floating-point val using
//$LK,"Raw","MN:Raw"$ screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgF(%15e)",d;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgAdd(U8 *add,I64 mS=100)
//Shows an addr using $LK,"Raw","MN:Raw"$ screen
//output for a length of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
"DbgAdd(%P)",add;
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgD(U8 *add,I64 cnt=0x80,I64 mS=100)
//Dumps a block of mem using $LK,"Raw","MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
D(add,cnt);
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 DbgDm(U8 *add,I64 cnt=0x80,I64 mS=100)
//Dumps a block of mem using $LK,"Raw","MN:Raw"$
//screen output for a fixed length
//of time.
{
Bool old_raw,old_input_filter;
PushFD;
Cli;
old_raw=Raw(ON);
old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);
Dm(add,cnt);
BusyWait(mS<<10);
PopFD;
LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);
Raw(old_raw);
}
U0 D(U8 *buf,I64 cnt=0x80,Bool show_offset=TRUE)
//Dump mem, showing offsets.
//See $LK,"DocD","MN:DocD"$() for a live dump.
{
I64 i,j,ch;
U8 *b=buf;
while (cnt) {
if (show_offset)
"%08X ",b-buf;
else
"%010X ",b;
j= cnt>16 ? 16:cnt;
for (i=0;i<j;i++)
"%02X ",b[i];
for (;i<16;i++)
" ";
for (i=0;i<j;i++) {
ch=b[i];
if (ch<CH_SHIFT_SPACE || ch==CH_BACKSPACE)
ch='.';
'' ch;
if (ch=='$$')
'' ch;
}
NewLine;
cnt-=j;
b+=j;
}
}
U0 Dm(U8 *buf,I64 cnt=0x80)
//Show mem addr, not offsets
{
D(buf,cnt,FALSE);
}
U0 Da(U8 **b,I64 cnt=0x10)
//Dump mem, showing symbolic addresses
{
while (cnt-->0) {
"%08X:%08X,%P\n",b,*b,*b;
b++;
}
}
I64 *TaskRegAdd(CTask *task,I64 reg_num)
{
switch (reg_num) {
case CREG_RAX: return &task->rax;
case CREG_RCX: return &task->rcx;
case CREG_RDX: return &task->rdx;
case CREG_RBX: return &task->rbx;
case CREG_RSP: return &task->rsp;
case CREG_RBP: return &task->rbp;
case CREG_RSI: return &task->rsi;
case CREG_RDI: return &task->rdi;
case 8 : return &task->r8;
case 9 : return &task->r9;
case 10: return &task->r10;
case 11: return &task->r11;
case 12: return &task->r12;
case 13: return &task->r13;
case 14: return &task->r14;
case 15: return &task->r15;
}
return NULL;
}
U0 Dr(CTask *task=NULL)
{//Dump registers
I64 i;
if (!task) task=Fs;
for (i=0;i<16;i++)
"%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAdd(task,i);
"RIP:%016X\n",task->rip;
}
U0 OverRideSingleUserSwap()
{
Bool old_single=SingleUser(OFF);
Yield;
SingleUser(old_single);
}
U0 DefineRegs() //A courtesy for dbgging
{
DefineLoad("RAX","Fs->rax");
DefineLoad("RBX","Fs->rbx");
DefineLoad("RCX","Fs->rcx");
DefineLoad("RDX","Fs->rdx");
DefineLoad("RSI","Fs->rsi");
DefineLoad("RDI","Fs->rdi");
DefineLoad("RBP","Fs->rbp");
DefineLoad("RSP","Fs->rsp");
DefineLoad("RIP","Fs->rip");
DefineLoad("R8" ,"Fs->r8");
DefineLoad("R9" ,"Fs->r9");
DefineLoad("R10","Fs->r10");
DefineLoad("R11","Fs->r11");
DefineLoad("R12","Fs->r12");
DefineLoad("R13","Fs->r13");
DefineLoad("R14","Fs->r14");
DefineLoad("R15","Fs->r15");
}
U8 *SysMGetS(I64)
{
U8 buf[512];
GetS(buf,512,FALSE);
return StrNew(buf);
}
U0 SysDbgExit()
{
if (IsInDbg) {
"Exit Dbg\n";
Btr(&Fs->last_lex->flags,Lf_PROMPT);
}
}
U0 Go1()
{
if (IsInDbg && ext[EXT_EXIT_DEBUGGER])
CallExtNum(EXT_EXIT_DEBUGGER);
}
U0 SysDbgEnter(Bool was_in_debugger)
{
Bool old_user_task,old_waiting_msg;
I64 i,old_dbg_mgets;
U8 buf[200];
CHashTable *tempht;
if (IsRaw) {
i=Fs->rip;
Ui(buf,&i,64);
PutS(buf);
} else
U(Fs->rip,1);
if (!was_in_debugger) {
old_waiting_msg=LBtr(&Fs->task_flags,TASKf_AWAITING_MSG);
old_user_task =LBts(&Fs->task_flags,TASKf_USER);
TaskInitExt;
sys_focus_task=Fs;
sys_cur_scan_code=0;
old_dbg_mgets=fp_mgets;
fp_mgets=&SysMGetS;
while (!mouse_install_attempts)
OverRideSingleUserSwap;
tempht=HashTableNew(STD_HASH_SIZE);
tempht->next=Fs->hash_table;
Fs->hash_table=tempht;
DefineRegs;
UserTaskCont;
Fs->hash_table=tempht->next;
HashTableDel(tempht);
fp_mgets=old_dbg_mgets;
LBEqu(&Fs->task_flags,TASKf_USER,old_user_task);
LBEqu(&Fs->task_flags,TASKf_AWAITING_MSG,old_waiting_msg);
}
}
U0 DbgHelp()
{
"\n"
"The cmd line is basically the same as normal. Here are some common\n"
"debugging commands.\n\n"
">EdLite(\"FileName\");\t\t//Edit file.\n"
">D(0x100000);\t\t\t//Dump page tables.\n"
">Dm(0x100000);\t\t\t//Dump page tables.\n"
">Dm(Fs,sizeof(CTask));\t\t//Dump current task record.\n"
">ClassRep(\"CTask\",Fs,1);\t//Dump current task record.\n"
">CallerRep;\t\t\t//Stack trace report.\n"
">Da(RSP);\t\t\t//Dump stk.\n"
">Dr;\t\t\t\t//Dump Registers.\n"
">1+2*3+&PutS;\t\t\t//Show calculation result.\n"
">*(0x70000)(I64 *)=0x123456789;\t//Assign value to 0x70000-0x70007.\n"
">RAX=0x1234;\t\t\t//Set RAX to 0x1234.\n"
">RIP=&SysThrowBreak;\t\t//Set RIP.\n"
">I64 i;\t\t\t\t//Declare variable.\n"
">i=RCX+RDX;\t\t\t//Assign to variable.\n"
">U(&PrintF+0x8);\t\t//Unassemble PrintF.\n"
">Uf(\"PutS\");\t\t\t//Unassembler function \"PutS\".\n"
">BptS(&Main+0x20);\t\t//Set break point.\n"
">BptR(&Main+0x20);\t\t//Reset (clear) break point.\n"
">BptsR;\t\t\t\t//Reset (clear) all break points.\n"
">Step;\t\t\t\t//Single step.\n"
">Go1;\t\t\t\t//Resume execution.\n"
">Go2;\t\t\t\t//Better resume execution.\n"
">Go3;\t\t\t\t//BptsR;VGAFlush;WinFocus;Go2;\n"
">Exit;\t\t\t\t//Exit (kill) task.\n\n"
"After resuming, <CTRL-ALT-T> changes focus task.\n"
"After resuming, <CTRL-ALT-F> flushes screen VGA cache.\n\n";
}
U0 Dbg(U8 *msg=NULL,I64 num=0,Bool fault=FALSE)
//Enters the debugger.
//This can be used as a kernel panic.
{
Bool was_in_dbg,was_single_user,was_raw;
I64 old_dc_flags=sys_raw_dc_flags;
PushFD;
Cli;
if (Gs->num && mp_crash) {
mp_cnt=1;
mp_crash->cpu_num=Gs->num;
mp_crash->task=Fs;
mp_crash->msg=msg;
mp_crash->msg_num=num;
MPInt(I_MP_CRASH,0);
SysHlt;
}
was_single_user=SingleUser(ON);
was_raw=Raw(ON);
was_in_dbg=InDbg(ON);
sys_raw_dc_flags|=RDCF_SHOW_DOLLAR|RDCF_SCROLL;
if (!fault && !was_in_dbg)
sys_dbg_focus_task=sys_focus_task;
"\n\tSparrowOS Debugger\n\n"
">Help;\t//For help.\n\n";
Beep(500,TRUE);
if (msg) {
"\n!!! %s",msg;
if (num)
"%016X",num;
" !!!\n\n";
}
CallerRep;
if (ext[EXT_DEBUGGER])
CallExtNum(EXT_DEBUGGER,was_in_dbg);
else {
"No Debugger\n";
SysHlt;
}
InDbg(was_in_dbg);
SingleUser(was_single_user);
Raw(was_raw);
sys_raw_dc_flags=old_dc_flags;
PopFD;
if (!fault && LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))
Exit;
}
U0 Fault2() //Called from $LK,"Fault2","FF:::/SparrowOS/OSMain/Interrupts.CPP.Z,Fault2"$
{
//$BK,1$Be careful not to swap-out and ruin the saved context$BK,0$
Bool was_raw,was_single_user;
I64 i,old_fault_num=sys_dbg_fault_num,
old_dc_flags=sys_raw_dc_flags;
U8 *old_fault_rip=sys_dbg_fault_rip;
if (Fs->fault_num==I_DIVIDE_BY_ZERO)
throw(EXCEPT_DIVIDE_BY_ZERO,Fs->rip);
was_single_user=SingleUser(ON);
if (!IsInDbg)
sys_dbg_focus_task=sys_focus_task;
sys_focus_task=NULL;
sys_dbg_fault_num=Fs->fault_num;
if (Fs->fault_num==I_BPT)
Fs->rip--;
sys_dbg_fault_rip=Fs->rip;
if (Fs->dbg_task)
CallExtNum(EXT_RESUME_DBG); //See $LK,"IDEResumeDbg","FF:::/SparrowOS/Adam/Doc/DocIDE.CPP.Z,IDEResumeDbg"$
else {
was_raw=Raw(ON);
sys_raw_dc_flags|=RDCF_SHOW_DOLLAR|RDCF_SCROLL;
"Task \"";
"" Fs->task_title;
"\"\n";
"Fault:0x%02X %Z\t\tErr Code:%08X\n",Fs->fault_num,Fs->fault_num,"ST_INT_NAMES",Fs->fault_err_code;
"RIP:%08X",Fs->rip; //Sometimes crashes on %P, so do this first
":%P RSP:%08X\n",Fs->rip,Fs->rsp;
if (Fs->fault_num==I_PAGE_FAULT) {
asm { MOV_RAX_CR2 }
i=GetRAX;
"Fault Addr:%08X:%P\n",i,i;
}
Dbg(NULL,0,TRUE);
Raw(was_raw);
sys_raw_dc_flags=old_dc_flags;
}
sys_dbg_fault_num=old_fault_num;
sys_dbg_fault_rip=old_fault_rip;
SingleUser(was_single_user);
if (LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))
Exit;
}