1 /* Energize (formerly known as Cadillac) interface routines.
2 Copyright 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. */
27 #include <sys/types.h>
29 #include <sys/param.h>
30 #include "energize/connection.h"
31 #include "energize/genericreq.h"
32 #include "energize/debuggerreq.h"
33 #include "energize/debuggerconn.h"
34 #include "energize/ttyconn.h"
41 #include <sys/filio.h>
44 #include <sys/errno.h>
48 /* Non-zero means that we're doing the energize interface. */
51 /* Connection block for debugger<=>kernel communications. */
52 static Connection *conn = 0;
54 /* fd for our socket to the kernel. */
57 /* The kernel's ID for this instance of the program. */
58 static int program_id;
60 static int instance_id;
62 /* The fd for the pty associated with the inferior. */
63 static int inferior_pty = -1;
64 static int inferior_tty = -1;
66 static int has_run = 0;
68 extern int pgrp_inferior;
70 extern char *source_path;
72 /* The name of the executable file */
73 static char *exec_file;
75 /* Tell energize_command_line_input() where to get its text from */
76 static int doing_breakcommands_message = 0;
78 /* Stash command text here */
79 static char *command_line_text = 0;
80 static int command_line_length = 0;
82 /* Flags returned by wait_for_events() */
83 #define KERNEL_EVENT 1
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. */
95 CVWriteTranscriptInfo (conn, instance_id, (char *)ptr);
101 energize_query(query, args)
110 vsprintf(buf, query, args);
112 CVWriteQueryInfo(conn,
117 ""); /* transcript */
121 energize_acknowledge_query(ack)
124 CVWriteQueryInfo(conn,
129 ""); /* transcript */
132 /* Copy all data from the pty to the kernel. */
143 cc = read(inferior_pty, buf, sizeof(buf));
147 && errno == EWOULDBLOCK))
154 perror("pty read error");
158 req = CWriteTtyRequest(conn, TextIORType);
159 CWriteVstringLen(conn, buf, cc);
162 CWriteRequestBuffer(conn);
165 /* Copy data from the kernel to the pty. */
168 kernel_to_pty(data, len)
174 cc = write(inferior_pty, data, len);
182 perror("pty write error");
185 printf("Couldn't write all the data to the pty, wanted %d, got %d\n",
191 full_filename(symtab)
192 struct symtab *symtab;
200 if (symtab->fullname)
201 return savestring(symtab->fullname, strlen(symtab->fullname));
204 pathlen = strlen(symtab->dirname);
207 if (symtab->filename)
208 pathlen += strlen(symtab->filename);
210 filename = xmalloc(pathlen+1);
213 strcpy(filename, symtab->dirname);
216 if (symtab->filename)
217 strcat(filename, symtab->filename);
222 /* Tell the energize kernel how high the stack is so that frame numbers (which
223 are relative to the current stack height make sense.
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
241 /* Non-zero means that Energize kernel already knows how high the stack is. */
242 static int stack_info_valid = 0;
247 struct pclist *pclist = 0, *pli, *opli;
248 static struct pclist *old_pclist;
252 if (stack_info_valid)
258 /* First, calculate the stack height, and build the new pclist */
260 for (frame = get_current_frame();
262 frame = get_prev_frame(frame))
265 pli = (struct pclist *)xmalloc(sizeof(struct pclist));
272 /* Now, figure out how much of the stack hasn't changed */
274 for (pli = pclist, opli = old_pclist;
275 pli != 0 && opli != 0;
276 pli = pli->next, opli = opli->next, (similar)++)
278 if ((pli->pc != opli->pc)
279 && (get_pc_function_start(pli->pc)
280 != get_pc_function_start(opli->pc)))
284 /* Free up all elements of the old pclist */
295 old_pclist = pclist; /* Install the new pclist */
297 CVWriteStackSizeInfo(conn,
299 height, /* Frame depth */
301 similar, /* Frame diff */
305 stack_info_valid = 1;
308 /* Tell the kernel where we are in the program, and what the stack looks like.
314 static int linecount = 48;
315 struct symtab_and_line sal;
316 struct symbol *symbol;
317 char *funcname, *filename;
318 static int sent_prog_inst = 0;
323 if (inferior_pid == 0) /* target has died */
325 CVWriteProgramTerminatedInfo(conn,
332 sal = find_pc_line(stop_pc, 0);
333 symbol = find_pc_function(stop_pc);
335 funcname = symbol ? symbol->name : "";
336 filename = full_filename(sal.symtab);
341 CVWriteProgramInstanceInfo(conn,
352 CVWriteStackFrameInfo(conn,
356 0, /* XXX - frame # */
359 "" /* XXX ? transcript */
362 CVWriteProgramStoppedInfo(conn,
364 0, /* XXX - breakpoint # or signal # */
367 "" /* XXX ? transcript */
374 /* Call this to output annotated function names. Names will be demangled if
375 necessary. arg_mode contains flags that are passed on to cplus_demangle. */
378 energize_annotate_function(funcname, arg_mode, level)
384 char *demangled_name = NULL;
386 if (funcname == NULL)
391 demangled_name = cplus_demangle(funcname, arg_mode);
394 funcname = demangled_name;
399 if (level < 0) level = 0;
401 CVWriteBackTraceEntryInfo(conn,
407 free(demangled_name);
410 /* Call this just prior to printing out the name & value of a variable. This
411 tells the kernel where to annotate the output. */
414 expression - A text handle on what GDB can use to reference this value.
415 This can be a symbol name, or a convenience var, etc...
416 symbol - Used to determine the scope of the data. May be NULL.
417 type - Determines if we have a pointer ref, and the print name of the type.
418 Used in ShowValue message.
419 valaddr - The address in target memory of the data.
420 field - The field name of the struct or union element being referenced.
423 static char cum_expr[200]; /* Cumulative expression */
424 static char *expr_stack[100] = {cum_expr}; /* Pointers to end of expressions */
425 static char **last_expr = expr_stack; /* Current expr stack pointer */
428 energize_start_variable_annotation(expression, symbol, type, valaddr, field)
430 struct symbol *symbol;
437 enum type_code type_code;
438 enum address_class sym_class;
446 strcpy(*last_expr++, expression);
447 *last_expr = *(last_expr-1) + strlen(expression);
449 switch (TYPE_CODE(type))
451 case TYPE_CODE_ARRAY:
452 case TYPE_CODE_STRUCT:
453 case TYPE_CODE_UNION:
457 ref_type = CValueValueRef;
460 ref_type = CValuePointerRef;
463 ref_type = CValueUndefRef;
467 /* Make sure that pointer points at something we understand */
469 if (ref_type == CValuePointerRef)
470 switch (TYPE_CODE(TYPE_TARGET_TYPE(type)))
473 case TYPE_CODE_ARRAY:
474 case TYPE_CODE_STRUCT:
475 case TYPE_CODE_UNION:
481 ref_type = CValueUndefRef;
487 sym_class = SYMBOL_CLASS(symbol);
492 case LOC_CONST_BYTES:
493 stor_cl = CValueStorStaticConst;
496 stor_cl = CValueStorStaticVar;
500 stor_cl = CValueStorRegister;
506 stor_cl = CValueStorLocalVar;
509 stor_cl = CValueStorUndef;
514 stor_cl = CValueStorUndef;
516 type_cast = TYPE_NAME(type);
518 CVWriteValueBeginInfo(conn,
523 0, /* XXX - frameno */
527 ""); /* transcript */
531 energize_end_variable_annotation()
536 last_expr--; /* Pop the expr stack */
537 **last_expr = '\000'; /* Cut off the last part of the expr */
539 CVWriteValueEndInfo(conn,
541 ""); /* transcript */
544 /* Tell the kernel that the target is now running. */
549 CVWriteProgramBusyInfo(conn,
551 ""); /* XXX ? transcript */
552 CWriteRequestBuffer(conn); /* Must take place synchronusly! */
553 stack_info_valid = 0;
558 energize_symbol_file(objfile)
559 struct objfile *objfile;
564 CVWriteSymbolTableInfo(conn,
566 ""); /* Transcript */
569 /* execute_command_1(echo, queue, cmd, args) - echo - non-zero means echo the
570 command. queue - non-zero means don't execute it now, just save it away for
571 later. cmd - string containing printf control sequences. args - list of
572 arguments needed by those control sequences.
575 /* Linked list of queued up commands */
576 static struct command_line *queued_commands = 0;
577 static struct command_line *last_queued_command = 0;
579 /* Call this routine to save a command for later. The command string is
580 copied into freshly malloc'ed memory. */
587 struct command_line *cl;
590 s = (strlen(cmd) + 1) + 7 & ~(unsigned long)7;
592 buf = (char *)xmalloc(s + sizeof(struct command_line));
593 cl = (struct command_line *)(buf + s);
597 strncpy(cl->line, cmd, s);
600 last_queued_command->next = cl;
602 queued_commands = cl;
604 last_queued_command = cl;
607 /* Call this procedure to take a command off of the command queue. It returns
608 a pointer to a buf which the caller is responsible for freeing. NULL is
609 returned if there are no commands queued. */
614 struct command_line *cl;
617 cl = queued_commands;
622 queued_commands = cl->next;
628 execute_command_1(va_alist)
631 char buf[100]; /* XXX - make buf dynamic! */
640 echo = va_arg(args, int);
641 queue = va_arg(args, int);
642 cmd = va_arg(args, char *);
644 vsprintf(buf, cmd, args);
651 printf_filtered("%s\n", buf);
652 execute_command(buf, 1);
662 kernel_record(fd, ptr, num)
667 fwrite(ptr, num, 1, kerout);
669 return write(fd, ptr, num);
674 energize_condition_breakpoint(b)
675 struct breakpoint *b;
678 CVWriteBreakConditionInfo(conn,
681 b->cond_string ? b->cond_string : "",
687 energize_commands_breakpoint(b)
688 struct breakpoint *b;
690 struct command_line *l;
695 CVWriteBreakCommandBegInfo(conn,
698 ""); /* transcript */
700 for (l = b->commands; l; l = l->next)
701 CVWriteBreakCommandEntryInfo(conn,
704 ""); /* transcript */
706 CVWriteBreakCommandEndInfo(conn,
708 ""); /* transcript */
712 breakpoint_notify(b, action)
713 struct breakpoint *b;
719 char *included_in_filename = "";
724 if (b->type != bp_breakpoint)
727 filename = full_filename(b->symtab);
729 sym = find_pc_function(b->address);
731 funcname = SYMBOL_NAME(sym);
733 CVWriteBreakpointInfo (conn,
742 filename ? filename : "",
743 "", /* included_in_filename */
748 energize_commands_breakpoint(b);
750 energize_condition_breakpoint(b);
757 energize_create_breakpoint(b)
758 struct breakpoint *b;
760 breakpoint_notify(b, CEnableBreakpoint);
764 energize_delete_breakpoint(b)
765 struct breakpoint *b;
767 breakpoint_notify(b, CDeleteBreakpoint);
771 energize_enable_breakpoint(b)
772 struct breakpoint *b;
774 breakpoint_notify(b, CEnableBreakpoint);
778 energize_disable_breakpoint(b)
779 struct breakpoint *b;
781 breakpoint_notify(b, CDisableBreakpoint);
785 energize_ignore_breakpoint(b)
786 struct breakpoint *b;
788 breakpoint_notify(b, CBreakAttrUnchanged);
791 /* Open up a pty and its associated tty. Return the fd of the tty. */
799 struct termios termios;
801 #define HIGHPTY (('z' - 'p') * 16 - 1)
803 for (n = 0; n <= HIGHPTY; n++)
805 sprintf(dev, "/dev/pty%c%x", n/16 + 'p', n%16);
806 if (stat(dev, &statbuf))
808 ptyfd = open(dev, O_RDWR);
811 sprintf(dev, "/dev/tty%c%x", n/16 + 'p', n%16);
812 ttyfd = open(dev, O_RDWR);
813 if (ttyfd < 0) {close(ptyfd); continue;}
815 /* Setup pty for non-blocking I/O. Also make it give us a SIGIO when
816 there's data available. */
818 n = fcntl(ptyfd, F_GETFL, 0);
819 fcntl(ptyfd, F_SETFL, n|FNDELAY|FASYNC);
820 fcntl(ptyfd, F_SETOWN, getpid());
822 tcgetattr(ttyfd, &termios);
823 termios.c_oflag &= ~OPOST; /* No post-processing */
824 tcsetattr(ttyfd, TCSANOW, &termios);
826 inferior_pty = ptyfd;
827 inferior_tty = ttyfd;
831 error ("getpty: can't get a pty\n");
834 /* Examine a protocol packet from the driver. */
837 kernel_dispatch(queue)
838 int queue; /* Non-zero means we should just queue up
841 register CHeader *head;
843 head = (CHeader *)CPeekNextRequest (conn);
846 fprintf (stderr, "EOF on kernel read!\n");
850 if (head->reqType < LastTtyRequestRType)
852 CTtyRequest* req = CReadTtyRequest (conn);
853 switch (req->head.reqType)
855 case AcceptConnectionRType:
856 /* Tell the rest of the world that energize is now set up */
860 case RefuseConnectionRType:
861 fprintf (stderr, "Debugger connection refused\n");
864 case KillProgramRType:
872 p = CGetVstring(conn, &len);
873 kernel_to_pty(p, len);
877 fprintf(stderr, "Unknown Tty request type = %d\n",
884 CVDebuggerRequest *req = CVReadDebuggerRequest (conn);
887 fprintf (stderr, "CVReadDebuggerRequest returned NULL, type = %d\n",
892 switch (req->head.request->reqType)
894 case OpenProgramInstanceRType:
896 char *arglist, buf[100]; /* XXX - Make buf dynamic! */
898 /* XXX - should notice when program_id changes */
899 arglist = req->openProgramInstance.progArglist.text;
900 arglen = req->openProgramInstance.progArglist.byteLen;
902 execute_command_1(1, queue, "break main");
903 execute_command_1(1, queue, "enable delete $bpnum");
906 execute_command_1(1, queue, "set args %.*s", arglen, arglist);
908 execute_command_1(1, queue, "run");
911 case SearchPathRType:
912 directory_command(req->searchPath.searchPath.text, 0);
914 case QuitDebuggerRType:
915 execute_command_1(1, queue, "quit");
918 if (req->run.request->useArglist == CNewArglist)
920 execute_command_1(1, queue, "set args %.*s",
921 req->run.progArglist.byteLen,
922 req->run.progArglist.text);
924 execute_command_1(1, queue, "run");
927 execute_command_1(1, queue, "continue");
930 execute_command_1(1, queue, "step %d", req->step.request->stepCount);
933 execute_command_1(1, queue, "next %d", req->next.request->nextCount);
935 case ChangeStackFrameRType:
936 switch (req->changeStackFrame.request->frameMovement)
938 case CToCurrentStackFrame:
939 execute_command_1(1, queue, "frame %d",
940 req->changeStackFrame.request->frameNo);
942 case CToInnerStackFrame:
943 execute_command_1(1, queue, "down %d",
944 req->changeStackFrame.request->frameNo);
946 case CToOuterStackFrame:
947 execute_command_1(1, queue, "up %d",
948 req->changeStackFrame.request->frameNo);
950 case CToAbsoluteStackFrame:
951 execute_command_1(1, queue, "frame %d",
952 req->changeStackFrame.request->frameNo);
957 /* XXX - deal with limit??? */
958 execute_command_1(1, queue, "backtrace");
961 execute_command_1(1, queue, "finish");
963 case TerminateProgramRType:
964 execute_command_1(1, queue, "kill");
966 case NewBreakpointRType:
971 tail = strrchr(req->newBreakpoint.fileName.text, '/');
973 tail = req->newBreakpoint.fileName.text;
976 skipped = tail - req->newBreakpoint.fileName.text;
977 execute_command_1(1, queue, "break %.*s:%d",
978 req->newBreakpoint.fileName.byteLen - skipped,
980 req->newBreakpoint.request->fileLinePos);
984 killpg(pgrp_inferior, SIGINT);
991 /* XXX - should really break command up into seperate lines
992 and spoon-feed it to execute_command */
994 text = req->userInput.userInput.text;
995 len = req->userInput.userInput.byteLen;
997 if (text[len-1] == '\n') text[len-1] = '\000';
999 while (*text == ' ' || *text == '\t') text++;
1001 if (strcmp(text, "]*[") == 0) /* XXX - What does this mean??? */
1004 if (*text != '\000')
1005 execute_command_1(0, queue, "%s", text);
1007 print_prompt(); /* User just typed a blank line */
1010 case QueryResponseRType:
1014 if (req->queryResponse.request->response)
1018 execute_command_1(1, 1, resp);
1019 printf_filtered("%s\n", resp);
1022 case ChangeBreakpointRType:
1023 switch (req->changeBreakpoint.request->breakpointAttr)
1025 case CBreakAttrUnchanged:
1026 execute_command_1(1, queue, "ignore %d %d",
1027 req->changeBreakpoint.request->breakpointId,
1028 req->changeBreakpoint.request->ignoreCount);
1030 case CEnableBreakpoint:
1031 execute_command_1(1, queue, "enable %d",
1032 req->changeBreakpoint.request->breakpointId);
1034 case CDisableBreakpoint:
1035 execute_command_1(1, queue, "disable %d",
1036 req->changeBreakpoint.request->breakpointId);
1038 case CDeleteBreakpoint:
1039 execute_command_1(1, queue, "delete %d",
1040 req->changeBreakpoint.request->breakpointId);
1042 case CEnableDisableBreakpoint:
1043 execute_command_1(1, queue, "enable once %d",
1044 req->changeBreakpoint.request->breakpointId);
1046 case CEnableDeleteBreakpoint:
1047 execute_command_1(1, queue, "enable delete %d",
1048 req->changeBreakpoint.request->breakpointId);
1051 printf_filtered("ChangeBreakpointRType: unknown breakpointAttr\n");
1052 printf_filtered(" breakpointAttr = %d\n",
1053 req->changeBreakpoint.request->breakpointAttr);
1054 printf_filtered(" breakpointId = %d\n",
1055 req->changeBreakpoint.request->breakpointId);
1056 printf_filtered(" breakpointType = %d\n",
1057 req->changeBreakpoint.request->breakpointType);
1058 printf_filtered(" ignoreCount = %d\n",
1059 req->changeBreakpoint.request->ignoreCount);
1063 case BreakConditionRType:
1064 execute_command_1(1, queue, "condition %d %.*s",
1065 req->breakCondition.request->breakpointId,
1066 req->breakCondition.condition.byteLen,
1067 req->breakCondition.condition.text);
1069 case BreakCommandsRType:
1070 /* Put pointers to where energize_command_line_input() can find
1072 doing_breakcommands_message = 1;
1073 command_line_length = req->breakCommands.commands.byteLen;
1074 command_line_text = req->breakCommands.commands.text;
1075 execute_command_1(1, queue, "commands %d",
1076 req->breakCommands.request->breakpointId);
1077 command_line_text = (char *)NULL;
1078 command_line_length = 0;
1079 doing_breakcommands_message = 0;
1081 case ShowValueRType:
1083 char expr[100], *p = expr;
1087 if (req->showValue.request->ref_type == CValuePointerRef)
1090 if (req->showValue.type_cast.byteLen)
1093 strncat(expr, req->showValue.type_cast.text,
1094 req->showValue.type_cast.byteLen);
1098 if (req->showValue.field.byteLen)
1101 strncat(expr, req->showValue.expression.text,
1102 req->showValue.expression.byteLen);
1104 if (req->showValue.field.byteLen)
1108 strncat(expr, req->showValue.field.text,
1109 req->showValue.field.byteLen);
1112 execute_command_1(1, queue, "print %s", expr);
1117 char expr[100], *p = expr;
1121 if (req->setValue.request->ref_type == CValuePointerRef)
1125 if (req->setValue.type_cast.byteLen)
1128 strncat(expr, req->setValue.type_cast.text,
1129 req->setValue.type_cast.byteLen);
1133 if (req->setValue.field.byteLen)
1136 strncat(expr, req->setValue.expression.text,
1137 req->setValue.expression.byteLen);
1139 if (req->setValue.field.byteLen)
1143 strncat(expr, req->setValue.field.text,
1144 req->setValue.field.byteLen);
1147 execute_command_1(1, queue, "print %s = (%s) %s", expr,
1148 req->setValue.type_cast.text,
1149 req->setValue.value.text);
1152 case DynamicLoadRType:
1156 filename = req->dynamicLoad.filenames.byteLen ?
1157 req->dynamicLoad.filenames.text : exec_file;
1159 switch (req->dynamicLoad.request->action)
1161 case CDynamicLoadUpdateSymtab:
1162 execute_command_1(1, queue, "exec-file %s", filename);
1163 execute_command_1(1, queue, "symbol-file %s", filename);
1166 printf_filtered("DynamicLoadRType: unknown action=%d, filename=%s\n",
1167 req->dynamicLoad.request->action,
1168 req->dynamicLoad.filenames.text);
1174 fprintf(stderr, "Unknown Debugger request type = %d\n",
1175 req->head.request->reqType);
1178 free (req); /* Should probably call CVFreeDebuggerRequest() here, but
1179 can't do so if interrupt level has mucked with req->
1180 request. CVFreeDebuggerRequest() only ends up calling
1185 /* Return a bitmask indicating if the kernel or the pty did something
1186 interesting. Set poll to non-zero if you don't want to wait. */
1189 wait_for_events(poll)
1195 static struct timeval tv = {0};
1197 /* Output all pending requests. */
1198 CWriteRequestBuffer(conn);
1202 /* Wait till there's some activity from the kernel or the pty. */
1205 FD_SET(kerfd, &readfds);
1206 if (inferior_pty > 0)
1207 FD_SET(inferior_pty, &readfds);
1209 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, &tv);
1211 numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0);
1213 while (numfds <= 0 && !poll);
1215 if (FD_ISSET(inferior_pty, &readfds))
1216 eventmask |= PTY_EVENT;
1218 if (FD_ISSET(kerfd, &readfds))
1219 eventmask |= KERNEL_EVENT;
1224 /* This is called from read_command_lines() to provide the text for breakpoint
1225 commands, which is supplied in a BreakCommands message. Each call to this
1226 routine supplies a single line of text, with the newline removed. */
1228 /* This routine may be invoked in two different contexts. In the first, it
1229 is being called as a result of the BreakCommands message. In this case,
1230 all of the command text is immediately available. In the second case, it is
1231 called as a result of the user typing the 'command' command. The command
1232 text then needs to be glommed out of UserInput messages (and possibly other
1233 messages as well). The most 'straighforward' way of doing this is to
1234 basically simulate the main loop, but just accumulate the command text
1235 instead of sending it to execute_command(). */
1238 energize_command_line_input(prompt, repeat)
1245 return command_line_input(prompt, repeat);
1247 if (doing_breakcommands_message)
1249 if (command_line_length <= 0)
1250 return (char *)NULL;
1252 p = command_line_text;
1254 while (command_line_length-- > 0)
1256 if (*command_line_text == '\n')
1258 *command_line_text = '\000';
1259 command_line_text++;
1262 command_line_text++;
1265 printf_filtered("%s\n", p);
1270 /* We come here when the user has typed the 'command' or 'define' command
1271 to the GDB window. We are basically deep inside of the 'command'
1272 command processing routine right now, and will be called to get a new
1273 line of input. We expect that kernel_dispatch will queue up only one
1274 command at a time. */
1277 static char buf[100];
1279 eventmask = wait_for_events(0);
1281 if (eventmask & PTY_EVENT)
1284 if (eventmask & KERNEL_EVENT)
1285 kernel_dispatch(1); /* Queue up commands */
1287 /* Note that command has been echoed by the time we get here */
1289 p = dequeue_command();
1293 strncpy(buf, p, sizeof(buf));
1302 /* Establish contact with the kernel. */
1305 energize_initialize(energize_id, execarg)
1311 extern long strtol(char *str, char **ptr, int base);
1312 char pathname[MAXPATHLEN];
1318 if (!execarg) execarg = "";
1320 exec_file = strdup(execarg); /* Save for later */
1322 printf("\ngdb-debugger pid=%d\n", getpid()); /* XXX - debugging only */
1324 /* First establish the connection with the kernel. */
1326 kerfd = COpenClientSocket(NULL);
1328 printf("COpenClientSocket() failed\n");
1332 /* Setup for I/O interrupts when appropriate. */
1334 n = fcntl(kerfd, F_GETFL, 0);
1335 fcntl(kerfd, F_SETFL, n|FASYNC);
1336 fcntl(kerfd, F_SETOWN, getpid());
1338 /* Setup connection buffering. */
1340 CSetSocketBufferSize (kerfd, 12000);
1342 /* Generate a new connection control block. */
1344 conn = NewConnection (0, kerfd, kerfd);
1346 printf("NewConnection() failed\n");
1350 #ifdef KERNEL_RECORD
1351 kerout = fopen("kernel.output", "+w");
1353 CReadWriteHooks(conn, conn->previewMethod, conn->readMethod, kernel_record);
1356 /* Tell the kernel that we are the "debugger". */
1358 req = CWriteTtyRequest (conn, QueryConnectionRType);
1359 req->generic.queryconnection.major = 0;
1360 req->generic.queryconnection.minor = 0;
1361 req->generic.queryconnection.cadillacId1=strtol(energize_id, &ctmp, 16);
1362 req->generic.queryconnection.cadillacId2 = strtol(++ctmp, NULL, 16);
1363 req->generic.queryconnection.nProtocols = 1;
1364 CWriteProtocol (conn, 0, 0, "debugger");
1365 CWriteLength (conn);
1367 /* Tell the kernel that we are actually running. */
1369 /* KROCK ALERT!!! The kernel doesn't really care about the arguments to
1370 the program at all! It only cares that argument 7 be the name of the
1371 target program. So, we just fill in the rest of the slots with
1372 padding. I hope the kernel never cares about this! */
1374 req = CWriteTtyRequest (conn, RunningProgramRType);
1375 req->runningprogram.argc = 8;
1377 CWriteVstring0 (conn, pathname);
1379 CWriteVstring0 (conn, "0");
1380 CWriteVstring0 (conn, "1");
1381 CWriteVstring0 (conn, "2");
1382 CWriteVstring0 (conn, "3");
1383 CWriteVstring0 (conn, "4");
1384 CWriteVstring0 (conn, "5");
1385 CWriteVstring0 (conn, "6");
1386 CWriteVstring0 (conn, execarg);
1387 CWriteLength (conn);
1389 /* Tell the kernel our PID and all that */
1392 CVWriteDebugProgramInfo(conn,
1398 /* Tell the rest of the world that Energize is now set up. */
1401 setsid(); /* Drop controlling tty, become pgrp master */
1402 getpty(); /* Setup the pty */
1403 dup2(inferior_tty, 0); /* Attach all GDB I/O to the pty */
1404 dup2(inferior_tty, 1);
1405 dup2(inferior_tty, 2);
1408 /* This is called from execute_command, and provides a wrapper around
1409 various command routines in a place where both protocol messages and
1410 user input both flow through.
1414 energize_call_command(cmdblk, arg, from_tty)
1415 struct cmd_list_element *cmdblk;
1421 (*cmdblk->function.cfunc) (arg, from_tty);
1425 if (cmdblk->class == class_run)
1429 (*cmdblk->function.cfunc)(arg, from_tty);
1433 (*cmdblk->function.cfunc)(arg, from_tty);
1439 energize_new_process()
1441 instance_id = inferior_pid;
1452 eventmask = wait_for_events(1);
1457 if (eventmask & PTY_EVENT)
1460 if (eventmask & KERNEL_EVENT)
1466 energize_wait(status)
1472 return wait(status);
1474 signal(SIGIO, iosig);
1478 signal(SIGIO, SIG_DFL);
1488 /* All requests from the Energize kernel eventually end up here. */
1491 energize_main_loop()
1494 struct cleanup *old_chain;
1496 doing_breakcommands_message = 0;
1498 /* We will come thru here any time there is an error, so send status if
1505 /* The actual event loop! */
1512 old_chain = make_cleanup(null_routine, 0);
1514 /* First, empty out the command queue, then check for new requests. */
1516 while (cmd = dequeue_command())
1518 execute_command_1(1, 0, cmd);
1522 eventmask = wait_for_events(0);
1524 if (eventmask & PTY_EVENT)
1527 if (eventmask & KERNEL_EVENT)
1530 bpstat_do_actions(&stop_bpstat);
1531 do_cleanups(old_chain);