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;
}
Historical capture: 2010-11-24. Home | Power on LoseThos | Sources and changes