|
@@ -0,0 +1,508 @@
|
|
|
+/* $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 */;
|
|
|
+}
|