A ton of changes to improve C++ debugging. See ChangeLog.
[deliverable/binutils-gdb.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.060151 seconds and 4 git commands to generate.