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