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