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