CACAO
cacaodbgserver.c
Go to the documentation of this file.
1 
2 /* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
3  process controls the cacao vm through gdb
4 
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
9 
10  This file is part of CACAO.
11 
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.
16 
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.
21 
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
25  02111-1307, USA.
26 
27  Contact: cacao@complang.tuwien.ac.at
28 
29  Authors: Martin Platter
30 
31  Changes: Edwin Steiner
32  Samuel Vinson
33 
34 */
35 
37 #include "native/jvmti/cacaodbg.h"
38 #include "native/jvmti/dbg.h"
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <signal.h>
42 #include <sys/wait.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <assert.h>
46 #include <string.h>
47 
48 FILE *gdbin, *gdbout; /* file descriptor for gdb pipes */
49 
51  int brknumber;
52  unsigned long threadid;
53  char* regs;
54 };
55 
58 
59 
60 static void closepipeend (int fd) {
61  if (close(fd) == -1) {
62  perror("unable to close pipe - ");
63  exit(1);
64  }
65 }
66 
67 /* startgdb *******************************************************************
68 
69  starts a gdb session and creates two pipes connection gdb stdout/stdin to
70  gdbin/gdbout
71 
72 *******************************************************************************/
73 
74 static void startgdb() {
75  char gdbargs[20];
76  int cacao2gdbpipe[2],gdb2cacaopipe[2];
77 
78  pipe(cacao2gdbpipe);
79  pipe(gdb2cacaopipe);
80 
81  snprintf(gdbargs,20,"--pid=%d",getppid());
82 
83  switch(fork()) {
84  case -1:
85  fprintf(stderr,"cacaodbgserver: fork error\n");
86  exit(1);
87  case 0:
88  /* child */
89  closepipeend(gdb2cacaopipe[0]); /* read end */
90  closepipeend(cacao2gdbpipe[1]); /* write end */
91 
92  /* connect stdin of gdb to cacao2gdbpipe */
93  dup2(cacao2gdbpipe[0],0);
94  /* connect stdout of gdb to gdb2cacaopipe */
95  dup2(gdb2cacaopipe[1],1);
96 
97  if (execlp("gdb","gdb","--interpreter=mi" ,gdbargs,(char *) NULL)==-1){
98  fprintf(stderr,"cacaodbgserver: unable to start gdb\n");
99  exit(1);
100  }
101  default:
102  /* parent */
103  closepipeend(gdb2cacaopipe[1]); /* write end */
104  closepipeend(cacao2gdbpipe[0]); /* read end */
105 
106  gdbin = fdopen(gdb2cacaopipe[0],"r");
107  gdbout = fdopen(cacao2gdbpipe[1],"w");
108  }
109 
110 }
111 
112 
113 #define SENDCMD(CMD) \
114  fprintf(gdbout,"%s",CMD); \
115  fflush(gdbout); \
116 
117 
118 static void getgdboutput(char *inbuf,int buflen) {
119  int i=0;
120  inbuf[0]='\0';
121  do {
122  i += strlen(&inbuf[i]);
123  if (fgets(&inbuf[i],buflen-i,gdbin)==NULL) {
124  perror("cacaodbgserver: ");
125  exit(1);
126  }
127  } while(!(strncmp(OUTPUTEND,&inbuf[i],OUTPUTENDSIZE)==0));
128 }
129 
130 
131 /* dataevaluate ***************************************************************
132 
133  evaluates expr returning long in gdb and returns the result
134 
135 *******************************************************************************/
136 
137 static unsigned long dataevaluate(char *expr) {
138  char *match, inbuf[160];
139 
140  fprintf(gdbout,"-data-evaluate-expression %s\n",expr);
141  fflush(gdbout);
142 
143  getgdboutput(inbuf,160);
144  if ((match=strstr(inbuf,DATAEVALUATE)) == NULL) {
145  fprintf(stderr,"dataevaluate: no matching value\n");
146  return -1;
147  }
148  return strtoll(&match[strlen(DATAEVALUATE)], NULL, 16);
149 }
150 
151 
152 /* commonbreakpointhandler *****************************************************
153 
154  called by gdb and hard coded breakpoint handler
155 
156 *******************************************************************************/
157 
158 static bool commonbreakpointhandler(char* sigbuf, int sigtrap) {
159  int numberofbreakpoints, i;
160  char tmp[INBUFLEN], *match;
161  unsigned long addr;
162 
163  if ((match=strstr(sigbuf,SIGADDR))==NULL) {
164  fprintf(stderr,"commonbreakpointhandler: no matching address(%s)\n",
165  sigbuf);
166  return true;
167  }
168 
169  addr = strtoll(&match[strlen(SIGADDR)],NULL,16);
170  if (sigtrap) addr--;
171 
172 
173  numberofbreakpoints = (int)dataevaluate("dbgcom->jvmtibrkpt.num");
174 
175  i = -1;
176  do {
177  i++;
178  snprintf(tmp,INBUFLEN,"dbgcom->jvmtibrkpt.brk[%d].addr",i);
179  } while ((i<numberofbreakpoints) && (dataevaluate(tmp) != addr));
180 
181  assert(i<numberofbreakpoints);
182 
183  /* handle system breakpoints */
184  switch(i) {
185  case SETSYSBRKPT:
186  /* add a breakpoint */
187  fprintf(gdbout,"break *0x%lx\n",dataevaluate("dbgcom->brkaddr"));
188  fflush(gdbout);
189  getgdboutput(tmp,INBUFLEN);
190  break;
191  case CACAODBGSERVERQUIT:
192  SENDCMD("-gdb-exit\n");
193  return false;
194  default:
195  /* other breakpoints -> call jvmti_cacao_generic_breakpointhandler
196  in the cacao vm */
197  fprintf(gdbout,"call jvmti_cacao_generic_breakpointhandler(%d)\n",i);
198  fflush(gdbout);
199  getgdboutput(tmp,INBUFLEN);
200  }
201  SENDCMD(CONTINUE);
202  getgdboutput(tmp,INBUFLEN);
203  return true;
204 }
205 
206 /* controlloop ****************************************************************
207 
208  this function controls the gdb behaviour
209 
210 *******************************************************************************/
211 
212 static void controlloop() {
213  char inbuf[INBUFLEN], *match;
214  bool running = true;
215 
217  pending_brkpts = malloc(sizeof(struct _pending_brkpt)*pending_brkpts_size);
218 
219  getgdboutput(inbuf,INBUFLEN); /* read gdb welcome message */
220 
221  SENDCMD("handle SIGSEGV SIGPWR SIGXCPU SIGBUS noprint nostop\n");
222  getgdboutput(inbuf,INBUFLEN);
223 
224  SENDCMD("print dbgcom\n");
225  getgdboutput(inbuf,INBUFLEN);
226 
227  SENDCMD(CONTINUE);
228  getgdboutput(inbuf,INBUFLEN);
229 
230  while(running) {
231  getgdboutput(inbuf,INBUFLEN);
232 
233  if ((match=strstr(inbuf,HCSIGTRAP))!=NULL) {
234  running = commonbreakpointhandler(match,1);
235  continue;
236  }
237 
238  if ((match=strstr(inbuf,GDBBREAKPOINT))!=NULL) {
239  running = commonbreakpointhandler(match,0);
240  continue;
241  }
242 
243  if (strstr(inbuf,EXITEDNORMALLY) != NULL) {
244  /* quit gdb */
245  SENDCMD ("-gdb-exit");
246  running = false;
247  continue;
248  }
249 
250  if ((inbuf[0]!=LOGSTREAMOUTPUT) && (inbuf[0]!=CONSOLESTREAMOUTPUT)) {
251  fprintf(stderr,"gdbin not handled %s\n",inbuf);
252  fprintf(gdbout,"bt\n");
253  fflush(gdbout);
254  fprintf(stderr,"not handled 1\n");
255  fflush(stderr);
256  getgdboutput(inbuf,INBUFLEN);
257  fprintf(stderr,"gdbin: %s\n",inbuf);
258  SENDCMD("-gdb-exit\n");
259  return;
260  }
261  }
262 
263  free(pending_brkpts);
264 }
265 
266 /* main (cacaodbgserver) ******************************************************
267 
268  main function for cacaodbgserver process.
269 
270 *******************************************************************************/
271 
272 int main(int argc, char **argv) {
273  startgdb();
274 
275  controlloop();
276 
277  return 0;
278 }
279 
280 
281 /*
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  * ---------------------------------------------------------------------
286  * Local variables:
287  * mode: c
288  * indent-tabs-mode: t
289  * c-basic-offset: 4
290  * tab-width: 4
291  * End:
292  * vim:noexpandtab:sw=4:ts=4:
293  */
#define CONSOLESTREAMOUTPUT
#define CONTINUE
static void controlloop()
static void closepipeend(int fd)
#define SENDCMD(CMD)
unsigned long threadid
#define OUTPUTEND
static void getgdboutput(char *inbuf, int buflen)
#define SIGADDR
FILE * gdbin
int pending_brkpts_size
int main(int argc, char **argv)
Definition: cacao.cpp:61
static unsigned long dataevaluate(char *expr)
#define LOGSTREAMOUTPUT
#define HCSIGTRAP
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
static void startgdb()
#define INBUFLEN
#define EXITEDNORMALLY
#define CACAODBGSERVERQUIT
Definition: cacaodbg.h:77
FILE * gdbout
MIIterator i
#define OUTPUTENDSIZE
static bool commonbreakpointhandler(char *sigbuf, int sigtrap)
#define DATAEVALUATE
struct _pending_brkpt * pending_brkpts
#define GDBBREAKPOINT
#define SETSYSBRKPT
Definition: cacaodbg.h:76