mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2025-04-11 18:28:36 +01:00
766 lines
15 KiB
HolyC
Executable file
766 lines
15 KiB
HolyC
Executable file
Bool CheckPtr(U8 *ptr)
|
||
{//Check if address is valid pointer.
|
||
if (mem_heap_base <= ptr <= mem_mapped_space)
|
||
return *MemPageTable(ptr) & 1;
|
||
else
|
||
return mem_boot_base < ptr < VGAM_GRAPHICS;
|
||
}
|
||
|
||
Bool CheckCodePtr(U8 *ptr)
|
||
{//Check if address is valid code address.
|
||
if (mem_heap_base <= ptr <= mem_heap_limit)
|
||
return *MemPageTable(ptr) & 1;
|
||
else
|
||
return mem_boot_base < ptr < VGAM_GRAPHICS;
|
||
}
|
||
|
||
Bool CheckOnStack(U8 *ptr, CTask *task=NULL)
|
||
{//Check if address is valid stack address.
|
||
Bool res = FALSE;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (task)
|
||
{
|
||
if (&task->stack->stack_base <= ptr <= (&task->stack->stack_base)(U8 *) + task->stack->stack_size)
|
||
res = TRUE;
|
||
}
|
||
else if (mem_heap_base <= ptr <= mem_heap_limit)
|
||
res = TRUE;
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
I64 UnusedStack(CTask *task=NULL)
|
||
{//Count of usused bytes in task's stack.
|
||
I64 res;
|
||
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (task == Fs)
|
||
res = RSPGet()(U8 *) - (&task->stack->stack_base)(U8 *);
|
||
else
|
||
res = task->rsp(U8 *) - (&task->stack->stack_base)(U8 *);
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
U8 *Caller(I64 num=1)
|
||
{//Returns the address of the function which called this one,
|
||
//or the caller of the caller, etc.
|
||
U8 **rbp = RBPGet, **ptr;
|
||
|
||
while (num--)
|
||
{
|
||
if (rbp >= *rbp)
|
||
return NULL;
|
||
rbp = *rbp;
|
||
if (!CheckOnStack(rbp, Fs))
|
||
return NULL;
|
||
}
|
||
ptr = rbp + 1;
|
||
return *ptr;
|
||
}
|
||
|
||
U8 *TaskCaller(CTask *task=NULL, I64 num=0, Bool saved_context=FALSE)
|
||
{//Fetches address of Nth caller on task's stack.
|
||
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 (CheckOnStack(rbp, task))
|
||
{
|
||
ptr = rbp + 1;
|
||
if (! --num)
|
||
return *ptr;
|
||
if (rbp >= *rbp)
|
||
break;
|
||
rbp = *rbp;
|
||
}
|
||
return NULL;
|
||
}
|
||
else
|
||
{
|
||
if (task->rip == _RET)
|
||
return *rsp;
|
||
else
|
||
return task->rip;
|
||
}
|
||
}
|
||
#define STACK_REP_LEN 32
|
||
|
||
U0 StackRep(CTask *task=NULL)
|
||
{//Reports whats on the stack.
|
||
I64 i, j, addr, **rbp, **rsp, *my_rsp[STACK_REP_LEN];
|
||
CHashTable *old_hash = Fs->hash_table;
|
||
|
||
if (!task)
|
||
task = Fs;
|
||
if (!TaskValidate(task))
|
||
return;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (task == Fs)
|
||
{
|
||
rbp = RBPGet;
|
||
rsp = rbp + 3;
|
||
rbp = *rbp;
|
||
}
|
||
else
|
||
{
|
||
rsp = task->rsp;
|
||
rbp = task->rbp;
|
||
}
|
||
if (task->rip == _RET)
|
||
addr = *rsp;
|
||
else
|
||
addr = task->rip;
|
||
MemCopy(my_rsp, rsp, STACK_REP_LEN * sizeof(U8 *));
|
||
POPFD
|
||
|
||
Fs->hash_table = task->hash_table;
|
||
if (!IsRaw)
|
||
"$$LTCYAN$$";
|
||
"RSP RSP+Offset: Value Value/Link\n";
|
||
if (!IsRaw)
|
||
"$$FG$$";
|
||
for (i = 0; i < STACK_REP_LEN; i++)
|
||
{
|
||
"%08X [RSP+%04X]: %016X ", rsp + i, i * sizeof(U8 *), my_rsp[i];
|
||
while (TRUE)
|
||
{
|
||
if (!(&task->stack->stack_base <= rbp < (&task->stack->stack_base)(U8 *) + task->stack->stack_size))
|
||
break;
|
||
j = rbp - rsp;
|
||
if (j >= i)
|
||
break;
|
||
addr = my_rsp[j + 1];
|
||
if (rbp >= my_rsp[j])
|
||
break;
|
||
rbp = my_rsp[j];
|
||
}
|
||
if (my_rsp[i] == addr && !IsRaw)
|
||
"$$BG,YELLOW$$";
|
||
"%P", my_rsp[i];
|
||
if (!IsRaw)
|
||
"$$BG$$";
|
||
'\n';
|
||
}
|
||
'\n';
|
||
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)
|
||
{
|
||
if (task == Fs)
|
||
rbp = RBPGet;
|
||
else
|
||
rbp = task->rbp;
|
||
}
|
||
"CallerRep:\n";
|
||
if (!IsRaw)
|
||
"$$LTCYAN$$RBP: *RBP: *RBP:$$FG$$\n";
|
||
else
|
||
"RBP: *RBP: *RBP\n";
|
||
while (CheckOnStack(rbp, task))
|
||
{
|
||
ptr = rbp + 1;
|
||
"%08X: %08tX: %P\n", ptr, *ptr, *ptr;
|
||
if (rbp >= *rbp)
|
||
break;
|
||
rbp = *rbp;
|
||
}
|
||
}
|
||
|
||
U0 D(U8 *addr, I64 count=0x80, Bool show_offset=TRUE)
|
||
{//Dump mem, showing offsets.
|
||
//See $LK,"DocD",A="MN:DocD"$() for a live dump.
|
||
I64 i, j, ch;
|
||
U8 *ptr = addr;
|
||
|
||
while (count)
|
||
{
|
||
if (show_offset)
|
||
"%08X ", ptr - addr;
|
||
else
|
||
"%010X ", ptr;
|
||
if (count > 16)
|
||
j = 16;
|
||
else
|
||
j = count;
|
||
for (i = 0; i < j; i++)
|
||
"%02X ", ptr[i];
|
||
for (; i < 16; i++)
|
||
" ";
|
||
for (i = 0; i < j; i++)
|
||
{
|
||
ch = ptr[i];
|
||
if (ch < CH_SPACE || ch == CH_BACKSPACE)
|
||
ch = '.';
|
||
'' ch;
|
||
if (ch == '$$')
|
||
'' ch;
|
||
}
|
||
'\n';
|
||
count -= j;
|
||
ptr += j;
|
||
}
|
||
}
|
||
|
||
U0 Dm(U8 *addr, I64 count=0x80)
|
||
{//Show mem address, not offsets.
|
||
D(addr, count, FALSE);
|
||
}
|
||
|
||
U0 Da(U8 **addr, I64 count=0x10)
|
||
{//Dump mem, showing symbolic addresses.
|
||
while (count-- > 0)
|
||
{
|
||
"%08X:%08X,%P\n", addr, *addr, *addr;
|
||
addr++;
|
||
}
|
||
}
|
||
|
||
U0 RawPrint(I64 mS=100, U8 *format, ...)
|
||
{//Print using $LK,"Raw",A="MN:Raw"$ screen output for a length of time.
|
||
//$BK,1$Your heap must be good.$BK,0$
|
||
U8 *buf = StrPrintJoin(NULL, format, argc, argv);
|
||
Bool old_raw, old_input_filter;
|
||
|
||
PUSHFD
|
||
CLI
|
||
old_raw = Raw(ON);
|
||
old_input_filter = LBtr(&Fs->task_flags, TASKf_INPUT_FILTER_TASK);
|
||
"%s", buf;
|
||
Busy(mS << 10);
|
||
POPFD
|
||
|
||
LBEqual(&Fs->task_flags, TASKf_INPUT_FILTER_TASK, old_input_filter);
|
||
Raw(old_raw);
|
||
Free(buf);
|
||
}
|
||
|
||
U0 RawD(I64 mS=100, U8 *addr, I64 count=0x80)
|
||
{//Dumps a block of mem using $LK,"Raw",A="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(addr, count);
|
||
Busy(mS << 10);
|
||
POPFD
|
||
|
||
LBEqual(&Fs->task_flags, TASKf_INPUT_FILTER_TASK, old_input_filter);
|
||
Raw(old_raw);
|
||
}
|
||
|
||
U0 RawDm(I64 mS=100, U8 *addr, I64 count=0x80)
|
||
{//Dumps a block of mem using $LK,"Raw",A="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(addr, count);
|
||
Busy(mS << 10);
|
||
POPFD
|
||
|
||
LBEqual(&Fs->task_flags, TASKf_INPUT_FILTER_TASK, old_input_filter);
|
||
Raw(old_raw);
|
||
}
|
||
|
||
I64 *TaskRegAddr(CTask *task, I64 reg_num)
|
||
{
|
||
switch (reg_num)
|
||
{
|
||
case REG_RAX: return &task->rax;
|
||
case REG_RCX: return &task->rcx;
|
||
case REG_RDX: return &task->rdx;
|
||
case REG_RBX: return &task->rbx;
|
||
case REG_RSP: return &task->rsp;
|
||
case REG_RBP: return &task->rbp;
|
||
case REG_RSI: return &task->rsi;
|
||
case REG_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;
|
||
}
|
||
|
||
#define RAWDR_COL (text.cols - 40)
|
||
|
||
U0 RawDr(CTask *task=NULL)
|
||
{
|
||
I64 i, j, old_col = text.raw_col;
|
||
Bool old_raw = Raw(ON);
|
||
U8 buf[200];
|
||
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
text.raw_col = RAWDR_COL;
|
||
'<EFBFBD>';
|
||
for (j = 0; j < text.cols - RAWDR_COL - 1; j++)
|
||
'<EFBFBD>';
|
||
|
||
for (i = 0; i < 16; i++)
|
||
{
|
||
text.raw_col = (i + 1) * text.cols + RAWDR_COL;
|
||
"<EFBFBD>%3Z: %016X\n", i, "ST_U64_REGS", *TaskRegAddr(task, i);
|
||
}
|
||
|
||
i++;
|
||
|
||
text.raw_col = i++ * text.cols + RAWDR_COL;
|
||
"<EFBFBD>RIP: %016X\n", task->rip;
|
||
|
||
text.raw_col = i++ * text.cols + RAWDR_COL;
|
||
"<EFBFBD>%-*tp\n", text.cols - (RAWDR_COL + 1) - 1, Fs->rip;
|
||
|
||
text.raw_col = i++ * text.cols + RAWDR_COL;
|
||
'<EFBFBD>';
|
||
if (Bt(&sys_run_level, RLf_COMPILER))
|
||
{
|
||
j = Fs->rip;
|
||
Ui(buf, &j,,, TRUE);
|
||
"%s", buf;
|
||
}
|
||
else
|
||
'\n';
|
||
|
||
text.raw_col = i * text.cols + RAWDR_COL;
|
||
'<EFBFBD>';
|
||
for (j = 0; j < text.cols - RAWDR_COL - 1; j++)
|
||
'<EFBFBD>';
|
||
|
||
text.raw_col = text.cols - 1;
|
||
'<EFBFBD>';
|
||
for (j = 2; j < i + 1; j++)
|
||
{
|
||
text.raw_col = j * text.cols - 1;
|
||
'<EFBFBD>';
|
||
}
|
||
text.raw_col = j * text.cols - 1;
|
||
'<EFBFBD>';
|
||
|
||
text.raw_col = old_col;
|
||
Raw(old_raw);
|
||
}
|
||
|
||
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", *TaskRegAddr(task, i);
|
||
"RIP: %016X\n", task->rip;
|
||
}
|
||
|
||
U8 *SysGetStr2(I64)
|
||
{
|
||
U8 buf[512];
|
||
|
||
StrNGet(buf, 512, FALSE);
|
||
return StrNew(buf);
|
||
}
|
||
|
||
CBpt *BptFind(U8 *needle_addr, CTask *haystack_task=NULL, Bool rem=FALSE)
|
||
{
|
||
CBpt *res=NULL, *tmpb, *tmpb1, *tmpb2;
|
||
|
||
if (!haystack_task)
|
||
haystack_task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
tmpb1 = &haystack_task->bpt_list;
|
||
tmpb = haystack_task->bpt_list;
|
||
while (tmpb)
|
||
{
|
||
tmpb2 = tmpb->next;
|
||
if (tmpb->addr == needle_addr)
|
||
{
|
||
res = tmpb;
|
||
if (rem)
|
||
tmpb1->next = tmpb2;
|
||
else
|
||
tmpb1 = &tmpb->next;
|
||
}
|
||
else
|
||
tmpb1 = &tmpb->next;
|
||
tmpb = tmpb2;
|
||
}
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
Bool BptS(U8 *addr, CTask *task=NULL, Bool live=TRUE)
|
||
{//Set breakpoint.
|
||
CBpt *tmpb;
|
||
Bool res = TRUE;
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (!(tmpb = BptFind(addr, task, FALSE)))
|
||
{
|
||
tmpb = CAlloc(sizeof(CBpt), task);
|
||
tmpb->addr = addr;
|
||
tmpb->val = *addr;
|
||
res = FALSE;
|
||
tmpb->next = task->bpt_list;
|
||
|
||
task->bpt_list = tmpb;
|
||
if (task == Fs && live)
|
||
*addr = OC_BPT;
|
||
}
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
Bool BptR(U8 *addr, CTask *task=NULL, Bool live=TRUE, Bool rem=TRUE)
|
||
{//Remove breakpoint.
|
||
CBpt *tmpb;
|
||
Bool res = FALSE;
|
||
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (tmpb = BptFind(addr, task, rem))
|
||
{
|
||
if (task == Fs && live)
|
||
*tmpb->addr = tmpb->val;
|
||
res = TRUE;
|
||
if (rem)
|
||
Free(tmpb);
|
||
}
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
Bool B(U8 *addr, CTask *task=NULL, Bool live=TRUE)
|
||
{//Toggle breakpoint.
|
||
//Return: TRUE if removed.
|
||
Bool res = FALSE;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (BptFind(addr, task, FALSE))
|
||
{
|
||
BptR(addr, task, live, TRUE);
|
||
res = TRUE;
|
||
}
|
||
else
|
||
BptS(addr, task, live);
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
I64 B2(CTask *task=NULL, Bool live=TRUE)
|
||
{//Remove all breakpoints.
|
||
//Return: count of removed.
|
||
I64 res = 0;
|
||
CBpt *tmpb, *tmpb1;
|
||
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
tmpb = task->bpt_list;
|
||
task->bpt_list = NULL;
|
||
while (tmpb)
|
||
{
|
||
tmpb1 = tmpb->next;
|
||
if (task == Fs && live)
|
||
*tmpb->addr = tmpb->val;
|
||
Free(tmpb);
|
||
tmpb = tmpb1;
|
||
res++;
|
||
}
|
||
POPFD
|
||
|
||
return res;
|
||
}
|
||
|
||
U0 G(U8 *ip=INVALID_PTR, CTask *task=NULL)
|
||
{//Go
|
||
if (!task)
|
||
task = Fs;
|
||
if (ip != INVALID_PTR)
|
||
task->rip = ip;
|
||
if (BptFind(task->rip, task))
|
||
"\nBreakpoints found.\n"
|
||
"Do one of the following, first:\n"
|
||
">S;\t\t\t//Single step\n"
|
||
">B2;\t\t//Clear all break points\n"
|
||
">G2;\t\t//Clear all break points and Go\n\n"
|
||
"After resuming, <CTRL-ALT-n> next focus task\n"
|
||
"After resuming, <CTRL-ALT-v> flushes screen VGA cache\n";
|
||
else
|
||
{
|
||
LBtr(&task->task_flags, TASKf_DISABLE_BPTS);
|
||
LBtr(&task->rflags, RFLAGf_TRAP);//No single step
|
||
Suspend(task, FALSE);
|
||
if (task == Fs)
|
||
{
|
||
if (IsDebugMode && task->next_cc != &task->next_cc)
|
||
{
|
||
"Exit Debug\n";
|
||
Btr(&task->last_cc->flags, CCf_PROMPT);
|
||
}
|
||
}
|
||
else
|
||
Exit;
|
||
}
|
||
}
|
||
|
||
U0 G2(U8 *ip=INVALID_PTR, CTask *task=NULL)
|
||
{//Remove all breakpoints and Go.
|
||
if (!task)
|
||
task = Fs;
|
||
B2(task);
|
||
if (ext[EXT_WIN_FOCUS])
|
||
CallExtNum(EXT_WIN_FOCUS, debug.focus_task);
|
||
LFBFlush;
|
||
G(ip, task);
|
||
}
|
||
|
||
public U0 S(U8 *ip=INVALID_PTR, CTask *task=NULL) //Single-step.
|
||
{//Single step.
|
||
if (!task)
|
||
task = Fs;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (ip != INVALID_PTR)
|
||
task->rip = ip;
|
||
LBts(&task->task_flags, TASKf_DISABLE_BPTS);
|
||
LBts(&task->rflags, RFLAGf_TRAP);
|
||
Suspend(task, FALSE);
|
||
if (task == Fs)
|
||
{
|
||
if (IsDebugMode)
|
||
{
|
||
if (task->next_cc != &task->next_cc)
|
||
Btr(&task->last_cc->flags, CCf_PROMPT);
|
||
}
|
||
}
|
||
else
|
||
Exit;
|
||
POPFD
|
||
}
|
||
|
||
U0 DebugHelp()
|
||
{
|
||
"\n"
|
||
"The cmd line is basically the same as normal. Here are some common\n"
|
||
"debugging commands.\n\n"
|
||
">EdLite(\"FileName\");\t\t\t\t// Edit file.\n"
|
||
">D(0x100000);\t\t\t\t\t\t// Dump page tables.\n"
|
||
">Dm(0x100000);\t\t\t\t\t\t// Dump page tables.\n"
|
||
">Dm(Fs, sizeof(CTask));\t\t\t\t// Dump current task record.\n"
|
||
">ClassRep(Fs, \"CTask\", 1);\t\t\t// Dump current task record.\n"
|
||
">ClassRep(Fs,, 1);\t\t\t\t\t// (It knows lastclass.)\n"
|
||
">CallerRep;\t\t\t\t\t\t\t// Stack trace report.\n"
|
||
">Da(_RSP);\t\t\t\t\t\t\t// Dump stack.\n"
|
||
">Dr;\t\t\t\t\t\t\t\t// Dump Registers.\n"
|
||
">1 + 2 * 3 + &Print;\t\t\t\t// Show calculation res.\n"
|
||
">*(0x70000)(I64 *) = 0x123456789;\t// Assign value to 0x70000-0x70007.\n"
|
||
">_RAX = 0x1234;\t\t\t\t\t\t// Set RAX to 0x1234.\n"
|
||
">_RIP = &Break;\t\t\t\t\t\t// Set RIP.\n"
|
||
">I64 i;\t\t\t\t\t\t\t\t// Declare variable.\n"
|
||
">i = _RCX + _RDX;\t\t\t\t\t// Assign to variable.\n"
|
||
">U(&Print+0x8);\t\t\t\t\t\t// Unassemble Print.\n"
|
||
">Uf(\"Print\");\t\t\t\t\t\t// Unassembler function \"Print\".\n"
|
||
">Man(\"Print\");\t\t\t\t\t\t// Edit Src for \"Print\".\n"
|
||
">E(_RIP);\t\t\t\t\t\t\t// Edit Src Code.\n"
|
||
">Fix;\t\t\t\t\t\t\t\t// Edit Last Err Src Code.\n"
|
||
">B(&Main+0x20);\t\t\t\t\t\t// Toggle break point.\n\n"
|
||
">B2;\t\t\t\t\t\t\t\t// Clear all break points.\n"
|
||
">S;\t\t\t\t\t\t\t\t\t// Single step.\n"
|
||
">G;\t\t\t\t\t\t\t\t\t// Resume execution.\n"
|
||
">G2;\t\t\t\t\t\t\t\t// B2;LFBFlush;WinFocus;G;\n"
|
||
">Exit;\t\t\t\t\t\t\t\t// Exit (kill) task.\n\n"
|
||
"After resuming, <CTRL-ALT-n> next focus task.\n"
|
||
"After resuming, <CTRL-ALT-v> flushes screen VGA cache.\n\n";
|
||
}
|
||
|
||
U0 Debug2()
|
||
{
|
||
Bool old_win_inhibit, old_waiting_message, old_single;
|
||
I64 i, old_getstr2;
|
||
U8 buf[200];
|
||
|
||
if (debug.panic)
|
||
{
|
||
if (IsRaw)
|
||
{
|
||
i = Fs->rip;
|
||
Ui(buf, &i);
|
||
"%s", buf;
|
||
}
|
||
else
|
||
U(Fs->rip, 1);
|
||
}
|
||
else
|
||
debug.panic = TRUE;
|
||
old_waiting_message = LBtr(&Fs->task_flags, TASKf_AWAITING_MESSAGE);
|
||
old_win_inhibit = Fs->win_inhibit;
|
||
Fs->win_inhibit = WIG_USER_TASK_DEFAULT;
|
||
sys_focus_task = Fs;
|
||
kbd.scan_code = 0;
|
||
old_getstr2 = fp_getstr2;
|
||
fp_getstr2 = &SysGetStr2;
|
||
old_single = SingleUser(OFF);
|
||
while (!mouse_hard.install_attempts)
|
||
Yield;
|
||
SingleUser(old_single);
|
||
UserTaskCont;
|
||
fp_getstr2 = old_getstr2;
|
||
Fs->win_inhibit = old_win_inhibit;
|
||
LBEqual(&Fs->task_flags, TASKf_AWAITING_MESSAGE, old_waiting_message);
|
||
}
|
||
|
||
U0 Fault3(I64 fault_num, I64 fault_err_code)
|
||
{
|
||
no_warn fault_err_code;
|
||
|
||
PUSHFD
|
||
CLI
|
||
if (Gs->num && debug.mp_crash)
|
||
{
|
||
mp_count = 1;
|
||
debug.mp_crash->cpu_num = Gs->num;
|
||
debug.mp_crash->task = Fs;
|
||
debug.mp_crash->rip = Fs->rip;
|
||
debug.mp_crash->message = debug.message;
|
||
debug.mp_crash->message_num = debug.message_num;
|
||
MPInt(I_MP_CRASH, 0);
|
||
SysHlt;
|
||
}
|
||
|
||
"\n\tZealOS Debugger\n\n"
|
||
" Type Help; for help.\n\n";
|
||
|
||
Beep(62, TRUE);
|
||
if (fault_num == I_DEBUG)
|
||
{
|
||
if (debug.message)
|
||
{
|
||
"\n!!! %s", debug.message;
|
||
if (debug.message_num)
|
||
"%016X", debug.message_num;
|
||
" !!!\n\n";
|
||
}
|
||
}
|
||
if (debug.panic)
|
||
CallerRep;
|
||
Debug2;
|
||
POPFD
|
||
}
|
||
|
||
U0 Fault2(I64 fault_num, I64 fault_err_code)
|
||
{//Called from $LK,"Fault2",A="FF:::/Kernel/KInterrupts.CC,Fault2"$.
|
||
//$BK,1$Be careful not to swap-out and ruin the saved context$BK,0$
|
||
Bool was_raw, was_single_user, was_silent, was_in_debug, was_mouse_enabled;
|
||
I64 i, old_raw_flags = text.raw_flags;
|
||
|
||
was_single_user = SingleUser(ON);
|
||
if (!IsDebugMode)
|
||
debug.focus_task = sys_focus_task;
|
||
sys_focus_task = NULL;
|
||
if (fault_num == I_BPT)
|
||
Fs->rip--;
|
||
if (Fs->debug_task)
|
||
CallExtNum(EXT_DEBUG_RESUME, fault_num, fault_err_code);
|
||
else
|
||
{
|
||
was_mouse_enabled = CallExtStr("MouseHardEnable", FALSE);
|
||
was_raw = Raw(ON);
|
||
was_silent = Silent(OFF);
|
||
text.raw_flags |= RAWF_SHOW_DOLLAR|RAWF_SCROLL;
|
||
|
||
"Task \"";
|
||
"%s", Fs->task_title;
|
||
"\"\n\n";
|
||
"Fault: 0x%02X %Z\n", fault_num, fault_num, "ST_INT_NAMES";
|
||
"Err Code: %08X\n", fault_err_code;
|
||
was_in_debug = DebugMode(ON);
|
||
"RIP: %08X", Fs->rip; //Sometimes crashes on %p, so do this first
|
||
":%p\nRSP: %08X\n", Fs->rip, Fs->rsp;
|
||
if (fault_num == I_PAGE_FAULT)
|
||
{
|
||
MOV_RAX_CR2
|
||
i = RAXGet;
|
||
"Fault Addr: %08X:%p\n", i, i;
|
||
}
|
||
Fault3(fault_num, fault_err_code);
|
||
DebugMode(was_in_debug);
|
||
Silent(was_silent);
|
||
Raw(was_raw);
|
||
CallExtStr("MouseHardEnable", was_mouse_enabled);
|
||
text.raw_flags = old_raw_flags;
|
||
}
|
||
SingleUser(was_single_user);
|
||
if (LBtr(&Fs->task_flags, TASKf_KILL_AFTER_DEBUG))
|
||
Exit;
|
||
}
|
||
|
||
U0 Panic(U8 *message=NULL, I64 message_num=0, Bool panic=TRUE)
|
||
{//Enter the debugger with panic?
|
||
PUSHFD
|
||
CLI
|
||
debug.message = message;
|
||
debug.message_num = message_num;
|
||
debug.panic = panic;
|
||
INT I_DEBUG
|
||
POPFD
|
||
}
|
||
|
||
U0 Debug(U8 *message=NULL, I64 message_num=0)
|
||
{//Enter debugger, no panic.
|
||
Panic(message, message_num, FALSE);
|
||
}
|