Trivial Solutions The LoseThos 64-bit PC Operating System File:/LT/OSMain/Dbg1a.CPZ This, and all LoseThos files, are public domain. Do whatever you like. God is watching; God is just; God is never out-done in generosity. He talks! LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote. Boot the LoseThos CD and you can compile it. Not in Kansas anymore! Click here for preliminary compiler information you need. Project: OSMain BoolI64 IsDbgTask() { TaskStruct *task=Fs->parent_task; if (TaskValidate(task) && task->dbg_task==Fs) return TRUE; else return FALSE; } BoolI64 ChkPtr(U0 *ptr) { if (sys_heap_base<=ptr<=MAPPED_MEM_SPACE) { if (*MemPointAtPageTableEntry(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; } BoolI64 ChkOnStk(U0 *ptr,TaskStruct *task=NULL) { BoolI8 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(TaskStruct *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; } U0 *Caller(U64 num=1) //Returns the address of the fun //which called this one, or the caller //of the caller, etc. { U0 **rbp=GetBasePtr,**ptr; while (num--) { if (rbp>=*rbp) return NULL; rbp=*rbp; if (!ChkOnStk(rbp,Fs)) return NULL; } ptr=rbp+1; return *ptr; } U0 *TaskCaller(TaskStruct *task=NULL,I64 num=0,BoolI8 saved_context=FALSE) { U0 **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_POINT) return *rsp; else return task->rip; } } #define STK_REP_LEN 32 U0 StkRep(TaskStruct *task=NULL) //Reports whats on the stk { I64 i,j,add; U64 **rbp,**rsp; U64 *my_rsp[STK_REP_LEN]; SysHashTable *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_POINT) add=*rsp; else add=task->rip; MemCpy(my_rsp,rsp,STK_REP_LEN*sizeof(U0 *)); PopFD; Fs->hash_table=task->hash_table; for (i=0;i<STK_REP_LEN;i++) { PrintF("%08X [RSP+%04X]: %016X ",rsp+i, i*sizeof(U0 *),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) cout "$FG,RED$"; PrintF("%P$FG$\r\n",my_rsp[i]); } CrLf; Fs->hash_table=old_hash; } U0 CallerRep(U0 **rbp=NULL,TaskStruct *task=NULL) //Prints a report of calling routines { U64 **ptr; if (!task) task=Fs; if (!rbp) rbp=GetBasePtr; while (ChkOnStk(rbp,task)) { ptr=rbp+1; PrintF("%08X:%08tX:%P\r\n",ptr,*ptr,*ptr); if (rbp>=*rbp) break; rbp=*rbp; } } U0 DbgStr(U8 *st,U64 mS=100) //Shows a string using //Raw screen output for a fixed length //of time. { BoolI8 old_raw,old_input_filter; PushFD; Cli; old_raw=Raw(ON); old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK); cout "DbgStr(",st,")"; BusyWait(mS<<10); PopFD; LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter); Raw(old_raw); } U0 DbgNum(U64 num,U64 mS=100) //Shows a hex num using //Raw screen output for a fixed length //of time. { BoolI8 old_raw,old_input_filter; PushFD; Cli; old_raw=Raw(ON); old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK); cout "DbgNum(",num,")"; BusyWait(mS<<10); PopFD; LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter); Raw(old_raw); } U0 DbgF(F64 d,U64 mS=100) //Shows a floating-point val using //Raw screen output for a fixed length //of time. { BoolI8 old_raw,old_input_filter; PushFD; Cli; old_raw=Raw(ON); old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK); cout "DbgF(",d,")"; BusyWait(mS<<10); PopFD; LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter); Raw(old_raw); } U0 DbgAdd(U0 *add,U64 mS=100) //Shows an address using Raw screen //output for a length of time. { BoolI8 old_raw,old_input_filter; PushFD; Cli; old_raw=Raw(ON); old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK); PrintF("DbgAdd(%P)",add); BusyWait(mS<<10); PopFD; LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter); Raw(old_raw); } U0 DbgD(U0 *add,U64 cnt=0x80,U64 mS=100) //Dumps a block of mem using Raw //screen output for a fixed length //of time. { BoolI8 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(U0 *add,U64 cnt=0x80,U64 mS=100) //Dumps a block of mem using Raw //screen output for a fixed length //of time. { BoolI8 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,U64 cnt=0x80,BoolI8 show_offset=TRUE) //Dump mem, showing offsets. //See LtfD() for a live dump. { U64 i,j,ch; U8 *b=buf; while (cnt) { if (show_offset) cout (b-buf)><(U32)," "; else cout b><(U64)," "; j= cnt>16 ? 16:cnt; for (i=0;i<j;i++) cout b[i]," "; for (;i<16;i++) cout " "; for (i=0;i<j;i++) { ch=b[i]; if (ch<CH_SHIFT_SPACE || ch==CH_BACKSPACE) ch='.'; PutChar(ch); if (ch=='$') PutChar(ch); } CrLf; cnt-=j; b+=j; } } U0 Dm(U8 *buf,U64 cnt=0x80) //Show mem address, not offsets { D(buf,cnt,FALSE); } U0 Da(U0 **b,U64 cnt=0x10) //Dump mem, showing symic addresses { while (cnt-->0) { PrintF("%08X:%08X,%P\r\n",b,*b,*b); b++; } } U64 *TaskRegAdd(TaskStruct *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(TaskStruct *task=NULL) {//Dump registers U64 i; if (!task) task=Fs; for (i=0;i<16;i++) PrintF("%3Z:%016X\r\n",i,"ST_U64_REGS",*TaskRegAdd(task,i)); PrintF("RIP:%016X\r\n",task->rip); } U0 OverRideSingleUserSwap() { BoolI8 old_single=SingleUser(OFF); Yield; SingleUser(old_single); } U0 DbgExit() { if (IsInDbg && ext[EXT_EXIT_DEBUGGER]) CallExtNum(EXT_EXIT_DEBUGGER); } U0 Dbg(U8 *msg=NULL,U64 num=0,BoolI8 fault=FALSE) //Enters the debugger. //This can be used as a kernel panic. { BoolI8 was_in_dbg,was_single_user,was_raw; U64 old_dc_flags=sys_dc_flags; 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_dc_flags|=DCF_SHOW_DOLLAR|DCF_SCROLL; coutln "\r\n\tLoseThos Debugger"; coutln "Use EdLite(\"name\"); for editing."; coutln "\"DbgExit;\" might work.\r\n"; Beep(500,TRUE); if (msg) { cout "\r\n!!! ",msg; if (num) cout num; cout " !!!\r\n\r\n"; } CallerRep; if (ext[EXT_DEBUGGER]) CallExtNum(EXT_DEBUGGER,was_in_dbg); else { coutln "No Debugger"; while (TRUE); } InDbg(was_in_dbg); SingleUser(was_single_user); Raw(was_raw); sys_dc_flags=old_dc_flags; if (!fault && LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG)) Exit; } U0 Fault2() { //Be careful not to swap-out and ruin the saved context BoolI8 was_raw,was_single_user; U64 i,old_fault_num=sys_dbg_fault_num; U8 *old_fault_rip=sys_dbg_fault_rip; U64 old_dc_flags=sys_dc_flags; if (Fs->fault_num==I_DIVIDE_BY_ZERO) throw(EXCEPT_DIVIDE_BY_ZERO,Fs->rip); was_single_user=SingleUser(ON); sys_cur_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 IDEResumeDbg else { was_raw=Raw(ON); sys_dc_flags|=DCF_SHOW_DOLLAR|DCF_SCROLL; coutln "Task \"",Fs->task_title,"\""; PrintF("Fault:0x%02X %Z\t\tErr Code:%08X\r\n",Fs->fault_num,Fs->fault_num,"ST_INT_NAMES",Fs->fault_err_code); PrintF("RIP:%08X",Fs->rip); //Sometimes crashes on %P, so do this first PrintF(":%P RSP:%08X\r\n",Fs->rip,Fs->rsp); if (Fs->fault_num==I_PAGE_FAULT) { asm { MOV_RAX_CR2 } i=GetRAX; PrintF("Fault Address:%08X:%P\r\n",i,i); } Dbg(NULL,0,TRUE); Raw(was_raw); sys_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; }