51a520bc49c5f88f6c6ead919d972fc814e97b0e
[cacao.git] / src / native / jvmti / cacaodbgserver.c
1 /* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
2                                        process controls the debuggee/cacao vm.
3
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
8
9    This file is part of CACAO.
10
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.
15
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.
20
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
24    02111-1307, USA.
25
26    Contact: cacao@complang.tuwien.ac.at
27
28    Authors: Martin Platter
29
30    Changes: Edwin Steiner
31             Samuel Vinson
32
33    $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
34
35 */
36
37 #include "native/jvmti/cacaodbgserver.h"
38 #include "native/jvmti/cacaodbg.h"
39 #include "native/jvmti/dbg.h"
40 #include <sys/types.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <sys/wait.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46
47 pid_t debuggee;
48
49 /* getchildprocptrace *********************************************************
50
51    Get data count number of bytes from address addr for child process address 
52    space. Requested  data is stored in the array pointed to by ptr.
53
54 *******************************************************************************/
55 static void getchildprocptrace (char *ptr, void* addr, int cnt) {
56         long i, longcnt;
57         long *p = (long*) ptr;
58         
59         longcnt = cnt/sizeof(long);
60         for (i=0; i<longcnt; i++) {
61                 p[i]=GETMEM(debuggee,addr);
62                 if (p[i]==-1)
63                 {
64                         fprintf(stderr,"cacaodbgserver process: getchildprocptrace: %ld\n",i);
65                         perror("cacaodbgserver process: getchildprocptrace:");
66                         exit(1);
67                 }
68                 addr+=sizeof(long);
69         }
70         i = GETMEM(debuggee,addr);
71         memcpy(p+longcnt,&i,cnt%sizeof(long));
72 }
73
74
75 /* waitloop *******************************************************************
76
77    waits and handles signals from debuggee/child process. Returns true if 
78    cacaodbgserver should exit.
79
80 *******************************************************************************/
81
82 static bool waitloop(void* dbgcvm) {
83     int status,retval,signal;
84     void* ip;
85         basic_event ev;
86         cacaodbgcommunication vm;
87         long data;
88         struct _brkpt* brk;
89
90         fprintf(stderr,"waitloop\n");
91
92         retval = wait(&status);
93
94         fprintf(stderr,"cacaodbgserver: waitloop we got something to do\n");
95         if (retval == -1) {
96                 fprintf(stderr,"error in waitloop\n");
97                 perror("cacaodbgserver process: waitloop: ");
98                 return true;
99         }
100         
101         if (retval != debuggee) {
102                 fprintf(stderr,"cacaodbgserver got signal from process other then debuggee/cacao vm\n");
103                 return false;
104         }
105         
106         if (WIFSTOPPED(status)) {
107                 signal = WSTOPSIG(status);
108                 
109                 /* ignore SIGSEGV, SIGPWR, SIGBUS and SIGXCPU for now.
110                    todo: in future this signals could be used to detect Garbage 
111                    Collection Start/Finish or NullPointerException Events */
112                 if ((signal == SIGSEGV) || (signal == SIGPWR) || 
113                         (signal == SIGBUS)      || (signal == SIGXCPU)) {
114                         fprintf(stderr,"cacaodbgserver: ignore internal signal (%d)\n",signal);
115                         CONT(debuggee,signal);
116                         return false;
117                 }
118                 
119                 if (signal == SIGABRT) {
120                         fprintf(stderr,"cacaodbgserver: got SIGABRT from debugee - exit\n");
121                         return true;
122                 }
123                 
124                 ip = getip(debuggee);
125                 ip--; /* EIP has already been incremented */
126                 fprintf(stderr,"got signal: %d IP %X\n",signal,ip);
127                 
128                         
129                 ev.signal = signal;
130                 ev.ip = ip;
131                 
132                 /* handle breakpoint */
133                 getchildprocptrace((char*)&vm,dbgcvm,sizeof(cacaodbgcommunication));
134                 
135                 if (vm.setbrkpt) {
136                         /* set a breakpoint */
137                         setbrk(debuggee, vm.brkaddr, &vm.brkorig);
138                         CONT(debuggee,0);
139                         return false;
140                 }
141
142                 if (signal == SIGTRAP) {
143                         /* Breakpoint hit. Place original instruction and notify cacao vm to
144                            handle it */
145                         fprintf(stderr,"breakpoint hit\n");
146                 }
147
148                 return false;
149         }
150         
151         if (WIFEXITED(status)) {
152                 fprintf(stderr,"cacaodbgserver: debuggee/cacao vm exited.\n");
153                 return true;
154         }
155         
156         if (WIFSIGNALED(status)) {
157                 fprintf(stderr,"cacaodbgserver: child terminated by signal %d\n",WTERMSIG(status));
158                 return true;
159         }
160         
161         if (WIFCONTINUED(status)) {
162                 fprintf(stderr,"cacaodbgserver: continued\n");
163                 return false;
164         }
165         
166         
167         fprintf(stderr,"wait not handled(child not exited or stopped)\n");
168         fprintf(stderr,"retval: %d status: %d\n",retval,status);
169         CONT(debuggee,0);               
170         return false;
171 }
172
173 /* main (cacaodbgserver) ******************************************************
174
175    main function for cacaodbgserver process.
176
177 *******************************************************************************/
178
179 int main(int argc, char **argv) {
180         bool running = true;
181         void *dbgcvm;
182         int status;
183         
184         if (argc != 2) {
185                 fprintf(stderr,"cacaodbgserver: not enough arguments\n");
186                 fprintf(stderr, "cacaodbgserver cacaodbgcommunicationaddress\n");
187
188                 fprintf(stderr,"argc %d argv[0] %s\n",argc,argv[0]);
189                 exit(1);
190         }
191
192         dbgcvm=(cacaodbgcommunication*)strtol(argv[1],NULL,16);
193
194         fprintf(stderr,"cacaodbgserver started pid %d ppid %d\n",getpid(), getppid());
195
196         debuggee = getppid();
197
198         if (TRACEATTACH(debuggee) == -1) perror("cacaodbgserver: ");
199
200         fprintf(stderr,"cacaovm attached\n");
201
202         if (wait(&status) == -1) {
203                 fprintf(stderr,"error initial wait\n");
204                 perror("cacaodbgserver: ");
205                 exit(1);
206         }
207
208         if (WIFSTOPPED(status)) 
209                 if (WSTOPSIG(status) == SIGSTOP)
210                         CONT(debuggee,0);
211         
212         while(running) {
213                 running = !waitloop(dbgcvm);
214         }
215         fprintf(stderr,"cacaodbgserver exit\n");
216 }
217
218
219 /*
220  * These are local overrides for various environment variables in Emacs.
221  * Please do not remove this and leave it at the end of the file, where
222  * Emacs will automagically detect them.
223  * ---------------------------------------------------------------------
224  * Local variables:
225  * mode: c
226  * indent-tabs-mode: t
227  * c-basic-offset: 4
228  * tab-width: 4
229  * End:
230  * vim:noexpandtab:sw=4:ts=4:
231  */