bfeee43b53a905ede73cb9896860e0f60d879dde
[cacao.git] / src / native / jvmti / cacaodbg.c
1 /* src/native/jvmti/cacaodbg.c - contains entry points for debugging support 
2                                  in cacao.
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/jvmti.h"
38 #include "native/jvmti/cacaodbg.h"
39 #include "native/jvmti/cacaodbgserver.h"
40 #include "native/jvmti/dbg.h"
41 #include "vm/vm.h"
42 #include "vm/loader.h"
43 #include "vm/exceptions.h"
44 #include "vm/builtin.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/stringlocal.h"
47 #include "toolbox/logging.h"
48 #include "threads/native/threads.h"
49
50 #include <sys/types.h>
51 #include <unistd.h>
52 #include <signal.h>
53 #include <stdlib.h>
54 #include <assert.h>
55
56
57 /* allthreads *****************************************************************
58
59    Gets an array of threadobjects of all threads
60
61 *******************************************************************************/
62 jvmtiError allthreads (jint * threads_count_ptr, threadobject*** threads_ptr) {
63     int i = 0, cnt = 8; 
64     threadobject *thread, **tthreads;
65         
66 #if defined(ENABLE_THREADS)
67         tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
68
69         thread = mainthreadobj;
70     do {
71         if(thread->o.thread != NULL) {
72                         fflush(stderr); 
73
74                    /* count and copy only live threads */
75                    if (i>=cnt) {
76                            MREALLOC(tthreads,threadobject*,cnt,cnt+8);
77                            cnt += 8;
78                    }
79                    tthreads[i] = thread;
80                    i++;
81                 }
82                 thread = thread->info.prev;
83
84                 /* repeat until we got the pointer to the mainthread twice */
85         } while (mainthreadobj != thread);
86
87         fflush(stderr); 
88
89     *threads_count_ptr = i;
90         *threads_ptr = tthreads;
91
92     return JVMTI_ERROR_NONE;
93 #else
94         return JVMTI_ERROR_NOT_AVAILABLE;
95 #endif
96 }
97
98
99 /* getcurrentthread ***********************************************************
100
101    Get jthread structure of current thread. 
102
103 *******************************************************************************/
104 jthread getcurrentthread() {
105         return (jthread)(threads_get_current_threadobject())->o.thread;
106 }
107
108
109
110 /* brktablecreator*************************************************************
111
112    helper function to enlarge the breakpoint table if needed
113
114 *******************************************************************************/
115
116 static void brktablecreator() {
117         struct _brkpt* tmp;
118         struct brkpts *jvmtibrkpt;
119
120         jvmtibrkpt = &dbgcom->jvmtibrkpt;;
121         if (jvmtibrkpt->size == 0) {
122                 jvmtibrkpt->brk = MNEW(struct _brkpt, 16);
123                 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*16);
124                 jvmtibrkpt->size = 16;
125                 jvmtibrkpt->num = BEGINUSERBRK;
126         } else {
127                 jvmtibrkpt->size += 16;
128                 tmp = jvmtibrkpt->brk;
129                 jvmtibrkpt->brk = MNEW(struct _brkpt, jvmtibrkpt->size);
130                 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*(jvmtibrkpt->size));
131                 memcpy((void*)jvmtibrkpt->brk,(void*)tmp,jvmtibrkpt->size);
132                 MFREE(tmp,struct _brkpt,jvmtibrkpt->size-16);
133         }       
134 }
135
136
137 /* setsysbrkpt ****************************************************************
138
139    sets a system breakpoint in breakpoint table and calls set breakpoint
140
141 *******************************************************************************/
142
143 void setsysbrkpt(int sysbrk, void* addr) {      
144         struct brkpts *jvmtibrkpt;
145
146         pthread_mutex_lock(&dbgcomlock);
147         jvmtibrkpt = &dbgcom->jvmtibrkpt;;
148
149         if (jvmtibrkpt->size == jvmtibrkpt->num)
150                 brktablecreator();
151
152         assert (sysbrk < BEGINUSERBRK);
153         jvmtibrkpt->brk[sysbrk].addr = addr;
154
155
156         dbgcom->setbrkpt = true;
157         dbgcom->brkaddr = addr;
158         jvmtibrkpt->brk[sysbrk].orig = dbgcom->brkorig;
159         pthread_mutex_unlock(&dbgcomlock);
160
161         /* call cacaodbgserver */
162         TRAP; 
163
164         fprintf (stderr,"setsysbrk %d %X  done\n",sysbrk, addr);
165 }
166
167
168 /* addbrkpt *******************************************************************
169
170    adds a breakpoint to breakpoint table and calls set breakpoint
171
172 *******************************************************************************/
173
174 void addbrkpt(void* addr, jmethodID method, jlocation location) {
175         struct brkpts *jvmtibrkpt;
176
177         pthread_mutex_lock(&dbgcomlock);
178         jvmtibrkpt = &dbgcom->jvmtibrkpt;;
179
180         if (jvmtibrkpt->size == jvmtibrkpt->num)
181                 brktablecreator();
182
183         assert (jvmtibrkpt->size > jvmtibrkpt->num);
184         fprintf (stderr,"add brk add: %X\n",addr);
185         jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
186         jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
187         jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
188
189         /* todo: set breakpoint */
190 /*      jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
191         jvmtibrkpt->num++;
192         pthread_mutex_unlock(&dbgcomlock);
193
194         fprintf (stderr,"add brk done\n");
195 }
196
197
198 /* setup_jdwp_thread *****************************************************
199
200    Helper function to start JDWP threads
201
202 *******************************************************************************/
203
204 void setup_jdwp_thread(char* transport) {
205         java_objectheader *o;
206         methodinfo *m;
207         java_lang_String  *s;
208         classinfo *class;
209
210         /* new gnu.classpath.jdwp.Jdwp() */
211         class = load_class_from_sysloader(
212             utf_new_char("gnu.classpath.jdwp.Jdwp"));
213         if (!class)
214                 throw_main_exception_exit();
215
216         o = builtin_new(class);
217
218         if (!o)
219                 throw_main_exception_exit();
220         
221         m = class_resolveclassmethod(class,
222                                      utf_init, 
223                                      NULL,
224                                      class_java_lang_Object,
225                                      true);
226         if (!m)
227             throw_main_exception_exit();
228         
229         vm_call_method(m,o);
230         
231         /* configure(transport,NULL) */
232         m = class_resolveclassmethod(
233             class, utf_new_char("configure"), 
234             utf_new_char("(Ljava/lang/String;)V"),
235             class_java_lang_Object,
236             false);
237
238         s = javastring_new_from_ascii(&transport[1]);
239
240         vm_call_method(m,o,s);
241
242         if (!m)
243                 throw_main_exception_exit();
244
245
246         /* _doInitialization */
247         m = class_resolveclassmethod(class,
248                                      utf_new_char("_doInitialization"), 
249                                      utf_new_char("()V"),
250                                      class,
251                                      false);
252         
253         if (!m)
254             throw_main_exception_exit();
255         
256         vm_call_method(m,o);
257 }
258
259 /* cacaobreakpointhandler **********************************************************
260
261    handles breakpoints. called by cacaodbgserver.
262
263 *******************************************************************************/
264
265 void cacaobreakpointhandler() {
266         basic_event ev;
267         genericEventData data;
268         int i;
269
270         /* XXX to be continued :-) */
271
272         fprintf(stderr,"breakpoint handler called\n");
273         log_text(" - signal %d", ev.signal);
274         switch (ev.signal) {
275         case SIGTRAP:
276                 /* search the breakpoint that has been triggered */
277                 i=0;
278                 while ((ev.ip!=dbgcom->jvmtibrkpt.brk[i].addr) && (i<dbgcom->jvmtibrkpt.num)) i++;
279                 
280                 fprintf(stderr,"cacaodbglisten SIGTRAP switch after while loop i %d\n",i);
281                 
282                 switch (i) {
283                 case SETTHREADOBJECTBRK:
284                         /* threads_set_current_threadobject */
285                         fprintf(stderr,"IP %X == threads_set_current_threadobject\n",ev.ip);
286                         data.ev=JVMTI_EVENT_THREAD_START;
287                         fireEvent(&data);
288                         break;
289                 default:
290                         if ((i >= BEGINUSERBRK) && (i<dbgcom->jvmtibrkpt.num)) {
291                                 log_text("todo: user defined breakpoints are not handled yet");
292                         } else 
293                                 log_text("breakpoint not handled - continue anyway");
294                 }
295                 break;
296         case SIGQUIT:
297                 log_text("debugger process SIGQUIT");
298                 data.ev=JVMTI_EVENT_VM_DEATH;
299                 fireEvent(&data);               
300                 break;
301         default:
302                 log_text("signal not handled");
303         }
304 }
305
306
307 /*
308  * These are local overrides for various environment variables in Emacs.
309  * Please do not remove this and leave it at the end of the file, where
310  * Emacs will automagically detect them.
311  * ---------------------------------------------------------------------
312  * Local variables:
313  * mode: c
314  * indent-tabs-mode: t
315  * c-basic-offset: 4
316  * tab-width: 4
317  * End:
318  * vim:noexpandtab:sw=4:ts=4:
319  */