Building An OS-Aware Debugger
by Stewart Christie

Listing One
  ....
  memset(&osCalls, 0, sizeof(osCalls));
     osCalls.flag = OS_TASK_LIST | OS_TASK_INFO | OS_GET_TASK_ID |
             OS_LOAD_INFO | OS_QUERY | OS_COMMAND | OS_GET_ERROR_MESSAGE;
     osCalls.OS_Task_List = callOSTaskList;
     osCalls.OS_Task_Info = callOSTaskInfo;
     osCalls.OS_Get_Task_ID = callOSGetTaskID;
     osCalls.OS_Load_Info = callOSLoadInfo;
     osCalls.OS_Query = callOSQuery;
     osCalls.OS_Command = callOSCommand;
     osCalls.OS_Get_Error_Message = callOSGetErrorMessage;
  m386_setOScalls((OS_calls_t far *)&osCalls);
  .....

Listing Two
/* Function Pointers */
#pragma noalign  (s_calls)
typedef struct s_calls {
  OS_int flag;  /* flag for available functions */
#define OS_TASK_LIST     (1 <<  0)
#define OS_TASK_INFO     (1 <<  1)
#define OS_SET_TASK     (1 <<  2)
#define OS_GET_TASK     (1 <<  3)
#define OS_GET_TSS     (1 <<  4)
#define OS_SET_TSS     (1 <<  5)
#define OS_GET_TASK_ID     (1 <<  6)
#define OS_COMMAND     (1 <<  7)
#define OS_GET_OUTPUT     (1 <<  8)
#define OS_GET_ERROR_MESSAGE    (1 <<  9)
#define OS_LOAD      (1 << 10)
#define OS_LOAD_INFO     (1 << 11)
#define OS_SET_COMPLEX_BREAKPOINT_CONDITION  (1 << 12)
#define OS_GET_COMPLEX_BREAKPOINT_CONDITION  (1 << 13)
#define OS_DELETE_COMPLEX_BREAKPOINT_CONDITION (1 << 14)
#define OS_QUERY     (1 << 15)
#define OS_GET_FPU     (1 << 16)
#define OS_SET_FPU     (1 << 17)
#define OS_BREAK     (1 << 18)
/*  1 */OS_int far (*OS_Task_List)(OS_asbyte, OS_task_t far *);
/*  2 */OS_int far (*OS_Task_Info)(OS_int, OS_msg_t far *);
/*  3 */OS_int far (*OS_Set_Task)(OS_int, OS_int, OS_int far *);
/*  4 */OS_int far (*OS_Get_Task)(OS_int far *);
/*  5 */OS_int far (*OS_Get_TSS)(OS_int, OS_tss_t far *, OS_void far *);
/*  6 */OS_int far (*OS_Set_TSS)(OS_int, OS_tss_t far *);
/*  7 */OS_int far (*OS_Get_Task_ID)(OS_asbyte, OS_byte far *);
/*  8 */OS_int far (*OS_Command)(OS_asbyte, OS_byte far *, OS_msg_t far*);
/*  9 */OS_int far (*OS_Get_Output)(OS_asbyte, OS_asbyte, OS_msg_t far*);
/*  0 */OS_int far (*OS_Get_Error_Message)(OS_asbyte, OS_err_t far *);
/* 11 */OS_int far (*OS_Load)(OS_asbyte, OS_byte far *, OS_msg_t far *);
/* 12 */OS_int far (*OS_Load_Info) 
                    (OS_asbyte, OS_asbyte, OS_byte far *,OS_load_t far *);
/* 13 */OS_int far (*OS_Set_Complex_Breakpoint_Condition)
                    (OS_asbyte, OS_byte far *);
/* 14 */OS_int far (*OS_Get_Complex_Breakpoint_Condition)
                    (OS_asbyte, OS_msg_t far *);
/* 15 */OS_int far (*OS_Delete_Complex_Breakpoint_Condition)(OS_long);
/* 16 */OS_int far  (*OS_Query)(OS_asbyte, OS_byte far *, OS_msg_t far*);
/* 17 */OS_int far  (*OS_Get_FPU)(OS_int, OS_fpu_t far *);
/* 18 */OS_int far  (*OS_Set_FPU)(OS_int, OS_fpu_t far *);
/* 19 */OS_int far  (*OS_Break)(OS_int *);
#define OS_CALLS_MAX 19
} OS_calls_t;

Listing Three
/* ---------------------------------------------------------------------
 * MethodName: callOSTaskList
 * ---------------------------------------------------------------------

 * Description: wrapper function for near/far pointer conversion;
 * OSTaskList  can be found in file 'moninit.c'
 * ---------------------------------------------------------------------

 * Access: global
 * ---------------------------------------------------------------------

 * Parameter: length
 * -----------------------------------------
 * Parameter: pTask
 *            pointer to caller's task structure to be filled
 * ---------------------------------------------------------------------

 * Return: OS_SUCCESS, for successful result
 * ---------------------------------------------------------------------

 * Pre: none
 * ---------------------------------------------------------------------
 */
OS_int far callOSTaskList(OS_asbyte length, OS_task_t far* pTask)
{
 struct OS_near_task task;
 OS_int   result;
 task.ID = pTask->ID;
 task.state = pTask->state;
 task.length = pTask->length;
 task.name = (OS_byte*)pTask->name;

 result = (*pOSTaskList)(length, (OS_task_t*)&task);

 pTask->ID = task.ID;
 pTask->state = task.state;
 pTask->length = task.length;
 pTask->name = (OS_byte far*)task.name;

 return result;
}


Listing Four
OS_int OSTaskList(OS_asbyte n, OS_task_t* pTask)
{
 pthread_t p;
 ...
 p = GetTask(n);

 if (p)
 {
  static char szBuffer[20];
  sprintf(szBuffer, "%08x", p);
  pTask->ID = (OS_int)p;
  pTask->state = p->state;
  pTask->length = 9;
  pTask->name = szBuffer;
 }
 else
 {.....
      }
      return n == GetTaskCount() - 1 ? OS_NONE : n + 1;
}
pthread_t GetTask(int n)
{
 int  I = 0;
 pthread_t p = rtl_sched[i].rtl_tasks;
 for (i = 0; I <= n && p != 0; i++)
 {
  // first element is 0, second is 1, etc.
  if (i == n)
  {
   return p;
  }
  p = p->next;
 }
 return NULL;
}

Listing Five
OS_int OSTaskList(OS_asbyte n, OS_task_t* pTask)
{
 struct task* p;
 p = GetTask(n);
 if (!p)
 {
 pTask->ID = p->pid;
 pTask->state = p->state;
 pTask->length = strlen(p->cmdline) + 1;
 pTask->name = (void*)&(p->cmdline);

 if (p->pid == GetAttachedProcessID())
 {
  pTask->state = OS_DEBUG;
 }
 return n == GetTaskCount() - 1 ? OS_NONE : n + 1;
}





3


