1 /* Cadillac interface routines.
2 Copyright 1986, 1987, 1988, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
24 #include <sys/types.h>
26 #include <sys/param.h>
27 #include <connection.h>
28 #include <genericreq.h>
29 #include <debuggerreq.h>
30 #include <debuggerconn.h>
35 #include <sys/filio.h>
38 #include <sys/errno.h>
42 /* Connection block for debugger<=>kernel communications. */
43 static Connection
*conn
= 0;
45 /* fd for our socket to the kernel. */
48 /* The kernel's ID for this instance of the program. */
49 static int program_id
;
51 static int instance_id
;
53 /* The fd for the pty associated with the inferior. */
54 static int inferior_pty
= -1;
55 static int inferior_tty
= -1;
57 static int has_run
= 0;
61 char **pprompt
; /* Pointer to pointer to prompt */
66 fputs_filtered(*pprompt
, stdout
);
69 /* This routine redirects the output of fputs_filtered to the kernel so that
70 the user can see what's going on in his debugger window. */
77 CVWriteTranscriptInfo (conn
, instance_id
, ptr
);
82 /* Copy all data from the pty to the kernel. */
93 cc
= read(inferior_pty
, buf
, sizeof(buf
));
97 && errno
== EWOULDBLOCK
))
104 perror("pty read error");
108 req
= CWriteTtyRequest(conn
, TextIORType
);
109 CWriteVstringLen(conn
, buf
, cc
);
112 CWriteRequestBuffer(conn
);
115 /* Copy data from the kernel to the pty. */
118 kernel_to_pty(data
, len
)
124 cc
= write(inferior_pty
, data
, len
);
132 perror("pty write error");
135 printf("Couldn't write all the data to the pty, wanted %d, got %d\n",
140 /* Tell the kernel where we are in the program, and what the stack looks like.
146 static int linecount
= 48;
147 struct symtab_and_line sal
;
148 struct symbol
*symbol
;
149 char *funcname
, *filename
;
151 static int sent_prog_inst
= 0;
156 if (inferior_pid
== 0) /* target has died */
158 CVWriteProgramTerminatedInfo(conn
,
165 sal
= find_pc_line(stop_pc
, 0);
166 symbol
= find_pc_function(stop_pc
);
168 funcname
= symbol
? symbol
->name
: "";
169 filename
= sal
.symtab
? sal
.symtab
->filename
: "";
174 CVWriteProgramInstanceInfo(conn
,
183 CVWriteStackSizeInfo(conn
,
185 1, /* XXX - frame depth */
187 foo
++ ? 1 : 0, /* XXX - frame diff */
191 CVWriteStackFrameInfo(conn
,
195 0, /* XXX - frame # */
198 "" /* XXX ? transcript */
201 CVWriteProgramStoppedInfo(conn
,
203 0, /* XXX - breakpoint # or signal # */
206 "" /* XXX ? transcript */
210 /* Tell the kernel that the target is now running. */
215 CVWriteProgramBusyInfo(conn
,
217 ""); /* XXX ? transcript */
218 CWriteRequestBuffer(conn
); /* Must take place synchronusly! */
221 /* This wrapper routine is needed because execute_command modifies the command
222 string that it's given. It also echos the commands. */
225 execute_command_1(va_alist
)
228 char buf
[100]; /* XXX - make buf dynamic! */
234 cmd
= va_arg(args
, char *);
236 vsprintf(buf
, cmd
, args
);
238 printf_filtered("%s\n", buf
);
239 execute_command(buf
, 1);
248 kernel_record(fd
, ptr
, num
)
253 fwrite(ptr
, num
, 1, kerout
);
255 return write(fd
, ptr
, num
);
260 cadillac_condition_breakpoint(b
)
261 struct breakpoint
*b
;
263 CVWriteBreakConditionInfo(conn
,
266 b
->cond_string
? b
->cond_string
: "",
272 cadillac_commands_breakpoint(b
)
273 struct breakpoint
*b
;
275 struct command_line
*l
;
277 CVWriteBreakCommandBegInfo(conn
,
280 ""); /* transcript */
282 for (l
= b
->commands
; l
; l
= l
->next
)
283 CVWriteBreakCommandEntryInfo(conn
,
286 ""); /* transcript */
288 CVWriteBreakCommandEndInfo(conn
,
290 ""); /* transcript */
294 breakpoint_notify(b
, action
)
295 struct breakpoint
*b
;
300 char *funcname
= "", *filename
= "", *included_in_filename
= "";
302 if (b
->type
!= bp_breakpoint
)
309 filename
= s
->filename
;
310 s1
= find_pc_function(b
->address
);
312 funcname
= SYMBOL_NAME(s1
);
315 CVWriteBreakpointInfo (conn
,
325 "", /* included_in_filename */
330 cadillac_commands_breakpoint(b
);
334 cadillac_create_breakpoint(b
)
335 struct breakpoint
*b
;
337 breakpoint_notify(b
, CEnableBreakpoint
);
341 cadillac_delete_breakpoint(b
)
342 struct breakpoint
*b
;
344 breakpoint_notify(b
, CDeleteBreakpoint
);
348 cadillac_enable_breakpoint(b
)
349 struct breakpoint
*b
;
351 breakpoint_notify(b
, CEnableBreakpoint
);
355 cadillac_disable_breakpoint(b
)
356 struct breakpoint
*b
;
358 breakpoint_notify(b
, CDisableBreakpoint
);
362 cadillac_ignore_breakpoint(b
)
363 struct breakpoint
*b
;
365 breakpoint_notify(b
, CBreakAttrUnchanged
);
368 static int command_line_length
= 0;
369 static char *command_line_text
= 0;
374 if (command_line_text
)
381 cadillac_command_line_input()
385 if (command_line_length
<= 0)
388 p
= command_line_text
;
390 while (command_line_length
-- > 0)
392 if (*command_line_text
== '\n')
394 *command_line_text
= '\000';
404 /* Open up a pty and its associated tty. Return the fd of the tty. */
412 struct termios termios
;
414 #define HIGHPTY (('z' - 'p') * 16 - 1)
416 if (inferior_pty
>= 0) /* Only do this once */
419 for (n
= 0; n
<= HIGHPTY
; n
++)
421 sprintf(dev
, "/dev/pty%c%x", n
/16 + 'p', n
%16);
422 if (stat(dev
, &statbuf
))
424 ptyfd
= open(dev
, O_RDWR
);
427 sprintf(dev
, "/dev/tty%c%x", n
/16 + 'p', n
%16);
428 ttyfd
= open(dev
, O_RDWR
);
429 if (ttyfd
< 0) {close(ptyfd
); continue;}
431 /* Setup pty for non-blocking I/O. Also make it give us a SIGIO when
432 there's data available. */
434 n
= fcntl(ptyfd
, F_GETFL
, 0);
435 fcntl(ptyfd
, F_SETFL
, n
|FNDELAY
|FASYNC
);
436 fcntl(ptyfd
, F_SETOWN
, getpid());
438 tcgetattr(ttyfd
, &termios
);
439 termios
.c_oflag
&= ~OPOST
; /* No post-processing */
440 tcsetattr(ttyfd
, TCSANOW
, &termios
);
442 inferior_pty
= ptyfd
;
443 inferior_tty
= ttyfd
;
447 error ("getpty: can't get a pty\n");
450 /* Examine a protocol packet from the driver. */
453 kernel_dispatch(interrupt
)
454 int interrupt
; /* Non-zero means we are at interrupt level
455 and can only do a few commands. */
457 register CHeader
*head
;
459 head
= (CHeader
*)CPeekNextRequest (conn
);
462 fprintf (stderr
, "EOF on kernel read!\n");
467 switch (head
->reqType
)
469 case KillProgramRType
:
477 if (head
->reqType
< LastTtyRequestRType
)
479 CTtyRequest
* req
= CReadTtyRequest (conn
);
480 switch (req
->head
.reqType
)
482 case AcceptConnectionRType
:
483 /* Tell the rest of the world that cadillac is now set up */
487 case RefuseConnectionRType
:
488 fprintf (stderr
, "Debugger connection refused\n");
491 case KillProgramRType
:
499 p
= CGetVstring(conn
, &len
);
500 kernel_to_pty(p
, len
);
504 fprintf(stderr
, "Unknown request type = %d\n",
511 CVDebuggerRequest
*req
= CVReadDebuggerRequest (conn
);
514 fprintf (stderr
, "CVReadDebuggerRequest returned NULL, type = %d\n",
519 switch (req
->head
.request
->reqType
)
521 case OpenProgramInstanceRType
:
523 char *arglist
, buf
[100]; /* XXX - Make buf dynamic! */
525 /* XXX - should notice when program_id changes */
526 arglist
= req
->openProgramInstance
.progArglist
.text
;
527 arglen
= req
->openProgramInstance
.progArglist
.byteLen
;
529 execute_command_1("break main");
530 execute_command_1("enable delete $bpnum");
533 execute_command_1("set args %.*s", arglen
, arglist
);
535 execute_command_1("run");
538 case QuitDebuggerRType
:
541 if (req
->run
.request
->useArglist
== CNewArglist
)
543 execute_command_1("set args %.*s",
544 req
->run
.progArglist
.byteLen
,
545 req
->run
.progArglist
.text
);
547 execute_command_1("run");
550 execute_command_1("continue");
553 execute_command_1("step %d", req
->step
.request
->stepCount
);
556 execute_command_1("next %d", req
->next
.request
->nextCount
);
558 case ChangeStackFrameRType
:
559 switch (req
->changeStackFrame
.request
->frameMovement
)
561 case CToCurrentStackFrame
:
562 execute_command_1("frame %d",
563 req
->changeStackFrame
.request
->frameNo
);
565 case CToInnerStackFrame
:
566 execute_command_1("down %d",
567 req
->changeStackFrame
.request
->frameNo
);
569 case CToOuterStackFrame
:
570 execute_command_1("up %d",
571 req
->changeStackFrame
.request
->frameNo
);
573 case CToAbsoluteStackFrame
:
574 printf_filtered("ChangeStackFrame ToAbsolute\n");
579 /* XXX - deal with limit??? */
580 execute_command_1("backtrace");
583 execute_command_1("finish");
585 case TerminateProgramRType
:
586 execute_command_1("kill");
588 case NewBreakpointRType
:
593 tail
= rindex(req
->newBreakpoint
.fileName
.text
, '/');
595 tail
= req
->newBreakpoint
.fileName
.text
;
598 skipped
= tail
- req
->newBreakpoint
.fileName
.text
;
599 execute_command_1("break %.*s:%d",
600 req
->newBreakpoint
.fileName
.byteLen
- skipped
,
602 req
->newBreakpoint
.request
->fileLinePos
);
607 extern int pgrp_inferior
;
608 killpg(pgrp_inferior
, SIGINT
);
616 /* XXX - should really break command up into seperate lines
617 and spoon-feed it to execute_command */
619 text
= req
->userInput
.userInput
.text
;
620 len
= req
->userInput
.userInput
.byteLen
;
622 if (text
[len
-1] == '\n') text
[len
-1] = '\000';
623 execute_command (text
);
626 case ChangeBreakpointRType
:
627 switch (req
->changeBreakpoint
.request
->breakpointAttr
)
629 case CEnableBreakpoint
:
630 execute_command_1("enable %d",
631 req
->changeBreakpoint
.request
->breakpointId
);
633 case CDisableBreakpoint
:
634 execute_command_1("disable %d",
635 req
->changeBreakpoint
.request
->breakpointId
);
637 case CDeleteBreakpoint
:
638 execute_command_1("delete %d",
639 req
->changeBreakpoint
.request
->breakpointId
);
641 case CBreakAttrUnchanged
:
642 execute_command_1("ignore %d %d",
643 req
->changeBreakpoint
.request
->breakpointId
,
644 req
->changeBreakpoint
.request
->ignoreCount
);
647 printf_filtered("Got to ChangeBreakpoint\n");
648 printf_filtered(" breakpointId = %d\n",
649 req
->changeBreakpoint
.request
->breakpointId
);
650 printf_filtered(" breakpointType = %d\n",
651 req
->changeBreakpoint
.request
->breakpointType
);
652 printf_filtered(" breakpointAttr = %d\n",
653 req
->changeBreakpoint
.request
->breakpointAttr
);
654 printf_filtered(" ignoreCount = %d\n",
655 req
->changeBreakpoint
.request
->ignoreCount
);
659 case BreakConditionRType
:
660 execute_command_1("condition %d %.*s",
661 req
->breakCondition
.request
->breakpointId
,
662 req
->breakCondition
.condition
.byteLen
,
663 req
->breakCondition
.condition
.text
);
665 case BreakCommandsRType
:
666 /* Put pointers to where cadillac_command_line_input() can find
668 command_line_length
= req
->breakCommands
.commands
.byteLen
;
669 command_line_text
= req
->breakCommands
.commands
.text
;
670 execute_command_1("commands %d",
671 req
->breakCommands
.request
->breakpointId
);
672 command_line_text
= (char *)NULL
;
673 command_line_length
= 0;
676 fprintf(stderr
, "Unknown request type = %d\n",
677 req
->head
.request
->reqType
);
680 free (req
); /* Should probably call CVFreeDebuggerRequest() here, but
681 can't do so if interrupt level has mucked with req->
682 request. CVFreeDebuggerRequest() only ends up calling
687 #define KERNEL_EVENT 1
690 /* Return a bitmask indicating if the kernel or the pty did something
691 interesting. Set poll to non-zero if you don't want to wait. */
694 wait_for_events(poll
)
700 static struct timeval tv
= {0};
702 /* Output all pending requests. */
703 CWriteRequestBuffer(conn
);
705 /* Wait till there's some activity from the kernel or the pty. */
709 FD_SET(kerfd
, &readfds
);
710 if (inferior_pty
> 0)
711 FD_SET(inferior_pty
, &readfds
);
713 numfds
= select(sizeof(readfds
)*8, &readfds
, 0, 0, &tv
);
715 numfds
= select(sizeof(readfds
)*8, &readfds
, 0, 0, 0);
717 while (numfds
<= 0 && !poll
);
719 if (FD_ISSET(inferior_pty
, &readfds
))
720 eventmask
|= PTY_EVENT
;
722 if (FD_ISSET(kerfd
, &readfds
))
723 eventmask
|= KERNEL_EVENT
;
728 /* Establish contact with the kernel. */
731 cadillac_initialize(cadillac_id
, execarg
)
737 extern long strtol(char *str
, char **ptr
, int base
);
738 char pathname
[MAXPATHLEN
];
741 if (!execarg
) execarg
= "";
743 printf("gdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
745 /* First establish the connection with the kernel. */
747 kerfd
= COpenClientSocket(NULL
);
749 printf("COpenClientSocket() failed\n");
753 /* Setup for I/O interrupts when appropriate. */
755 n
= fcntl(kerfd
, F_GETFL
, 0);
756 fcntl(kerfd
, F_SETFL
, n
|FASYNC
);
757 fcntl(kerfd
, F_SETOWN
, getpid());
759 /* Setup connection buffering. */
761 CSetSocketBufferSize (kerfd
, 12000);
763 /* Generate a new connection control block. */
765 conn
= NewConnection (0, kerfd
, kerfd
);
767 printf("NewConnection() failed\n");
772 kerout
= fopen("kernel.output", "+w");
774 CReadWriteHooks(conn
, conn
->previewMethod
, conn
->readMethod
, kernel_record
);
777 /* Tell the kernel that we are the "debugger". */
779 req
= CWriteTtyRequest (conn
, QueryConnectionRType
);
780 req
->generic
.queryconnection
.major
= 0;
781 req
->generic
.queryconnection
.minor
= 0;
782 req
->generic
.queryconnection
.cadillacId1
=strtol(cadillac_id
, &ctmp
, 16);
783 req
->generic
.queryconnection
.cadillacId2
= strtol(++ctmp
, NULL
, 16);
784 req
->generic
.queryconnection
.nProtocols
= 1;
785 CWriteProtocol (conn
, 0, 0, "debugger");
788 /* Tell the kernel that we are actually running. */
790 /* KROCK ALERT!!! The kernel doesn't really care about the arguments to
791 the program at all! It only cares that argument 7 be the name of the
792 target program. So, we just fill in the rest of the slots with
793 padding. I hope the kernel never cares about this! */
795 req
= CWriteTtyRequest (conn
, RunningProgramRType
);
796 req
->runningprogram
.argc
= 8;
798 CWriteVstring0 (conn
, pathname
);
800 CWriteVstring0 (conn
, "0");
801 CWriteVstring0 (conn
, "1");
802 CWriteVstring0 (conn
, "2");
803 CWriteVstring0 (conn
, "3");
804 CWriteVstring0 (conn
, "4");
805 CWriteVstring0 (conn
, "5");
806 CWriteVstring0 (conn
, "6");
807 CWriteVstring0 (conn
, execarg
);
810 /* Tell the kernel our PID and all that */
813 CVWriteDebugProgramInfo(conn
,
819 /* Tell the rest of the world that Cadillac is now set up. */
823 /* This is called from execute_command, and provides a wrapper around
824 various command routines in a place where both protocol messages and
825 user input both flow through.
829 cadillac_call_command(cmdblk
, arg
, from_tty
)
830 struct cmd_list_element
*cmdblk
;
834 if (cmdblk
->class == class_run
)
838 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
842 (*cmdblk
->function
.cfunc
)(arg
, from_tty
);
848 cadillac_new_process()
850 instance_id
= inferior_pid
;
860 eventmask
= wait_for_events(1);
865 if (eventmask
& PTY_EVENT
)
868 if (eventmask
& KERNEL_EVENT
)
874 cadillac_wait(status
)
879 signal(SIGIO
, iosig
);
883 signal(SIGIO
, SIG_DFL
);
893 /* All requests from the Cadillac kernel eventually end up here. */
896 cadillac_main_loop(pp
)
900 struct cleanup
*old_chain
;
904 /* We will come thru here any time there is an error, so send status if
911 /* The actual event loop! */
917 eventmask
= wait_for_events(0);
919 if (eventmask
& PTY_EVENT
)
922 if (eventmask
& KERNEL_EVENT
)
924 old_chain
= make_cleanup(null_routine
, 0);
926 bpstat_do_actions(&stop_bpstat
);
927 do_cleanups(old_chain
);
This page took 0.104753 seconds and 4 git commands to generate.