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/thread.h"
38 #include <sys/types.h>
46 /* jvmti_get_all_threads ******************************************************
48 Gets an array of threadobjects of all threads
50 *******************************************************************************/
51 jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
52 threadobject*** threads_ptr) {
54 threadobject *thread, **tthreads;
56 #if defined(ENABLE_THREADS)
57 tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
59 thread = mainthreadobj;
61 if(thread->o.thread != NULL) {
64 /* count and copy only live threads */
66 MREALLOC(tthreads,threadobject*,cnt,cnt+8);
72 thread = thread->prev;
74 /* repeat until we got the pointer to the mainthread twice */
75 } while (mainthreadobj != thread);
79 *threads_count_ptr = i;
80 *threads_ptr = tthreads;
82 return JVMTI_ERROR_NONE;
84 return JVMTI_ERROR_NOT_AVAILABLE;
89 /* jvmti_get_current_thread ***************************************************
91 Get jthread structure of current thread.
93 *******************************************************************************/
94 jthread jvmti_get_current_thread() {
95 return (jthread)(thread_get_current)->o.thread;
100 /* breakpointtable_creator ***************************************************
102 helper function to enlarge the breakpoint table if needed
104 *******************************************************************************/
106 static void breakpointtable_creator() {
108 struct brkpts *jvmtibrkpt;
110 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
111 if (jvmtibrkpt->size == 0) {
112 jvmtibrkpt->brk = MNEW(struct _brkpt, 16);
113 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*16);
114 jvmtibrkpt->size = 16;
115 jvmtibrkpt->num = BEGINUSERBRK;
117 jvmtibrkpt->size += 16;
118 tmp = jvmtibrkpt->brk;
119 jvmtibrkpt->brk = MNEW(struct _brkpt, jvmtibrkpt->size);
120 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*(jvmtibrkpt->size));
121 memcpy((void*)jvmtibrkpt->brk,(void*)tmp,jvmtibrkpt->size);
122 MFREE(tmp,struct _brkpt,jvmtibrkpt->size-16);
127 /* jvmti_set_system_breakpoint ************************************************
129 sets a system breakpoint in breakpoint table and calls set breakpoint
131 *******************************************************************************/
133 void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
134 struct brkpts *jvmtibrkpt;
136 pthread_mutex_lock(&dbgcomlock);
137 jvmtibrkpt = &dbgcom->jvmtibrkpt;
139 assert (sysbrk < BEGINUSERBRK);
140 if (jvmtibrkpt->size == jvmtibrkpt->num)
141 breakpointtable_creator();
145 if (jvmtibrkpt->brk[sysbrk].count > 0) {
146 jvmtibrkpt->brk[sysbrk].count++;
147 pthread_mutex_unlock(&dbgcomlock);
150 dbgcom->addbrkpt = true;
151 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
153 /* remove breakpoint*/
154 if ((jvmtibrkpt->brk[sysbrk].count == 1) ) {
155 jvmtibrkpt->brk[sysbrk].count--;
156 /* remove breakpoint */
157 dbgcom->addbrkpt = false;
158 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
160 /* avoid negative counter values */
161 if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
162 pthread_mutex_unlock(&dbgcomlock);
166 pthread_mutex_unlock(&dbgcomlock);
167 /* call cacaodbgserver */
168 __asm__ ("setsysbrkpt:");
173 /* jvmti_add_breakpoint *******************************************************
175 adds a breakpoint to breakpoint table and calls set breakpoint
177 *******************************************************************************/
179 void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
180 struct brkpts *jvmtibrkpt;
182 pthread_mutex_lock(&dbgcomlock);
183 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
185 if (jvmtibrkpt->size == jvmtibrkpt->num)
186 breakpointtable_creator();
188 assert (jvmtibrkpt->size > jvmtibrkpt->num);
189 fprintf (stderr,"add brk add: %p\n",addr);
190 jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
191 jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
192 jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
194 /* todo: set breakpoint */
195 /* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
197 pthread_mutex_unlock(&dbgcomlock);
199 fprintf (stderr,"add brk done\n");
205 /* jvmti_cacaodbgserver_quit **************************************************
207 quits cacaodbgserver if the last jvmti environment gets disposed
209 *******************************************************************************/
210 void jvmti_cacaodbgserver_quit(){
211 pthread_mutex_lock(&dbgcomlock);
213 if (dbgcom->running == 0) {
214 __asm__ ("cacaodbgserver_quit:");
216 /* get cacaodbserver exit */
220 pthread_mutex_unlock(&dbgcomlock);
225 /* jvmti_cacao_generic_breakpointhandler **************************************
227 convert cacao breakpoints in jvmti events and fire event
229 *******************************************************************************/
231 static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
232 genericEventData data;
236 data.ev=JVMTI_EVENT_THREAD_START;
239 data.ev=JVMTI_EVENT_THREAD_END;
242 data.ev=JVMTI_EVENT_CLASS_LOAD;
245 data.ev=JVMTI_EVENT_CLASS_PREPARE;
247 case CLASSFILELOADHOOKBRK:
248 data.ev=JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
250 case COMPILEDMETHODLOADBRK:
251 data.ev=JVMTI_EVENT_COMPILED_METHOD_LOAD;
253 case COMPILEDMETHODUNLOADBRK:
254 data.ev=JVMTI_EVENT_COMPILED_METHOD_UNLOAD;
257 fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
260 jvmti_fireEvent(&data);
265 /* jvmti_cacao_debug_init ***************************************************************
267 starts up a new cacaodbgserver process if needed
269 *******************************************************************************/
271 void jvmti_cacao_debug_init() {
274 /* start new cacaodbgserver if needed*/
275 pthread_mutex_lock(&dbgcomlock);
276 if (dbgcom == NULL) {
277 dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
281 breakpointtable_creator();
282 /* set addresses of hard coded TRAPs */
283 __asm__ ("movl $setsysbrkpt,%0;"
284 :"=m"(dbgcom->jvmtibrkpt.brk[SETSYSBRKPT].addr));
285 __asm__ ("movl $cacaodbgserver_quit,%0;"
286 :"=m"(dbgcom->jvmtibrkpt.brk[CACAODBGSERVERQUIT].addr));
289 if (dbgserver == (-1)) {
290 log_text("cacaodbgserver fork error");
293 if (dbgserver == 0) {
294 if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
295 log_text("unable to execute cacaodbgserver");
300 pthread_mutex_unlock(&dbgcomlock);
301 /* let cacaodbgserver get ready */
305 pthread_mutex_unlock(&dbgcomlock);
310 /* jvmti_ClassFileLoadHook ****************************************************
312 prepares firing a new Class File Load Hook event
314 *******************************************************************************/
316 void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
317 unsigned char* class_data,
318 java_objectheader* loader,
319 java_objectheader* protection_domain,
320 jint* new_class_data_len,
321 unsigned char** new_class_data) {
324 d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
325 d.klass = NULL; /* class is not redefined */
327 d.name = (char*)MNEW(char,(utf_bytes(name)+1));
328 utf_sprint_convert_to_latin1(d.name, name);
329 d.protection_domain = protection_domain;
330 d.class_data = class_data;
331 d.jint1 = class_data_len;
332 d.new_class_data_len = new_class_data_len;
333 d.new_class_data = new_class_data;
336 MFREE(d.name,char,utf_bytes(name)+1);
340 /* jvmti_ClassFileLoadHook ****************************************************
342 prepares firing a new Class Prepare or Load event
344 *******************************************************************************/
346 void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
350 d.ev = JVMTI_EVENT_CLASS_PREPARE;
352 d.ev = JVMTI_EVENT_CLASS_LOAD;
359 /* jvmti_MonitorContendedEntering *********************************************
361 prepares firing a new Monitor Contended Enter or Entered event
363 *******************************************************************************/
365 void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
369 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
371 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
378 /* jvmti_MonitorWaiting ******************************************************
380 prepares firing a new Monitor Wait or Waited event
382 *******************************************************************************/
384 void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
388 d.ev = JVMTI_EVENT_MONITOR_WAIT;
391 d.ev = JVMTI_EVENT_MONITOR_WAITED;
400 /* jvmti_ThreadStartEnd ********************************************************
402 prepares firing a new Thread Start or End event
404 *******************************************************************************/
406 void jvmti_ThreadStartEnd(jvmtiEvent ev) {
413 /* jvmti_NativeMethodBind *****************************************************
415 prepares firing a new Native Method Bind event
417 *******************************************************************************/
419 void jvmti_NativeMethodBind(jmethodID method, void* address,
420 void** new_address_ptr) {
423 d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
426 d.new_address_ptr = new_address_ptr;
434 * These are local overrides for various environment variables in Emacs.
435 * Please do not remove this and leave it at the end of the file, where
436 * Emacs will automagically detect them.
437 * ---------------------------------------------------------------------
440 * indent-tabs-mode: t
444 * vim:noexpandtab:sw=4:ts=4: