Pristine Ack-5.5
[Ack-5.5.git] / mach / proto / grind / atlin.c
1 /* $Id: atlin.c,v 1.2 1994/06/24 13:33:22 ceriel Exp $ */
2
3 #define DEBUGGEE
4 #include "message.h"
5
6 #define MAXBP   128
7 #define MAXTRACE 16
8
9 static int      nbp;                    /* # of breakpoints */
10 static char     *bp[MAXBP];
11 static int      ntrace;
12 static struct trace {
13   char  *begin_trace, *end_trace;
14 } trace_buf[MAXTRACE];
15
16 static struct message_hdr ok_message;
17
18 #define OFF     0
19 #define SS      1                       /* single stepping */
20 #define SSF     2                       /* single stepping, counting functions
21                                            as single statements */
22
23 static char *
24 BUFTOA(p)
25   register char *p;
26 {
27   register long l = 0;
28   register int i;
29
30   for (i = PS; i>0; i--) {
31         l = (l << 8) | (*p++ & 0377);
32   }
33   return (char *) l;
34 }
35
36 static long
37 BUFTOL(p)
38   register char *p;
39 {
40   register long l = 0;
41   register int i;
42
43   for (i = LS; i>0; i--) {
44         l = (l << 8) | (*p++ & 0377);
45   }
46   return l;
47 }
48
49 static
50 ATOBUF(p, cp)
51   register char *p;
52   char *cp;
53 {
54   register int i;
55   register long l = (long) cp;
56
57   p += PS;
58   for (i = PS; i > 0; i--) {
59         *--p = l;
60         l >>= 8;
61   }
62 }
63
64 static
65 LTOBUF(p, l)
66   register char *p;
67   register long l;
68 {
69   register int i;
70
71   p += LS;
72   for (i = LS; i > 0; i--) {
73         *--p = l;
74         l >>= 8;
75   }
76 }
77
78 static int single_stepping = OFF;
79 static int db_ss = 0;
80 static int step_count = 0;
81 static char     *savedlb;
82 static int      break_flag = 0;
83 static int      reading = 0;
84 static char     *retaddr;
85 static char     *LB;
86 static char     *currbrk;
87
88 extern char *__Get_LB();
89 extern char *__Get_Hol0();
90 extern char *__Get_PC();
91 extern char *__Cvt_LB_AB();
92 extern char *__Get_HP();
93 extern char *_sbrk();
94 extern int  etext;
95 extern __Set_PC();
96 static send_ok();
97
98 #define check_ptr(c)    (((c) >= (char *)&etext && (c) <= currbrk) || (c) >= LB)
99
100 #define IN_FD   3
101 #define OUT_FD  6
102
103 static int
104 ureceive(p, c)
105   char  *p;
106   long  c;
107 {
108   int   i;
109   int   retval = 1;
110
111   reading = 1;
112   while (c >= 0x1000) {
113         i = _read(IN_FD, p, 0x1000);
114         if (i == 0) return 0;
115         if (i < 0) {
116                 retval = 0;
117                 c -= 0x1000;
118         }
119         else {
120                 p += i;
121                 c -= i;
122         }
123   }
124   while (c > 0) {
125         i = _read(IN_FD, p, (int)c);
126         if (i == 0) return 0;
127         if (i < 0) {
128                 retval = 0;
129                 break;
130         }
131         else {
132                 p += i;
133                 c -= i;
134         }
135   }
136   reading = 0;
137   return retval;
138 }
139
140 static int
141 usend(p, c)
142   char  *p;
143   long  c;
144 {
145   int   i;
146
147   while (c >= 0x1000) {
148         i = _write(OUT_FD, p, 0x1000);
149         if (i < 0) {
150                 return 0;
151         }
152         p += i;
153         c -= i;
154   }
155   while (c > 0) {
156         i = _write(OUT_FD, p, (int)c);
157         if (i < 0) {
158                 return 0;
159         }
160         p += i;
161         c -= i;
162   }
163   return 1;
164 }
165
166 static int
167 ugetm(message)
168   struct message_hdr *message;
169 {
170   if (! ureceive((char *) message, (long) sizeof(struct message_hdr))) {
171         return 0;
172   }
173   return 1;
174 }
175
176 static int
177 uputm(message)
178   struct message_hdr *message;
179 {
180   if (! usend((char *) message, (long) sizeof(struct message_hdr))) {
181         return 0;
182   }
183   return 1;
184 }
185
186 static int
187 sendreply(m, p, sz)
188   struct message_hdr *m;
189   char *p;
190   long sz;
191 {
192   if (! uputm(m) || ! (sz && p ? usend(p, sz) : 1)) {
193         return 0;
194   }
195   return 1;
196 }
197
198 static int
199 do_request()
200 {
201   /* obtain a request from the debugger and perform it */
202   int fail = 0;
203   register int i;
204   register char *c;
205   char *c1;
206   long sz;
207   struct message_hdr message;
208
209 start:
210   if (! ugetm(&message)) {
211         /* failed to get a message. Something is wrong. Let process continue */
212         return 1;
213   }
214
215   if (message.m_type & M_DB_SS) db_ss = 1;
216   message.m_type &= 0177;
217   switch(message.m_type) {
218   case M_OK:
219         /* sometimes sent to child to see if it lives */
220         goto start;
221   case M_SETBP:
222         /* set a breakpoint */
223         if (nbp == MAXBP) {
224                 fail = 1;
225                 break;
226         }
227         bp[nbp++] = BUFTOA(message.m_buf+1);
228         break;
229   case M_SETTRACE:
230         if (ntrace == MAXTRACE) {
231                 fail = 1;
232                 break;
233         }
234         trace_buf[ntrace].begin_trace = BUFTOA(message.m_buf+1);
235         trace_buf[ntrace++].end_trace = BUFTOA(message.m_buf+(PS+1));
236         break;
237   case M_CLRBP:
238         i = 0;
239         c = BUFTOA(message.m_buf+1);
240         while (i < nbp && bp[i] != c) {
241                   i++;
242         }
243         if (i < nbp) {
244                 while (i < nbp) {
245                         bp[i] = bp[i+1];
246                         i++;
247                 }
248                 nbp--;
249         }
250         else {
251                 fail = 1;
252         }
253         break;
254   case M_CLRTRACE:
255         i = 0;
256         c = BUFTOA(message.m_buf+1);
257         c1 = BUFTOA(message.m_buf+(PS+1));
258         while (i < ntrace &&
259                trace_buf[i].begin_trace != c &&
260                trace_buf[i].end_trace != c1){
261                   i++;
262         }
263         if (i < ntrace) {
264                 while (i < ntrace) {
265                         trace_buf[i] = trace_buf[i+1];
266                         i++;
267                 }
268                 ntrace--;
269         }
270         else {
271                 fail = 1;
272         }
273         break;
274   case M_SETSS:
275         single_stepping = SS;
276         step_count = BUFTOL(message.m_buf+1);
277         return 1;
278   case M_CLRSS:
279         single_stepping = OFF;
280         break;
281   case M_SETSSF:
282         savedlb = __Get_LB(2);
283         step_count = BUFTOL(message.m_buf+1);
284         single_stepping = SSF;
285         return 1;
286   case M_GETBYTES:
287         message.m_type = M_DATA;
288         sz = BUFTOL(message.m_buf+1);
289         c = BUFTOA(message.m_buf+(LS+1));
290         currbrk = _sbrk(0);
291         if (! check_ptr(c) || ! check_ptr(c+sz-1)) {
292                 fail = 1;
293                 break;
294         }
295         return sendreply(&message, c, sz)
296                 ? 0
297                 : -1;
298
299   case M_GETSTR:
300         sz = BUFTOL(message.m_buf+1);
301         c1 = c = BUFTOA(message.m_buf+(LS+1));
302         currbrk = _sbrk(0);
303         if (check_ptr(c)) {
304                 while (*c) {
305                         if (c - c1 + 1 >= sz) break;
306                         c++;
307                         if (! check_ptr(c)) {
308                                 fail = 1;
309                                 break;
310                         }
311                 }
312         }
313         else    fail = 1;
314         if (fail) break;
315         message.m_type = M_DATA;
316         sz = c - c1 + 1;
317         LTOBUF(message.m_buf+1, sz);
318         return sendreply(&message, c1, sz)
319                 ? 0
320                 : -1;
321
322   case M_SETBYTES:
323         if (! ureceive(BUFTOA(message.m_buf+(LS+1)), BUFTOL(message.m_buf+1))) {
324                 fail = 1;
325         }
326         break;
327
328   case M_GETEMREGS:
329         i = BUFTOL(message.m_buf+1);
330         c = __Get_LB(i+2);              /* local base */
331         c1 = __Get_LB(i+1);             /* needed to find PC and SP */
332         ATOBUF(message.m_buf+LB_OFF, c);
333         ATOBUF(message.m_buf+AB_OFF, __Cvt_LB_AB(c));
334         ATOBUF(message.m_buf+PC_OFF, __Get_PC(c1));
335         ATOBUF(message.m_buf+HP_OFF, __Get_HP());
336         ATOBUF(message.m_buf+SP_OFF, __Cvt_LB_AB(c1));
337         return sendreply(&message, (char *) 0, 0L) ? 0 : -1;
338
339   case M_SETEMREGS:
340         /* actually, only the program counter is settable */
341         i = BUFTOL(message.m_buf+1);
342         c = __Get_LB(i+1);
343         __Set_PC(c, BUFTOA(message.m_buf+PC_OFF));
344         break;
345
346   case M_CONT:
347         return 1;
348
349   case M_DUMP:
350         currbrk = _sbrk(0);
351         c = __Get_Hol0();
352         c1 = currbrk;
353         message.m_type = M_DGLOB;
354         sz = c1 - c;
355         LTOBUF(message.m_buf+1, sz);
356         ATOBUF(message.m_buf + HP_OFF, __Get_HP());
357         ATOBUF(message.m_buf + PC_OFF, __Get_PC(__Get_LB(1)));
358         ATOBUF(message.m_buf + LB_OFF, c1);
359
360         sendreply(&message, c, sz);
361         if (! ___topsave()) {
362                 /* we get here after a ___topload() ! */
363                 step_count = 0;
364                 nbp = 0;
365                 single_stepping = 0;
366                 savedlb = 0;
367                 break_flag = 0;
368                 db_ss = 0;
369                 break;
370         }
371         return 0;
372   case M_DGLOB:
373         _brk(BUFTOA(message.m_buf + LB_OFF));
374         __Set_HP(BUFTOA(message.m_buf+HP_OFF));
375         if (! ureceive(__Get_Hol0(), BUFTOL(message.m_buf+1))) {}
376         ___topload(BUFTOA(message.m_buf + SP_OFF));
377         /*NOTREACHED*/
378   }
379   send_ok(fail ? M_FAIL : M_OK);
380   return fail ? -1 : 0;
381 }
382
383 ___sendtop(addr, SP, sz)
384   char *addr, *SP;
385   unsigned sz;
386 {
387   struct message_hdr m;
388
389   m.m_type = M_DSTACK;
390   LTOBUF(m.m_buf+1, (long) sz);
391   ATOBUF(m.m_buf+SP_OFF, SP);
392   sendreply(&m, addr, (long)sz);
393 }
394
395 ___restoretop(SP)
396   char *SP;
397 {
398   struct message_hdr m;
399
400   if (! ugetm(&m)) {}
401   if (! ureceive(SP, BUFTOL(m.m_buf+1))) {}
402 }
403
404 static
405 sigcatch()
406 {
407   signal(7, sigcatch);
408   if (reading) send_ok(M_INTR);
409   else break_flag = 1;
410   db_ss = 0;
411 }
412
413 static int
414 check_bp()
415 {
416   register int i;
417
418   for (i = 0; i < nbp; i++) {
419         if (bp[i] == retaddr) {
420                 return 1;
421         }
422   }
423   return 0;
424 }
425
426 static int
427 check_trace()
428 {
429   register int i;
430
431   for (i = 0; i < ntrace; i++) {
432         if (trace_buf[i].begin_trace <= retaddr &&
433             trace_buf[i].end_trace >= retaddr) {
434                 return 1;
435         }
436   }
437   return 0;
438 }
439
440 static
441 send_ok(type)
442 {
443   register int i;
444
445   ok_message.m_type = type;
446   LTOBUF(ok_message.m_buf+1, (long) retaddr);
447   uputm(&ok_message);
448 }
449
450 void
451 __uX_LiB()
452 /* This function must be called after every LIN and LNI */
453 {
454   int status = M_CONT;
455
456   LB = __Get_LB(0);
457   if ( retaddr) {
458         /* not the first time ... */
459         retaddr = __Get_PC(LB);
460
461         /* first, adjust step_count when single stepping
462         */
463         if (single_stepping == SS) step_count--;
464         else if (single_stepping == SSF) {
465                 char *lb = __Get_LB(1);
466                 if (!((char *) &lb < lb && lb >= savedlb ||
467                     (char *) &lb > lb && lb <= savedlb)) {
468                 }
469                 else {
470                         savedlb = lb;
471                         step_count--;
472                 }
473         }
474
475         if (single_stepping != OFF && step_count <= 0) {
476                 status = M_END_SS;
477                 single_stepping = OFF;
478         }
479         else if (break_flag) status = M_INTR;
480   }
481   else {
482         signal(7, sigcatch);
483         retaddr = __Get_PC(LB);
484         status = M_OK;
485   }
486
487   if (status == M_CONT) {
488         if ((nbp != 0 && check_bp() != 0) ||
489             (ntrace != 0 && check_trace() != 0)) {
490                 status = M_OK;
491         }
492         else if (break_flag) status = M_INTR;
493         else {
494                 if (db_ss) {
495                         db_ss = 0;
496                         send_ok(M_DB_SS);
497                         while (do_request() <= 0) /* nothing */;
498                 }
499                 if (break_flag) status = M_INTR;
500                 else return;
501         }
502   }
503
504   break_flag = 0;
505   send_ok(status);
506   db_ss = 0;
507   while (do_request() <= 0) /* nothing */;
508 }