1 /* src/native/jvmti/cacaodbg.c - contains entry points for debugging support
4 Copyright (C) 1996-2005, 2006, 2008
5 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
7 This file is part of CACAO.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License as
11 published by the Free Software Foundation; either version 2, or (at
12 your option) any later version.
14 This program is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include "native/jvmti/jvmti.h"
27 #include "native/jvmti/cacaodbg.h"
28 #include "native/jvmti/dbg.h"
30 #include "vm/loader.h"
31 #include "vm/exceptions.h"
32 #include "vm/builtin.h"
33 #include "vm/jit/asmpart.h"
34 #include "vm/stringlocal.h"
35 #include "toolbox/logging.h"
36 #include "threads/mutex.h"
37 #include "threads/thread.hpp"
39 #include <sys/types.h>
47 /* jvmti_get_all_threads ******************************************************
49 Gets an array of threadobjects of all threads
51 *******************************************************************************/
52 jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
53 threadobject*** threads_ptr) {
55 threadobject *thread, **tthreads;
57 #if defined(ENABLE_THREADS)
58 tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
60 thread = mainthreadobj;
62 if(thread->o.thread != NULL) {
65 /* count and copy only live threads */
67 MREALLOC(tthreads,threadobject*,cnt,cnt+8);
73 thread = thread->prev;
75 /* repeat until we got the pointer to the mainthread twice */
76 } while (mainthreadobj != thread);
80 *threads_count_ptr = i;
81 *threads_ptr = tthreads;
83 return JVMTI_ERROR_NONE;
85 return JVMTI_ERROR_NOT_AVAILABLE;
90 /* jvmti_get_current_thread ***************************************************
92 Get jthread structure of current thread.
94 *******************************************************************************/
95 jthread jvmti_get_current_thread() {
96 return (jthread)(thread_get_current)->o.thread;
101 /* breakpointtable_creator ***************************************************
103 helper function to enlarge the breakpoint table if needed
105 *******************************************************************************/
107 static void breakpointtable_creator() {
109 struct brkpts *jvmtibrkpt;
111 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
112 if (jvmtibrkpt->size == 0) {
113 jvmtibrkpt->brk = MNEW(struct _brkpt, 16);
114 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*16);
115 jvmtibrkpt->size = 16;
116 jvmtibrkpt->num = BEGINUSERBRK;
118 jvmtibrkpt->size += 16;
119 tmp = jvmtibrkpt->brk;
120 jvmtibrkpt->brk = MNEW(struct _brkpt, jvmtibrkpt->size);
121 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*(jvmtibrkpt->size));
122 memcpy((void*)jvmtibrkpt->brk,(void*)tmp,jvmtibrkpt->size);
123 MFREE(tmp,struct _brkpt,jvmtibrkpt->size-16);
128 /* jvmti_set_system_breakpoint ************************************************
130 sets a system breakpoint in breakpoint table and calls set breakpoint
132 *******************************************************************************/
134 void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
135 struct brkpts *jvmtibrkpt;
137 mutex_lock(&dbgcomlock);
138 jvmtibrkpt = &dbgcom->jvmtibrkpt;
140 assert (sysbrk < BEGINUSERBRK);
141 if (jvmtibrkpt->size == jvmtibrkpt->num)
142 breakpointtable_creator();
146 if (jvmtibrkpt->brk[sysbrk].count > 0) {
147 jvmtibrkpt->brk[sysbrk].count++;
148 mutex_unlock(&dbgcomlock);
151 dbgcom->addbrkpt = true;
152 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
154 /* remove breakpoint*/
155 if ((jvmtibrkpt->brk[sysbrk].count == 1) ) {
156 jvmtibrkpt->brk[sysbrk].count--;
157 /* remove breakpoint */
158 dbgcom->addbrkpt = false;
159 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
161 /* avoid negative counter values */
162 if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
163 mutex_unlock(&dbgcomlock);
167 mutex_unlock(&dbgcomlock);
168 /* call cacaodbgserver */
169 __asm__ ("setsysbrkpt:");
174 /* jvmti_add_breakpoint *******************************************************
176 adds a breakpoint to breakpoint table and calls set breakpoint
178 *******************************************************************************/
180 void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
181 struct brkpts *jvmtibrkpt;
183 mutex_lock(&dbgcomlock);
184 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
186 if (jvmtibrkpt->size == jvmtibrkpt->num)
187 breakpointtable_creator();
189 assert (jvmtibrkpt->size > jvmtibrkpt->num);
190 fprintf (stderr,"add brk add: %p\n",addr);
191 jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
192 jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
193 jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
195 /* todo: set breakpoint */
196 /* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
198 mutex_unlock(&dbgcomlock);
200 fprintf (stderr,"add brk done\n");
206 /* jvmti_cacaodbgserver_quit **************************************************
208 quits cacaodbgserver if the last jvmti environment gets disposed
210 *******************************************************************************/
211 void jvmti_cacaodbgserver_quit(){
212 mutex_lock(&dbgcomlock);
214 if (dbgcom->running == 0) {
215 __asm__ ("cacaodbgserver_quit:");
217 /* get cacaodbserver exit */
221 mutex_unlock(&dbgcomlock);
226 /* jvmti_cacao_generic_breakpointhandler **************************************
228 convert cacao breakpoints in jvmti events and fire event
230 *******************************************************************************/
232 static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
233 genericEventData data;
237 data.ev=JVMTI_EVENT_THREAD_START;
240 data.ev=JVMTI_EVENT_THREAD_END;
243 data.ev=JVMTI_EVENT_CLASS_LOAD;
246 data.ev=JVMTI_EVENT_CLASS_PREPARE;
248 case CLASSFILELOADHOOKBRK:
249 data.ev=JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
251 case COMPILEDMETHODLOADBRK:
252 data.ev=JVMTI_EVENT_COMPILED_METHOD_LOAD;
254 case COMPILEDMETHODUNLOADBRK:
255 data.ev=JVMTI_EVENT_COMPILED_METHOD_UNLOAD;
258 fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
261 jvmti_fireEvent(&data);
266 /* jvmti_cacao_debug_init ***************************************************************
268 starts up a new cacaodbgserver process if needed
270 *******************************************************************************/
272 void jvmti_cacao_debug_init() {
275 /* start new cacaodbgserver if needed*/
276 mutex_lock(&dbgcomlock);
277 if (dbgcom == NULL) {
278 dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
282 breakpointtable_creator();
283 /* set addresses of hard coded TRAPs */
284 __asm__ ("movl $setsysbrkpt,%0;"
285 :"=m"(dbgcom->jvmtibrkpt.brk[SETSYSBRKPT].addr));
286 __asm__ ("movl $cacaodbgserver_quit,%0;"
287 :"=m"(dbgcom->jvmtibrkpt.brk[CACAODBGSERVERQUIT].addr));
290 if (dbgserver == (-1)) {
291 log_text("cacaodbgserver fork error");
294 if (dbgserver == 0) {
295 if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
296 log_text("unable to execute cacaodbgserver");
301 mutex_unlock(&dbgcomlock);
302 /* let cacaodbgserver get ready */
306 mutex_unlock(&dbgcomlock);
311 /* jvmti_ClassFileLoadHook ****************************************************
313 prepares firing a new Class File Load Hook event
315 *******************************************************************************/
317 void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
318 unsigned char* class_data,
319 java_objectheader* loader,
320 java_objectheader* protection_domain,
321 jint* new_class_data_len,
322 unsigned char** new_class_data) {
325 d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
326 d.klass = NULL; /* class is not redefined */
328 d.name = (char*)MNEW(char,(utf_bytes(name)+1));
329 utf_sprint_convert_to_latin1(d.name, name);
330 d.protection_domain = protection_domain;
331 d.class_data = class_data;
332 d.jint1 = class_data_len;
333 d.new_class_data_len = new_class_data_len;
334 d.new_class_data = new_class_data;
337 MFREE(d.name,char,utf_bytes(name)+1);
341 /* jvmti_ClassFileLoadHook ****************************************************
343 prepares firing a new Class Prepare or Load event
345 *******************************************************************************/
347 void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
351 d.ev = JVMTI_EVENT_CLASS_PREPARE;
353 d.ev = JVMTI_EVENT_CLASS_LOAD;
360 /* jvmti_MonitorContendedEntering *********************************************
362 prepares firing a new Monitor Contended Enter or Entered event
364 *******************************************************************************/
366 void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
370 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
372 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
379 /* jvmti_MonitorWaiting ******************************************************
381 prepares firing a new Monitor Wait or Waited event
383 *******************************************************************************/
385 void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
389 d.ev = JVMTI_EVENT_MONITOR_WAIT;
392 d.ev = JVMTI_EVENT_MONITOR_WAITED;
401 /* jvmti_ThreadStartEnd ********************************************************
403 prepares firing a new Thread Start or End event
405 *******************************************************************************/
407 void jvmti_ThreadStartEnd(jvmtiEvent ev) {
414 /* jvmti_NativeMethodBind *****************************************************
416 prepares firing a new Native Method Bind event
418 *******************************************************************************/
420 void jvmti_NativeMethodBind(jmethodID method, void* address,
421 void** new_address_ptr) {
424 d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
427 d.new_address_ptr = new_address_ptr;
435 * These are local overrides for various environment variables in Emacs.
436 * Please do not remove this and leave it at the end of the file, where
437 * Emacs will automagically detect them.
438 * ---------------------------------------------------------------------
441 * indent-tabs-mode: t
445 * vim:noexpandtab:sw=4:ts=4: