1 # 2 /* 3 * 4 * UNIX debugger 5 * 6 */ 7 8 #include "defs.h" 9 static char sccsid[] = "@(#)runpcs.c 4.2 10/28/82"; 10 11 extern MAP txtmap; 12 13 MSG NOFORK; 14 MSG ENDPCS; 15 MSG BADWAIT; 16 17 CHAR *lp; 18 ADDR sigint; 19 ADDR sigqit; 20 21 /* breakpoints */ 22 BKPTR bkpthead; 23 24 REGLIST reglist[]; 25 26 CHAR lastc; 27 28 INT fcor; 29 INT fsym; 30 STRING errflg; 31 INT errno; 32 INT signo; 33 INT sigcode; 34 35 L_INT dot; 36 STRING symfil; 37 INT wtflag; 38 L_INT pid; 39 L_INT expv; 40 INT adrflg; 41 L_INT loopcnt; 42 43 44 45 46 47 /* service routines for sub process control */ 48 49 getsig(sig) 50 { return(expr(0) ? expv : sig); 51 } 52 53 ADDR userpc = 1; 54 55 runpcs(runmode,execsig) 56 { 57 INT rc; 58 REG BKPTR bkpt; 59 IF adrflg THEN userpc=dot; FI 60 printf("%s: running\n", symfil); 61 62 WHILE --loopcnt>=0 63 DO 64 #ifdef DEBUG 65 printf("\ncontinue %x %d\n",userpc,execsig); 66 #endif 67 IF runmode==SINGLE 68 THEN delbp(); /* hardware handles single-stepping */ 69 ELSE /* continuing from a breakpoint is hard */ 70 IF bkpt=scanbkpt(userpc) 71 THEN execbkpt(bkpt,execsig); execsig=0; 72 FI 73 setbp(); 74 FI 75 ptrace(runmode,pid,userpc,execsig); 76 bpwait(); chkerr(); execsig=0; delbp(); readregs(); 77 78 IF (signo==0) ANDF (bkpt=scanbkpt(userpc)) 79 THEN /* stopped by BPT instruction */ 80 #ifdef DEBUG 81 printf("\n BPT code; '%s'%o'%o'%d", 82 bkpt->comm,bkpt->comm[0],EOR,bkpt->flag); 83 #endif 84 dot=bkpt->loc; 85 IF bkpt->flag==BKPTEXEC 86 ORF ((bkpt->flag=BKPTEXEC) 87 ANDF bkpt->comm[0]!=EOR 88 ANDF command(bkpt->comm,':') 89 ANDF --bkpt->count) 90 THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++; 91 ELSE bkpt->count=bkpt->initcnt; rc=1; 92 FI 93 ELSE execsig=signo; rc=0; 94 FI 95 OD 96 return(rc); 97 } 98 99 #define BPOUT 0 100 #define BPIN 1 101 INT bpstate = BPOUT; 102 103 endpcs() 104 { 105 REG BKPTR bkptr; 106 IF pid 107 THEN ptrace(EXIT,pid,0,0); pid=0; userpc=1; 108 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 109 DO IF bkptr->flag 110 THEN bkptr->flag=BKPTSET; 111 FI 112 OD 113 FI 114 bpstate=BPOUT; 115 } 116 117 #ifdef VFORK 118 nullsig() 119 { 120 121 } 122 #endif 123 124 setup() 125 { 126 close(fsym); fsym = -1; 127 #ifndef VFORK 128 IF (pid = fork()) == 0 129 #else 130 IF (pid = vfork()) == 0 131 #endif 132 THEN ptrace(SETTRC,0,0,0); 133 #ifdef VFORK 134 signal(SIGTRAP,nullsig); 135 #endif 136 signal(SIGINT,sigint); signal(SIGQUIT,sigqit); 137 doexec(); exit(0); 138 ELIF pid == -1 139 THEN error(NOFORK); 140 ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0; 141 fsym=open(symfil,wtflag); 142 IF errflg 143 THEN printf("%s: cannot execute\n",symfil); 144 endpcs(); error(0); 145 FI 146 FI 147 bpstate=BPOUT; 148 } 149 150 execbkpt(bkptr,execsig) 151 BKPTR bkptr; 152 { 153 #ifdef DEBUG 154 printf("exbkpt: %d\n",bkptr->count); 155 #endif 156 delbp(); 157 ptrace(SINGLE,pid,bkptr->loc,execsig); 158 bkptr->flag=BKPTSET; 159 bpwait(); chkerr(); readregs(); 160 } 161 162 163 doexec() 164 { 165 STRING argl[MAXARG]; 166 CHAR args[LINSIZ]; 167 STRING p, *ap, filnam; 168 extern STRING environ; 169 ap=argl; p=args; 170 *ap++=symfil; 171 REP IF rdc()==EOR THEN break; FI 172 *ap = p; 173 /* 174 * First thing is to look for direction characters 175 * and get filename. Do not use up the args for filenames. 176 * Then get rid of spaces before next args. 177 */ 178 IF lastc=='<' 179 THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE 180 filnam = p; 181 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>' 182 DO *p++=lastc; readchar(); OD 183 *p = 0; 184 close(0); 185 IF open(filnam,0)<0 186 THEN printf("%s: cannot open\n",filnam); _exit(0); 187 FI 188 p = *ap; 189 ELIF lastc=='>' 190 THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE 191 filnam = p; 192 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='<' 193 DO *p++=lastc; readchar(); OD 194 *p = '\0'; 195 close(1); 196 IF creat(filnam,0666)<0 197 THEN printf("%s: cannot create\n",filnam); _exit(0); 198 FI 199 p = *ap; 200 ELSE 201 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>' ANDF lastc!='<' 202 DO *p++=lastc; readchar(); OD 203 *p++ = '\0'; 204 ap++; 205 FI 206 WHILE lastc==SP ORF lastc==TB DO readchar(); OD 207 208 PER lastc!=EOR DONE 209 *ap++=0; 210 exect(symfil, argl, environ); 211 perror(symfil); 212 } 213 214 BKPTR scanbkpt(adr) 215 ADDR adr; 216 { 217 REG BKPTR bkptr; 218 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 219 DO IF bkptr->flag ANDF bkptr->loc==adr 220 THEN break; 221 FI 222 OD 223 return(bkptr); 224 } 225 226 delbp() 227 { 228 REG ADDR a; 229 REG BKPTR bkptr; 230 IF bpstate!=BPOUT 231 THEN 232 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 233 DO IF bkptr->flag 234 THEN a=bkptr->loc; 235 IF a < txtmap.e1 THEN 236 ptrace(WIUSER,pid,a, 237 (bkptr->ins&0xFF)|(ptrace(RIUSER,pid,a,0)&~0xFF)); 238 ELSE 239 ptrace(WDUSER,pid,a, 240 (bkptr->ins&0xFF)|(ptrace(RDUSER,pid,a,0)&~0xFF)); 241 FI 242 FI 243 OD 244 bpstate=BPOUT; 245 FI 246 } 247 248 setbp() 249 { 250 REG ADDR a; 251 REG BKPTR bkptr; 252 253 IF bpstate!=BPIN 254 THEN 255 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 256 DO IF bkptr->flag 257 THEN a = bkptr->loc; 258 IF a < txtmap.e1 THEN 259 bkptr->ins = ptrace(RIUSER, pid, a, 0); 260 ptrace(WIUSER, pid, a, BPT | (bkptr->ins&~0xFF)); 261 ELSE 262 bkptr->ins = ptrace(RDUSER, pid, a, 0); 263 ptrace(WDUSER, pid, a, BPT | (bkptr->ins&~0xFF)); 264 FI 265 IF errno 266 THEN prints("cannot set breakpoint: "); 267 psymoff(bkptr->loc,ISYM,"\n"); 268 FI 269 FI 270 OD 271 bpstate=BPIN; 272 FI 273 } 274 275 bpwait() 276 { 277 REG ADDR w; 278 ADDR stat; 279 280 signal(SIGINT, 1); 281 WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE 282 signal(SIGINT,sigint); 283 IF w == -1 284 THEN pid=0; 285 errflg=BADWAIT; 286 ELIF (stat & 0177) != 0177 287 THEN sigcode = 0; 288 IF signo = stat&0177 289 THEN sigprint(); 290 FI 291 IF stat&0200 292 THEN prints(" - core dumped"); 293 close(fcor); 294 setcor(); 295 FI 296 pid=0; 297 errflg=ENDPCS; 298 ELSE signo = stat>>8; 299 sigcode = ptrace(RUREGS, pid, &((struct user *)0)->u_code, 0); 300 IF signo!=SIGTRAP 301 THEN sigprint(); 302 ELSE signo=0; 303 FI 304 flushbuf(); 305 FI 306 } 307 308 readregs() 309 { 310 /*get REG values from pcs*/ 311 REG i; 312 FOR i=24; --i>=0; 313 DO *(ADDR *)(((ADDR)&u)+reglist[i].roffs) = 314 ptrace(RUREGS, pid, reglist[i].roffs, 0); 315 OD 316 userpc= *(ADDR *)(((ADDR)&u)+PC); 317 } 318 319 320