123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- /* $Header$ */
- /* Running a process and communication */
- #include <signal.h>
- #include <stdio.h>
- #include <assert.h>
- #include <alloc.h>
- #include "ops.h"
- #include "message.h"
- #include "position.h"
- #include "tree.h"
- #include "file.h"
- #include "symbol.h"
- #include "idf.h"
- #include "scope.h"
- #define MAXARG 128
- extern char *strncpy();
- extern char *AObj;
- extern t_lineno currline;
- extern FILE *db_out;
- extern int debug;
- extern struct idf *str2idf();
- extern long pointer_size;
- static int child_pid; /* process id of child */
- static int to_child, from_child; /* file descriptors for communication */
- static int child_status;
- static int restoring;
- int db_ss;
- static int catch_sigpipe();
- static int stopped();
- static int uputm(), ugetm();
- static int fild1[2], fild2[2]; /* pipe file descriptors */
- int
- init_run()
- {
- /* take file descriptors so that listing cannot take them */
- int i;
- for (i = IN_FD; i <= OUT_FD; i++) close(i);
- if (pipe(fild1) < 0 ||
- pipe(fild2) < 0 ||
- fild1[0] != IN_FD ||
- fild2[1] != OUT_FD) {
- return 0;
- }
- to_child = fild1[1];
- from_child = fild2[0];
- return 1;
- }
- int
- start_child(p)
- p_tree p;
- {
- /* start up the process to be debugged and set up communication */
- char *argp[MAXARG]; /* argument list */
- register p_tree pt = p->t_args[0], pt1;
- unsigned int nargs = 1; /* #args */
- char *in_redirect = 0; /* standard input redirected */
- char *out_redirect = 0; /* standard output redirected */
- signal_child(SIGKILL); /* like families in China, this debugger is only
- allowed one child
- */
- /* first check arguments and redirections and build argument list */
- while (pt) {
- switch(pt->t_oper) {
- case OP_LINK:
- pt1 = pt->t_args[1];
- pt = pt->t_args[0];
- continue;
- case OP_NAME:
- if (nargs < (MAXARG-1)) {
- argp[nargs++] = pt->t_str;
- }
- else {
- error("too many arguments");
- return 0;
- }
- break;
- case OP_INPUT:
- if (in_redirect) {
- error("input redirected twice?");
- return 0;
- }
- in_redirect = pt->t_str;
- break;
- case OP_OUTPUT:
- if (out_redirect) {
- error("output redirected twice?");
- return 0;
- }
- out_redirect = pt->t_str;
- break;
- }
- if (pt != pt1) pt = pt1;
- else break;
- }
- argp[0] = AObj;
- argp[nargs] = 0;
- /* create child process */
- child_pid = fork();
- if (child_pid < 0) {
- error("could not create child");
- return 0;
- }
- if (child_pid == 0) {
- /* this is the child process */
- close(fild1[1]);
- close(fild2[0]);
- signal(SIGINT, SIG_IGN);
- /* I/O redirection */
- if (in_redirect) {
- int fd;
- close(0);
- if ((fd = open(in_redirect, 0)) < 0) {
- error("could not open input file");
- exit(-1);
- }
- if (fd != 0) {
- dup2(fd, 0);
- close(fd);
- }
- }
- if (out_redirect) {
- int fd;
- close(1);
- if ((fd = creat(in_redirect, 0666)) < 0) {
- error("could not open output file");
- exit(-1);
- }
- if (fd != 1) {
- dup2(fd, 1);
- close(fd);
- }
- }
- /* and run process to be debugged */
- execv(AObj, argp);
- error("could not exec %s", AObj);
- exit(-1);
- }
- /* debugger */
- close(fild1[0]);
- close(fild2[1]);
- pipe(fild1); /* to occupy file descriptors */
- signal(SIGPIPE, catch_sigpipe);
- if (! wait_for_child((char *) 0)) {
- error("child not responding");
- return 0;
- }
- do_items();
- if (! restoring) send_cont(1);
- return 1;
- }
- int
- wait_for_child(s)
- char *s; /* to pass on to 'stopped' */
- {
- struct message_hdr m;
- if (child_pid) {
- if (ugetm(&m)) {
- return stopped(s, (t_addr) m.m_size);
- }
- return 0;
- }
- return 1;
- }
- signal_child(sig)
- {
- if (child_pid) {
- kill(child_pid, sig);
- if (sig == SIGKILL) {
- wait(&child_status);
- init_run();
- }
- }
- }
- static int
- catch_sigpipe()
- {
- child_pid = 0;
- }
- static int
- ureceive(p, c)
- char *p;
- long c;
- {
- int i;
- if (! child_pid) return 0;
- while (c >= 0x1000) {
- i = read(from_child, p, 0x1000);
- if (i <= 0) {
- if (i == 0) child_pid = 0;
- return 0;
- }
- p += i;
- c -= i;
- }
- while (c > 0) {
- i = read(from_child, p, (int)c);
- if (i <= 0) {
- if (i == 0) child_pid = 0;
- return 0;
- }
- p += i;
- c -= i;
- }
- return c == 0;
- }
- static int
- usend(p, c)
- char *p;
- long c;
- {
- int i;
- while (c >= 0x1000) {
- i = write(to_child, p, 0x1000);
- if (i < 0) return 0;
- p += i;
- c -= i;
- }
- while (c > 0) {
- i = write(to_child, p, (int)c);
- if (i < 0) return 0;
- p += i;
- c -= i;
- }
- return 1;
- }
- static int
- ugetm(message)
- struct message_hdr *message;
- {
- if (! ureceive((char *) message, (long) sizeof(struct message_hdr))) {
- return 0;
- }
- if (debug) printf("Got %d\n", message->m_type);
- return 1;
- }
- static int
- uputm(message)
- struct message_hdr *message;
- {
- if (! usend((char *) message, (long) sizeof(struct message_hdr))) {
- return 0;
- }
- if (debug) printf("Sent %d\n", message->m_type);
- return 1;
- }
- static struct message_hdr answer;
- static int single_stepping;
- static int
- stopped(s, a)
- char *s; /* stop message */
- t_addr a; /* address where stopped */
- {
- p_position pos;
- if (s) {
- fprintf(db_out, "%s ", s);
- pos = print_position((t_addr) a, 1);
- newfile(str2idf(pos->filename, 1));
- currline = pos->lineno;
- fputs("\n", db_out);
- lines(currfile->sy_file, (int)currline, (int)currline);
- }
- return 1;
- }
- static int
- could_send(m, stop_message)
- struct message_hdr *m;
- {
- int type;
- t_addr a;
- for (;;) {
- if (child_pid) {
- if (! uputm(m) ||
- ! ugetm(&answer)) {
- if (child_pid) {
- error("something wrong!");
- return 1;
- }
- wait(&child_status);
- init_run();
- if (child_status & 0177) {
- fprintf(db_out,
- "Child died with signal %d\n",
- child_status & 0177);
- }
- else {
- fprintf(db_out,
- "Child terminated, exit status %d\n",
- child_status >> 8);
- }
- return 1;
- }
- a = answer.m_size;
- type = answer.m_type;
- if (m->m_type & DB_RUN) {
- /* run command */
- CurrentScope = get_scope_from_addr((t_addr) a);
- if (! item_addr_actions(a) &&
- ( type == DB_SS || type == OK)) {
- /* no explicit breakpoints at this position.
- Also, child did not stop because of
- SETSS or SETSSF, otherwise we would
- have gotten END_SS.
- So, continue.
- */
- if ((m->m_type & ~ DB_SS) != CONT) {
- m->m_type = CONT | (m->m_type & DB_SS);
- }
- continue;
- }
- if (type != END_SS && single_stepping) {
- m->m_type = CLRSS;
- uputm(m) && ugetm(&answer);
- }
- single_stepping = 0;
- }
- if (stop_message) stopped("stopped", a);
- return 1;
- }
- return 0;
- }
- /*NOTREACHED*/
- }
- int
- get_bytes(size, from, to)
- long size;
- t_addr from;
- char *to;
- {
- struct message_hdr m;
- m.m_type = GETBYTES;
- m.m_size = size;
- ATOBUF(m.m_buf, (char *) from);
- if (! could_send(&m, 0)) {
- return 0;
- }
- assert(answer.m_type == DATA && answer.m_size == m.m_size);
- return ureceive(to, answer.m_size);
- }
- int
- get_dump(globmessage, globbuf, stackmessage, stackbuf)
- struct message_hdr *globmessage, *stackmessage;
- char **globbuf, **stackbuf;
- {
- struct message_hdr m;
- m.m_type = DUMP;
- if (! could_send(&m, 0)) {
- return 0;
- }
- assert(answer.m_type == DGLOB);
- *globmessage = answer;
- *globbuf = Malloc((unsigned) answer.m_size);
- if (! ureceive(*globbuf, answer.m_size) || ! ugetm(stackmessage)) {
- free(*globbuf);
- return 0;
- }
- assert(stackmessage->m_type == DSTACK);
- *stackbuf = Malloc((unsigned) stackmessage->m_size);
- if (! ureceive(*stackbuf, stackmessage->m_size)) {
- free(*globbuf);
- free(*stackbuf);
- return 0;
- }
- ATOBUF(globmessage->m_buf+SP_OFF*pointer_size,
- BUFTOA(stackmessage->m_buf+SP_OFF*pointer_size));
- return 1;
- }
- int
- put_dump(globmessage, globbuf, stackmessage, stackbuf)
- struct message_hdr *globmessage, *stackmessage;
- char *globbuf, *stackbuf;
- {
- struct message_hdr m;
- if (! child_pid) {
- restoring = 1;
- start_child(run_command);
- restoring = 0;
- }
- return uputm(globmessage) &&
- usend(globbuf, globmessage->m_size) &&
- uputm(stackmessage) &&
- usend(stackbuf, stackmessage->m_size) &&
- ugetm(&m) && stopped("restored", m.m_size);
- }
- t_addr *
- get_EM_regs(level)
- int level;
- {
- struct message_hdr m;
- static t_addr buf[5];
- register t_addr *to = &buf[0];
- m.m_type = GETEMREGS;
- m.m_size = level;
- if (! could_send(&m, 0)) {
- return 0;
- }
- *to++ = (t_addr) BUFTOA(answer.m_buf);
- *to++ = (t_addr) BUFTOA(answer.m_buf+pointer_size);
- *to++ = (t_addr) BUFTOA(answer.m_buf+2*pointer_size);
- *to++ = (t_addr) BUFTOA(answer.m_buf+3*pointer_size);
- *to++ = (t_addr) BUFTOA(answer.m_buf+4*pointer_size);
- return buf;
- }
- int
- set_pc(PC)
- t_addr PC;
- {
- struct message_hdr m;
- m.m_type = SETEMREGS;
- m.m_size = 0;
- ATOBUF(m.m_buf+PC_OFF*pointer_size, (char *)PC);
- return could_send(&m, 0);
- }
- int
- send_cont(stop_message)
- int stop_message;
- {
- struct message_hdr m;
- m.m_type = (CONT | (db_ss ? DB_SS : 0));
- m.m_size = 0;
- return could_send(&m, stop_message);
- }
- int
- do_single_step(type, count)
- int type;
- long count;
- {
- struct message_hdr m;
- m.m_type = type | (db_ss ? DB_SS : 0);
- m.m_size = count;
- single_stepping = 1;
- if (could_send(&m, 1)) {
- return 1;
- }
- single_stepping = 0;
- return 0;
- }
- int
- set_or_clear_breakpoint(a, type)
- t_addr a;
- int type;
- {
- struct message_hdr m;
- if (a == ILL_ADDR || a == NO_ADDR) return 0;
- m.m_type = type;
- m.m_size = a;
- if (debug) printf("%s breakpoint at 0x%lx\n", type == SETBP ? "setting" : "clearing", (long) a);
- if (! could_send(&m, 0)) { }
- return 1;
- }
- int
- set_or_clear_trace(start, end, type)
- t_addr start, end;
- int type;
- {
- struct message_hdr m;
- m.m_type = type;
- ATOBUF(m.m_buf, (char *) start);
- ATOBUF(m.m_buf+pointer_size, (char *) end);
- if (debug) printf("%s trace at [0x%lx,0x%lx]\n", type == SETTRACE ? "setting" : "clearing", (long) start, (long) end);
- if (! could_send(&m, 0)) { }
- return 1;
- }
|