1 /* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
2 process controls the cacao vm through gdb
4 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
5 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
6 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
7 J. Wenninger, Institut f. Computersprachen - TU Wien
9 This file is part of CACAO.
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License as
13 published by the Free Software Foundation; either version 2, or (at
14 your option) any later version.
16 This program is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 Contact: cacao@complang.tuwien.ac.at
28 Authors: Martin Platter
30 Changes: Edwin Steiner
37 #include "native/jvmti/cacaodbgserver.h"
38 #include "native/jvmti/cacaodbg.h"
39 #include "native/jvmti/dbg.h"
40 #include <sys/types.h>
49 FILE *gdbin, *gdbout; /* file descriptor for gdb pipes */
51 struct _pending_brkpt {
53 unsigned long threadid;
57 struct _pending_brkpt *pending_brkpts;
58 int pending_brkpts_size;
61 static void closepipeend (int fd) {
62 if (close(fd) == -1) {
63 perror("unable to close pipe - ");
68 /* startgdb *******************************************************************
70 starts a gdb session and creates two pipes connection gdb stdout/stdin to
73 *******************************************************************************/
75 static void startgdb() {
77 int cacao2gdbpipe[2],gdb2cacaopipe[2];
82 snprintf(gdbargs,20,"--pid=%d",getppid());
86 fprintf(stderr,"cacaodbgserver: fork error\n");
90 closepipeend(gdb2cacaopipe[0]); /* read end */
91 closepipeend(cacao2gdbpipe[1]); /* write end */
93 /* connect stdin of gdb to cacao2gdbpipe */
94 dup2(cacao2gdbpipe[0],0);
95 /* connect stdout of gdb to gdb2cacaopipe */
96 dup2(gdb2cacaopipe[1],1);
98 if (execlp("gdb","gdb","--interpreter=mi" ,gdbargs,(char *) NULL)==-1){
99 fprintf(stderr,"cacaodbgserver: unable to start gdb\n");
104 closepipeend(gdb2cacaopipe[1]); /* write end */
105 closepipeend(cacao2gdbpipe[0]); /* read end */
107 gdbin = fdopen(gdb2cacaopipe[0],"r");
108 gdbout = fdopen(cacao2gdbpipe[1],"w");
114 #define SENDCMD(CMD) \
115 fprintf(gdbout,"%s",CMD); \
119 static void getgdboutput(char *inbuf,int buflen) {
123 i += strlen(&inbuf[i]);
124 if (fgets(&inbuf[i],buflen-i,gdbin)==NULL) {
125 perror("cacaodbgserver: ");
128 } while(!(strncmp(OUTPUTEND,&inbuf[i],OUTPUTENDSIZE)==0));
132 /* dataevaluate ***************************************************************
134 evaluates expr returning long in gdb and returns the result
136 *******************************************************************************/
138 static unsigned long dataevaluate(char *expr) {
139 char *match, inbuf[160];
141 fprintf(gdbout,"-data-evaluate-expression %s\n",expr);
144 getgdboutput(inbuf,160);
145 if ((match=strstr(inbuf,DATAEVALUATE))==NULL) {
146 fprintf(stderr,"dataevaluate: no matching value\n");
149 return strtoll(&match[strlen(DATAEVALUATE)],NULL,16);
153 /* commonbreakpointhandler *****************************************************
155 called by gdb and hard coded breakpoint handler
157 *******************************************************************************/
159 static bool commonbreakpointhandler(char* sigbuf, int sigtrap) {
160 int numberofbreakpoints, i;
161 char tmp[INBUFLEN], *match;
164 if ((match=strstr(sigbuf,SIGADDR))==NULL) {
165 fprintf(stderr,"commonbreakpointhandler: no matching address(%s)\n",
170 addr = strtoll(&match[strlen(SIGADDR)],NULL,16);
174 numberofbreakpoints = (int)dataevaluate("dbgcom->jvmtibrkpt.num");
179 snprintf(tmp,INBUFLEN,"dbgcom->jvmtibrkpt.brk[%d].addr",i);
180 } while ((i<numberofbreakpoints) && (dataevaluate(tmp) != addr));
182 assert(i<numberofbreakpoints);
184 /* handle system breakpoints */
187 /* add a breakpoint */
188 fprintf(gdbout,"break *0x%lx\n",dataevaluate("dbgcom->brkaddr"));
190 getgdboutput(tmp,INBUFLEN);
192 case CACAODBGSERVERQUIT:
193 SENDCMD("-gdb-exit\n");
196 /* other breakpoints -> call jvmti_cacao_generic_breakpointhandler
198 fprintf(gdbout,"call jvmti_cacao_generic_breakpointhandler(%d)\n",i);
200 getgdboutput(tmp,INBUFLEN);
203 getgdboutput(tmp,INBUFLEN);
207 /* controlloop ****************************************************************
209 this function controls the gdb behaviour
211 *******************************************************************************/
213 static void controlloop() {
214 char inbuf[INBUFLEN], *match;
217 pending_brkpts_size = 5;
218 pending_brkpts = malloc(sizeof(struct _pending_brkpt)*pending_brkpts_size);
220 getgdboutput(inbuf,INBUFLEN); /* read gdb welcome message */
222 SENDCMD("handle SIGSEGV SIGPWR SIGXCPU SIGBUS noprint nostop\n");
223 getgdboutput(inbuf,INBUFLEN);
225 SENDCMD("print dbgcom\n");
226 getgdboutput(inbuf,INBUFLEN);
229 getgdboutput(inbuf,INBUFLEN);
232 getgdboutput(inbuf,INBUFLEN);
234 if ((match=strstr(inbuf,HCSIGTRAP))!=NULL) {
235 running = commonbreakpointhandler(match,1);
239 if ((match=strstr(inbuf,GDBBREAKPOINT))!=NULL) {
240 running = commonbreakpointhandler(match,0);
244 if (strstr(inbuf,EXITEDNORMALLY) != NULL) {
246 SENDCMD ("-gdb-exit");
251 if ((inbuf[0]!=LOGSTREAMOUTPUT) && (inbuf[0]!=CONSOLESTREAMOUTPUT))
252 fprintf(stderr,"gdbin not handled %s\n",inbuf);
255 free(pending_brkpts);
258 /* main (cacaodbgserver) ******************************************************
260 main function for cacaodbgserver process.
262 *******************************************************************************/
264 int main(int argc, char **argv) {
274 * These are local overrides for various environment variables in Emacs.
275 * Please do not remove this and leave it at the end of the file, where
276 * Emacs will automagically detect them.
277 * ---------------------------------------------------------------------
280 * indent-tabs-mode: t
284 * vim:noexpandtab:sw=4:ts=4: