1 /* 2 * 3 * debugger 4 * 5 */ 6 7 #include "defs.h" 8 #include "fns.h" 9 10 char BADEQ[] = "unexpected `='"; 11 12 BOOL executing; 13 extern char *lp; 14 15 extern char lastc, peekc; 16 char eqformat[ARB] = "z"; 17 char stformat[ARB] = "zMi"; 18 19 ADDR ditto; 20 21 ADDR dot; 22 WORD dotinc; 23 WORD adrval, cntval, loopcnt; 24 int adrflg, cntflg; 25 26 /* command decoding */ 27 28 command(char *buf, int defcom) 29 { 30 char *reg; 31 char savc; 32 char *savlp=lp; 33 char savlc = lastc; 34 char savpc = peekc; 35 static char lastcom = '=', savecom = '='; 36 37 if (defcom == 0) 38 defcom = lastcom; 39 if (buf) { 40 if (*buf==EOR) 41 return(FALSE); 42 clrinp(); 43 lp=buf; 44 } 45 do { 46 adrflg=expr(0); /* first address */ 47 if (adrflg) 48 dot=ditto=expv; 49 adrval=dot; 50 51 if (rdc()==',' && expr(0)) { /* count */ 52 cntflg=TRUE; 53 cntval=expv; 54 } else { 55 cntflg=FALSE; 56 cntval=1; 57 reread(); 58 } 59 60 if (!eol(rdc())) 61 lastcom=lastc; /* command */ 62 else { 63 if (adrflg==0) 64 dot=inkdot(dotinc); 65 reread(); 66 lastcom=defcom; 67 } 68 switch(lastcom) { 69 case '/': 70 case '=': 71 case '?': 72 savecom = lastcom; 73 acommand(lastcom); 74 break; 75 76 case '>': 77 lastcom = savecom; 78 savc=rdc(); 79 if (reg=regname(savc)) 80 rput(cormap, reg, dot); 81 else 82 error("bad variable"); 83 break; 84 85 case '!': 86 lastcom=savecom; 87 shell(); 88 break; 89 90 case '$': 91 lastcom=savecom; 92 printtrace(nextchar()); 93 break; 94 95 case ':': 96 if (!executing) { 97 executing=TRUE; 98 subpcs(nextchar()); 99 executing=FALSE; 100 lastcom=savecom; 101 } 102 break; 103 104 case 0: 105 prints(DBNAME); 106 break; 107 108 default: 109 error("bad command"); 110 } 111 flushbuf(); 112 } while (rdc()==';'); 113 if (buf == 0) 114 reread(); 115 else { 116 clrinp(); 117 lp=savlp; 118 lastc = savlc; 119 peekc = savpc; 120 } 121 122 if(adrflg) 123 return dot; 124 return 1; 125 } 126 127 /* 128 * [/?][wml] 129 */ 130 131 void 132 acommand(int pc) 133 { 134 int eqcom; 135 Map *map; 136 char *fmt; 137 char buf[512]; 138 139 if (pc == '=') { 140 eqcom = 1; 141 fmt = eqformat; 142 map = dotmap; 143 } else { 144 eqcom = 0; 145 fmt = stformat; 146 if (pc == '/') 147 map = cormap; 148 else 149 map = symmap; 150 } 151 if (!map) { 152 sprint(buf, "no map for %c", pc); 153 error(buf); 154 } 155 156 switch (rdc()) 157 { 158 case 'm': 159 if (eqcom) 160 error(BADEQ); 161 cmdmap(map); 162 break; 163 164 case 'L': 165 case 'l': 166 if (eqcom) 167 error(BADEQ); 168 cmdsrc(lastc, map); 169 break; 170 171 case 'W': 172 case 'w': 173 if (eqcom) 174 error(BADEQ); 175 cmdwrite(lastc, map); 176 break; 177 178 default: 179 reread(); 180 getformat(fmt); 181 scanform(cntval, !eqcom, fmt, map, eqcom); 182 } 183 } 184 185 void 186 cmdsrc(int c, Map *map) 187 { 188 long w; 189 long locval, locmsk; 190 ADDR savdot; 191 ushort sh; 192 char buf[512]; 193 int ret; 194 195 if (c == 'L') 196 dotinc = 4; 197 else 198 dotinc = 2; 199 savdot=dot; 200 expr(1); 201 locval=expv; 202 if (expr(0)) 203 locmsk=expv; 204 else 205 locmsk = ~0; 206 if (c == 'L') 207 while ((ret = get4(map, dot, &w)) > 0 && (w&locmsk) != locval) 208 dot = inkdot(dotinc); 209 else 210 while ((ret = get2(map, dot, &sh)) > 0 && (sh&locmsk) != locval) 211 dot = inkdot(dotinc); 212 if (ret < 0) { 213 dot=savdot; 214 error("%r"); 215 } 216 symoff(buf, 512, dot, CANY); 217 dprint(buf); 218 } 219 220 static char badwrite[] = "can't write process memory or text image"; 221 222 void 223 cmdwrite(int wcom, Map *map) 224 { 225 ADDR savdot; 226 char *format; 227 int pass; 228 229 if (wcom == 'w') 230 format = "x"; 231 else 232 format = "X"; 233 expr(1); 234 pass = 0; 235 do { 236 pass++; 237 savdot=dot; 238 exform(1, 1, format, map, 0, pass); 239 dot=savdot; 240 if (wcom == 'W') { 241 if (put4(map, dot, expv) <= 0) 242 error(badwrite); 243 } else { 244 if (put2(map, dot, expv) <= 0) 245 error(badwrite); 246 } 247 savdot=dot; 248 dprint("=%8t"); 249 exform(1, 0, format, map, 0, pass); 250 newline(); 251 } while (expr(0)); 252 dot=savdot; 253 } 254 255 /* 256 * collect a register name; return register offset 257 * this is not what i'd call a good division of labour 258 */ 259 260 char * 261 regname(int regnam) 262 { 263 static char buf[64]; 264 char *p; 265 int c; 266 267 p = buf; 268 *p++ = regnam; 269 while (isalnum(c = readchar())) { 270 if (p >= buf+sizeof(buf)-1) 271 error("register name too long"); 272 *p++ = c; 273 } 274 *p = 0; 275 reread(); 276 return (buf); 277 } 278 279 /* 280 * shell escape 281 */ 282 283 void 284 shell(void) 285 { 286 int rc, unixpid; 287 char *argp = lp; 288 289 while (lastc!=EOR) 290 rdc(); 291 if ((unixpid=fork())==0) { 292 *lp=0; 293 execl("/bin/rc", "rc", "-c", argp, 0); 294 exits("execl"); /* botch */ 295 } else if (unixpid == -1) { 296 error("cannot fork"); 297 } else { 298 mkfault = 0; 299 while ((rc = wait(0)) != unixpid){ 300 if(rc == -1 && mkfault){ 301 mkfault = 0; 302 continue; 303 } 304 break; 305 } 306 prints("!"); 307 reread(); 308 } 309 } 310