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
36 #include "native/jvmti/cacaodbgserver.h"
37 #include "native/jvmti/cacaodbg.h"
38 #include "native/jvmti/dbg.h"
39 #include <sys/types.h>
48 FILE *gdbin, *gdbout; /* file descriptor for gdb pipes */
50 struct _pending_brkpt {
52 unsigned long threadid;
56 struct _pending_brkpt *pending_brkpts;
57 int pending_brkpts_size;
60 static void closepipeend (int fd) {
61 if (close(fd) == -1) {
62 perror("unable to close pipe - ");
67 /* startgdb *******************************************************************
69 starts a gdb session and creates two pipes connection gdb stdout/stdin to
72 *******************************************************************************/
74 static void startgdb() {
76 int cacao2gdbpipe[2],gdb2cacaopipe[2];
81 snprintf(gdbargs,20,"--pid=%d",getppid());
85 fprintf(stderr,"cacaodbgserver: fork error\n");
89 closepipeend(gdb2cacaopipe[0]); /* read end */
90 closepipeend(cacao2gdbpipe[1]); /* write end */
92 /* connect stdin of gdb to cacao2gdbpipe */
93 dup2(cacao2gdbpipe[0],0);
94 /* connect stdout of gdb to gdb2cacaopipe */
95 dup2(gdb2cacaopipe[1],1);
97 if (execlp("gdb","gdb","--interpreter=mi" ,gdbargs,(char *) NULL)==-1){
98 fprintf(stderr,"cacaodbgserver: unable to start gdb\n");
103 closepipeend(gdb2cacaopipe[1]); /* write end */
104 closepipeend(cacao2gdbpipe[0]); /* read end */
106 gdbin = fdopen(gdb2cacaopipe[0],"r");
107 gdbout = fdopen(cacao2gdbpipe[1],"w");
113 #define SENDCMD(CMD) \
114 fprintf(gdbout,"%s",CMD); \
118 static void getgdboutput(char *inbuf,int buflen) {
122 i += strlen(&inbuf[i]);
123 if (fgets(&inbuf[i],buflen-i,gdbin)==NULL) {
124 perror("cacaodbgserver: ");
127 } while(!(strncmp(OUTPUTEND,&inbuf[i],OUTPUTENDSIZE)==0));
131 /* dataevaluate ***************************************************************
133 evaluates expr returning long in gdb and returns the result
135 *******************************************************************************/
137 static unsigned long dataevaluate(char *expr) {
138 char *match, inbuf[160];
140 fprintf(gdbout,"-data-evaluate-expression %s\n",expr);
143 getgdboutput(inbuf,160);
144 if ((match=strstr(inbuf,DATAEVALUATE)) == NULL) {
145 fprintf(stderr,"dataevaluate: no matching value\n");
148 return strtoll(&match[strlen(DATAEVALUATE)], NULL, 16);
152 /* commonbreakpointhandler *****************************************************
154 called by gdb and hard coded breakpoint handler
156 *******************************************************************************/
158 static bool commonbreakpointhandler(char* sigbuf, int sigtrap) {
159 int numberofbreakpoints, i;
160 char tmp[INBUFLEN], *match;
163 if ((match=strstr(sigbuf,SIGADDR))==NULL) {
164 fprintf(stderr,"commonbreakpointhandler: no matching address(%s)\n",
169 addr = strtoll(&match[strlen(SIGADDR)],NULL,16);
173 numberofbreakpoints = (int)dataevaluate("dbgcom->jvmtibrkpt.num");
178 snprintf(tmp,INBUFLEN,"dbgcom->jvmtibrkpt.brk[%d].addr",i);
179 } while ((i<numberofbreakpoints) && (dataevaluate(tmp) != addr));
181 assert(i<numberofbreakpoints);
183 /* handle system breakpoints */
186 /* add a breakpoint */
187 fprintf(gdbout,"break *0x%lx\n",dataevaluate("dbgcom->brkaddr"));
189 getgdboutput(tmp,INBUFLEN);
191 case CACAODBGSERVERQUIT:
192 SENDCMD("-gdb-exit\n");
195 /* other breakpoints -> call jvmti_cacao_generic_breakpointhandler
197 fprintf(gdbout,"call jvmti_cacao_generic_breakpointhandler(%d)\n",i);
199 getgdboutput(tmp,INBUFLEN);
202 getgdboutput(tmp,INBUFLEN);
206 /* controlloop ****************************************************************
208 this function controls the gdb behaviour
210 *******************************************************************************/
212 static void controlloop() {
213 char inbuf[INBUFLEN], *match;
216 pending_brkpts_size = 5;
217 pending_brkpts = malloc(sizeof(struct _pending_brkpt)*pending_brkpts_size);
219 getgdboutput(inbuf,INBUFLEN); /* read gdb welcome message */
221 SENDCMD("handle SIGSEGV SIGPWR SIGXCPU SIGBUS noprint nostop\n");
222 getgdboutput(inbuf,INBUFLEN);
224 SENDCMD("print dbgcom\n");
225 getgdboutput(inbuf,INBUFLEN);
228 getgdboutput(inbuf,INBUFLEN);
231 getgdboutput(inbuf,INBUFLEN);
233 if ((match=strstr(inbuf,HCSIGTRAP))!=NULL) {
234 running = commonbreakpointhandler(match,1);
238 if ((match=strstr(inbuf,GDBBREAKPOINT))!=NULL) {
239 running = commonbreakpointhandler(match,0);
243 if (strstr(inbuf,EXITEDNORMALLY) != NULL) {
245 SENDCMD ("-gdb-exit");
250 if ((inbuf[0]!=LOGSTREAMOUTPUT) && (inbuf[0]!=CONSOLESTREAMOUTPUT)) {
251 fprintf(stderr,"gdbin not handled %s\n",inbuf);
252 fprintf(gdbout,"bt\n");
254 fprintf(stderr,"not handled 1\n");
256 getgdboutput(inbuf,INBUFLEN);
257 fprintf(stderr,"gdbin: %s\n",inbuf);
258 SENDCMD("-gdb-exit\n");
263 free(pending_brkpts);
266 /* main (cacaodbgserver) ******************************************************
268 main function for cacaodbgserver process.
270 *******************************************************************************/
272 int main(int argc, char **argv) {
282 * These are local overrides for various environment variables in Emacs.
283 * Please do not remove this and leave it at the end of the file, where
284 * Emacs will automagically detect them.
285 * ---------------------------------------------------------------------
288 * indent-tabs-mode: t
292 * vim:noexpandtab:sw=4:ts=4: