Pristine Ack-5.5
[Ack-5.5.git] / util / grind / run.c
1 /* $Id: run.c,v 1.18 1994/06/24 11:01:05 ceriel Exp $ */
2
3 /* Running a process and communication */
4
5 #include <signal.h>
6 #include <stdio.h>
7 #include <assert.h>
8 #include <alloc.h>
9 #include <errno.h>
10
11 #include "ops.h"
12 #include "message.h"
13 #include "position.h"
14 #include "tree.h"
15 #include "file.h"
16 #include "symbol.h"
17 #include "idf.h"
18 #include "scope.h"
19 #include "type.h"
20 #include "expr.h"
21 #include "misc.h"
22
23 #define MAXARG  128
24
25 extern char     *strncpy();
26 extern char     *malloc();
27 extern struct idf *str2idf();
28
29 extern char     *AObj;
30 extern FILE     *db_out;
31 extern int      debug;
32 extern char     *progname;
33 extern int      child_interrupted;
34 extern int      interrupted;
35 extern t_lineno currline;
36
37 static int      child_pid;              /* process id of child */
38 static int      to_child, from_child;   /* file descriptors for communication */
39 static int      child_status;
40 static int      restoring;
41 static int      fild1[2], fild2[2];     /* pipe file descriptors */
42
43 int             disable_intr = 1;
44 int             db_ss;
45 int             stack_offset;
46
47 void            signal_child();
48
49 static void     catch_sigpipe();
50 static int      stopped();
51 static int      uputm(), ugetm();
52 static t_addr   curr_stop;
53 p_tree          run_command;
54
55 static void
56 ITOBUF(p, l, sz)
57   register char *p;
58   long  l;
59   int sz;
60 {
61   register int i;
62
63   p +=sz;
64   for (i = sz; i > 0; i--) {
65         *--p = l;
66         l >>= 8;
67   }
68 }
69
70 static long
71 BUFTOI(p, sz)
72   register char *p;
73   int sz;
74 {
75   register long l = 0;
76   register int i;
77
78   for (i = sz; i>0; i--) {
79         l = (l << 8) | (*p++ & 0377);
80   }
81   return l;
82 }
83
84 void
85 init_run()
86 {
87   /* take file descriptors so that listing cannot take them */
88   int i;
89
90   for (i = 3; i <= 6; i++) close(i);
91   if (pipe(fild1) < 0 ||
92       pipe(fild2) < 0 ||
93       fild1[0] != 3 ||
94       fild2[1] != 6) {
95         fatal("something wrong with file descriptors");
96   }
97   to_child = fild1[1];
98   from_child = fild2[0];
99   child_pid = 0;
100   if (currfile) CurrentScope = currfile->sy_file->f_scope;
101   currline = 0;
102 }
103
104 extern int errno;
105
106 start_child(p)
107   p_tree        p;
108 {
109   /* start up the process to be debugged and set up communication */
110
111   char *argp[MAXARG];                           /* argument list */
112   register p_tree pt = p->t_args[0], pt1 = 0;
113   unsigned int  nargs = 1;                      /* #args */
114   char  *in_redirect = 0;                       /* standard input redirected */
115   char  *out_redirect = 0;                      /* standard output redirected */
116
117   signal_child(SIGKILL); /* like families in China, this debugger is only
118                             allowed one child
119                          */
120
121   if (p != run_command) {
122         freenode(run_command);
123         run_command = p;
124   }
125   /* first check arguments and redirections and build argument list */
126   while (pt) {
127         switch(pt->t_oper) {
128         case OP_LINK:
129                 pt1 = pt->t_args[1];
130                 pt = pt->t_args[0];
131                 continue;
132         case OP_NAME:
133                 if (nargs < (MAXARG-1)) {
134                         argp[nargs++] = pt->t_str;
135                 }
136                 else {
137                         error("too many arguments");
138                         return;
139                 }
140                 break;
141         case OP_INPUT:
142                 if (in_redirect) {
143                         error("input redirected twice?");
144                         return;
145                 }
146                 in_redirect = pt->t_str;
147                 break;
148         case OP_OUTPUT:
149                 if (out_redirect) {
150                         error("output redirected twice?");
151                         return;
152                 }
153                 out_redirect = pt->t_str;
154                 break;
155         }
156         if (pt != pt1) pt = pt1;
157         else break;
158   }
159   argp[0] = AObj;
160   argp[nargs] = 0;
161
162   /* create child process */
163   child_pid = fork();
164   if (child_pid < 0) {
165         error("could not create child");
166         return;
167   }
168   if (child_pid == 0) {
169         /* this is the child process */
170         close(fild1[1]);
171         close(fild2[0]);
172
173         signal(SIGINT, SIG_IGN);
174
175         /* I/O redirection */
176         if (in_redirect) {
177                 int fd;
178
179                 close(0);
180                 if ((fd = open(in_redirect, 0)) < 0 ||
181                     (fd != 0 && dup2(fd, 0) < 0)) {
182                         perror(progname);
183                         exit(1);
184                 }
185                 if (fd != 0) {
186                         close(fd);
187                 }
188         }
189         if (out_redirect) {
190                 int fd;
191
192                 close(1);
193                 if ((fd = creat(out_redirect, 0666)) < 0 ||
194                     (fd != 1 && dup2(fd, 1) < 0)) {
195                         perror(progname);
196                         exit(1);
197                 }
198                 if (fd != 1) {
199                         close(fd);
200                 }
201         }
202
203         /* and run process to be debugged */
204         execv(AObj, argp);
205         error("could not exec %s", AObj);
206         exit(1);
207   }
208
209   /* close fild1[0] and fild2[1]; but we want those file descriptors occupied,
210      so we re-occupy them.
211   */
212
213   close(fild1[0]);
214   close(fild2[1]);
215   pipe(fild1);          /* to occupy file descriptors */
216
217   signal(SIGPIPE, catch_sigpipe);
218   {
219         struct message_hdr m;
220
221         if (! ugetm(&m)) {
222                 error("child not responding");
223                 init_run();
224                 return;
225         }
226         curr_stop = BUFTOI(m.m_buf+1, PS);
227         CurrentScope = get_scope_from_addr(curr_stop);
228   }
229   perform_items();
230   if (! restoring) {
231         int stop_reason = item_addr_actions(curr_stop, 1, 1);
232         if (! stop_reason) (void) send_cont(1);
233         else (void) stopped("stopped", curr_stop, stop_reason);
234   }
235 }
236
237 void
238 signal_child(sig)
239 {
240   if (child_pid) {
241         kill(child_pid, sig);
242         if (sig == SIGKILL) {
243                 wait(&child_status);
244                 init_run();
245         }
246   }
247 }
248
249 static void
250 catch_sigpipe()
251 {
252   child_pid = 0;
253 }
254
255 extern int errno;
256 static int
257 do_read(f, p, c)
258   char  *p;
259 {
260   int i = read(f, p, c);
261
262   while (i < 0 && errno == EINTR) i = read(f, p, c);
263   return i;
264 }
265
266 static int
267 ureceive(p, c)
268   char  *p;
269   long  c;
270 {
271   int   i;
272   char buf[0x1000];
273
274   if (! child_pid) {
275         error("no process");
276         return 0;
277   }
278
279   if (! p) p = buf;
280   while (c >= 0x1000) {
281         i = do_read(from_child, p, 0x1000);
282         if (i <= 0) {
283                 if (i == 0) {
284                         child_pid = 0;
285                 }
286                 else    error("read failed");
287                 return 0;
288         }
289         if (p != buf) p += i;
290         c -= i;
291   }
292   while (c > 0) {
293         i = do_read(from_child, p, (int)c);
294         if (i <= 0) {
295                 if (i == 0) {
296                         child_pid = 0;
297                 }
298                 else    error("read failed");
299                 return 0;
300         }
301         p += i;
302         c -= i;
303   }
304   return 1;
305 }
306
307 static int
308 usend(p, c)
309   char  *p;
310   long  c;
311 {
312   int   i;
313
314   if (! child_pid) {
315         error("no process");
316         return 0;
317   }
318   while (c >= 0x1000) {
319         i = write(to_child, p, 0x1000);
320         if (i < 0) {
321                 if (child_pid) error("write failed");
322                 return 0;
323         }
324         p += i;
325         c -= i;
326   }
327   while (c > 0) {
328         i = write(to_child, p, (int)c);
329         if (i < 0) {
330                 if (child_pid) error("write failed");
331                 return 0;
332         }
333         p += i;
334         c -= i;
335   }
336   return 1;
337 }
338
339 static int
340 ugetm(message)
341   struct message_hdr *message;
342 {
343   if (! ureceive((char *) message, (long) sizeof(struct message_hdr))) {
344         return 0;
345   }
346   if (debug) printf("Got %d\n", message->m_type);
347   return 1;
348 }
349
350 static int
351 uputm(message)
352   struct message_hdr *message;
353 {
354   if (! usend((char *) message, (long) sizeof(struct message_hdr))) {
355         return 0;
356   }
357   if (debug) printf("Sent %d\n", message->m_type);
358   return 1;
359 }
360
361 static struct message_hdr       answer;
362 static int      single_stepping;
363
364 static int
365 stopped(s, a, stop_reason)
366   char  *s;             /* stop message */
367   t_addr a;             /* address where stopped */
368   int   stop_reason;    /* status entry causing the stop */
369 {
370   p_position pos;
371
372   if (s && a) {
373         fprintf(db_out, "%s ", s);
374         pos = print_position(a, 1);
375         if (stop_reason) {
376                 fprintf(db_out, " (status entry %d)", stop_reason);
377         }
378         fputs("\n", db_out);
379         list_position(pos);
380         handle_displays();
381   }
382   curr_stop = a;
383   CurrentScope = get_scope_from_addr(a);
384   return 1;
385 }
386
387 static int
388 could_send(m, stop_message)
389   struct message_hdr    *m;
390 {
391   int   type;
392   t_addr a;
393   static int level = 0;
394   int child_dead = 0;
395   int stop_reason;
396
397   level++;
398   for (;;) {
399         stop_reason = 0;
400         if (! child_pid) {
401                 error("no process");
402                 return 0;
403         }
404         if (m->m_type & M_DB_RUN) {
405                 disable_intr = 0;
406                 stack_offset = 0;
407         }
408         if (!child_interrupted && (! uputm(m) || ! ugetm(&answer))) {
409                 child_dead = 1;
410         }
411         disable_intr = 1;
412         if ((interrupted || child_interrupted) && ! child_dead) {
413                 while (child_interrupted && answer.m_type != M_INTR) {
414                         if (! ugetm(&answer)) {
415                                 child_dead = 1;
416                                 break;
417                         }
418                 }
419                 if (interrupted && ! child_dead) {
420                         level--;
421                         if (! level) {
422                                 child_interrupted = 0;
423                                 interrupted = 0;
424                                 return stopped("interrupted", (t_addr) BUFTOI(answer.m_buf+1, PS), 0);
425                         }
426                         return 1;
427                 }
428         }
429         if (child_dead) {
430                 wait(&child_status);
431                 if (child_status & 0177) {
432                         fprintf(db_out,
433                                 "child died with signal %d\n",
434                                 child_status & 0177);
435                 }
436                 else {
437                         fprintf(db_out,
438                                 "child terminated, exit status %d\n",
439                                 child_status >> 8);
440                 }
441                 init_run();
442                 level--;
443                 return 1;
444         }
445         a = BUFTOI(answer.m_buf+1, PS);
446         type = answer.m_type & 0377;
447         if (type == M_END_SS) type = 0;
448         else if (type == M_OK || type == M_DB_SS) type = 1;
449         else type = 2;
450         if (m->m_type & M_DB_RUN) {
451                 /* run command */
452                 CurrentScope = get_scope_from_addr((t_addr) a);
453                 if (!(stop_reason = item_addr_actions(a, type, stop_message))
454                     && (type == 1)) {
455                         /* no explicit breakpoints at this position.
456                            Also, child did not stop because of
457                            SETSS or SETSSF, otherwise we would
458                            have gotten END_SS.
459                            So, continue.
460                         */
461                         if ((m->m_type & 0177) != M_CONT) {
462                                 m->m_type = M_CONT | (m->m_type & M_DB_SS);
463                         }
464                         continue;
465                 }
466                 if (type != 0 && single_stepping) {
467                         m->m_type = M_CLRSS;
468                         if (! uputm(m) || ! ugetm(&answer)) return 0;
469                 }
470                 single_stepping = 0;
471         }
472         level--;
473         if (stop_message) {
474                 return stopped("stopped", a, stop_reason);
475         }
476         return 1;
477   }
478   /*NOTREACHED*/
479 }
480
481 static int
482 getbytes(size, from, to, kind, errmess)
483   long  size;
484   t_addr from;
485   char  *to;
486   int kind;
487   int errmess;
488 {
489   struct message_hdr    m;
490
491   m.m_type = kind;
492   ITOBUF(m.m_buf+1, size, LS);
493   ITOBUF(m.m_buf+LS+1, (long)from, PS);
494
495   if (! could_send(&m, 0)) {
496         return 0;
497   }
498
499   switch(answer.m_type) {
500   case M_FAIL:
501         if (errmess) error("could not get value");
502         return 0;
503   case M_INTR:
504         if (errmess) error("interrupted");
505         return 0;
506   case M_DATA:
507         return ureceive(to, BUFTOI(answer.m_buf+1, LS));
508   default:
509         assert(0);
510   }
511   /*NOTREACHED*/
512 }
513
514 int
515 get_bytes(size, from, to)
516   long  size;
517   t_addr from;
518   char  *to;
519 {
520   return getbytes(size, from, to, M_GETBYTES, 1);
521 }
522
523 int
524 get_string(size, from, to)
525   long  size;
526   t_addr from;
527   char  *to;
528 {
529   int retval = getbytes(size, from, to, M_GETSTR, 0);
530
531   to[(int)BUFTOI(answer.m_buf+1, LS)] = 0;
532   return retval;
533 }
534
535 void
536 set_bytes(size, from, to)
537   long  size;
538   char  *from;
539   t_addr to;
540 {
541   struct message_hdr    m;
542
543   m.m_type = M_SETBYTES;
544   ITOBUF(m.m_buf+1, size, LS);
545   ITOBUF(m.m_buf+LS+1, (long) to, PS);
546
547   if (! uputm(&m) || ! usend(from, size) || ! ugetm(&m)) {
548         return;
549   }
550   switch(answer.m_type) {
551   case M_FAIL:
552         error("could not handle this SET request");
553         break;
554   case M_INTR:
555         error("interrupted");
556         break;
557   case M_OK:
558         break;
559   default:
560         assert(0);
561   }
562 }
563
564 t_addr
565 get_dump(globbuf, stackbuf)
566   char **globbuf, **stackbuf;
567 {
568   struct message_hdr    m;
569   struct message_hdr *globm, *stackm;
570   long sz;
571
572   m.m_type = M_DUMP;
573   if (! could_send(&m, 0)) {
574         return 0;
575   }
576   switch(answer.m_type) {
577   case M_FAIL:
578         error("request for DUMP failed");
579         return 0;
580   case M_INTR:
581         error("interrupted");
582         return 0;
583   case M_DGLOB:
584         break;
585   default:
586         assert(0);
587   }
588
589   sz = BUFTOI(answer.m_buf+1, LS);
590   *globbuf = malloc((unsigned) (sz+sizeof(struct message_hdr)));
591   if (! *globbuf
592       || ! ureceive(*globbuf+sizeof(struct message_hdr), sz)
593       || ! ugetm(&m)) {
594         if (*globbuf) free(*globbuf);
595         else error("could not allocate enougn memory");
596         return 0;
597   }
598   globm = (struct message_hdr *) *globbuf;
599   *globm = answer;
600
601   assert(m.m_type == M_DSTACK);
602   sz = BUFTOI(m.m_buf+1, LS);
603   *stackbuf = malloc((unsigned) sz+sizeof(struct message_hdr));
604   if (! *stackbuf || ! ureceive(*stackbuf+sizeof(struct message_hdr), sz)) {
605         free(*globbuf);
606         if (*stackbuf) free(*stackbuf);
607         else error("could not allocate enougn memory");
608         return 0;
609   }
610   stackm = (struct message_hdr *) *stackbuf;
611   *stackm = m;
612   ITOBUF(globm->m_buf+SP_OFF, BUFTOI(stackm->m_buf+SP_OFF, PS), PS);
613   return BUFTOI(globm->m_buf+PC_OFF, PS);
614 }
615
616 int
617 put_dump(globbuf, stackbuf)
618   char *globbuf, *stackbuf;
619 {
620   struct message_hdr m;
621   struct message_hdr *globm = (struct message_hdr *) globbuf,
622                      *stackm = (struct message_hdr *) stackbuf;
623
624   stackbuf += sizeof(struct message_hdr);
625   globbuf += sizeof(struct message_hdr);
626   if (! child_pid) {
627         restoring = 1;
628         start_child(run_command);
629         restoring = 0;
630   }
631   return        uputm(globm)
632                 && usend(globbuf, BUFTOI(globm->m_buf+1, LS))
633                 && uputm(stackm)
634                 && usend(stackbuf, BUFTOI(stackm->m_buf+1, LS))
635                 && ugetm(&m)
636                 && stopped("restored", BUFTOI(m.m_buf+1, PS), 0);
637 }
638
639 t_addr *
640 get_EM_regs(level)
641   int   level;
642 {
643   struct message_hdr    m;
644   static t_addr buf[5];
645   register t_addr *to = &buf[0];
646
647   m.m_type = M_GETEMREGS;
648   ITOBUF(m.m_buf+1, (long) level, LS);
649
650   if (! could_send(&m, 0)) {
651         return 0;
652   }
653   switch(answer.m_type) {
654   case M_FAIL:
655         error("request for registers failed");
656         return 0;
657   case M_INTR:
658         error("interrupted");
659         return 0;
660   case M_GETEMREGS:
661         break;
662   default:
663         assert(0);
664   }
665   *to++ = (t_addr) BUFTOI(answer.m_buf+LB_OFF, PS);
666   *to++ = (t_addr) BUFTOI(answer.m_buf+AB_OFF, PS);
667   *to++ = (t_addr) BUFTOI(answer.m_buf+PC_OFF, PS);
668   *to++ = (t_addr) BUFTOI(answer.m_buf+HP_OFF, PS);
669   *to++ = (t_addr) BUFTOI(answer.m_buf+PC_OFF, PS);
670   return buf;
671 }
672
673 int
674 set_pc(PC)
675   t_addr        PC;
676 {
677   struct message_hdr    m;
678
679   m.m_type = M_SETEMREGS;
680   ITOBUF(m.m_buf+PC_OFF, (long)PC, PS);
681   if (! could_send(&m, 0)) return 0;
682   switch(answer.m_type) {
683   case M_FAIL:
684         error("could not set PC to %lx", (long) PC);
685         return 0;
686   case M_INTR:
687         error("interrupted");
688         return 0;
689   case M_OK:
690         return 1;
691   default:
692         assert(0);
693   }
694   /*NOTREACHED*/
695 }
696
697 int
698 send_cont(stop_message)
699   int   stop_message;
700 {
701   struct message_hdr    m;
702
703   m.m_type = (M_CONT | (db_ss ? M_DB_SS : 0));
704   return could_send(&m, stop_message) && child_pid;
705 }
706
707 int
708 singlestep(type, count)
709   int   type;
710   long  count;
711 {
712   struct message_hdr    m;
713
714   m.m_type = (type ? M_SETSSF : M_SETSS) | (db_ss ? M_DB_SS : 0);
715   ITOBUF(m.m_buf+1, count, LS);
716   single_stepping = 1;
717   if (could_send(&m, 1) && child_pid) return 1;
718   single_stepping = 0;
719   return 0;
720 }
721
722 int
723 set_or_clear_breakpoint(a, type)
724   t_addr        a;
725   int   type;
726 {
727   struct message_hdr m;
728
729   m.m_type = type ? M_SETBP : M_CLRBP;
730   ITOBUF(m.m_buf+1, (long) a, PS);
731   if (debug) printf("%s breakpoint at 0x%lx\n", type ? "setting" : "clearing", (long) a);
732   if (child_pid && ! could_send(&m, 0)) {
733   }
734
735   return 1;
736 }
737
738 int
739 set_or_clear_trace(start, end, type)
740   t_addr start, end;
741   int   type;
742 {
743   struct message_hdr m;
744
745   m.m_type = type ? M_SETTRACE : M_CLRTRACE;
746   ITOBUF(m.m_buf+1, (long)start, PS);
747   ITOBUF(m.m_buf+PS+1, (long)end, PS);
748   if (debug) printf("%s trace at [0x%lx,0x%lx]\n", type ? "setting" : "clearing", (long) start, (long) end);
749   if (child_pid && ! could_send(&m, 0)) {
750         return 0;
751   }
752
753   return 1;
754 }