ack/mach/proto/grind/atlin.c
1994-06-24 14:02:31 +00:00

509 lines
8.5 KiB
C

/* $Id$ */
#define DEBUGGEE
#include "message.h"
#define MAXBP 128
#define MAXTRACE 16
static int nbp; /* # of breakpoints */
static char *bp[MAXBP];
static int ntrace;
static struct trace {
char *begin_trace, *end_trace;
} trace_buf[MAXTRACE];
static struct message_hdr ok_message;
#define OFF 0
#define SS 1 /* single stepping */
#define SSF 2 /* single stepping, counting functions
as single statements */
static char *
BUFTOA(p)
register char *p;
{
register long l = 0;
register int i;
for (i = PS; i>0; i--) {
l = (l << 8) | (*p++ & 0377);
}
return (char *) l;
}
static long
BUFTOL(p)
register char *p;
{
register long l = 0;
register int i;
for (i = LS; i>0; i--) {
l = (l << 8) | (*p++ & 0377);
}
return l;
}
static
ATOBUF(p, cp)
register char *p;
char *cp;
{
register int i;
register long l = (long) cp;
p += PS;
for (i = PS; i > 0; i--) {
*--p = l;
l >>= 8;
}
}
static
LTOBUF(p, l)
register char *p;
register long l;
{
register int i;
p += LS;
for (i = LS; i > 0; i--) {
*--p = l;
l >>= 8;
}
}
static int single_stepping = OFF;
static int db_ss = 0;
static int step_count = 0;
static char *savedlb;
static int break_flag = 0;
static int reading = 0;
static char *retaddr;
static char *LB;
static char *currbrk;
extern char *__Get_LB();
extern char *__Get_Hol0();
extern char *__Get_PC();
extern char *__Cvt_LB_AB();
extern char *__Get_HP();
extern char *_sbrk();
extern int etext;
extern __Set_PC();
static send_ok();
#define check_ptr(c) (((c) >= (char *)&etext && (c) <= currbrk) || (c) >= LB)
#define IN_FD 3
#define OUT_FD 6
static int
ureceive(p, c)
char *p;
long c;
{
int i;
int retval = 1;
reading = 1;
while (c >= 0x1000) {
i = _read(IN_FD, p, 0x1000);
if (i == 0) return 0;
if (i < 0) {
retval = 0;
c -= 0x1000;
}
else {
p += i;
c -= i;
}
}
while (c > 0) {
i = _read(IN_FD, p, (int)c);
if (i == 0) return 0;
if (i < 0) {
retval = 0;
break;
}
else {
p += i;
c -= i;
}
}
reading = 0;
return retval;
}
static int
usend(p, c)
char *p;
long c;
{
int i;
while (c >= 0x1000) {
i = _write(OUT_FD, p, 0x1000);
if (i < 0) {
return 0;
}
p += i;
c -= i;
}
while (c > 0) {
i = _write(OUT_FD, p, (int)c);
if (i < 0) {
return 0;
}
p += i;
c -= i;
}
return 1;
}
static int
ugetm(message)
struct message_hdr *message;
{
if (! ureceive((char *) message, (long) sizeof(struct message_hdr))) {
return 0;
}
return 1;
}
static int
uputm(message)
struct message_hdr *message;
{
if (! usend((char *) message, (long) sizeof(struct message_hdr))) {
return 0;
}
return 1;
}
static int
sendreply(m, p, sz)
struct message_hdr *m;
char *p;
long sz;
{
if (! uputm(m) || ! (sz && p ? usend(p, sz) : 1)) {
return 0;
}
return 1;
}
static int
do_request()
{
/* obtain a request from the debugger and perform it */
int fail = 0;
register int i;
register char *c;
char *c1;
long sz;
struct message_hdr message;
start:
if (! ugetm(&message)) {
/* failed to get a message. Something is wrong. Let process continue */
return 1;
}
if (message.m_type & M_DB_SS) db_ss = 1;
message.m_type &= 0177;
switch(message.m_type) {
case M_OK:
/* sometimes sent to child to see if it lives */
goto start;
case M_SETBP:
/* set a breakpoint */
if (nbp == MAXBP) {
fail = 1;
break;
}
bp[nbp++] = BUFTOA(message.m_buf+1);
break;
case M_SETTRACE:
if (ntrace == MAXTRACE) {
fail = 1;
break;
}
trace_buf[ntrace].begin_trace = BUFTOA(message.m_buf+1);
trace_buf[ntrace++].end_trace = BUFTOA(message.m_buf+(PS+1));
break;
case M_CLRBP:
i = 0;
c = BUFTOA(message.m_buf+1);
while (i < nbp && bp[i] != c) {
i++;
}
if (i < nbp) {
while (i < nbp) {
bp[i] = bp[i+1];
i++;
}
nbp--;
}
else {
fail = 1;
}
break;
case M_CLRTRACE:
i = 0;
c = BUFTOA(message.m_buf+1);
c1 = BUFTOA(message.m_buf+(PS+1));
while (i < ntrace &&
trace_buf[i].begin_trace != c &&
trace_buf[i].end_trace != c1){
i++;
}
if (i < ntrace) {
while (i < ntrace) {
trace_buf[i] = trace_buf[i+1];
i++;
}
ntrace--;
}
else {
fail = 1;
}
break;
case M_SETSS:
single_stepping = SS;
step_count = BUFTOL(message.m_buf+1);
return 1;
case M_CLRSS:
single_stepping = OFF;
break;
case M_SETSSF:
savedlb = __Get_LB(2);
step_count = BUFTOL(message.m_buf+1);
single_stepping = SSF;
return 1;
case M_GETBYTES:
message.m_type = M_DATA;
sz = BUFTOL(message.m_buf+1);
c = BUFTOA(message.m_buf+(LS+1));
currbrk = _sbrk(0);
if (! check_ptr(c) || ! check_ptr(c+sz-1)) {
fail = 1;
break;
}
return sendreply(&message, c, sz)
? 0
: -1;
case M_GETSTR:
sz = BUFTOL(message.m_buf+1);
c1 = c = BUFTOA(message.m_buf+(LS+1));
currbrk = _sbrk(0);
if (check_ptr(c)) {
while (*c) {
if (c - c1 + 1 >= sz) break;
c++;
if (! check_ptr(c)) {
fail = 1;
break;
}
}
}
else fail = 1;
if (fail) break;
message.m_type = M_DATA;
sz = c - c1 + 1;
LTOBUF(message.m_buf+1, sz);
return sendreply(&message, c1, sz)
? 0
: -1;
case M_SETBYTES:
if (! ureceive(BUFTOA(message.m_buf+(LS+1)), BUFTOL(message.m_buf+1))) {
fail = 1;
}
break;
case M_GETEMREGS:
i = BUFTOL(message.m_buf+1);
c = __Get_LB(i+2); /* local base */
c1 = __Get_LB(i+1); /* needed to find PC and SP */
ATOBUF(message.m_buf+LB_OFF, c);
ATOBUF(message.m_buf+AB_OFF, __Cvt_LB_AB(c));
ATOBUF(message.m_buf+PC_OFF, __Get_PC(c1));
ATOBUF(message.m_buf+HP_OFF, __Get_HP());
ATOBUF(message.m_buf+SP_OFF, __Cvt_LB_AB(c1));
return sendreply(&message, (char *) 0, 0L) ? 0 : -1;
case M_SETEMREGS:
/* actually, only the program counter is settable */
i = BUFTOL(message.m_buf+1);
c = __Get_LB(i+1);
__Set_PC(c, BUFTOA(message.m_buf+PC_OFF));
break;
case M_CONT:
return 1;
case M_DUMP:
currbrk = _sbrk(0);
c = __Get_Hol0();
c1 = currbrk;
message.m_type = M_DGLOB;
sz = c1 - c;
LTOBUF(message.m_buf+1, sz);
ATOBUF(message.m_buf + HP_OFF, __Get_HP());
ATOBUF(message.m_buf + PC_OFF, __Get_PC(__Get_LB(1)));
ATOBUF(message.m_buf + LB_OFF, c1);
sendreply(&message, c, sz);
if (! ___topsave()) {
/* we get here after a ___topload() ! */
step_count = 0;
nbp = 0;
single_stepping = 0;
savedlb = 0;
break_flag = 0;
db_ss = 0;
break;
}
return 0;
case M_DGLOB:
_brk(BUFTOA(message.m_buf + LB_OFF));
__Set_HP(BUFTOA(message.m_buf+HP_OFF));
if (! ureceive(__Get_Hol0(), BUFTOL(message.m_buf+1))) {}
___topload(BUFTOA(message.m_buf + SP_OFF));
/*NOTREACHED*/
}
send_ok(fail ? M_FAIL : M_OK);
return fail ? -1 : 0;
}
___sendtop(addr, SP, sz)
char *addr, *SP;
unsigned sz;
{
struct message_hdr m;
m.m_type = M_DSTACK;
LTOBUF(m.m_buf+1, (long) sz);
ATOBUF(m.m_buf+SP_OFF, SP);
sendreply(&m, addr, (long)sz);
}
___restoretop(SP)
char *SP;
{
struct message_hdr m;
if (! ugetm(&m)) {}
if (! ureceive(SP, BUFTOL(m.m_buf+1))) {}
}
static
sigcatch()
{
signal(7, sigcatch);
if (reading) send_ok(M_INTR);
else break_flag = 1;
db_ss = 0;
}
static int
check_bp()
{
register int i;
for (i = 0; i < nbp; i++) {
if (bp[i] == retaddr) {
return 1;
}
}
return 0;
}
static int
check_trace()
{
register int i;
for (i = 0; i < ntrace; i++) {
if (trace_buf[i].begin_trace <= retaddr &&
trace_buf[i].end_trace >= retaddr) {
return 1;
}
}
return 0;
}
static
send_ok(type)
{
register int i;
ok_message.m_type = type;
LTOBUF(ok_message.m_buf+1, (long) retaddr);
uputm(&ok_message);
}
void
__uX_LiB()
/* This function must be called after every LIN and LNI */
{
int status = M_CONT;
LB = __Get_LB(0);
if ( retaddr) {
/* not the first time ... */
retaddr = __Get_PC(LB);
/* first, adjust step_count when single stepping
*/
if (single_stepping == SS) step_count--;
else if (single_stepping == SSF) {
char *lb = __Get_LB(1);
if (!((char *) &lb < lb && lb >= savedlb ||
(char *) &lb > lb && lb <= savedlb)) {
}
else {
savedlb = lb;
step_count--;
}
}
if (single_stepping != OFF && step_count <= 0) {
status = M_END_SS;
single_stepping = OFF;
}
else if (break_flag) status = M_INTR;
}
else {
signal(7, sigcatch);
retaddr = __Get_PC(LB);
status = M_OK;
}
if (status == M_CONT) {
if ((nbp != 0 && check_bp() != 0) ||
(ntrace != 0 && check_trace() != 0)) {
status = M_OK;
}
else if (break_flag) status = M_INTR;
else {
if (db_ss) {
db_ss = 0;
send_ok(M_DB_SS);
while (do_request() <= 0) /* nothing */;
}
if (break_flag) status = M_INTR;
else return;
}
}
break_flag = 0;
send_ok(status);
db_ss = 0;
while (do_request() <= 0) /* nothing */;
}