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