508 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			508 lines
		
	
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* $Header$ */
 | 
						|
 | 
						|
#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 */;
 | 
						|
}
 |