home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1990 by Sozobon, Limited. Authors: Johann Ruegg, Don Dugger
- *
- * Permission is granted to anyone to use this software for any purpose
- * on any computer system, and to redistribute it freely, with the
- * following restrictions:
- * 1) No charge may be made other than reasonable charges for reproduction.
- * 2) Modified versions must be clearly marked as such.
- * 3) The authors are not responsible for any harmful consequences
- * of using this software, even if they result from defects in it.
- *
- * pcs.c
- */
- /*
- * Modifications:
- * - cmdcol() changed for a cooperation with stepping commands
- * - added function getrequs() which handles turning on/off
- * execution on breakpoints and stepping commands
- * - added function findval() which returns values of read-only
- * internal variables
- *
- * Anthony Howe, Michal Jaegermann, April 1990
- *
- * - prnstack now uses Unwind function from stepping.c to find
- * a chain of return addresses. (MJ - November 1990)
- */
- #include <setjmp.h>
- #include <ctype.h>
- #include "adb.h"
-
- #define IN_PCS
- #include "lang.h"
-
- #ifndef NULL
- #define NULL 0L
- #endif
-
- unsigned long esp;
- struct basepg *bpage;
- jmp_buf cont_buf;
- static int got_args = 0;
-
- extern long dot;
- extern long olddot;
- extern int dotset;
- extern int dotoff;
- extern int lastc;
- extern int print_regs;
- extern int click;
- extern struct regs regs[];
- extern next_step next_list[];
- extern next_step jump_list[];
-
- prstack (argsflg)
- {
- int first, at_sp;
- long pc, fp, sp, ap;
- long npc, nfp;
- long getn ();
- short *Unwind();
- struct basepg *bp = bpage;
-
- pc = *(regs[PC].value);
- fp = *(regs[FP].value);
- sp = *(regs[SP].value);
- at_sp = first = 1;
-
- while (pc) {
- prtf ("%A", pc);
- npc = (long) Unwind (&at_sp, pc, sp, fp);
- /* this may modify value of at_sp */
- if (first && at_sp) {
- nfp = fp;
- ap = sp + 4;
- at_sp = 0; /* get the next return address from fp */
- }
- else {
- nfp = getn (fp, 4);
- ap = fp + 8;
- }
- if (argsflg && npc)
- funargs (npc, ap, nfp);
- putchr ('\n');
-
- if (nfp < (long) bp->p_bbase + bp->p_blen ||
- nfp > (long) bp->p_hitpa ||
- nfp <= sp || nfp < fp ||
- (nfp == fp && !first))
- break;
- pc = npc;
- fp = nfp;
- first = 0;
- }
- }
-
- funargs (retpc, argp, limit)
- long retpc, argp, limit;
- {
- int i, n;
- unsigned w;
-
- n = numargs (retpc);
-
- if (n == 0) { /* optimized out maybe */
- /* prtf("(? at %I)", argp); */
- prtf (M1, argp);
- return;
- }
-
- putchr ('(');
- for (i = 0; i < n; i++, argp += 2) {
- w = getn (argp, 2);
- prt4x (w);
- if (argp + 2 >= limit)
- break;
- if ((i + 1) < n)
- putchr (',');
- }
- putchr (')');
- }
-
- prt4x (w)
- unsigned w;
- {
- int i, j, k;
-
- k = 12;
- for (k = 12; k >= 0; k -= 4) {
- j = w >> k;
- j &= 0xf;
- putchr ("0123456789abcdef"[j]);
- }
- }
-
- numargs (retpc)
- long retpc;
- {
- int ins, n;
- long getn ();
-
- ins = getn (retpc, 2);
- if ((ins & 0xf1ff) == 0x504f ||
- (ins & 0xf1ff) == 0x508f) { /* addq.[wl] #n,A7 */
- n = (ins >> 9) & 7;
- if (n == 0)
- n = 8;
- }
- else if (ins == 0xdefc) { /* adda.w #n,A7 */
- n = getn (retpc + 2, 2);
- }
- else if (ins == 0xdffc) { /* adda.l #n,A7 */
- n = getn (retpc + 2, 4);
- }
- else
- n = 0;
-
- if (n < 0)
- n = 0;
- return n / 2;
- }
-
- long
- atbranch (loc)
- long loc;
- {
- int ins, i;
-
- ins = getn (loc, 2);
- if ((ins & 0xff00) == 0x6000) {
- i = ins & 0xff;
- if (i == 0)
- i = getn (loc + 2, 2);
- return loc + 2 + i;
- }
- return 0;
- }
-
- atlink (loc)
- long loc;
- {
- int ins;
-
- ins = getn (loc, 2);
- return (ins == 0x4e56); /* link a6,#N */
- }
-
- atrts (loc)
- long loc;
- {
- int ins;
-
- ins = getn (loc, 2);
- return (ins == 0x4e75);
- }
-
- prbasepg ()
- {
- int n, i;
- unsigned char c;
- struct basepg *bp;
-
- if (dotset)
- bp = (struct basepg *) dot;
- else
- bp = bpage;
-
- /* prtf("base page at %I", bp); */
- prtf (M2, bp);
- /* prt("low tpa "); */
- prt (M3);
- prtn (bp->p_lowtpa, 10);
- /* prt(" hi tpa "); */
- prt (M4);
- prtn (bp->p_hitpa, 10);
- /* prt("\ntext at "); */
- prt (M5);
- prtn (bp->p_tbase, 10);
- /* prt(" size "); */
- prt (M6);
- prtn (bp->p_tlen, 10);
- /* prt("\ndata at "); */
- prt (M7);
- prtn (bp->p_dbase, 10);
- /* prt(" size "); */
- prt (M6);
- prtn (bp->p_dlen, 10);
- /* prt("\nbss at "); */
- prt (M8);
- prtn (bp->p_bbase, 10);
- /* prt(" size "); */
- prt (M6);
- prtn (bp->p_blen, 10);
- /* prt("\nenv ptr "); */
- prt (M9);
- prtn (bp->p_env, 10);
- /* prt(" parent "); */
- prt (M10);
- prtn (bp->p_parent, 10);
-
- prtf ("\nargs: ");
- n = bp->p_cmdlin[0];
- for (i = 0; i < n;) {
- c = bp->p_cmdlin[++i];
- if (c < ' ') {
- putchr ('^');
- c += 'A';
- }
- putchr (c);
- }
- putchr ('\n');
- }
-
- loadpcs ()
- {
- int **ip;
- char parms[80], *envp;
- extern struct basepg *gemdos ();
- extern struct file binary;
- extern struct basepg *_base;
- extern unsigned long ossp;
-
- parms[0] = '\0';
- envp = _base->p_env;
- if ((bpage = gemdos (0x4b, 3, binary.name, parms, envp)) < 0) {
- /* prtf("can't load %s\n", binary.name); */
- prtf (M11, binary.name);
- return -1;
- }
- ip = (int **) (bpage->p_hitpa);
- *--ip = (int *) bpage;
- --ip;
- *(regs[SP].value) = (unsigned long) ip;
- *(regs[PC].value) = dot = olddot = (unsigned long) bpage->p_tbase;
- *(regs[XSP].value) = ossp;
- #ifdef OLD
- bpage->p_parent = _base;
- #else
- bpage->p_parent = 0;
- #endif
- return 0;
- }
-
- void
- cmdcol (c, fmt, get)
- int c;
- char *fmt;
- long (*get) ();
- {
- extern int MakeReq ();
- int kind, tmp;
-
- if ('b' == c) { /* set breakpoint */
- SetBpt (dot);
- }
- else if ('d' == c) { /* clear breakpoint */
- ClrBpt (dot);
- }
- else { /* tracing */
- if (dotset)
- *regs[PC].value = dot;
- else
- dot = *regs[PC].value;
-
- c = ((print_regs = isupper (c)) ? tolower (c) : c);
- if ('s' == c)
- kind = CM_STEP;
- else if ('n' == c || 'j' == c)
- kind = CM_NEXT;
- else if ('f' == c)
- kind = CM_FINISH;
- else {
- kind = CM_CONT; /* we hope */
- if (click) /* command line started with :: */
- c = 0; /* force error */
- }
-
- if (CM_CONT == kind || 0 == MakeReq (kind)) {
- switch (c) {
- case 's':
- SingleStep (dot, CM_STEP);
- break;
- case 'c':
- getargs ();
- if (setjmp (cont_buf)) {
- dot = *regs[PC].value;
- }
- FullStep (dot, (short *) NULL, CM_CONT);
- break;
- case 'n':
- NextStep (dot, next_list);
- break;
- case 'j':
- NextStep (dot, jump_list);
- break;
- case 'f':
- FuncStep (dot);
- break;
- default:
- prt (UNKNOWN_CMD);
- } /* switch */
- } /* if (click) */
- } /* if ('b' == c) */
- click = 0; /* next time around execute */
- return;
- } /* cmdcol */
-
- int
- getrequs (buf)
- char *buf;
- /*
- * If 'click' is off and if on a current position, and after all white space
- * was skipped, there is a character other then '\n', then copy all remaining
- * characters on a line into a supplied buffer buf. Terminate with '\n\0'.
- * Return ON if something was copied and BLANK otherwise.
- * If click is ON return one of the status comands depending on what follows.
- * Skip to the next delimiter and push '\n'.
- */
- {
- register int c;
- register char *pos = buf;
- int status;
- extern int getchr (), nb ();
-
- if (0 == click) {
- if ('\n' != PEEKC) {
- do {
- *pos++ = c = getchr (1);
- } while ('\n' != c);
- *pos++ = '\0';
- status = NEW;
- }
- else /* '\n' is pushed */
- return BLANK;
- }
- else { /* we are changing status of attached
- * commands - ignore buffer */
- switch (c = nb ()) {
- case '+':
- status = ON;
- break;
- case '-':
- status = SILENT;
- break;
- case '_':
- status = DOWN;
- break;
- case '`':
- status = REVERT;
- break;
- default:
- status = IGNORE;
- }
- while (getchr (0) != '\n') /* skip to the next delimiter */
- ;
- }
- PUSHC ('\n');
- return (status);
- } /* getrequs */
-
- getargs ()
- {
- char c, *cp;
- int n;
-
- c = nb ();
- if (c == '\n')
- return;
-
- if (got_args)
- return;
- got_args++;
-
- n = 1;
- cp = &bpage->p_cmdlin[n];
- *cp++ = c;
- while ((c = getchr (1)) != '\n') {
- *cp++ = c;
- n++;
- if (n >= 0x7f)
- break;
- }
- bpage->p_cmdlin[0] = n;
- *cp = 0;
- PUSHC ('\n');
- }
-
- void
- copyargs (argc, argv)
- int argc;
- char **argv;
- /*
- * If argc > 0 copy command line arguments into a base page of
- * process to debug. Terminating zero not included in count.
- */
- {
- char c, *cp;
- int n;
-
- if (0 == argc) {
- bpage->p_cmdlin[0] = 0;
- return;
- }
- got_args++;
-
- n = 0;
- cp = &bpage->p_cmdlin[1];
- for (;;) {
- if (n >= 0x7e)
- break;
- while (0 != (c = *(*argv)++)) {
- *cp++ = c;
- n++;
- if (n >= 0x7e)
- goto out;
- }
- if (--argc == 0)
- break;
- *cp++ = ' ';
- n++;
- }
- out:
- *cp = 0;
- bpage->p_cmdlin[0] = n;
- }
-
-
- #ifdef GONER
- cleanup (fp)
- struct file *fp;
- {
-
- ptrace (KILL_PID, fp->pid, 0, 0);
- return;
- }
-
- #endif
-
- prbpt (pc)
- long pc;
- {
- dot = pc;
- dotoff = 0;
- prtad (dot + dotoff);
- putchr (':');
- puti ();
- return;
- }
-
- long
- findval (buf, err_p)
- char *buf;
- int *err_p;
- /*
- * If a string in buf is "l", "b", "t" or "d" return value of
- * text segment base, data segment base, text size and data size
- * respectively. Otherwise set error indicator and return 0.
- *
- * Names are chosen to avoid conflicts with a Un*x adb. Names
- * "b", "t", "d" and some other are already taken.
- */
- {
- struct basepg *bp = bpage;
-
- if (0 == (*err_p = buf[1])) {
- switch (buf[0]) {
- case 'l':
- return (bp->p_tbase);
- case 'b':
- return (bp->p_dbase);
- case 'd':
- return (bp->p_dlen);
- case 't':
- return (bp->p_tlen);
- }
- }
- *err_p = 1;
- return 0;
- }
-