|
|
MiNT 0.96 pl14
/*
* sample program for demonstrating the debugging calls
* Written by Alex Kiernan
*/
#include <mintbind.h>
#include <stddef.h>
typedef struct _context {
long regs[15]; /* registers d0-d7, a0-a6 */
long usp; /* user stack pointer (a7) */
short sr; /* status register */
long pc; /* program counter */
long ssp; /* supervisor stack pointer */
long term_vec; /* GEMDOS terminate vector (0x102) */
/*
* AGK: if running on a TT and the user is playing with the FPU then we
* must save and restore the context. We should also consider this for
* I/O based co-processors, although this may be difficult due to
* possibility of a context switch in the middle of an I/O handshaking
* exchange.
*/
unsigned char fstate[216]; /* FPU internal state */
long fregs[3*8]; /* registers fp0-fp7 */
long fctrl[3]; /* FPCR/FPSR/FPIAR */
/*
* AGK: for long (time-wise) co-processor instructions (FMUL etc.), the
* FPU returns NULL, come-again with interrupts allowed primitives. It
* is highly likely that a context switch will occur in one of these if
* running a mathematically intensive application, hence we must handle
* the mid-instruction interrupt stack. We do this by saving the extra
* 3 long words and the stack format word here.
*/
unsigned short sfmt; /* stack frame format identifier */
short internal[42]; /* internal state -- see framesizes[] for size */
char ptrace; /* trace exception is pending */
} CONTEXT;
#define PPROCADDR (('P'<< 8) | 1)
#define PBASEADDR (('P'<< 8) | 2)
#define PCTXTSIZE (('P'<< 8) | 3)
#define PSETFLAGS (('P'<< 8) | 4)
#define PGETFLAGS (('P'<< 8) | 5)
#define PTRACESFLAGS (('P'<< 8) | 6)
#define PTRACEGFLAGS (('P'<< 8) | 7)
# define P_ENABLE (1 << 0) /* enable tracing */
#ifdef NOTYETDEFINED
# define P_DOS (1 << 1) /* trace DOS calls - unimplemented */
# define P_BIOS (1 << 2) /* trace BIOS calls - unimplemented */
# define P_XBIOS (1 << 3) /* trace XBIOS calls - unimplemented */
#endif
#define PTRACEGO (('P'<< 8) | 8) /* these 4 must be together */
#define PTRACEFLOW (('P'<< 8) | 9)
#define PTRACESTEP (('P'<< 8) | 10)
#define PTRACE11 (('P'<< 8) | 11)
/* lseek() origins */
#define SEEK_SET 0 /* from beginning of file */
#define SEEK_CUR 1 /* from current location */
#define SEEK_END 2 /* from end of file */
#define WNOHANG 1
#define WUNTRACED 2
/* these definitions are incompatible with <sys/wait.h> */
#define WIFEXITED(x) ((int)((x) & 0xFF00) == 0)
#define WEXITSTATUS(x) ((int)((x) & 0xFF))
#define WIFSIGNALED(x) (((int)((x) & 0xFF00) > 0) && ((int)(((x) & 0xFF) == 0)))
#define WTERMSIG(x) ((int)(((x) & 0xFF00) >> 8))
#define WIFSTOPPED(x) (((int)((x) & 0xFF) == 0x7F) && ((int)(((x) >> 8) & 0xFF) != 0))
#define WSTOPSIG(x) ((int)(((x) >> 8) & 0xFF))
#define SIGTRAP 5 /* trace trap */
void
dumpCTXT(ctxt)
CONTEXT *ctxt;
{
int i, j;
for (i = 0; i < 16; i += 4) {
for (j = 0; j < 4; j++) {
/* oh dear... we output too many commas - c'est la vie */
printf("%c%d=$%08lx, ", i < 8 ? 'D' : 'A',
i + j - (i >= 8 ? 8 : 0),
ctxt[0].regs[i + j]);
}
putchar('\n');
}
printf("SR=$%04x\n", ctxt[0].sr);
printf("PC=$%08lx\n", ctxt[0].pc);
printf("SSP=$%08lx\n", ctxt[0].ssp);
printf("term_vec=$%08lx\n", ctxt[0].term_vec);
printf("fstate[0]=%u\n", ctxt[0].fstate[0]);
for (i = 0; i < 8; i++) {
printf("FP%d=$%08lx%08lx%08lx\n",
i,
ctxt[0].fregs[i * 3 + 0],
ctxt[0].fregs[i * 3 + 1],
ctxt[0].fregs[i * 3 + 2]);
}
printf("frame format=%u\n", ctxt[0].sfmt >> 12);
printf("vector offset=$%x\n", ctxt[0].sfmt & 0xfff);
/* could print internal state here internal[0..41] */
}
int
main(argc,argv)
int argc;
char *argv[];
{
int pid;
unsigned long status;
int fd;
char fpid[13];
CONTEXT ctxt;
long pctxt;
long sizeof_ctxt;
unsigned short sig;
if (isdigit(*argv[1])) {
pid = atoi(argv[1]);
sprintf(fpid, "U:\\PROC\\.%03d", pid);
fd = Fopen(fpid, 0);
sig = 1;
Fcntl(fd, (long)&sig, PTRACESFLAGS); /* capture it */
Pkill(pid, SIGTRAP); /* and stop it */
}
else {
pid = Pexec(0x8000 | 100, argv[1], "\0", NULL);
/* check pid */
printf("pid = %d\n", pid);
sprintf(fpid, "U:\\PROC\\.%03d", pid);
fd = Fopen(fpid, 0);
}
/* check fd */
Fcntl(fd, (long)&pctxt, PPROCADDR);
Fcntl(fd, (long)&sizeof_ctxt, PCTXTSIZE);
pctxt -= 2 * sizeof_ctxt;
do {
status = Pwait3(WUNTRACED, NULL);
if (WIFSTOPPED(status)) {
printf("pid = %d\, WSTOPSIG = %d\n", (int)(status >> 16), WSTOPSIG(status));
Fseek((long)pctxt, fd, SEEK_SET);
Fread(fd, sizeof(ctxt), &ctxt); /* note _not_ sizeof_ctxt */
dumpCTXT(&ctxt);
switch (Cconin() & 0xff) {
case 's':
case 'S':
Fcntl(fd, (long)NULL, PTRACESTEP); /* single step */
break;
case 'g':
case 'G':
Fcntl(fd, (long)NULL, PTRACEGO); /* go */
break;
case 'f':
case 'F':
Fcntl(fd, (long)NULL, PTRACEFLOW); /* go to flow change */
break;
case 'x':
case 'X':
sig = WSTOPSIG(status);
Fcntl(fd, (long)&sig, PTRACEGO); /* kill it */
break;
}
}
putchar('\n');
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
if (WIFEXITED(status))
printf("pid = %d, WEXITSTATUS = %d\n", (int)(status >> 16), WEXITSTATUS(status));
else
printf("pid = %d, WTERMSIG = %d\n", (int)(status >> 16), WTERMSIG(status));
Fclose(fd); /* but the process is dead... (Jim!) */
return 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.