1 /* src/native/jvmti/cacaodbg.c - contains entry points for debugging support
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
30 Changes: Edwin Steiner
33 $Id: cacao.c,v 3.165 2006/01/03 23:44:38 twisti Exp $
37 #include "native/jvmti/jvmti.h"
38 #include "native/jvmti/cacaodbg.h"
39 #include "native/jvmti/dbg.h"
41 #include "vm/loader.h"
42 #include "vm/exceptions.h"
43 #include "vm/builtin.h"
44 #include "vm/jit/asmpart.h"
45 #include "vm/stringlocal.h"
46 #include "toolbox/logging.h"
47 #include "threads/native/threads.h"
49 #include <sys/types.h>
57 /* jvmti_get_all_threads ******************************************************
59 Gets an array of threadobjects of all threads
61 *******************************************************************************/
62 jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
63 threadobject*** threads_ptr) {
65 threadobject *thread, **tthreads;
67 #if defined(ENABLE_THREADS)
68 tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
70 thread = mainthreadobj;
72 if(thread->o.thread != NULL) {
75 /* count and copy only live threads */
77 MREALLOC(tthreads,threadobject*,cnt,cnt+8);
83 thread = thread->prev;
85 /* repeat until we got the pointer to the mainthread twice */
86 } while (mainthreadobj != thread);
90 *threads_count_ptr = i;
91 *threads_ptr = tthreads;
93 return JVMTI_ERROR_NONE;
95 return JVMTI_ERROR_NOT_AVAILABLE;
100 /* jvmti_get_current_thread ***************************************************
102 Get jthread structure of current thread.
104 *******************************************************************************/
105 jthread jvmti_get_current_thread() {
106 return (jthread)(threads_get_current_threadobject())->o.thread;
111 /* breakpointtable_creator ***************************************************
113 helper function to enlarge the breakpoint table if needed
115 *******************************************************************************/
117 static void breakpointtable_creator() {
119 struct brkpts *jvmtibrkpt;
121 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
122 if (jvmtibrkpt->size == 0) {
123 jvmtibrkpt->brk = MNEW(struct _brkpt, 16);
124 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*16);
125 jvmtibrkpt->size = 16;
126 jvmtibrkpt->num = BEGINUSERBRK;
128 jvmtibrkpt->size += 16;
129 tmp = jvmtibrkpt->brk;
130 jvmtibrkpt->brk = MNEW(struct _brkpt, jvmtibrkpt->size);
131 memset(jvmtibrkpt->brk, 0, sizeof(struct _brkpt)*(jvmtibrkpt->size));
132 memcpy((void*)jvmtibrkpt->brk,(void*)tmp,jvmtibrkpt->size);
133 MFREE(tmp,struct _brkpt,jvmtibrkpt->size-16);
138 /* jvmti_set_system_breakpoint ************************************************
140 sets a system breakpoint in breakpoint table and calls set breakpoint
142 *******************************************************************************/
144 void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
145 struct brkpts *jvmtibrkpt;
147 pthread_mutex_lock(&dbgcomlock);
148 jvmtibrkpt = &dbgcom->jvmtibrkpt;
150 assert (sysbrk < BEGINUSERBRK);
151 if (jvmtibrkpt->size == jvmtibrkpt->num)
152 breakpointtable_creator();
156 if (jvmtibrkpt->brk[sysbrk].count > 0) {
157 jvmtibrkpt->brk[sysbrk].count++;
158 pthread_mutex_unlock(&dbgcomlock);
161 dbgcom->addbrkpt = true;
162 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
164 /* remove breakpoint*/
165 if ((jvmtibrkpt->brk[sysbrk].count == 1) ) {
166 jvmtibrkpt->brk[sysbrk].count--;
167 /* remove breakpoint */
168 dbgcom->addbrkpt = false;
169 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
171 /* avoid negative counter values */
172 if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
173 pthread_mutex_unlock(&dbgcomlock);
177 pthread_mutex_unlock(&dbgcomlock);
178 /* call cacaodbgserver */
179 __asm__ ("setsysbrkpt:");
184 /* jvmti_add_breakpoint *******************************************************
186 adds a breakpoint to breakpoint table and calls set breakpoint
188 *******************************************************************************/
190 void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
191 struct brkpts *jvmtibrkpt;
193 pthread_mutex_lock(&dbgcomlock);
194 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
196 if (jvmtibrkpt->size == jvmtibrkpt->num)
197 breakpointtable_creator();
199 assert (jvmtibrkpt->size > jvmtibrkpt->num);
200 fprintf (stderr,"add brk add: %p\n",addr);
201 jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
202 jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
203 jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
205 /* todo: set breakpoint */
206 /* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
208 pthread_mutex_unlock(&dbgcomlock);
210 fprintf (stderr,"add brk done\n");
216 /* jvmti_cacaodbgserver_quit **************************************************
218 quits cacaodbgserver if the last jvmti environment gets disposed
220 *******************************************************************************/
221 void jvmti_cacaodbgserver_quit(){
222 pthread_mutex_lock(&dbgcomlock);
224 if (dbgcom->running == 0) {
225 __asm__ ("cacaodbgserver_quit:");
227 /* get cacaodbserver exit */
231 pthread_mutex_unlock(&dbgcomlock);
236 /* jvmti_cacao_generic_breakpointhandler **************************************
238 convert cacao breakpoints in jvmti events and fire event
240 *******************************************************************************/
242 static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
243 genericEventData data;
247 data.ev=JVMTI_EVENT_THREAD_START;
250 data.ev=JVMTI_EVENT_THREAD_END;
253 data.ev=JVMTI_EVENT_CLASS_LOAD;
256 data.ev=JVMTI_EVENT_CLASS_PREPARE;
258 case CLASSFILELOADHOOKBRK:
259 data.ev=JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
261 case COMPILEDMETHODLOADBRK:
262 data.ev=JVMTI_EVENT_COMPILED_METHOD_LOAD;
264 case COMPILEDMETHODUNLOADBRK:
265 data.ev=JVMTI_EVENT_COMPILED_METHOD_UNLOAD;
268 fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
271 jvmti_fireEvent(&data);
276 /* jvmti_cacao_debug_init ***************************************************************
278 starts up a new cacaodbgserver process if needed
280 *******************************************************************************/
282 void jvmti_cacao_debug_init() {
285 /* start new cacaodbgserver if needed*/
286 pthread_mutex_lock(&dbgcomlock);
287 if (dbgcom == NULL) {
288 dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
292 breakpointtable_creator();
293 /* set addresses of hard coded TRAPs */
294 __asm__ ("movl $setsysbrkpt,%0;"
295 :"=m"(dbgcom->jvmtibrkpt.brk[SETSYSBRKPT].addr));
296 __asm__ ("movl $cacaodbgserver_quit,%0;"
297 :"=m"(dbgcom->jvmtibrkpt.brk[CACAODBGSERVERQUIT].addr));
300 if (dbgserver == (-1)) {
301 log_text("cacaodbgserver fork error");
304 if (dbgserver == 0) {
305 if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
306 log_text("unable to execute cacaodbgserver");
311 pthread_mutex_unlock(&dbgcomlock);
312 /* let cacaodbgserver get ready */
316 pthread_mutex_unlock(&dbgcomlock);
321 /* jvmti_ClassFileLoadHook ****************************************************
323 prepares firing a new Class File Load Hook event
325 *******************************************************************************/
327 void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
328 unsigned char* class_data,
329 java_objectheader* loader,
330 java_objectheader* protection_domain,
331 jint* new_class_data_len,
332 unsigned char** new_class_data) {
335 d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
336 d.klass = NULL; /* class is not redefined */
338 d.name = (char*)MNEW(char,(utf_bytes(name)+1));
339 utf_sprint_convert_to_latin1(d.name, name);
340 d.protection_domain = protection_domain;
341 d.class_data = class_data;
342 d.jint1 = class_data_len;
343 d.new_class_data_len = new_class_data_len;
344 d.new_class_data = new_class_data;
347 MFREE(d.name,char,utf_bytes(name)+1);
351 /* jvmti_ClassFileLoadHook ****************************************************
353 prepares firing a new Class Prepare or Load event
355 *******************************************************************************/
357 void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
361 d.ev = JVMTI_EVENT_CLASS_PREPARE;
363 d.ev = JVMTI_EVENT_CLASS_LOAD;
370 /* jvmti_MonitorContendedEntering *********************************************
372 prepares firing a new Monitor Contended Enter or Entered event
374 *******************************************************************************/
376 void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
380 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
382 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
389 /* jvmti_MonitorWaiting ******************************************************
391 prepares firing a new Monitor Wait or Waited event
393 *******************************************************************************/
395 void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
399 d.ev = JVMTI_EVENT_MONITOR_WAIT;
402 d.ev = JVMTI_EVENT_MONITOR_WAITED;
411 /* jvmti_ThreadStartEnd ********************************************************
413 prepares firing a new Thread Start or End event
415 *******************************************************************************/
417 void jvmti_ThreadStartEnd(jvmtiEvent ev) {
424 /* jvmti_NativeMethodBind *****************************************************
426 prepares firing a new Native Method Bind event
428 *******************************************************************************/
430 void jvmti_NativeMethodBind(jmethodID method, void* address,
431 void** new_address_ptr) {
434 d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
437 d.new_address_ptr = new_address_ptr;
445 * These are local overrides for various environment variables in Emacs.
446 * Please do not remove this and leave it at the end of the file, where
447 * Emacs will automagically detect them.
448 * ---------------------------------------------------------------------
451 * indent-tabs-mode: t
455 * vim:noexpandtab:sw=4:ts=4: