2 /* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
3 process controls the cacao vm through gdb
5 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
6 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
7 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
8 J. Wenninger, Institut f. Computersprachen - TU Wien
10 This file is part of CACAO.
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2, or (at
15 your option) any later version.
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 Contact: cacao@complang.tuwien.ac.at
29 Authors: Martin Platter
31 Changes: Edwin Steiner
34 $Id: cacaodbgserver.c $
38 #include "native/jvmti/cacaodbgserver.h"
39 #include "native/jvmti/cacaodbg.h"
40 #include "native/jvmti/dbg.h"
41 #include <sys/types.h>
50 FILE *gdbin, *gdbout; /* file descriptor for gdb pipes */
52 struct _pending_brkpt {
54 unsigned long threadid;
58 struct _pending_brkpt *pending_brkpts;
59 int pending_brkpts_size;
62 static void closepipeend (int fd) {
63 if (close(fd) == -1) {
64 perror("unable to close pipe - ");
69 /* startgdb *******************************************************************
71 starts a gdb session and creates two pipes connection gdb stdout/stdin to
74 *******************************************************************************/
76 static void startgdb() {
78 int cacao2gdbpipe[2],gdb2cacaopipe[2];
83 snprintf(gdbargs,20,"--pid=%d",getppid());
87 fprintf(stderr,"cacaodbgserver: fork error\n");
91 closepipeend(gdb2cacaopipe[0]); /* read end */
92 closepipeend(cacao2gdbpipe[1]); /* write end */
94 /* connect stdin of gdb to cacao2gdbpipe */
95 dup2(cacao2gdbpipe[0],0);
96 /* connect stdout of gdb to gdb2cacaopipe */
97 dup2(gdb2cacaopipe[1],1);
99 if (execlp("gdb","gdb","--interpreter=mi" ,gdbargs,(char *) NULL)==-1){
100 fprintf(stderr,"cacaodbgserver: unable to start gdb\n");
105 closepipeend(gdb2cacaopipe[1]); /* write end */
106 closepipeend(cacao2gdbpipe[0]); /* read end */
108 gdbin = fdopen(gdb2cacaopipe[0],"r");
109 gdbout = fdopen(cacao2gdbpipe[1],"w");
115 #define SENDCMD(CMD) \
116 fprintf(gdbout,"%s",CMD); \
120 static void getgdboutput(char *inbuf,int buflen) {
124 i += strlen(&inbuf[i]);
125 if (fgets(&inbuf[i],buflen-i,gdbin)==NULL) {
126 perror("cacaodbgserver: ");
129 } while(!(strncmp(OUTPUTEND,&inbuf[i],OUTPUTENDSIZE)==0));
133 /* dataevaluate ***************************************************************
135 evaluates expr returning long in gdb and returns the result
137 *******************************************************************************/
139 static unsigned long dataevaluate(char *expr) {
140 char *match, inbuf[160];
142 fprintf(gdbout,"-data-evaluate-expression %s\n",expr);
145 getgdboutput(inbuf,160);
146 if ((match=strstr(inbuf,DATAEVALUATE)) == NULL) {
147 fprintf(stderr,"dataevaluate: no matching value\n");
150 return strtoll(&match[strlen(DATAEVALUATE)], NULL, 16);
154 /* commonbreakpointhandler *****************************************************
156 called by gdb and hard coded breakpoint handler
158 *******************************************************************************/
160 static bool commonbreakpointhandler(char* sigbuf, int sigtrap) {
161 int numberofbreakpoints, i;
162 char tmp[INBUFLEN], *match;
165 if ((match=strstr(sigbuf,SIGADDR))==NULL) {
166 fprintf(stderr,"commonbreakpointhandler: no matching address(%s)\n",
171 addr = strtoll(&match[strlen(SIGADDR)],NULL,16);
175 numberofbreakpoints = (int)dataevaluate("dbgcom->jvmtibrkpt.num");
180 snprintf(tmp,INBUFLEN,"dbgcom->jvmtibrkpt.brk[%d].addr",i);
181 } while ((i<numberofbreakpoints) && (dataevaluate(tmp) != addr));
183 assert(i<numberofbreakpoints);
185 /* handle system breakpoints */
188 /* add a breakpoint */
189 fprintf(gdbout,"break *0x%lx\n",dataevaluate("dbgcom->brkaddr"));
191 getgdboutput(tmp,INBUFLEN);
193 case CACAODBGSERVERQUIT:
194 SENDCMD("-gdb-exit\n");
197 /* other breakpoints -> call jvmti_cacao_generic_breakpointhandler
199 fprintf(gdbout,"call jvmti_cacao_generic_breakpointhandler(%d)\n",i);
201 getgdboutput(tmp,INBUFLEN);
204 getgdboutput(tmp,INBUFLEN);
208 /* controlloop ****************************************************************
210 this function controls the gdb behaviour
212 *******************************************************************************/
214 static void controlloop() {
215 char inbuf[INBUFLEN], *match;
218 pending_brkpts_size = 5;
219 pending_brkpts = malloc(sizeof(struct _pending_brkpt)*pending_brkpts_size);
221 getgdboutput(inbuf,INBUFLEN); /* read gdb welcome message */
223 SENDCMD("handle SIGSEGV SIGPWR SIGXCPU SIGBUS noprint nostop\n");
224 getgdboutput(inbuf,INBUFLEN);
226 SENDCMD("print dbgcom\n");
227 getgdboutput(inbuf,INBUFLEN);
230 getgdboutput(inbuf,INBUFLEN);
233 getgdboutput(inbuf,INBUFLEN);
235 if ((match=strstr(inbuf,HCSIGTRAP))!=NULL) {
236 running = commonbreakpointhandler(match,1);
240 if ((match=strstr(inbuf,GDBBREAKPOINT))!=NULL) {
241 running = commonbreakpointhandler(match,0);
245 if (strstr(inbuf,EXITEDNORMALLY) != NULL) {
247 SENDCMD ("-gdb-exit");
252 if ((inbuf[0]!=LOGSTREAMOUTPUT) && (inbuf[0]!=CONSOLESTREAMOUTPUT)) {
253 fprintf(stderr,"gdbin not handled %s\n",inbuf);
254 fprintf(gdbout,"bt\n");
256 fprintf(stderr,"not handled 1\n");
258 getgdboutput(inbuf,INBUFLEN);
259 fprintf(stderr,"gdbin: %s\n",inbuf);
260 SENDCMD("-gdb-exit\n");
265 free(pending_brkpts);
268 /* main (cacaodbgserver) ******************************************************
270 main function for cacaodbgserver process.
272 *******************************************************************************/
274 int main(int argc, char **argv) {
284 * These are local overrides for various environment variables in Emacs.
285 * Please do not remove this and leave it at the end of the file, where
286 * Emacs will automagically detect them.
287 * ---------------------------------------------------------------------
290 * indent-tabs-mode: t
294 * vim:noexpandtab:sw=4:ts=4: