1 #ifndef lint 2 static char sccsid[] = "@(#)runpcs.c 4.6 4/25/85"; 3 #endif 4 /* 5 * 6 * UNIX debugger 7 * 8 */ 9 10 #include "defs.h" 11 #include <sys/wait.h> 12 13 extern MAP txtmap; 14 15 MSG NOFORK; 16 MSG ENDPCS; 17 MSG BADWAIT; 18 19 CHAR *lp; 20 ADDR sigint; 21 ADDR sigqit; 22 23 /* breakpoints */ 24 BKPTR bkpthead; 25 26 extern REGLIST reglist[]; 27 extern INT nregs; 28 29 CHAR lastc; 30 31 INT fcor; 32 INT fsym; 33 STRING errflg; 34 int errno; 35 INT signo; 36 INT sigcode; 37 38 L_INT dot; 39 STRING symfil; 40 INT wtflag; 41 INT pid; 42 L_INT expv; 43 INT adrflg; 44 L_INT loopcnt; 45 46 47 48 49 50 /* service routines for sub process control */ 51 52 getsig(sig) 53 { return(expr(0) ? expv : sig); 54 } 55 56 ADDR userpc = 1; 57 58 runpcs(runmode,execsig) 59 { 60 INT rc; 61 REG BKPTR bkpt; 62 IF adrflg THEN userpc=dot; FI 63 printf("%s: running\n", symfil); 64 65 WHILE --loopcnt>=0 66 DO 67 #ifdef DEBUG 68 printf("\ncontinue %x %d\n",userpc,execsig); 69 #endif 70 IF runmode==SINGLE 71 THEN delbp(); /* hardware handles single-stepping */ 72 ELSE /* continuing from a breakpoint is hard */ 73 IF bkpt=scanbkpt(userpc) 74 THEN execbkpt(bkpt,execsig); execsig=0; 75 FI 76 setbp(); 77 FI 78 ptrace(runmode,pid,userpc,execsig); 79 bpwait(); chkerr(); execsig=0; delbp(); readregs(); 80 81 IF signo==0 82 ANDF runmode != SINGLE 83 #ifdef mc68000 84 ANDF (bkpt=scanbkpt(userpc - 2)) /* argh */ 85 #else 86 ANDF (bkpt=scanbkpt(userpc)) 87 #endif 88 THEN /* stopped by BPT instruction */ 89 #ifdef DEBUG 90 printf("\n BPT code; '%s'%o'%o'%d", 91 bkpt->comm,bkpt->comm[0],EOR,bkpt->flag); 92 #endif 93 dot=bkpt->loc; 94 userpc = dot; 95 *(ADDR *)(((ADDR)&u)+PC-getradj(1)) = userpc; 96 IF bkpt->flag==BKPTEXEC 97 ORF ((bkpt->flag=BKPTEXEC) 98 ANDF bkpt->comm[0]!=EOR 99 ANDF command(bkpt->comm,':') 100 ANDF --bkpt->count) 101 THEN execbkpt(bkpt,execsig); execsig=0; loopcnt++; 102 ELSE bkpt->count=bkpt->initcnt; rc=1; 103 FI 104 ELSE execsig=signo; rc=0; 105 FI 106 OD 107 return(rc); 108 } 109 110 #define BPOUT 0 111 #define BPIN 1 112 INT bpstate = BPOUT; 113 114 endpcs() 115 { 116 REG BKPTR bkptr; 117 IF pid 118 THEN ptrace(PT_KILL,pid,0,0); pid=0; userpc=1; 119 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 120 DO IF bkptr->flag 121 THEN bkptr->flag=BKPTSET; 122 FI 123 OD 124 FI 125 bpstate=BPOUT; 126 } 127 128 #ifdef VFORK 129 nullsig() 130 { 131 132 } 133 #endif 134 135 setup() 136 { 137 close(fsym); fsym = -1; 138 #ifndef VFORK 139 IF (pid = fork()) == 0 140 #else 141 IF (pid = vfork()) == 0 142 #endif 143 THEN ptrace(PT_TRACE_ME,0,0,0); 144 #ifdef VFORK 145 signal(SIGTRAP,nullsig); 146 #endif 147 signal(SIGINT,sigint); signal(SIGQUIT,sigqit); 148 doexec(); exit(0); 149 ELIF pid == -1 150 THEN error(NOFORK); 151 ELSE bpwait(); readregs(); lp[0]=EOR; lp[1]=0; 152 fsym=open(symfil,wtflag); 153 IF errflg 154 THEN printf("%s: cannot execute\n",symfil); 155 endpcs(); error(0); 156 FI 157 FI 158 bpstate=BPOUT; 159 } 160 161 execbkpt(bkptr,execsig) 162 BKPTR bkptr; 163 { 164 #ifdef DEBUG 165 printf("exbkpt: %d\n",bkptr->count); 166 #endif 167 delbp(); 168 ptrace(PT_STEP,pid,bkptr->loc,execsig); 169 bkptr->flag=BKPTSET; 170 bpwait(); chkerr(); readregs(); 171 } 172 173 174 doexec() 175 { 176 STRING argl[MAXARG]; 177 CHAR args[LINSIZ]; 178 STRING p, *ap, filnam; 179 extern STRING environ; 180 ap=argl; p=args; 181 *ap++=symfil; 182 REP IF rdc()==EOR THEN break; FI 183 *ap = p; 184 /* 185 * First thing is to look for direction characters 186 * and get filename. Do not use up the args for filenames. 187 * Then get rid of spaces before next args. 188 */ 189 IF 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(0); 196 IF open(filnam,0)<0 197 THEN printf("%s: cannot open\n",filnam); _exit(0); 198 FI 199 p = *ap; 200 ELIF lastc=='>' 201 THEN REP readchar(); PER lastc==SP ORF lastc==TB DONE 202 filnam = p; 203 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='<' 204 DO *p++=lastc; readchar(); OD 205 *p = '\0'; 206 close(1); 207 IF creat(filnam,0666)<0 208 THEN printf("%s: cannot create\n",filnam); _exit(0); 209 FI 210 p = *ap; 211 ELSE 212 WHILE lastc!=EOR ANDF lastc!=SP ANDF lastc!=TB ANDF lastc!='>' ANDF lastc!='<' 213 DO *p++=lastc; readchar(); OD 214 *p++ = '\0'; 215 ap++; 216 FI 217 PER lastc!=EOR DONE 218 *ap++=0; 219 exect(symfil, argl, environ); 220 perror(symfil); 221 } 222 223 BKPTR scanbkpt(adr) 224 ADDR adr; 225 { 226 REG BKPTR bkptr; 227 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 228 DO IF bkptr->flag ANDF bkptr->loc==adr 229 THEN break; 230 FI 231 OD 232 return(bkptr); 233 } 234 235 delbp() 236 { 237 REG ADDR a; 238 REG BKPTR bkptr; 239 IF bpstate!=BPOUT 240 THEN 241 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 242 DO IF bkptr->flag 243 THEN a=bkptr->loc; 244 IF a < txtmap.e1 THEN 245 ptrace(PT_WRITE_I,pid,a,bkptr->ins); 246 ELSE 247 ptrace(PT_WRITE_D,pid,a,bkptr->ins); 248 FI 249 FI 250 OD 251 bpstate=BPOUT; 252 FI 253 } 254 255 #ifdef pdp11 256 help -- I left my architecture manual at home 257 #endif 258 259 #ifdef vax 260 #define SETBP(ins) (BPT | ((ins) &~ 0xFF)) 261 #endif 262 263 #ifdef mc68000 264 #define SETBP(ins) ((BPT << 16) | ((ins) & 0xFFFF)) 265 #endif 266 267 #if !pdp11 && !vax && !mc68000 268 269 edit this file to handle your machines breakpoint indication 270 271 #endif 272 273 setbp() 274 { 275 REG ADDR a; 276 REG BKPTR bkptr; 277 278 IF bpstate!=BPIN 279 THEN 280 FOR bkptr=bkpthead; bkptr; bkptr=bkptr->nxtbkpt 281 DO IF bkptr->flag 282 THEN a = bkptr->loc; 283 IF a < txtmap.e1 THEN 284 bkptr->ins = ptrace(PT_READ_I, pid, a, 0); 285 ptrace(PT_WRITE_I, pid, a, SETBP(bkptr->ins)); 286 ELSE 287 bkptr->ins = ptrace(PT_READ_D, pid, a, 0); 288 ptrace(PT_WRITE_D, pid, a, SETBP(bkptr->ins)); 289 FI 290 IF errno 291 THEN prints("cannot set breakpoint: "); 292 psymoff(bkptr->loc,ISYM,"\n"); 293 FI 294 FI 295 OD 296 bpstate=BPIN; 297 FI 298 } 299 300 bpwait() 301 { 302 REG ADDR w; 303 union wait stat; 304 305 signal(SIGINT, 1); 306 WHILE (w = wait(&stat))!=pid ANDF w != -1 DONE 307 signal(SIGINT,sigint); 308 IF w == -1 309 THEN pid=0; 310 errflg=BADWAIT; 311 ELIF !WIFSTOPPED(stat) 312 THEN sigcode = 0; 313 IF signo = stat.w_termsig 314 THEN sigprint(); 315 FI 316 IF stat.w_coredump 317 THEN prints(" - core dumped"); 318 close(fcor); 319 setcor(); 320 FI 321 pid=0; 322 errflg=ENDPCS; 323 ELSE signo = stat.w_stopsig; 324 sigcode = ptrace(PT_READ_U, pid, &((struct user *)0)->u_code, 0); 325 IF signo!=SIGTRAP 326 THEN sigprint(); 327 ELSE signo=0; 328 FI 329 flushbuf(); 330 FI 331 } 332 333 readregs() 334 { 335 /*get REG values from pcs*/ 336 REG i; 337 L_INT radj = getradj(1); 338 L_INT offset; 339 340 FOR i=nregs; --i>=0; 341 DO IF (offset = reglist[i].roffs) >= sizeof (struct user) 342 THEN offset -= radj; 343 FI 344 *(ADDR *)(((ADDR)&u) + offset) = 345 ptrace(PT_READ_U, pid, offset, 0); 346 #ifdef hp300 347 /* XXX: 68881/68882 FP regs are 3 longwords */ 348 IF reglist[i].rtype == XPFLOAT 349 THEN offset += sizeof (ADDR); 350 *(ADDR *)(((ADDR)&u) + offset) = 351 ptrace(PT_READ_U, pid, offset, 0); 352 offset += sizeof (ADDR); 353 *(ADDR *)(((ADDR)&u) + offset) = 354 ptrace(PT_READ_U, pid, offset, 0); 355 FI 356 #endif 357 OD 358 userpc= *(ADDR *)(((ADDR)&u) + PC - radj); 359 } 360 361 #ifdef hp300 362 L_INT 363 getradj(running) 364 INT running; 365 { 366 L_INT radj; 367 368 /* this code assumes that u_ap always points to u_arg */ 369 IF running 370 THEN u.u_ar0 = (int *) ptrace(PT_READ_U, pid, 371 (ADDR)&u.u_ar0 - (ADDR) &u, 0); 372 #if 0 373 u.u_ap = (int *) ptrace(PT_READ_U, pid, 374 (ADDR)&u.u_ap - (ADDR) &u, 0); 375 #endif 376 IF u.u_ar0 == -1 377 #if 0 378 ORF u.u_ap == -1 379 #endif 380 THEN endpcs(); 381 error("can't read from running process"); 382 return (0); 383 FI 384 FI 385 IF !kcore 386 THEN 387 #if 0 388 radj = (ADDR) &u.u_arg - (ADDR) &u; /* offset of u_arg */ 389 radj = (ADDR) u.u_ap - radj; /* address of u */ 390 #endif 391 radj = (ADDR) 0xfff00000; 392 radj = (ADDR) u.u_ar0 - radj; /* offset of d0 */ 393 radj = D0 - radj; /* difference from expected offset */ 394 ELSE 395 radj = 0; 396 FI 397 return (radj); 398 } 399 #endif 400