]> Git Repo - binutils.git/blob - gdb/energize.c
Wed Sep 9 12:21:42 1992 Ian Lance Taylor ([email protected])
[binutils.git] / gdb / energize.c
1 /* Energize (formerly known as Cadillac) interface routines.
2    Copyright 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include "defs.h"
21 #include "symtab.h"
22 #include "inferior.h"
23 #include "command.h"
24 #include "bfd.h"
25 #include "symfile.h"
26 #include "objfiles.h"
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <sys/param.h>
30 #include "energize/connection.h"
31 #include "energize/genericreq.h"
32 #include "energize/debuggerreq.h"
33 #include "energize/debuggerconn.h"
34 #include "energize/ttyconn.h"
35 #include <varargs.h>
36 #include <sys/stat.h>
37 #ifdef USG
38 #include <sys/file.h>
39 #endif
40 #include <fcntl.h>
41 #include <sys/filio.h>
42 #include <setjmp.h>
43 #include <signal.h>
44 #include <sys/errno.h>
45 #include <termios.h>
46 #include <string.h>
47
48 /* Non-zero means that we're doing the energize interface. */
49 int energize = 0;
50
51 /* Connection block for debugger<=>kernel communications. */
52 static Connection *conn = 0;
53
54 /* fd for our socket to the kernel. */
55 static int kerfd;
56
57 /* The kernel's ID for this instance of the program. */
58 static int program_id;
59
60 static int instance_id;
61
62 /* The fd for the pty associated with the inferior. */
63 static int inferior_pty = -1;
64 static int inferior_tty = -1;
65
66 static int has_run = 0;
67
68 extern int pgrp_inferior;
69
70 extern char *source_path;
71
72 /* The name of the executable file */
73 static char *exec_file;
74
75 /* Tell energize_command_line_input() where to get its text from */
76 static int doing_breakcommands_message = 0;
77
78 /* Stash command text here */
79 static char *command_line_text = 0;
80 static int command_line_length = 0;
81
82 /* Flags returned by wait_for_events() */
83 #define KERNEL_EVENT 1
84 #define PTY_EVENT 2
85
86 \f
87 /* This routine redirects the output of fputs_filtered to the kernel so that
88    the user can see what's going on in his debugger window. */
89
90 void
91 energize_fputs(ptr)
92      const char *ptr;
93 {
94   if (conn)
95     CVWriteTranscriptInfo (conn, instance_id, (char *)ptr);
96   else
97     fputs (ptr, stdout);
98 }
99
100 void
101 energize_query(query, args)
102      char *query;
103      va_list args;
104 {
105   char buf[100];
106
107   if (!energize)
108     return;
109
110   vsprintf(buf, query, args);
111
112   CVWriteQueryInfo(conn,
113                    instance_id,
114                    CQueryConfirm,
115                    qno_unknown,
116                    buf,
117                    "");         /* transcript */
118 }
119
120 void
121 energize_acknowledge_query(ack)
122      char *ack;
123 {
124   CVWriteQueryInfo(conn,
125                    instance_id,
126                    CQueryAcknowleged,
127                    0,
128                    ack,
129                    "");         /* transcript */
130 }
131
132 /* Copy all data from the pty to the kernel. */
133
134 static void
135 pty_to_kernel()
136 {
137   CTtyRequest *req;
138   char buf[1024];
139   int cc;
140
141   while (1)
142     {
143       cc = read(inferior_pty, buf, sizeof(buf));
144
145       if (cc == 0
146           || (cc < 0
147               && errno == EWOULDBLOCK))
148         break;
149
150       if (cc < 0)
151         {
152           close(inferior_pty);
153           inferior_pty = -1;
154           perror("pty read error");
155           break;
156         }
157
158       req = CWriteTtyRequest(conn, TextIORType);
159       CWriteVstringLen(conn, buf, cc);
160       CWriteLength(conn);
161     }
162   CWriteRequestBuffer(conn);
163 }
164
165 /* Copy data from the kernel to the pty. */
166
167 static void
168 kernel_to_pty(data, len)
169      char *data;
170      int len;
171 {
172   int cc;
173
174   cc = write(inferior_pty, data, len);
175
176   if (cc != len)
177     {
178       if (cc < 0)
179         {
180           close(inferior_pty);
181           inferior_pty = -1;
182           perror("pty write error");
183           return;
184         }
185       printf("Couldn't write all the data to the pty, wanted %d, got %d\n",
186              len, cc);
187     }
188 }
189 \f
190 static char *
191 full_filename(symtab)
192      struct symtab *symtab;
193 {
194   int pathlen;
195   char *filename;
196
197   if (!symtab)
198     return NULL;
199
200   if (symtab->fullname)
201     return savestring(symtab->fullname, strlen(symtab->fullname));
202
203   if (symtab->dirname)
204     pathlen = strlen(symtab->dirname);
205   else
206     pathlen = 0;
207   if (symtab->filename)
208     pathlen += strlen(symtab->filename);
209
210   filename = xmalloc(pathlen+1);
211
212   if (symtab->dirname)
213     strcpy(filename, symtab->dirname);
214   else
215     *filename = '\000';
216   if (symtab->filename)
217     strcat(filename, symtab->filename);
218
219   return filename;
220 }
221
222 /* Tell the energize kernel how high the stack is so that frame numbers (which
223    are relative to the current stack height make sense.
224
225    Calculate the number of frames on the stack, and the number of subroutine
226    invocations that haven't changed since the last call to this routine.  The
227    second number is calculated by comparing the PCs of the current stack frames
228    to the PCs of the previous set of stack frames.  The screw here is that a
229    subroutine may call several different procedures, which means that the PC
230    in its frame changes, even though you are still in the same subroutine.  We
231    resolve this by converting the frames PC into the PC at the start of the
232    function (for efficiency, this is done only if the simple comparison test
233    fails). */
234
235 struct pclist
236 {
237   CORE_ADDR pc;
238   struct pclist *next;
239 };
240
241 /* Non-zero means that Energize kernel already knows how high the stack is. */
242 static int stack_info_valid = 0;
243
244 static void
245 send_stack_info()
246 {
247   struct pclist *pclist = 0, *pli, *opli;
248   static struct pclist *old_pclist;
249   FRAME frame;
250   int height, similar;
251
252   if (stack_info_valid)
253     return;
254
255   height = 0;
256   similar = 0;
257
258 /* First, calculate the stack height, and build the new pclist */
259
260   for (frame = get_current_frame();
261        frame != 0;
262        frame = get_prev_frame(frame))
263     {
264       (height)++;
265       pli = (struct pclist *)xmalloc(sizeof(struct pclist));
266
267       pli->pc = frame->pc;
268       pli->next = pclist;
269       pclist = pli;
270     }
271
272 /* Now, figure out how much of the stack hasn't changed */
273
274   for (pli = pclist, opli = old_pclist;
275        pli != 0 && opli != 0;
276        pli = pli->next, opli = opli->next, (similar)++)
277     {
278       if ((pli->pc != opli->pc)
279           && (get_pc_function_start(pli->pc)
280               != get_pc_function_start(opli->pc)))
281         break;
282     }
283
284 /* Free up all elements of the old pclist */
285
286   opli = old_pclist;
287
288   while (opli)
289     {
290       pli = opli->next;
291       free (opli);
292       opli = pli;
293     }
294
295   old_pclist = pclist;          /* Install the new pclist */
296
297   CVWriteStackSizeInfo(conn,
298                        instance_id,
299                        height,  /* Frame depth */
300                        CInnerFrameIs0,
301                        similar, /* Frame diff */
302                        ""       /* Transcript */
303                        );
304
305   stack_info_valid = 1;
306 }
307
308 /* Tell the kernel where we are in the program, and what the stack looks like.
309    */
310
311 static void
312 send_status()
313 {
314   static int linecount = 48;
315   struct symtab_and_line sal;
316   struct symbol *symbol;
317   char *funcname, *filename;
318   static int sent_prog_inst = 0;
319
320   if (!has_run)
321     return;
322
323   if (inferior_pid == 0)        /* target has died */
324     {
325       CVWriteProgramTerminatedInfo(conn,
326                                    instance_id,
327                                    ""
328                                    );
329       return;
330     }
331
332   sal = find_pc_line(stop_pc, 0);
333   symbol = find_pc_function(stop_pc);
334
335   funcname = symbol ? symbol->name : "";
336   filename = full_filename(sal.symtab);
337
338   if (!sent_prog_inst)
339     {
340       sent_prog_inst = 1;
341       CVWriteProgramInstanceInfo(conn,
342                                  program_id,
343                                  instance_id,
344                                  "", /* hostname */
345                                  "", /* arglist */
346                                  ""
347                                  );
348     }
349
350   send_stack_info();
351
352   CVWriteStackFrameInfo(conn,
353                         instance_id,
354                         sal.line,
355                         CFileLinePos,
356                         0,      /* XXX - frame # */
357                         funcname,
358                         filename,
359                         ""      /* XXX ? transcript */
360                         );
361
362   CVWriteProgramStoppedInfo(conn,
363                             instance_id,
364                             0,  /* XXX - breakpoint # or signal # */
365                             CDebuggerCommand,
366                             funcname,
367                             ""  /* XXX ? transcript */
368                             );
369
370   if (filename)
371     free(filename);
372 }
373
374 /* Call this to output annotated function names.  Names will be demangled if
375    necessary.  arg_mode contains flags that are passed on to cplus_demangle. */
376
377 void
378 energize_annotate_function(funcname, arg_mode, level)
379      char *funcname;
380      int arg_mode;
381      int level;
382 {
383   extern int demangle;
384   char *demangled_name = NULL;
385
386   if (funcname == NULL)
387     return;
388
389   if (demangle)
390     {
391       demangled_name = cplus_demangle(funcname, arg_mode);
392
393       if (demangled_name)
394         funcname = demangled_name;
395     }
396
397   send_stack_info();
398
399   if (level < 0) level = 0;
400
401   CVWriteBackTraceEntryInfo(conn,
402                             instance_id,
403                             level, /* frameNo */
404                             funcname);
405
406   if (demangled_name)
407     free(demangled_name);
408 }
409
410 /* Call this just prior to printing out the name & value of a variable.  This
411    tells the kernel where to annotate the output. */
412
413 /* The args are:
414    expression - A text handle on what GDB can use to reference this value.
415                 This can be a symbol name, or a convenience var, etc...
416    symbol - Used to determine the scope of the data.  May be NULL.
417    type - Determines if we have a pointer ref, and the print name of the type.
418           Used in ShowValue message.
419    valaddr - The address in target memory of the data.
420    field - The field name of the struct or union element being referenced.
421 */
422
423 static char cum_expr[200];      /* Cumulative expression */
424 static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
425 static char **last_expr = expr_stack;   /* Current expr stack pointer */
426
427 void
428 energize_start_variable_annotation(expression, symbol, type, valaddr, field)
429      char *expression;
430      struct symbol *symbol;
431      struct type *type;
432      CORE_ADDR valaddr;
433      char *field;
434 {
435   int ref_type;
436   int stor_cl;
437   enum type_code type_code;
438   enum address_class sym_class;
439   char *type_cast;
440
441   if (!energize)
442     return;
443
444   send_stack_info();
445
446   strcpy(*last_expr++, expression);
447   *last_expr = *(last_expr-1) + strlen(expression);
448
449   switch (TYPE_CODE(type))
450     {
451     case TYPE_CODE_ARRAY:
452     case TYPE_CODE_STRUCT:
453     case TYPE_CODE_UNION:
454     case TYPE_CODE_ENUM:
455     case TYPE_CODE_INT:
456     case TYPE_CODE_FLT:
457       ref_type = CValueValueRef;
458       break;
459     case TYPE_CODE_PTR:
460       ref_type = CValuePointerRef;
461       break;
462     default:
463       ref_type = CValueUndefRef;
464       break;
465     }
466
467 /* Make sure that pointer points at something we understand */
468
469   if (ref_type == CValuePointerRef)
470     switch (TYPE_CODE(TYPE_TARGET_TYPE(type)))
471       {
472       case TYPE_CODE_PTR:
473       case TYPE_CODE_ARRAY:
474       case TYPE_CODE_STRUCT:
475       case TYPE_CODE_UNION:
476       case TYPE_CODE_ENUM:
477       case TYPE_CODE_INT:
478       case TYPE_CODE_FLT:
479         break;
480       default:
481         ref_type = CValueUndefRef;
482         break;
483       }
484
485   if (symbol)
486     {
487       sym_class = SYMBOL_CLASS(symbol);
488
489       switch (sym_class)
490         {
491         case LOC_CONST:
492         case LOC_CONST_BYTES:
493           stor_cl = CValueStorStaticConst;
494           break;
495         case LOC_STATIC:
496           stor_cl = CValueStorStaticVar;
497           break;
498         case LOC_REGISTER:
499         case LOC_REGPARM:
500           stor_cl = CValueStorRegister;
501           break;
502         case LOC_ARG:
503         case LOC_REF_ARG:
504         case LOC_LOCAL:
505         case LOC_LOCAL_ARG:
506           stor_cl = CValueStorLocalVar;
507           break;
508         default:
509           stor_cl = CValueStorUndef;
510           break;
511         }
512     }
513   else
514     stor_cl = CValueStorUndef;
515
516   type_cast = TYPE_NAME(type);
517
518   CVWriteValueBeginInfo(conn,
519                         instance_id,
520                         valaddr,
521                         ref_type,
522                         stor_cl,
523                         0,      /* XXX - frameno */
524                         cum_expr,
525                         field,
526                         type_cast,
527                         "");    /* transcript */
528 }
529
530 void
531 energize_end_variable_annotation()
532 {
533   if (!energize)
534     return;
535
536   last_expr--;                  /* Pop the expr stack */
537   **last_expr = '\000';         /* Cut off the last part of the expr */
538
539   CVWriteValueEndInfo(conn,
540                       instance_id,
541                       "");      /* transcript */
542 }
543 \f
544 /* Tell the kernel that the target is now running. */
545
546 static void
547 go_busy()
548 {
549   CVWriteProgramBusyInfo(conn,
550                          instance_id,
551                          "");   /* XXX ? transcript */
552   CWriteRequestBuffer(conn);    /* Must take place synchronusly! */
553   stack_info_valid = 0;
554 }
555
556 \f
557 void
558 energize_symbol_file(objfile)
559      struct objfile *objfile;
560 {
561   if (!energize)
562     return;
563
564   CVWriteSymbolTableInfo(conn,
565                          objfile->name,
566                          "");   /* Transcript */
567 }
568
569 /* execute_command_1(echo, queue, cmd, args) - echo - non-zero means echo the
570    command.  queue - non-zero means don't execute it now, just save it away for
571    later.  cmd - string containing printf control sequences.  args - list of
572    arguments needed by those control sequences.
573  */
574
575 /* Linked list of queued up commands */
576 static struct command_line *queued_commands = 0;
577 static struct command_line *last_queued_command = 0;
578
579 /* Call this routine to save a command for later.  The command string is
580    copied into freshly malloc'ed memory. */
581
582 static void
583 queue_command(cmd)
584      char *cmd;
585 {
586   char *buf;
587   struct command_line *cl;
588   unsigned long s;
589
590   s = (strlen(cmd) + 1) + 7 & ~(unsigned long)7;
591
592   buf = (char *)xmalloc(s + sizeof(struct command_line));
593   cl = (struct command_line *)(buf + s);
594   cl->next = 0;
595   cl->line = buf;
596
597   strncpy(cl->line, cmd, s);
598
599   if (queued_commands)
600     last_queued_command->next = cl;
601   else
602     queued_commands = cl;
603
604   last_queued_command = cl;
605 }
606
607 /* Call this procedure to take a command off of the command queue.  It returns
608    a pointer to a buf which the caller is responsible for freeing.  NULL is
609    returned if there are no commands queued. */
610
611 static char *
612 dequeue_command()
613 {
614   struct command_line *cl;
615   char *cmd;
616
617   cl = queued_commands;
618
619   if (!cl)
620     return NULL;
621
622   queued_commands = cl->next;
623
624   return cl->line;
625 }
626
627 static void
628 execute_command_1(va_alist)
629      va_dcl
630 {
631   char buf[100];                /* XXX - make buf dynamic! */
632   
633   int echo;
634   int queue;
635   char *cmd;
636   va_list args;
637
638   va_start(args);
639
640   echo = va_arg(args, int);
641   queue = va_arg(args, int);
642   cmd = va_arg(args, char *);
643
644   vsprintf(buf, cmd, args);
645
646   if (queue)
647     queue_command(buf);
648   else
649     {
650       if (echo)
651         printf_filtered("%s\n", buf);
652       execute_command(buf, 1);
653     }
654
655   va_end(args);
656 }
657
658 #ifdef KERNEL_RECORD
659 FILE *kerout;
660
661 static int
662 kernel_record(fd, ptr, num)
663      int fd, num;
664      char *ptr;
665
666 {
667   fwrite(ptr, num, 1, kerout);
668   fflush(kerout);
669   return write(fd, ptr, num);
670 }
671 #endif
672
673 void
674 energize_condition_breakpoint(b)
675      struct breakpoint *b;
676 {
677   if (energize)
678     CVWriteBreakConditionInfo(conn,
679                               instance_id,
680                               b->number,
681                               b->cond_string ? b->cond_string : "",
682                               "" /* transcript */
683                               );
684 }
685
686 void
687 energize_commands_breakpoint(b)
688      struct breakpoint *b;
689 {
690   struct command_line *l;
691
692   if (!energize)
693     return;
694
695   CVWriteBreakCommandBegInfo(conn,
696                              instance_id,
697                              b->number,
698                              ""); /* transcript */
699
700   for (l = b->commands; l; l = l->next)
701     CVWriteBreakCommandEntryInfo(conn,
702                                  instance_id,
703                                  l->line,
704                                  ""); /* transcript */
705
706   CVWriteBreakCommandEndInfo(conn,
707                              instance_id,
708                              ""); /* transcript */
709 }
710
711 static void
712 breakpoint_notify(b, action)
713      struct breakpoint *b;
714      int action;
715 {
716   struct symbol *sym;
717   char *funcname = "";
718   char *filename;
719   char *included_in_filename = "";
720
721   if (!energize)
722     return;
723
724   if (b->type != bp_breakpoint)
725     return;
726
727   filename = full_filename(b->symtab);
728
729   sym = find_pc_function(b->address);
730   if (sym)
731     funcname = SYMBOL_NAME(sym);
732
733   CVWriteBreakpointInfo (conn,
734                          instance_id,
735                          b->number,
736                          b->line_number,
737                          CFileLinePos,
738                          CBreakOnInstrAccess,
739                          action,
740                          b->ignore_count,
741                          funcname,
742                          filename ? filename : "",
743                          "",    /* included_in_filename */
744                          ""     /* transcript */
745                          );
746
747   if (b->commands)
748     energize_commands_breakpoint(b);
749
750   energize_condition_breakpoint(b);
751
752   if (filename)
753     free(filename);
754 }
755
756 void
757 energize_create_breakpoint(b)
758      struct breakpoint *b;
759 {
760   breakpoint_notify(b, CEnableBreakpoint);
761 }
762
763 void
764 energize_delete_breakpoint(b)
765      struct breakpoint *b;
766 {
767   breakpoint_notify(b, CDeleteBreakpoint);
768 }
769
770 void
771 energize_enable_breakpoint(b)
772      struct breakpoint *b;
773 {
774   breakpoint_notify(b, CEnableBreakpoint);
775 }
776
777 void
778 energize_disable_breakpoint(b)
779      struct breakpoint *b;
780 {
781   breakpoint_notify(b, CDisableBreakpoint);
782 }
783
784 void
785 energize_ignore_breakpoint(b)
786      struct breakpoint *b;
787 {
788   breakpoint_notify(b, CBreakAttrUnchanged);
789 }
790 \f
791 /* Open up a pty and its associated tty.  Return the fd of the tty. */
792
793 static void
794 getpty()
795 {
796   int n, ptyfd, ttyfd;
797   static char dev[30];
798   struct stat statbuf;
799   struct termios termios;
800
801 #define HIGHPTY (('z' - 'p') * 16 - 1)
802
803   for (n = 0; n <= HIGHPTY; n++)
804     {
805       sprintf(dev, "/dev/pty%c%x", n/16 + 'p', n%16);
806       if (stat(dev, &statbuf))
807         break;
808       ptyfd = open(dev, O_RDWR);
809       if (ptyfd < 0)
810         continue;
811       sprintf(dev, "/dev/tty%c%x", n/16 + 'p', n%16);
812       ttyfd = open(dev, O_RDWR);
813       if (ttyfd < 0) {close(ptyfd); continue;}
814
815       /* Setup pty for non-blocking I/O.  Also make it give us a SIGIO when
816          there's data available.  */
817
818       n = fcntl(ptyfd, F_GETFL, 0);
819       fcntl(ptyfd, F_SETFL, n|FNDELAY|FASYNC);
820       fcntl(ptyfd, F_SETOWN, getpid());
821
822       tcgetattr(ttyfd, &termios);
823       termios.c_oflag &= ~OPOST; /* No post-processing */
824       tcsetattr(ttyfd, TCSANOW, &termios);
825
826       inferior_pty = ptyfd;
827       inferior_tty = ttyfd;
828       return;
829     }
830
831   error ("getpty: can't get a pty\n");
832 }
833 \f
834 /* Examine a protocol packet from the driver. */
835
836 static void
837 kernel_dispatch(queue)
838      int queue;                 /* Non-zero means we should just queue up
839                                    commands. */
840 {
841   register CHeader *head;
842
843   head = (CHeader *)CPeekNextRequest (conn);
844   if (head == NULL)
845     {
846       fprintf (stderr, "EOF on kernel read!\n");
847       exit (1);
848     }
849
850   if (head->reqType < LastTtyRequestRType)
851     {
852       CTtyRequest* req = CReadTtyRequest (conn);
853       switch (req->head.reqType)
854         {
855         case AcceptConnectionRType:
856           /* Tell the rest of the world that energize is now set up */
857           CSkipRequest (conn);
858           break;
859
860         case RefuseConnectionRType:
861           fprintf (stderr, "Debugger connection refused\n");
862           exit (1);
863
864         case KillProgramRType:
865           exit (0);
866
867         case TextIORType:
868           {
869             char *p;
870             ReqLen len;
871
872             p = CGetVstring(conn, &len);
873             kernel_to_pty(p, len);
874           }
875           break;
876         default:
877           fprintf(stderr, "Unknown Tty request type = %d\n",
878                   req->head.reqType);
879           break;
880         }
881     }
882   else
883     {
884       CVDebuggerRequest *req = CVReadDebuggerRequest (conn);
885       if (!req)
886         {
887           fprintf (stderr, "CVReadDebuggerRequest returned NULL, type = %d\n",
888                    head->reqType);
889           exit(1);
890         }
891
892       switch (req->head.request->reqType)
893         {
894         case OpenProgramInstanceRType:
895           {
896             char *arglist, buf[100]; /* XXX - Make buf dynamic! */
897             int arglen;
898             /* XXX - should notice when program_id changes */
899             arglist = req->openProgramInstance.progArglist.text;
900             arglen = req->openProgramInstance.progArglist.byteLen;
901
902             execute_command_1(1, queue, "break main");
903             execute_command_1(1, queue, "enable delete $bpnum");
904             if (arglist)
905               {
906                 execute_command_1(1, queue, "set args %.*s", arglen, arglist);
907               }
908             execute_command_1(1, queue, "run");
909           }
910           break;
911         case SearchPathRType:
912           directory_command(req->searchPath.searchPath.text, 0);
913           break;
914         case QuitDebuggerRType:
915           execute_command_1(1, queue, "quit");
916           break;
917         case RunRType:
918           if (req->run.request->useArglist == CNewArglist)
919             {
920               execute_command_1(1, queue, "set args %.*s",
921                                 req->run.progArglist.byteLen,
922                                 req->run.progArglist.text);
923             }
924           execute_command_1(1, queue, "run");
925           break;
926         case ContinueRType:
927           execute_command_1(1, queue, "continue");
928           break;
929         case StepRType:
930           execute_command_1(1, queue, "step %d", req->step.request->stepCount);
931           break;
932         case NextRType:
933           execute_command_1(1, queue, "next %d", req->next.request->nextCount);
934           break;
935         case ChangeStackFrameRType:
936           switch (req->changeStackFrame.request->frameMovement)
937             {
938             case CToCurrentStackFrame:
939               execute_command_1(1, queue, "frame %d",
940                                 req->changeStackFrame.request->frameNo);
941               break;
942             case CToInnerStackFrame:
943               execute_command_1(1, queue, "down %d",
944                                 req->changeStackFrame.request->frameNo);
945               break;
946             case CToOuterStackFrame:
947               execute_command_1(1, queue, "up %d",
948                                 req->changeStackFrame.request->frameNo);
949               break;
950             case CToAbsoluteStackFrame:
951               execute_command_1(1, queue, "frame %d",
952                                 req->changeStackFrame.request->frameNo);
953               break;
954             }
955           break;
956         case BackTraceRType:
957           /* XXX - deal with limit??? */
958           execute_command_1(1, queue, "backtrace");
959           break;
960         case FinishRType:
961           execute_command_1(1, queue, "finish");
962           break;
963         case TerminateProgramRType:
964           execute_command_1(1, queue, "kill");
965           break;
966         case NewBreakpointRType:
967           {
968             char *tail;
969             int skipped;
970
971             tail = strrchr(req->newBreakpoint.fileName.text, '/');
972             if (!tail)
973               tail = req->newBreakpoint.fileName.text;
974             else
975               tail++;
976             skipped = tail - req->newBreakpoint.fileName.text;
977             execute_command_1(1, queue, "break %.*s:%d",
978                               req->newBreakpoint.fileName.byteLen - skipped,
979                               tail,
980                               req->newBreakpoint.request->fileLinePos);
981           }
982           break;
983         case StopRType:
984           killpg(pgrp_inferior, SIGINT);
985           break;
986         case UserInputRType:
987           {
988             char *text;
989             long len;
990
991             /* XXX - should really break command up into seperate lines
992                and spoon-feed it to execute_command */
993
994             text = req->userInput.userInput.text;
995             len = req->userInput.userInput.byteLen;
996
997             if (text[len-1] == '\n') text[len-1] = '\000';
998
999             while (*text == ' ' || *text == '\t') text++;
1000
1001             if (strcmp(text, "]*[") == 0) /* XXX - What does this mean??? */
1002               break;
1003
1004             if (*text != '\000')
1005               execute_command_1(0, queue, "%s", text);
1006             else
1007               print_prompt();   /* User just typed a blank line */
1008           }
1009           break;
1010         case QueryResponseRType:
1011           {
1012             char *resp;
1013
1014             if (req->queryResponse.request->response)
1015               resp = "y";
1016             else
1017               resp = "n";
1018             execute_command_1(1, 1, resp);
1019             printf_filtered("%s\n", resp);
1020           }
1021           break;
1022         case ChangeBreakpointRType:
1023           switch (req->changeBreakpoint.request->breakpointAttr)
1024             {
1025             case CBreakAttrUnchanged:
1026               execute_command_1(1, queue, "ignore %d %d",
1027                                 req->changeBreakpoint.request->breakpointId,
1028                                 req->changeBreakpoint.request->ignoreCount);
1029               break;
1030             case CEnableBreakpoint:
1031               execute_command_1(1, queue, "enable %d",
1032                                 req->changeBreakpoint.request->breakpointId);
1033               break;
1034             case CDisableBreakpoint:
1035               execute_command_1(1, queue, "disable %d",
1036                                 req->changeBreakpoint.request->breakpointId);
1037               break;
1038             case CDeleteBreakpoint:
1039               execute_command_1(1, queue, "delete %d",
1040                                 req->changeBreakpoint.request->breakpointId);
1041               break;
1042             case CEnableDisableBreakpoint:
1043               execute_command_1(1, queue, "enable once %d",
1044                                 req->changeBreakpoint.request->breakpointId);
1045               break;
1046             case CEnableDeleteBreakpoint:
1047               execute_command_1(1, queue, "enable delete %d",
1048                                 req->changeBreakpoint.request->breakpointId);
1049               break;
1050             default:
1051               printf_filtered("ChangeBreakpointRType: unknown breakpointAttr\n");
1052               printf_filtered("  breakpointAttr = %d\n",
1053                               req->changeBreakpoint.request->breakpointAttr);
1054               printf_filtered("  breakpointId = %d\n",
1055                               req->changeBreakpoint.request->breakpointId);
1056               printf_filtered("  breakpointType = %d\n",
1057                               req->changeBreakpoint.request->breakpointType);
1058               printf_filtered("  ignoreCount = %d\n",
1059                               req->changeBreakpoint.request->ignoreCount);
1060               break;
1061             }
1062           break;
1063         case BreakConditionRType:
1064           execute_command_1(1, queue, "condition %d %.*s",
1065                           req->breakCondition.request->breakpointId,
1066                           req->breakCondition.condition.byteLen,
1067                           req->breakCondition.condition.text);
1068           break;
1069         case BreakCommandsRType:
1070           /* Put pointers to where energize_command_line_input() can find
1071              them. */
1072           doing_breakcommands_message = 1;
1073           command_line_length = req->breakCommands.commands.byteLen;
1074           command_line_text = req->breakCommands.commands.text;
1075           execute_command_1(1, queue, "commands %d",
1076                             req->breakCommands.request->breakpointId);
1077           command_line_text = (char *)NULL;
1078           command_line_length = 0;
1079           doing_breakcommands_message = 0;
1080           break;
1081         case ShowValueRType:
1082           {
1083             char expr[100], *p = expr;
1084
1085             expr[0] = 0;
1086
1087             if (req->showValue.request->ref_type == CValuePointerRef)
1088               strcat(expr, "* ");
1089
1090             if (req->showValue.type_cast.byteLen)
1091               {
1092                 strcat(expr, "(");
1093                 strncat(expr, req->showValue.type_cast.text,
1094                         req->showValue.type_cast.byteLen);
1095                 strcat(expr, ") ");
1096               }
1097
1098             if (req->showValue.field.byteLen)
1099               strcat(expr, "(");
1100
1101             strncat(expr, req->showValue.expression.text,
1102                     req->showValue.expression.byteLen);
1103
1104             if (req->showValue.field.byteLen)
1105               {
1106                 strcat(expr, ")");
1107
1108                 strncat(expr, req->showValue.field.text,
1109                         req->showValue.field.byteLen);
1110               }
1111
1112             execute_command_1(1, queue, "print %s", expr);
1113           }
1114           break;
1115         case SetValueRType:
1116           {
1117             char expr[100], *p = expr;
1118
1119             expr[0] = 0;
1120
1121             if (req->setValue.request->ref_type == CValuePointerRef)
1122               strcat(expr, "* ");
1123
1124 #if 0
1125             if (req->setValue.type_cast.byteLen)
1126               {
1127                 strcat(expr, "(");
1128                 strncat(expr, req->setValue.type_cast.text,
1129                         req->setValue.type_cast.byteLen);
1130                 strcat(expr, ") ");
1131               }
1132 #endif
1133             if (req->setValue.field.byteLen)
1134               strcat(expr, "(");
1135
1136             strncat(expr, req->setValue.expression.text,
1137                     req->setValue.expression.byteLen);
1138
1139             if (req->setValue.field.byteLen)
1140               {
1141                 strcat(expr, ")");
1142
1143                 strncat(expr, req->setValue.field.text,
1144                         req->setValue.field.byteLen);
1145               }
1146
1147             execute_command_1(1, queue, "print %s = (%s) %s", expr,
1148                               req->setValue.type_cast.text,
1149                               req->setValue.value.text);
1150           }
1151           break;
1152         case DynamicLoadRType:
1153           {
1154             char *filename;
1155
1156             filename = req->dynamicLoad.filenames.byteLen ?
1157               req->dynamicLoad.filenames.text : exec_file;
1158
1159             switch (req->dynamicLoad.request->action)
1160               {
1161               case CDynamicLoadUpdateSymtab:
1162                 execute_command_1(1, queue, "exec-file %s", filename);
1163                 execute_command_1(1, queue, "symbol-file %s", filename);
1164                 break;
1165               default:
1166                 printf_filtered("DynamicLoadRType: unknown action=%d, filename=%s\n",
1167                                 req->dynamicLoad.request->action,
1168                                 req->dynamicLoad.filenames.text);
1169                 break;
1170               }
1171           }
1172           break;
1173         default:
1174           fprintf(stderr, "Unknown Debugger request type = %d\n",
1175                   req->head.request->reqType);
1176           break;
1177         }
1178       free (req); /* Should probably call CVFreeDebuggerRequest() here, but
1179                      can't do so if interrupt level has mucked with req->
1180                      request.  CVFreeDebuggerRequest() only ends up calling
1181                      free() anyway! */
1182     }
1183 }
1184 \f
1185 /* Return a bitmask indicating if the kernel or the pty did something
1186    interesting.  Set poll to non-zero if you don't want to wait.  */
1187
1188 static int
1189 wait_for_events(poll)
1190      int poll;
1191 {
1192   fd_set readfds;
1193   int numfds;
1194   int eventmask = 0;
1195   static struct timeval tv = {0};
1196
1197   /* Output all pending requests. */
1198   CWriteRequestBuffer(conn);
1199
1200   FD_ZERO(&readfds);
1201
1202   /* Wait till there's some activity from the kernel or the pty. */
1203   do
1204     {
1205       FD_SET(kerfd, &readfds);
1206       if (inferior_pty > 0)
1207         FD_SET(inferior_pty, &readfds);
1208       if (poll)
1209         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, &tv);
1210       else
1211         numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1212     }
1213   while (numfds <= 0 && !poll);
1214
1215   if (FD_ISSET(inferior_pty, &readfds))
1216     eventmask |= PTY_EVENT;
1217
1218   if (FD_ISSET(kerfd, &readfds))
1219     eventmask |= KERNEL_EVENT;
1220
1221   return eventmask;
1222 }
1223 \f
1224 /* This is called from read_command_lines() to provide the text for breakpoint
1225    commands, which is supplied in a BreakCommands message.  Each call to this
1226    routine supplies a single line of text, with the newline removed. */
1227
1228 /* This routine may be invoked in two different contexts.  In the first, it
1229    is being called as a result of the BreakCommands message.  In this case,
1230    all of the command text is immediately available.  In the second case, it is
1231    called as a result of the user typing the 'command' command.  The command
1232    text then needs to be glommed out of UserInput messages (and possibly other
1233    messages as well).  The most 'straighforward' way of doing this is to
1234    basically simulate the main loop, but just accumulate the command text
1235    instead of sending it to execute_command().  */
1236
1237 char *
1238 energize_command_line_input(prompt, repeat)
1239      char *prompt;
1240      int repeat;
1241 {
1242   char *p;
1243
1244   if (!energize)
1245     return command_line_input(prompt, repeat);
1246
1247   if (doing_breakcommands_message)
1248     {
1249       if (command_line_length <= 0)
1250         return (char *)NULL;
1251
1252       p = command_line_text;
1253
1254       while (command_line_length-- > 0)
1255         {
1256           if (*command_line_text == '\n')
1257             {
1258               *command_line_text = '\000';
1259               command_line_text++;
1260               break;
1261             }
1262           command_line_text++;
1263         }
1264
1265       printf_filtered("%s\n", p);
1266       return p;
1267     }
1268   else
1269     {
1270       /* We come here when the user has typed the 'command' or 'define' command
1271          to the GDB window.  We are basically deep inside of the 'command'
1272          command processing routine right now, and will be called to get a new
1273          line of input.  We expect that kernel_dispatch will queue up only one
1274          command at a time. */
1275
1276       int eventmask;
1277       static char buf[100];
1278       
1279       eventmask = wait_for_events(0);
1280
1281       if (eventmask & PTY_EVENT)
1282         pty_to_kernel();
1283
1284       if (eventmask & KERNEL_EVENT)
1285         kernel_dispatch(1);     /* Queue up commands */
1286
1287 /* Note that command has been echoed by the time we get here */
1288
1289       p = dequeue_command();
1290
1291       if (p)
1292         {
1293           strncpy(buf, p, sizeof(buf));
1294           free(p);
1295           return buf;
1296         }
1297       else
1298         return NULL;
1299     }
1300 }
1301 \f
1302 /* Establish contact with the kernel. */
1303
1304 void
1305 energize_initialize(energize_id, execarg)
1306      char *energize_id;
1307      char *execarg;
1308 {
1309   CTtyRequest *req;
1310   char *ctmp;
1311   extern long strtol(char *str, char **ptr, int base);
1312   char pathname[MAXPATHLEN];
1313   int n;
1314
1315   if (!energize_id)
1316     return;
1317
1318   if (!execarg) execarg = "";
1319
1320   exec_file = strdup(execarg);  /* Save for later */
1321
1322   printf("\ngdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
1323   
1324   /* First establish the connection with the kernel. */
1325
1326   kerfd = COpenClientSocket(NULL);
1327   if (kerfd < 0) {
1328     printf("COpenClientSocket() failed\n");
1329     exit(1);
1330   }
1331
1332   /* Setup for I/O interrupts when appropriate. */
1333
1334   n = fcntl(kerfd, F_GETFL, 0);
1335   fcntl(kerfd, F_SETFL, n|FASYNC);
1336   fcntl(kerfd, F_SETOWN, getpid());
1337
1338   /* Setup connection buffering. */
1339
1340   CSetSocketBufferSize (kerfd, 12000);
1341
1342   /* Generate a new connection control block. */
1343
1344   conn = NewConnection (0, kerfd, kerfd);
1345   if (!conn) {
1346     printf("NewConnection() failed\n");
1347     exit(1);
1348   }
1349
1350 #ifdef KERNEL_RECORD
1351   kerout = fopen("kernel.output", "+w");
1352
1353   CReadWriteHooks(conn, conn->previewMethod, conn->readMethod, kernel_record);
1354 #endif
1355
1356   /* Tell the kernel that we are the "debugger". */
1357
1358   req = CWriteTtyRequest (conn, QueryConnectionRType);
1359   req->generic.queryconnection.major = 0;
1360   req->generic.queryconnection.minor = 0;
1361   req->generic.queryconnection.cadillacId1=strtol(energize_id, &ctmp, 16);
1362   req->generic.queryconnection.cadillacId2 = strtol(++ctmp, NULL, 16);
1363   req->generic.queryconnection.nProtocols = 1;
1364   CWriteProtocol (conn, 0, 0, "debugger");
1365   CWriteLength (conn);
1366
1367   /* Tell the kernel that we are actually running. */
1368
1369   /* KROCK ALERT!!!  The kernel doesn't really care about the arguments to
1370      the program at all!  It only cares that argument 7 be the name of the
1371      target program.  So, we just fill in the rest of the slots with
1372      padding.  I hope the kernel never cares about this! */
1373
1374   req = CWriteTtyRequest (conn, RunningProgramRType);
1375   req->runningprogram.argc = 8;
1376   getwd (pathname);
1377   CWriteVstring0 (conn, pathname);
1378
1379   CWriteVstring0 (conn, "0");
1380   CWriteVstring0 (conn, "1");
1381   CWriteVstring0 (conn, "2");
1382   CWriteVstring0 (conn, "3");
1383   CWriteVstring0 (conn, "4");
1384   CWriteVstring0 (conn, "5");
1385   CWriteVstring0 (conn, "6");
1386   CWriteVstring0 (conn, execarg);
1387   CWriteLength (conn);
1388
1389   /* Tell the kernel our PID and all that */
1390
1391   program_id = 1;
1392   CVWriteDebugProgramInfo(conn,
1393                           getpid(),
1394                           program_id,
1395                           execarg,
1396                           "");
1397
1398   /* Tell the rest of the world that Energize is now set up. */
1399   energize = 1;
1400
1401   setsid();                     /* Drop controlling tty, become pgrp master */
1402   getpty();                     /* Setup the pty */
1403   dup2(inferior_tty, 0);        /* Attach all GDB I/O to the pty */
1404   dup2(inferior_tty, 1);
1405   dup2(inferior_tty, 2);
1406 }
1407
1408 /* This is called from execute_command, and provides a wrapper around
1409    various command routines in a place where both protocol messages and
1410    user input both flow through.
1411 */
1412
1413 void
1414 energize_call_command(cmdblk, arg, from_tty)
1415      struct cmd_list_element *cmdblk;
1416      char *arg;
1417      int from_tty;
1418 {
1419   if (!energize)
1420     {
1421       (*cmdblk->function.cfunc) (arg, from_tty);
1422       return;
1423     }
1424
1425   if (cmdblk->class == class_run)
1426     {
1427       go_busy();
1428       has_run = 1;
1429       (*cmdblk->function.cfunc)(arg, from_tty);
1430       send_status();
1431     }
1432   else
1433     (*cmdblk->function.cfunc)(arg, from_tty);
1434
1435   print_prompt();
1436 }
1437
1438 void
1439 energize_new_process()
1440 {
1441   instance_id = inferior_pid;
1442 }
1443
1444 static void
1445 iosig(signo)
1446      int signo;
1447 {
1448   while (1)
1449     {
1450       int eventmask;
1451
1452       eventmask = wait_for_events(1);
1453
1454       if (eventmask == 0)
1455         return;
1456
1457       if (eventmask & PTY_EVENT)
1458         pty_to_kernel();
1459
1460       if (eventmask & KERNEL_EVENT)
1461         kernel_dispatch(1);
1462     }
1463 }
1464
1465 int
1466 energize_wait(status)
1467      int *status;
1468 {
1469   int pid;
1470
1471   if (!energize)
1472     return wait(status);
1473
1474   signal(SIGIO, iosig);
1475
1476   pid = wait(status);
1477
1478   signal(SIGIO, SIG_DFL);
1479   return pid;
1480 }
1481
1482 static void
1483 null_routine(arg)
1484      int arg;
1485 {
1486 }
1487
1488 /* All requests from the Energize kernel eventually end up here. */
1489
1490 void
1491 energize_main_loop()
1492 {
1493   CTtyRequest *req;
1494   struct cleanup *old_chain;
1495
1496   doing_breakcommands_message = 0;
1497
1498 /* We will come thru here any time there is an error, so send status if
1499    necessary. */
1500
1501   send_status();
1502
1503   print_prompt();
1504
1505   /* The actual event loop! */
1506
1507   while (1)
1508     {
1509       int eventmask;
1510       char *cmd;
1511
1512       old_chain = make_cleanup(null_routine, 0);
1513
1514 /* First, empty out the command queue, then check for new requests. */
1515
1516       while (cmd = dequeue_command())
1517         {
1518           execute_command_1(1, 0, cmd);
1519           free(cmd);
1520         }
1521
1522       eventmask = wait_for_events(0);
1523
1524       if (eventmask & PTY_EVENT)
1525         pty_to_kernel();
1526
1527       if (eventmask & KERNEL_EVENT)
1528         kernel_dispatch(0);
1529
1530       bpstat_do_actions(&stop_bpstat);
1531       do_cleanups(old_chain);
1532     }
1533 }
This page took 0.108831 seconds and 4 git commands to generate.