From: ceriel Date: Mon, 16 Sep 1991 11:47:43 +0000 (+0000) Subject: Added X-Git-Tag: release-5-5~879 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=132d7ddd95e0e11f82ea6d898c5dd6954e8ad42c;p=ack.git Added --- diff --git a/mach/m68020/libdb/.distr b/mach/m68020/libdb/.distr new file mode 100644 index 000000000..af5eda499 --- /dev/null +++ b/mach/m68020/libdb/.distr @@ -0,0 +1 @@ +machdep.s diff --git a/mach/m68020/libdb/machdep.s b/mach/m68020/libdb/machdep.s new file mode 100644 index 000000000..d6269c830 --- /dev/null +++ b/mach/m68020/libdb/machdep.s @@ -0,0 +1,63 @@ +.define ___Get_PC, ___Set_PC, ___u_LiB +.sect .text; .sect .rom; .sect .data + +! $Header$ + +! This is the machine-dependant part of the ACK debugger support. +! ___Get_PC takes a frame pointer (local base) argument and returns the +! return address from this frame. +! ___Set_PC takes a frame pointer (local base) argument plus a return +! address and sets the return address of this frame to the +! return address supplied. +! ___u_LiB saves the scratch registers and then calls ___uX_LiB; +! when ___uX_LiB returns, the scratch registers are restored. +! ___u_LiB is the solution chosen for the MC68020 back-end. +! Other back-ends could choose different solutions. + +! The local base of ___uX_LiB is kind of special: because of ___u_LiB, +! the "interesting" return address of this particular stack-frame is found +! in a different place than the one of a normal stack-frame: +! the "interesting" return address is in fact the return address of +! ___u_LiB. Therefore, we save the local base of ___uX_LiB in sv_a6. + +.sect .data +sv_a6: + .data4 0 + +.sect .text +___Get_PC: + move.l (4,sp),d0 + beq 1f + move.l d0,a0 + cmp.l (sv_a6),d0 + beq 2f + move.l (4,a0),d0 +1: + rts +2: + move.l (32,a0),d0 + rts + +___Set_PC: + move.l (4,sp),d0 + beq 1f + move.l d0,a0 + cmp.l (sv_a6),d0 + beq 2f + move.l (8,sp),(4,a0) +1: + rts +2: + move.l (8,sp),(32,a0) + rts + +___u_LiB: + movem.l d0/d1/d2/a0/a1,-(sp) + move.l (sv_a6),-(sp) + move.l sp,d0 + sub.l #8,d0 + move.l d0,(sv_a6) ! this is the LB of __uX_LiB + jsr (___uX_LiB) + move.l (sp)+,(sv_a6) + movem.l (sp)+,d0/d1/d2/a0/a1 + rts diff --git a/mach/proto/grind/.distr b/mach/proto/grind/.distr new file mode 100644 index 000000000..b57d195b7 --- /dev/null +++ b/mach/proto/grind/.distr @@ -0,0 +1,4 @@ +READ_ME +atlin.c +lib.e +par_misc.e diff --git a/mach/proto/grind/READ_ME b/mach/proto/grind/READ_ME new file mode 100644 index 000000000..9307a3a06 --- /dev/null +++ b/mach/proto/grind/READ_ME @@ -0,0 +1,17 @@ +$Header$ + +The machine-dependant part of the ACK debugger support requires three +routines: +___Get_PC takes a frame pointer (local base) argument and returns the + return address from this frame. +___Set_PC takes a frame pointer (local base) argument plus a return + address and sets the return address of this frame to the + return address supplied. +??? a third routine which is called at every line (see for + instance mach/m68020/ncg/mach.c for an example of how to + do this). This routine must save the scratch registers + and then call (or jump to) ___uX_LiB. If this is a call, + ___Get_PC and ___Set_PC are complicated by the existance + of a procedure frame that we do not want the "grind" user + to know about. See for instance the mach/m68020/libdb version + for how to solve this problem. diff --git a/mach/proto/grind/atlin.c b/mach/proto/grind/atlin.c new file mode 100644 index 000000000..e4f526a9e --- /dev/null +++ b/mach/proto/grind/atlin.c @@ -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 */; +} diff --git a/mach/proto/grind/lib.e b/mach/proto/grind/lib.e new file mode 100644 index 000000000..b29796a6e --- /dev/null +++ b/mach/proto/grind/lib.e @@ -0,0 +1,58 @@ +# + +; $Header$ + + mes 2, EM_WSIZE, EM_PSIZE + + exp $__Get_LB + pro $__Get_LB,0 + lor 0 +1 + lol 0 + zlt *2 + dup EM_PSIZE + zer EM_PSIZE + cmp + zeq *2 + dch + del 0 + bra *1 +2 + ret EM_PSIZE + end + + exp $__Get_Hol0 + pro $__Get_Hol0,0 + lae 0 + ret EM_PSIZE + end + + exp $__Get_HP + pro $__Get_HP,0 + lor 2 + ret EM_PSIZE + end + + exp $__Set_HP + pro $__Set_HP,0 + lal 0 + loi EM_PSIZE + str 2 + ret 0 + end + + exp $__Cvt_LB_AB + pro $__Cvt_LB_AB,0 + lal 0 + loi EM_PSIZE + zer EM_PSIZE + cmp + zeq *2 + lal 0 + loi EM_PSIZE + lpb + ret EM_PSIZE +2 + zer EM_PSIZE + ret EM_PSIZE + end diff --git a/mach/proto/grind/par_misc.e b/mach/proto/grind/par_misc.e new file mode 100644 index 000000000..7be77ea8e --- /dev/null +++ b/mach/proto/grind/par_misc.e @@ -0,0 +1,91 @@ +# +; +; (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