1 /* src/native/jvmti/cacaodbgserver.c - contains the cacaodbgserver process. This
2 process controls the debuggee.
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
33 $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
37 #include "native/jvmti/cacaodbgserver.h"
38 #include "native/jvmti/cacaodbg.h"
39 #include "native/jvmti/dbg.h"
40 #include <sys/types.h>
47 #include <semaphore.h>
49 #include <linux/user.h>
52 /* getchildprocptrace *********************************************************
54 Get data count number of bytes from address addr for child process address
55 space. Requested data is stored in the array pointed to by ptr.
57 *******************************************************************************/
58 static void getchildprocptrace (char *ptr, void* addr, int cnt) {
60 long *p = (long*) ptr;
62 longcnt = cnt/sizeof(long);
63 for (i=0; i<longcnt; i++) {
64 p[i]=GETMEM(debuggee,addr);
66 perror("cacaodbgserver process: getchildprocptrace: ");
69 longcnt = GETMEM(debuggee,addr);
70 memcpy(ptr,&longcnt,cnt%sizeof(long));
73 /* contchild ******************************************************************
75 Helper function to continue child process.
77 *******************************************************************************/
78 static bool contchild(int signal) {
79 /* get lock for running state */
80 sem_wait(&workingdata_lock);
81 fprintf(stderr,"cacaodbgserver: contchild called (hastostop: %d)\n",cdbgshmem->hastostop);
82 if(cdbgshmem->hastostop < 1) {
83 fprintf(stderr,"cacaodbgserver: going to continue child\n");
84 CONT(debuggee,signal);
85 cdbgshmem->hastostop = 0;
86 cdbgshmem->running=true;
87 /* release lock for running state */
88 sem_post(&workingdata_lock);
91 sem_post(&workingdata_lock);
96 /* msgqsendevent *******************************************************************
98 sends an event notification to the jdwp/debugger process through the
101 *******************************************************************************/
102 static void msgqsendevent(basic_event *ev) {
103 ev->mtype = MSGQDEBUGGER;
105 if (-1 == msgsnd(msgqid, ev, sizeof(basic_event), 0)) {
106 perror("cacaodbgserver process: cacaodbglisten send error: ");
111 /* waitloop *******************************************************************
113 waits and handles signals from debuggee/child process
115 *******************************************************************************/
117 static void waitloop() {
118 int status,retval,signal;
122 fprintf(stderr,"waitloop\n");
126 retval = wait(&status);
128 fprintf(stderr,"cacaodbgserver: waitloop we got something to do\n");
130 fprintf(stderr,"error in waitloop\n");
131 perror("cacaodbgserver process: waitloop: ");
135 if (retval != debuggee) {
136 fprintf(stderr,"cacaodbgserver got signal from process other then debuggee\n");
140 if (WIFEXITED(status)) {
141 /* generate event VMDeath */
148 if (WIFSTOPPED(status)) {
149 signal = WSTOPSIG(status);
151 /* ignore SIGSEGV, SIGPWR, SIGBUS and SIGXCPU for now.
152 todo: in future this signals can be used to detect Garbage
153 Collection Start/Finish or NullPointerException Events */
154 if ((signal == SIGSEGV) || (signal == SIGPWR) ||
155 (signal == SIGBUS) || (signal == SIGXCPU)) {
156 fprintf(stderr,"cacaodbgserver: ignore internal signal (%d)\n",signal);
161 if (signal == SIGABRT) {
162 fprintf(stderr,"cacaodbgserver: got SIGABRT from debugee - exit\n");
166 ip = getip(debuggee);
167 ip--; /* EIP has already been incremented */
168 fprintf(stderr,"got signal: %d IP %X\n",signal,ip);
170 sem_wait(&workingdata_lock);
171 cdbgshmem->running = false;
172 cdbgshmem->hastostop = 1;
173 sem_post(&workingdata_lock);
175 if (signal==SIGUSR2) {
176 fprintf(stderr,"SIGUSR2 - debuggee has stopped by jdwp process\n");
186 fprintf(stderr,"wait not handled(child not exited or stopped)\n");
187 fprintf(stderr,"retval: %d status: %d\n",retval,status);
191 /* ptraceloop *****************************************************************
193 this function handles the ptrace request from the jdwp/debugger process.
195 *******************************************************************************/
198 bool contdebuggee=false;
200 ptrace_reply *buffer;
202 struct user_regs_struct *regs;
204 fprintf(stderr,"ptraceloop\n");
206 while (!contdebuggee) {
207 if (-1 == msgrcv(msgqid, &pt, sizeof(ptrace_request), MSGQPTRACESND, 0))
208 perror("cacaodbgserver process: cacaodbglisten receive error: ");
212 /* continue debuggee process */
213 size= sizeof(ptrace_reply);
214 buffer =(ptrace_reply*) MNEW(char,size);
216 contdebuggee = contchild(pt.data);
218 buffer->mtype = MSGQPTRACERCV;
219 buffer->successful=true;
223 /* get memory content from the debuggee process */
224 size= sizeof(ptrace_reply)+pt.data;
225 buffer =(ptrace_reply*) MNEW(char,size);
227 buffer->mtype = MSGQPTRACERCV;
228 buffer->datasize = size-sizeof(ptrace_reply);
230 fprintf(stderr,"getchildprocptrace: pid %d get %p - %p cnt: %d (buffer %p buffer->data %p)\n",
231 debuggee, pt.addr,pt.addr+pt.data, buffer->datasize,buffer, buffer->data);
234 getchildprocptrace(buffer->data,pt.addr,buffer->datasize);
237 size= sizeof(ptrace_reply)+sizeof(long);
238 buffer =(ptrace_reply*) MNEW(char,size);
240 /* set new breakpoint */
241 buffer->mtype = MSGQPTRACERCV;
242 buffer->successful=true;
243 buffer->datasize=sizeof(long);
245 setbrk(debuggee,pt.addr, (long*)(buffer->data));
248 /* delete breakpoint */
249 size= sizeof(ptrace_reply);
250 buffer =(ptrace_reply*) MNEW(char,size);
252 DISABLEBRK(debuggee,pt.ldata,pt.addr);
254 buffer->mtype = MSGQPTRACERCV;
255 buffer->successful=true;
260 size= sizeof(ptrace_reply)+sizeof(struct user_regs_struct);
261 buffer =(ptrace_reply*) MNEW(char,size);
264 GETREGS(debuggee,*regs);
266 buffer->mtype = MSGQPTRACERCV;
267 buffer->successful=true;
268 buffer->datasize=sizeof(struct user_regs_struct);
271 fprintf(stderr,"unkown ptrace request %d\n",pt.kind);
275 if (-1 == msgsnd(msgqid, buffer, size, 0)) {
276 perror("cacaodbgserver process: cacaodbglisten send error: ");
279 MFREE(buffer,char,size);
283 /* cacaodbgserver *************************************************************
285 waits for eventes from and issues ptrace calls to debuggee/child process
287 *******************************************************************************/
289 void cacaodbgserver() {
290 fprintf(stderr,"cacaodbgserver started\n");
293 /* wait until debuggee process gets stopped
294 and inform debugger process */
296 /* give the debugger process the opportunity to issue ptrace calls */
298 /* ptraceloop returns after a PTRACE_CONT call has been issued */
304 * These are local overrides for various environment variables in Emacs.
305 * Please do not remove this and leave it at the end of the file, where
306 * Emacs will automagically detect them.
307 * ---------------------------------------------------------------------
310 * indent-tabs-mode: t