hschumann2/TempleOS-Source-Code
0838
1 2Bool ChkPtr(U8 *ptr)3{//Check if addr is valid ptr.4 if (mem_heap_base<=ptr<=mem_mapped_space) {5 if (*MemPageTable(ptr)&1)6 return TRUE;7 else8 return FALSE;9 } else if (ptr<mem_boot_base)10 return FALSE;11 else if (ptr<VGAM_GRAPHICS)12 return TRUE;13 else14 return FALSE;15}16 17Bool ChkCodePtr(U8 *ptr)18{//Check if addr is valid code addr.19 if (mem_heap_base<=ptr<=mem_heap_limit) {20 if (*MemPageTable(ptr)&1)21 return TRUE;22 else23 return FALSE;24 } else if (ptr<mem_boot_base)25 return FALSE;26 else if (ptr<VGAM_GRAPHICS)27 return TRUE;28 else29 return FALSE;30}31 32Bool ChkOnStk(U8 *ptr,CTask *task=NULL)33{//Check if addr is valid stk addr.34 Bool res=FALSE;35 PUSHFD36 CLI37 if (task) {38 if (&task->stk->stk_base<=ptr<=39 (&task->stk->stk_base)(U8 *)+task->stk->stk_size)40 res=TRUE;41 } else if (mem_heap_base<=ptr<=mem_heap_limit)42 res=TRUE;43 POPFD44 return res;45}46 47I64 UnusedStk(CTask *task=NULL)48{//Count of usused bytes in task's stk.49 I64 res;50 if (!task) task=Fs;51 PUSHFD52 CLI53 if (task==Fs)54 res=GetRSP()(U8 *)-(&task->stk->stk_base)(U8 *);55 else56 res=task->rsp(U8 *)-(&task->stk->stk_base)(U8 *);57 POPFD58 return res;59}60 61U8 *Caller(I64 num=1)62{//Returns the addr of the fun which called this one,63//or the caller of the caller, etc.64 U8 **rbp=GetRBP,**ptr;65 while (num--) {66 if (rbp>=*rbp)67 return NULL;68 rbp=*rbp;69 if (!ChkOnStk(rbp,Fs))70 return NULL;71 }72 ptr=rbp+1;73 return *ptr;74}75 76U8 *TaskCaller(CTask *task=NULL,I64 num=0,Bool saved_context=FALSE)77{//Fetches addr of Nth caller on task's stk.78 U8 **ptr,**rbp,**rsp;79 if (!task) task=Fs;80 if (!saved_context && task==Fs)81 return Caller(num+1);82 if (!TaskValidate(task))83 return NULL;84 rbp=task->rbp;85 rsp=task->rsp;86 if (num) {87 while (ChkOnStk(rbp,task)) {88 ptr=rbp+1;89 if (! --num)90 return *ptr;91 if (rbp>=*rbp)92 break;93 rbp=*rbp;94 }95 return NULL;96 } else {97 if (task->rip==_RET)98 return *rsp;99 else100 return task->rip;101 }102}103#define STK_REP_LEN 32104 105U0 StkRep(CTask *task=NULL)106{//Reports whats on the stk.107 I64 i,j,addr,108 **rbp,**rsp,*my_rsp[STK_REP_LEN];109 CHashTable *old_hash=Fs->hash_table;110 if (!task) task=Fs;111 if (!TaskValidate(task))112 return;113 PUSHFD114 CLI115 if (task==Fs) {116 rbp=GetRBP;117 rsp=rbp+3;118 rbp=*rbp;119 } else {120 rsp=task->rsp;121 rbp=task->rbp;122 }123 if (task->rip==_RET)124 addr=*rsp;125 else126 addr=task->rip;127 MemCpy(my_rsp,rsp,STK_REP_LEN*sizeof(U8 *));128 POPFD129 Fs->hash_table=task->hash_table;130 for (i=0;i<STK_REP_LEN;i++) {131 "%08X [RSP+%04X]: %016X ",rsp+i,132 i*sizeof(U8 *),my_rsp[i];133 while (TRUE) {134 if (!(&task->stk->stk_base<=rbp<135 (&task->stk->stk_base)(U8 *)+task->stk->stk_size))136 break;137 j=rbp-rsp;138 if (j>=i)139 break;140 addr=my_rsp[j+1];141 if (rbp>=my_rsp[j])142 break;143 rbp=my_rsp[j];144 }145 if (my_rsp[i]==addr)146 "$RED$";147 "%P$FG$\n",my_rsp[i];148 }149 '\n';150 Fs->hash_table=old_hash;151}152 153U0 CallerRep(U8 **rbp=NULL,CTask *task=NULL)154{//Prints a report of calling routines.155 I64 **ptr;156 if (!task) task=Fs;157 if (!rbp) {158 if (task==Fs)159 rbp=GetRBP;160 else161 rbp=task->rbp;162 }163 "CallerRep:\n";164 while (ChkOnStk(rbp,task)) {165 ptr=rbp+1;166 "%08X:%08tX:%P\n",ptr,*ptr,*ptr;167 if (rbp>=*rbp)168 break;169 rbp=*rbp;170 }171}172 173U0 D(U8 *addr,I64 cnt=0x80,Bool show_offset=TRUE)174{//Dump mem, showing offsets.175//See DocD() for a live dump.176 I64 i,j,ch;177 U8 *ptr=addr;178 while (cnt) {179 if (show_offset)180 "%08X ",ptr-addr;181 else182 "%010X ",ptr;183 if (cnt>16)184 j=16;185 else186 j=cnt;187 for (i=0;i<j;i++)188 "%02X ",ptr[i];189 for (;i<16;i++)190 " ";191 for (i=0;i<j;i++) {192 ch=ptr[i];193 if (ch<CH_SHIFT_SPACE || ch==CH_BACKSPACE)194 ch='.';195 '' ch;196 if (ch=='$')197 '' ch;198 }199 '\n';200 cnt-=j;201 ptr+=j;202 }203}204 205U0 Dm(U8 *addr,I64 cnt=0x80)206{//Show mem addr, not offsets.207 D(addr,cnt,FALSE);208}209 210U0 Da(U8 **addr,I64 cnt=0x10)211{//Dump mem, showing symbolic addresses.212 while (cnt-->0) {213 "%08X:%08X,%P\n",addr,*addr,*addr;214 addr++;215 }216}217 218U0 RawPrint(I64 mS=100,U8 *fmt,...)219{//Print using Raw scrn output for a length of time.220//Your heap must be good.221 U8 *buf=StrPrintJoin(NULL,fmt,argc,argv);222 Bool old_raw,old_input_filter;223 PUSHFD224 CLI225 old_raw=Raw(ON);226 old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);227 "%s",buf;228 Busy(mS<<10);229 POPFD230 LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);231 Raw(old_raw);232 Free(buf);233}234 235U0 RawD(I64 mS=100,U8 *addr,I64 cnt=0x80)236{//Dumps a block of mem using Raw237//scrn output for a fixed length238 //of time.239 Bool old_raw,old_input_filter;240 PUSHFD241 CLI242 old_raw=Raw(ON);243 old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);244 D(addr,cnt);245 Busy(mS<<10);246 POPFD247 LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);248 Raw(old_raw);249}250 251U0 RawDm(I64 mS=100,U8 *addr,I64 cnt=0x80)252{//Dumps a block of mem using Raw253//scrn output for a fixed length254 //of time.255 Bool old_raw,old_input_filter;256 PUSHFD257 CLI258 old_raw=Raw(ON);259 old_input_filter=LBtr(&Fs->task_flags,TASKf_INPUT_FILTER_TASK);260 Dm(addr,cnt);261 Busy(mS<<10);262 POPFD263 LBEqu(&Fs->task_flags,TASKf_INPUT_FILTER_TASK,old_input_filter);264 Raw(old_raw);265}266 267I64 *TaskRegAddr(CTask *task,I64 reg_num)268{269 switch (reg_num) {270 case REG_RAX: return &task->rax;271 case REG_RCX: return &task->rcx;272 case REG_RDX: return &task->rdx;273 case REG_RBX: return &task->rbx;274 case REG_RSP: return &task->rsp;275 case REG_RBP: return &task->rbp;276 case REG_RSI: return &task->rsi;277 case REG_RDI: return &task->rdi;278 case 8 : return &task->r8;279 case 9 : return &task->r9;280 case 10: return &task->r10;281 case 11: return &task->r11;282 case 12: return &task->r12;283 case 13: return &task->r13;284 case 14: return &task->r14;285 case 15: return &task->r15;286 }287 return NULL;288}289 290#define RAWDR_COL 40291 292U0 RawDr(CTask *task=NULL)293{294 I64 i,j,old_col=text.raw_col;295 Bool old_raw=Raw(ON);296 U8 buf[200];297 298 if (!task) task=Fs;299 300 for (i=0;i<16;i++) {301 text.raw_col=i*text.cols+RAWDR_COL;302 ".%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAddr(task,i);303 }304 305 text.raw_col=i++*text.cols+RAWDR_COL;306 ".RIP:%016X\n",task->rip;307 308 text.raw_col=i++*text.cols+RAWDR_COL;309 ".%-*tp\n",text.cols-(RAWDR_COL+1)-1,Fs->rip;310 311 text.raw_col=i++*text.cols+RAWDR_COL;312 '.';313 if (Bt(&sys_run_level,RLf_COMPILER)) {314 j=Fs->rip;315 Ui(buf,&j,,,TRUE);316 "%s",buf;317 } else318 '\n';319 320 text.raw_col=i*text.cols+RAWDR_COL;321 '.';322 for (j=0;j<text.cols-RAWDR_COL-1;j++)323 '.';324 325 text.raw_col=old_col;326 Raw(old_raw);327}328 329U0 Dr(CTask *task=NULL)330{//Dump regs331 I64 i;332 if (!task) task=Fs;333 for (i=0;i<16;i++)334 "%3Z:%016X\n",i,"ST_U64_REGS",*TaskRegAddr(task,i);335 "RIP:%016X\n",task->rip;336}337 338U8 *SysGetStr2(I64)339{340 U8 buf[512];341 GetS(buf,512,FALSE);342 return StrNew(buf);343}344 345CBpt *BptFind(U8 *needle_addr,CTask *haystack_task=NULL,Bool rem=FALSE)346{347 CBpt *res=NULL,*tmpb,*tmpb1,*tmpb2;348 if (!haystack_task) haystack_task=Fs;349 PUSHFD350 CLI351 tmpb1=&haystack_task->bpt_lst;352 tmpb=haystack_task->bpt_lst;353 while (tmpb) {354 tmpb2=tmpb->next;355 if (tmpb->addr==needle_addr) {356 res=tmpb;357 if (rem)358 tmpb1->next=tmpb2;359 else360 tmpb1=&tmpb->next;361 } else362 tmpb1=&tmpb->next;363 tmpb=tmpb2;364 }365 POPFD366 return res;367}368 369Bool BptS(U8 *addr,CTask *task=NULL,Bool live=TRUE)370{//Set breakpoint.371 CBpt *tmpb;372 Bool res=TRUE;373 if (!task) task=Fs;374 PUSHFD375 CLI376 if (!(tmpb=BptFind(addr,task,FALSE))) {377 tmpb=CAlloc(sizeof(CBpt),task);378 tmpb->addr=addr;379 tmpb->val=*addr;380 res=FALSE;381 tmpb->next=task->bpt_lst;382 task->bpt_lst=tmpb;383 if (task==Fs && live)384 *addr=OC_BPT;385 }386 POPFD387 return res;388}389 390Bool BptR(U8 *addr,CTask *task=NULL,Bool live=TRUE,Bool rem=TRUE)391{//Rem breakpoint.392 CBpt *tmpb;393 Bool res=FALSE;394 if (!task) task=Fs;395 PUSHFD396 CLI397 if (tmpb=BptFind(addr,task,rem)) {398 if (task==Fs && live)399 *tmpb->addr=tmpb->val;400 res=TRUE;401 if (rem)402 Free(tmpb);403 }404 POPFD405 return res;406}407 408Bool B(U8 *addr,CTask *task=NULL,Bool live=TRUE)409{//Toggle breakpoint.410//Return: TRUE if removed.411 Bool res=FALSE;412 PUSHFD413 CLI414 if (BptFind(addr,task,FALSE)) {415 BptR(addr,task,live,TRUE);416 res=TRUE;417 } else418 BptS(addr,task,live);419 POPFD420 return res;421}422 423I64 B2(CTask *task=NULL,Bool live=TRUE)424{//Rem all breakpoints.425//Return: cnt of removed.426 I64 res=0;427 CBpt *tmpb,*tmpb1;428 if (!task) task=Fs;429 PUSHFD430 CLI431 tmpb=task->bpt_lst;432 task->bpt_lst=NULL;433 while (tmpb) {434 tmpb1=tmpb->next;435 if (task==Fs && live)436 *tmpb->addr=tmpb->val;437 Free(tmpb);438 tmpb=tmpb1;439 res++;440 }441 POPFD442 return res;443}444 445U0 G(U8 *ip=INVALID_PTR,CTask *task=NULL)446{//Go447 if (!task) task=Fs;448 if (ip!=INVALID_PTR) task->rip=ip;449 if (BptFind(task->rip,task))450 "\nDo one of the following, first:\n"451 ">S;\t\t\t//Single step\n"452 ">B2;\t\t\t//Clear all break points\n"453 ">G2;\t\t\t//Clear all break points and Go\n\n"454 "After resuming, <CTRL-ALT-n> next focus task\n"455 "After resuming, <CTRL-ALT-v> flushes scrn VGA cache\n";456 else {457 LBtr(&task->task_flags,TASKf_DISABLE_BPTS);458 LBtr(&task->rflags,RFLAGf_TRAP);//No single step459 Suspend(task,FALSE);460 if (task==Fs) {461 if (IsDbgMode && task->next_cc!=&task->next_cc) {462 "Exit Dbg\n";463 Btr(&task->last_cc->flags,CCf_PMT);464 }465 } else466 Exit;467 }468}469 470U0 G2(U8 *ip=INVALID_PTR,CTask *task=NULL)471{//Rem all breakpoints and Go.472 if (!task) task=Fs;473 B2(task);474 if (ext[EXT_WIN_FOCUS])475 CallExtNum(EXT_WIN_FOCUS,dbg.focus_task);476 VGAFlush;477 G(ip,task);478}479 480public U0 S(U8 *ip=INVALID_PTR,CTask *task=NULL) //Single-step.481{//Single step.482 if (!task) task=Fs;483 PUSHFD484 CLI485 if (ip!=INVALID_PTR) task->rip=ip;486 LBts(&task->task_flags,TASKf_DISABLE_BPTS);487 LBts(&task->rflags,RFLAGf_TRAP);488 Suspend(task,FALSE);489 if (task==Fs) {490 if (IsDbgMode) {491 if (task->next_cc!=&task->next_cc)492 Btr(&task->last_cc->flags,CCf_PMT);493 }494 } else495 Exit;496 POPFD497}498 499U0 DbgHelp()500{501 "\n"502 "The cmd line is basically the same as normal. Here are some common\n"503 "debugging commands.\n\n"504 ">EdLite(\"FileName\");\t\t//Edit file.\n"505 ">D(0x100000);\t\t\t//Dump page tables.\n"506 ">Dm(0x100000);\t\t\t//Dump page tables.\n"507 ">Dm(Fs,sizeof(CTask));\t\t//Dump current task record.\n"508 ">ClassRep(Fs,\"CTask\",1);\t//Dump current task record.\n"509 ">ClassRep(Fs,,1);\t\t//(It knows lastclass.)\n"510 ">CallerRep;\t\t\t//Stack trace report.\n"511 ">Da(_RSP);\t\t\t//Dump stk.\n"512 ">Dr;\t\t\t\t//Dump Regs.\n"513 ">1+2*3+&Print;\t\t\t//Show calculation res.\n"514 ">*(0x70000)(I64 *)=0x123456789;\t//Assign value to 0x70000-0x70007.\n"515 ">_RAX=0x1234;\t\t\t//Set RAX to 0x1234.\n"516 ">_RIP=&Break;\t\t//Set RIP.\n"517 ">I64 i;\t\t\t\t//Declare variable.\n"518 ">i=_RCX+_RDX;\t\t\t//Assign to variable.\n"519 ">U(&Print+0x8);\t\t\t//Unassemble Print.\n"520 ">Uf(\"Print\");\t\t\t//Unassembler function \"Print\".\n"521 ">Man(\"Print\");\t\t\t//Edit Src for \"Print\".\n"522 ">E(_RIP);\t\t\t//Edit Src Code.\n"523 ">Fix;\t\t\t\t//Edit Last Err Src Code.\n"524 ">B(&Main+0x20);\t\t\t//Toggle break point.\n"525 ">B2;\t\t\t\t//Clear all break points.\n"526 ">S;\t\t\t\t//Single step.\n"527 ">G;\t\t\t\t//Resume execution.\n"528 ">G2;\t\t\t\t//B2;VGAFlush;WinFocus;G;\n"529 ">Exit;\t\t\t\t//Exit (kill) task.\n\n"530 "After resuming, <CTRL-ALT-n> next focus task.\n"531 "After resuming, <CTRL-ALT-v> flushes scrn VGA cache.\n\n";532}533 534U0 Dbg2()535{536 Bool old_win_inhibit,old_waiting_msg,old_single;537 I64 i,old_getstr2;538 U8 buf[200];539 if (dbg.panic) {540 if (IsRaw) {541 i=Fs->rip;542 Ui(buf,&i);543 "%s",buf;544 } else545 U(Fs->rip,1);546 } else547 dbg.panic=TRUE;548 old_waiting_msg=LBtr(&Fs->task_flags,TASKf_AWAITING_MSG);549 old_win_inhibit=Fs->win_inhibit;550 Fs->win_inhibit=WIG_USER_TASK_DFT;551 sys_focus_task=Fs;552 kbd.scan_code=0;553 old_getstr2=fp_getstr2;554 fp_getstr2=&SysGetStr2;555 old_single=SingleUser(OFF);556 while (!ms_hard.install_attempts)557 Yield;558 SingleUser(old_single);559 UserTaskCont;560 fp_getstr2=old_getstr2;561 Fs->win_inhibit=old_win_inhibit;562 LBEqu(&Fs->task_flags,TASKf_AWAITING_MSG,old_waiting_msg);563}564 565U0 Fault3(I64 fault_num,I64 fault_err_code)566{567 no_warn fault_err_code;568 PUSHFD569 CLI570 if (Gs->num && dbg.mp_crash) {571 mp_cnt=1;572 dbg.mp_crash->cpu_num=Gs->num;573 dbg.mp_crash->task=Fs;574 dbg.mp_crash->rip=Fs->rip;575 dbg.mp_crash->msg=dbg.msg;576 dbg.mp_crash->msg_num=dbg.msg_num;577 MPInt(I_MP_CRASH,0);578 SysHlt;579 }580 "\n\tTempleOS Debugger\n\n"581 ">Help;\t//For help.\n\n";582 Beep(62,TRUE);583 if (fault_num==I_DBG) {584 if (dbg.msg) {585 "\n!!! %s",dbg.msg;586 if (dbg.msg_num)587 "%016X",dbg.msg_num;588 " !!!\n\n";589 }590 }591 if (dbg.panic)592 CallerRep;593 Dbg2;594 POPFD595}596 597U0 Fault2(I64 fault_num,I64 fault_err_code)598{//Called from Fault2.599//Be careful not to swap-out and ruin the saved context600 Bool was_raw,was_single_user,was_silent,was_in_dbg;601 I64 i,old_raw_flags=text.raw_flags;602 was_single_user=SingleUser(ON);603 if (!IsDbgMode)604 dbg.focus_task=sys_focus_task;605 sys_focus_task=NULL;606 if (fault_num==I_BPT)607 Fs->rip--;608 if (Fs->dbg_task)609 CallExtNum(EXT_DBG_RESUME,fault_num,fault_err_code);610 else {611 was_raw=Raw(ON);612 was_silent=Silent(OFF);613 text.raw_flags|=RWF_SHOW_DOLLAR|RWF_SCROLL;614 615 "Task \"";616 "%s",Fs->task_title;617 "\"\n";618 "Fault:0x%02X %Z\t\tErr Code:%08X\n",619 fault_num,fault_num,"ST_INT_NAMES",fault_err_code;620 was_in_dbg=DbgMode(ON);621 "RIP:%08X",Fs->rip; //Sometimes crashes on %p, so do this first622 ":%p RSP:%08X\n",Fs->rip,Fs->rsp;623 if (fault_num==I_PAGE_FAULT) {624 MOV_RAX_CR2625 i=GetRAX;626 "Fault Addr:%08X:%p\n",i,i;627 }628 Fault3(fault_num,fault_err_code);629 DbgMode(was_in_dbg);630 Silent(was_silent);631 Raw(was_raw);632 text.raw_flags=old_raw_flags;633 }634 SingleUser(was_single_user);635 if (LBtr(&Fs->task_flags,TASKf_KILL_AFTER_DBG))636 Exit;637}638 639U0 Panic(U8 *msg=NULL,I64 msg_num=0,Bool panic=TRUE)640{//Enter the debugger with panic?641 PUSHFD642 CLI643 dbg.msg=msg;644 dbg.msg_num=msg_num;645 dbg.panic=panic;646 INT I_DBG647 POPFD648}649 650U0 Dbg(U8 *msg=NULL,I64 msg_num=0)651{//Enter debugger, no panic.652 Panic(msg,msg_num,FALSE);653}654 