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
36 #include "native/jvmti/jvmti.h"
37 #include "native/jvmti/cacaodbg.h"
38 #include "native/jvmti/dbg.h"
40 #include "vm/loader.h"
41 #include "vm/exceptions.h"
42 #include "vm/builtin.h"
43 #include "vm/jit/asmpart.h"
44 #include "vm/stringlocal.h"
45 #include "toolbox/logging.h"
46 #include "threads/native/threads.h"
48 #include <sys/types.h>
56 /* jvmti_get_all_threads ******************************************************
58 Gets an array of threadobjects of all threads
60 *******************************************************************************/
61 jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
62 threadobject*** threads_ptr) {
64 threadobject *thread, **tthreads;
66 #if defined(ENABLE_THREADS)
67 tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
69 thread = mainthreadobj;
71 if(thread->o.thread != NULL) {
74 /* count and copy only live threads */
76 MREALLOC(tthreads,threadobject*,cnt,cnt+8);
82 thread = thread->prev;
84 /* repeat until we got the pointer to the mainthread twice */
85 } while (mainthreadobj != thread);
89 *threads_count_ptr = i;
90 *threads_ptr = tthreads;
92 return JVMTI_ERROR_NONE;
94 return JVMTI_ERROR_NOT_AVAILABLE;
99 /* jvmti_get_current_thread ***************************************************
101 Get jthread structure of current thread.
103 *******************************************************************************/
104 jthread jvmti_get_current_thread() {
105 return (jthread)(threads_get_current_threadobject())->o.thread;
110 /* breakpointtable_creator ***************************************************
112 helper function to enlarge the breakpoint table if needed
114 *******************************************************************************/
116 static void breakpointtable_creator() {
118 struct brkpts *jvmtibrkpt;
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;
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);
137 /* jvmti_set_system_breakpoint ************************************************
139 sets a system breakpoint in breakpoint table and calls set breakpoint
141 *******************************************************************************/
143 void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
144 struct brkpts *jvmtibrkpt;
146 pthread_mutex_lock(&dbgcomlock);
147 jvmtibrkpt = &dbgcom->jvmtibrkpt;
149 assert (sysbrk < BEGINUSERBRK);
150 if (jvmtibrkpt->size == jvmtibrkpt->num)
151 breakpointtable_creator();
155 if (jvmtibrkpt->brk[sysbrk].count > 0) {
156 jvmtibrkpt->brk[sysbrk].count++;
157 pthread_mutex_unlock(&dbgcomlock);
160 dbgcom->addbrkpt = true;
161 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
163 /* remove breakpoint*/
164 if ((jvmtibrkpt->brk[sysbrk].count == 1) ) {
165 jvmtibrkpt->brk[sysbrk].count--;
166 /* remove breakpoint */
167 dbgcom->addbrkpt = false;
168 dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
170 /* avoid negative counter values */
171 if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
172 pthread_mutex_unlock(&dbgcomlock);
176 pthread_mutex_unlock(&dbgcomlock);
177 /* call cacaodbgserver */
178 __asm__ ("setsysbrkpt:");
183 /* jvmti_add_breakpoint *******************************************************
185 adds a breakpoint to breakpoint table and calls set breakpoint
187 *******************************************************************************/
189 void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
190 struct brkpts *jvmtibrkpt;
192 pthread_mutex_lock(&dbgcomlock);
193 jvmtibrkpt = &dbgcom->jvmtibrkpt;;
195 if (jvmtibrkpt->size == jvmtibrkpt->num)
196 breakpointtable_creator();
198 assert (jvmtibrkpt->size > jvmtibrkpt->num);
199 fprintf (stderr,"add brk add: %p\n",addr);
200 jvmtibrkpt->brk[jvmtibrkpt->num].addr = addr;
201 jvmtibrkpt->brk[jvmtibrkpt->num].method = method;
202 jvmtibrkpt->brk[jvmtibrkpt->num].location = location;
204 /* todo: set breakpoint */
205 /* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
207 pthread_mutex_unlock(&dbgcomlock);
209 fprintf (stderr,"add brk done\n");
215 /* jvmti_cacaodbgserver_quit **************************************************
217 quits cacaodbgserver if the last jvmti environment gets disposed
219 *******************************************************************************/
220 void jvmti_cacaodbgserver_quit(){
221 pthread_mutex_lock(&dbgcomlock);
223 if (dbgcom->running == 0) {
224 __asm__ ("cacaodbgserver_quit:");
226 /* get cacaodbserver exit */
230 pthread_mutex_unlock(&dbgcomlock);
235 /* jvmti_cacao_generic_breakpointhandler **************************************
237 convert cacao breakpoints in jvmti events and fire event
239 *******************************************************************************/
241 static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
242 genericEventData data;
246 data.ev=JVMTI_EVENT_THREAD_START;
249 data.ev=JVMTI_EVENT_THREAD_END;
252 data.ev=JVMTI_EVENT_CLASS_LOAD;
255 data.ev=JVMTI_EVENT_CLASS_PREPARE;
257 case CLASSFILELOADHOOKBRK:
258 data.ev=JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
260 case COMPILEDMETHODLOADBRK:
261 data.ev=JVMTI_EVENT_COMPILED_METHOD_LOAD;
263 case COMPILEDMETHODUNLOADBRK:
264 data.ev=JVMTI_EVENT_COMPILED_METHOD_UNLOAD;
267 fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
270 jvmti_fireEvent(&data);
275 /* jvmti_cacao_debug_init ***************************************************************
277 starts up a new cacaodbgserver process if needed
279 *******************************************************************************/
281 void jvmti_cacao_debug_init() {
284 /* start new cacaodbgserver if needed*/
285 pthread_mutex_lock(&dbgcomlock);
286 if (dbgcom == NULL) {
287 dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
291 breakpointtable_creator();
292 /* set addresses of hard coded TRAPs */
293 __asm__ ("movl $setsysbrkpt,%0;"
294 :"=m"(dbgcom->jvmtibrkpt.brk[SETSYSBRKPT].addr));
295 __asm__ ("movl $cacaodbgserver_quit,%0;"
296 :"=m"(dbgcom->jvmtibrkpt.brk[CACAODBGSERVERQUIT].addr));
299 if (dbgserver == (-1)) {
300 log_text("cacaodbgserver fork error");
303 if (dbgserver == 0) {
304 if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
305 log_text("unable to execute cacaodbgserver");
310 pthread_mutex_unlock(&dbgcomlock);
311 /* let cacaodbgserver get ready */
315 pthread_mutex_unlock(&dbgcomlock);
320 /* jvmti_ClassFileLoadHook ****************************************************
322 prepares firing a new Class File Load Hook event
324 *******************************************************************************/
326 void jvmti_ClassFileLoadHook(utf* name, int class_data_len,
327 unsigned char* class_data,
328 java_objectheader* loader,
329 java_objectheader* protection_domain,
330 jint* new_class_data_len,
331 unsigned char** new_class_data) {
334 d.ev = JVMTI_EVENT_CLASS_FILE_LOAD_HOOK;
335 d.klass = NULL; /* class is not redefined */
337 d.name = (char*)MNEW(char,(utf_bytes(name)+1));
338 utf_sprint_convert_to_latin1(d.name, name);
339 d.protection_domain = protection_domain;
340 d.class_data = class_data;
341 d.jint1 = class_data_len;
342 d.new_class_data_len = new_class_data_len;
343 d.new_class_data = new_class_data;
346 MFREE(d.name,char,utf_bytes(name)+1);
350 /* jvmti_ClassFileLoadHook ****************************************************
352 prepares firing a new Class Prepare or Load event
354 *******************************************************************************/
356 void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
360 d.ev = JVMTI_EVENT_CLASS_PREPARE;
362 d.ev = JVMTI_EVENT_CLASS_LOAD;
369 /* jvmti_MonitorContendedEntering *********************************************
371 prepares firing a new Monitor Contended Enter or Entered event
373 *******************************************************************************/
375 void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
379 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTERED;
381 d.ev = JVMTI_EVENT_MONITOR_CONTENDED_ENTER;
388 /* jvmti_MonitorWaiting ******************************************************
390 prepares firing a new Monitor Wait or Waited event
392 *******************************************************************************/
394 void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
398 d.ev = JVMTI_EVENT_MONITOR_WAIT;
401 d.ev = JVMTI_EVENT_MONITOR_WAITED;
410 /* jvmti_ThreadStartEnd ********************************************************
412 prepares firing a new Thread Start or End event
414 *******************************************************************************/
416 void jvmti_ThreadStartEnd(jvmtiEvent ev) {
423 /* jvmti_NativeMethodBind *****************************************************
425 prepares firing a new Native Method Bind event
427 *******************************************************************************/
429 void jvmti_NativeMethodBind(jmethodID method, void* address,
430 void** new_address_ptr) {
433 d.ev = JVMTI_EVENT_NATIVE_METHOD_BIND;
436 d.new_address_ptr = new_address_ptr;
444 * These are local overrides for various environment variables in Emacs.
445 * Please do not remove this and leave it at the end of the file, where
446 * Emacs will automagically detect them.
447 * ---------------------------------------------------------------------
450 * indent-tabs-mode: t
454 * vim:noexpandtab:sw=4:ts=4: