--- /dev/null
+/* $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 */;
+}
--- /dev/null
+#
+;
+; (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
+; See the copyright notice in the ACK home directory, in the file "Copyright".
+;
+
+;
+; Module: coroutine primitives
+; Author: Kees Bot, Edwin Scheffer, Ceriel Jacobs
+; Version: $Header$
+;
+; This has been taken from the ACK Modula-2 runtime system and adapted.
+;
+
+ mes 2,EM_WSIZE,EM_PSIZE
+
+;
+; ___topsave: save the stack by sending it to the debugger
+;
+ exp $___topsave
+ pro $___topsave, 0
+ mes 11
+ loe 0
+ lae 4 ; load line number and file name
+ loi EM_PSIZE
+ lim ; load ignore mask
+ lor 0 ; load LB
+
+; now find the last argument base: first find the local base that has
+; dynamic link 0.
+
+ lor 0
+1
+ dup EM_PSIZE
+ dch
+ zer EM_PSIZE
+ cmp
+ zeq *2
+ dch
+ bra *1
+2
+ lpb ; last argument base
+
+; Now the stuff between the current stack pointer and this argument base
+; is saved by sending it to the debugger.
+
+ lor 1
+ sbs EM_WSIZE
+ loc EM_WSIZE
+ adu EM_WSIZE ; gives size
+ lor 1 ; SP (the SP BEFORE pushing)
+ lor 1 ; SP (address of stack top to save)
+ cal $___sendtop ; ___sendtop(char *address, char *SP, unsigned size)
+ asp 4*EM_PSIZE+3*EM_WSIZE ; remove the lot from the stack
+ loc 1
+ ret EM_WSIZE ; return 1
+ end 0
+
+ exp $___topload
+ pro $___topload, 0
+
+ lal 0
+ loi EM_PSIZE
+
+ lxl 0
+2
+ dup EM_PSIZE
+ lal 0
+ loi EM_PSIZE ; compare target SP with current LB to see if we must
+ loi EM_PSIZE
+ cmp ; find another LB first
+ zgt *1
+ dch ; just follow dynamic chain to make sure we find
+ ; a legal one
+ bra *2
+1
+ str 0
+
+ str 1 ; restore SP
+ lor 1
+ adp -EM_PSIZE
+ cal $___restoretop ; ___restoretop(char *SP)
+ asp EM_PSIZE+EM_WSIZE
+ str 0 ; restore local base
+ sim ; ignore mask
+ lae 4
+ sti EM_PSIZE
+ ste 0 ; line and file
+ loc 0
+ ret EM_WSIZE ; return 0
+ end 0