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
command(char * buf,int defcom)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
acommand(int pc)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
cmdsrc(int c,Map * map)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
cmdwrite(int wcom,Map * map)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 *
regname(int regnam)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
shell(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