CACAO
cacaodbg.c
Go to the documentation of this file.
1 /* src/native/jvmti/cacaodbg.c - contains entry points for debugging support
2  in cacao.
3 
4  Copyright (C) 1996-2013
5  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 
7  This file is part of CACAO.
8 
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.
13 
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.
18 
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
22  02111-1307, USA.
23 
24 */
25 
26 #include "native/jvmti/jvmti.h"
27 #include "native/jvmti/cacaodbg.h"
28 #include "native/jvmti/dbg.h"
29 #include "vm/vm.hpp"
30 #include "vm/loader.hpp"
31 #include "vm/exceptions.hpp"
32 #include "vm/jit/builtin.hpp"
33 #include "vm/jit/asmpart.hpp"
34 #include "vm/string.hpp"
35 #include "toolbox/logging.hpp"
36 #include "threads/mutex.h"
37 #include "threads/thread.hpp"
38 
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <signal.h>
42 #include <stdlib.h>
43 #include <assert.h>
44 #include <sys/wait.h>
45 
46 
47 /* jvmti_get_all_threads ******************************************************
48 
49  Gets an array of threadobjects of all threads
50 
51 *******************************************************************************/
52 jvmtiError jvmti_get_all_threads (jint * threads_count_ptr,
53  threadobject*** threads_ptr) {
54  int i = 0, cnt = 8;
55  threadobject *thread, **tthreads;
56 
57 #if defined(ENABLE_THREADS)
58  tthreads = MNEW(threadobject*, (sizeof(threadobject*) * cnt));
59 
60  thread = mainthreadobj;
61  do {
62  if(thread->o.thread != NULL) {
63  fflush(stderr);
64 
65  /* count and copy only live threads */
66  if (i>=cnt) {
67  MREALLOC(tthreads,threadobject*,cnt,cnt+8);
68  cnt += 8;
69  }
70  tthreads[i] = thread;
71  i++;
72  }
73  thread = thread->prev;
74 
75  /* repeat until we got the pointer to the mainthread twice */
76  } while (mainthreadobj != thread);
77 
78  fflush(stderr);
79 
80  *threads_count_ptr = i;
81  *threads_ptr = tthreads;
82 
83  return JVMTI_ERROR_NONE;
84 #else
86 #endif
87 }
88 
89 
90 /* jvmti_get_current_thread ***************************************************
91 
92  Get jthread structure of current thread.
93 
94 *******************************************************************************/
96  return (jthread)(thread_get_current)->o.thread;
97 }
98 
99 
100 
101 /* breakpointtable_creator ***************************************************
102 
103  helper function to enlarge the breakpoint table if needed
104 
105 *******************************************************************************/
106 
107 static void breakpointtable_creator() {
108  struct _brkpt* tmp;
109  struct brkpts *jvmtibrkpt;
110 
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;
117  } else {
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);
124  }
125 }
126 
127 
128 /* jvmti_set_system_breakpoint ************************************************
129 
130  sets a system breakpoint in breakpoint table and calls set breakpoint
131 
132 *******************************************************************************/
133 
134 void jvmti_set_system_breakpoint(int sysbrk, bool mode) {
135  struct brkpts *jvmtibrkpt;
136 
137  mutex_lock(&dbgcomlock);
138  jvmtibrkpt = &dbgcom->jvmtibrkpt;
139 
140  assert (sysbrk < BEGINUSERBRK);
141  if (jvmtibrkpt->size == jvmtibrkpt->num)
143 
144  if (mode) {
145  /* add breakpoint*/
146  if (jvmtibrkpt->brk[sysbrk].count > 0) {
147  jvmtibrkpt->brk[sysbrk].count++;
148  mutex_unlock(&dbgcomlock);
149  return;
150  }
151  dbgcom->addbrkpt = true;
152  dbgcom->brkaddr = jvmtibrkpt->brk[sysbrk].addr;
153  } else {
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;
160  } else {
161  /* avoid negative counter values */
162  if (jvmtibrkpt->brk[sysbrk].count > 0) jvmtibrkpt->brk[sysbrk].count--;
163  mutex_unlock(&dbgcomlock);
164  return;
165  }
166  }
167  mutex_unlock(&dbgcomlock);
168  /* call cacaodbgserver */
169  __asm__ ("setsysbrkpt:");
170  TRAP;
171 }
172 
173 
174 /* jvmti_add_breakpoint *******************************************************
175 
176  adds a breakpoint to breakpoint table and calls set breakpoint
177 
178 *******************************************************************************/
179 
180 void jvmti_add_breakpoint(void* addr, jmethodID method, jlocation location) {
181  struct brkpts *jvmtibrkpt;
182 
183  mutex_lock(&dbgcomlock);
184  jvmtibrkpt = &dbgcom->jvmtibrkpt;;
185 
186  if (jvmtibrkpt->size == jvmtibrkpt->num)
188 
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;
194 
195  /* todo: set breakpoint */
196 /* jvmtibrkpt.brk[jvmtibrkpt.num].orig = */
197  jvmtibrkpt->num++;
198  mutex_unlock(&dbgcomlock);
199 
200  fprintf (stderr,"add brk done\n");
201 }
202 
203 
204 
205 
206 /* jvmti_cacaodbgserver_quit **************************************************
207 
208  quits cacaodbgserver if the last jvmti environment gets disposed
209 
210 *******************************************************************************/
212  mutex_lock(&dbgcomlock);
213  dbgcom->running--;
214  if (dbgcom->running == 0) {
215  __asm__ ("cacaodbgserver_quit:");
216  TRAP;
217  /* get cacaodbserver exit */
218  wait(NULL);
219  dbgcom = NULL;
220  }
221  mutex_unlock(&dbgcomlock);
222 }
223 
224 
225 
226 /* jvmti_cacao_generic_breakpointhandler **************************************
227 
228  convert cacao breakpoints in jvmti events and fire event
229 
230 *******************************************************************************/
231 
232 static void jvmti_cacao_generic_breakpointhandler(int kindofbrk){
233  genericEventData data;
234 
235  switch (kindofbrk) {
236  case THREADSTARTBRK:
238  break;
239  case THREADENDBRK:
241  break;
242  case CLASSLOADBRK:
244  break;
245  case CLASSPREPARERK:
247  break;
250  break;
253  break;
256  break;
257  default:
258  fprintf(stderr,"unhandled kind of cacao break %d\n",kindofbrk);
259  return;
260  }
261  jvmti_fireEvent(&data);
262 }
263 
264 
265 
266 /* jvmti_cacao_debug_init ***************************************************************
267 
268  starts up a new cacaodbgserver process if needed
269 
270 *******************************************************************************/
271 
273  pid_t dbgserver;
274 
275  /* start new cacaodbgserver if needed*/
276  mutex_lock(&dbgcomlock);
277  if (dbgcom == NULL) {
278  dbgcom = heap_allocate(sizeof(cacaodbgcommunication),true,NULL);
279  dbgcom->running = 1;
280  jvmti = true;
281 
283  /* set addresses of hard coded TRAPs */
284  __asm__ ("movl $setsysbrkpt,%0;"
286  __asm__ ("movl $cacaodbgserver_quit,%0;"
288 
289  dbgserver = fork();
290  if (dbgserver == (-1)) {
291  log_text("cacaodbgserver fork error");
292  exit(1);
293  } else {
294  if (dbgserver == 0) {
295  if (execlp("cacaodbgserver","cacaodbgserver",(char *) NULL) == -1) {
296  log_text("unable to execute cacaodbgserver");
297  exit(1);
298  }
299  }
300  }
301  mutex_unlock(&dbgcomlock);
302  /* let cacaodbgserver get ready */
303  sleep(1);
304  } else {
305  dbgcom->running++;
306  mutex_unlock(&dbgcomlock);
307  }
308 }
309 
310 
311 /* jvmti_ClassFileLoadHook ****************************************************
312 
313  prepares firing a new Class File Load Hook event
314 
315 *******************************************************************************/
316 
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) {
324 
326  d.klass = NULL; /* class is not redefined */
327  d.object = loader;
328  d.name = (char*)MNEW(char,(UTF_SIZE(name)+1));
332  d.jint1 = class_data_len;
335 
336  jvmti_fireEvent(&d);
337  MFREE(d.name,char,UTF_SIZE(name)+1);
338 }
339 
340 
341 /* jvmti_ClassFileLoadHook ****************************************************
342 
343  prepares firing a new Class Prepare or Load event
344 
345 *******************************************************************************/
346 
347 void jvmti_ClassLoadPrepare(bool prepared, classinfo *c) {
349 
350  if (prepared)
352  else
354 
355  d.klass = c;
356  jvmti_fireEvent(&d);
357 }
358 
359 
360 /* jvmti_MonitorContendedEntering *********************************************
361 
362  prepares firing a new Monitor Contended Enter or Entered event
363 
364 *******************************************************************************/
365 
366 void jvmti_MonitorContendedEntering(bool entered, jobject obj) {
368 
369  if (entered)
371  else
373 
374  d.object = obj;
375 
376  jvmti_fireEvent(&d);
377 }
378 
379 /* jvmti_MonitorWaiting ******************************************************
380 
381  prepares firing a new Monitor Wait or Waited event
382 
383 *******************************************************************************/
384 
385 void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout) {
387 
388  if (wait) {
390  d.jlong = timeout;
391  } else {
393  d.b = timeout != 0;
394  }
395 
396  d.object = obj;
397 
398  jvmti_fireEvent(&d);
399 }
400 
401 /* jvmti_ThreadStartEnd ********************************************************
402 
403  prepares firing a new Thread Start or End event
404 
405 *******************************************************************************/
406 
409 
410  d.ev = ev;
411  jvmti_fireEvent(&d);
412 }
413 
414 /* jvmti_NativeMethodBind *****************************************************
415 
416  prepares firing a new Native Method Bind event
417 
418 *******************************************************************************/
419 
420 void jvmti_NativeMethodBind(jmethodID method, void* address,
421  void** new_address_ptr) {
423 
425  d.method = method;
426  d.address = address;
428 
429  jvmti_fireEvent(&d);
430 }
431 
432 
433 
434 /*
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  * ---------------------------------------------------------------------
439  * Local variables:
440  * mode: c
441  * indent-tabs-mode: t
442  * c-basic-offset: 4
443  * tab-width: 4
444  * End:
445  * vim:noexpandtab:sw=4:ts=4:
446  */
mutex_t dbgcomlock
Definition: jvmti.c:79
jboolean b
Definition: cacaodbg.h:47
#define CLASSLOADBRK
Definition: cacaodbg.h:82
void jvmti_add_breakpoint(void *addr, jmethodID method, jlocation location)
Definition: cacaodbg.c:180
jobject object
Definition: cacaodbg.h:43
JNIEnv jclass jobject const char jobject protection_domain
Definition: jvmti.h:312
struct _brkpt * brk
Definition: cacaodbg.h:99
void jvmti_cacaodbgserver_quit()
Definition: cacaodbg.c:211
int size
Definition: cacaodbg.h:101
void jvmti_ThreadStartEnd(jvmtiEvent ev)
Definition: cacaodbg.c:407
#define CLASSFILELOADHOOKBRK
Definition: cacaodbg.h:84
void jvmti_ClassLoadPrepare(bool prepared, classinfo *c)
Definition: cacaodbg.c:347
JNIEnv jthread jmethodID void void ** new_address_ptr
Definition: jvmti.h:264
struct brkpts jvmtibrkpt
Definition: cacaodbg.h:109
bool jvmti
Definition: cacaodbg.h:114
void jvmti_ClassFileLoadHook(utf *name, int class_data_len, unsigned char *class_data, java_objectheader *loader, java_objectheader *protection_domain, jint *new_class_data_len, unsigned char **new_class_data)
Definition: cacaodbg.c:317
#define UTF_SIZE(u)
Definition: utf8.hpp:251
jclass klass
Definition: cacaodbg.h:42
unsigned char * class_data
Definition: cacaodbg.h:56
void * address
Definition: cacaodbg.h:48
jmethodID method
Definition: cacaodbg.h:91
JNIEnv jclass jobject const char * name
Definition: jvmti.h:312
JNIEnv jthread jobject jlong timeout
Definition: jvmti.h:373
void ** new_address_ptr
Definition: cacaodbg.h:49
jthread jvmti_get_current_thread()
Definition: cacaodbg.c:95
#define COMPILEDMETHODUNLOADBRK
Definition: cacaodbg.h:86
void jvmti_MonitorContendedEntering(bool entered, jobject obj)
Definition: cacaodbg.c:366
JNIEnv jclass jobject const char jobject jint class_data_len
Definition: jvmti.h:312
jvmtiError
Definition: jvmti.h:49
void jvmti_fireEvent(genericEventData *data)
Definition: jvmti.c:402
void jvmti_cacao_debug_init()
Definition: cacaodbg.c:272
#define THREADSTARTBRK
Definition: cacaodbg.h:80
JNIEnv jthread jmethodID method
Definition: jvmti.h:207
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
#define THREADENDBRK
Definition: cacaodbg.h:81
int count
Definition: cacaodbg.h:94
jvmtiError jvmti_get_all_threads(jint *threads_count_ptr, threadobject ***threads_ptr)
Definition: cacaodbg.c:52
#define CACAODBGSERVERQUIT
Definition: cacaodbg.h:77
JNIEnv jthread thread
Definition: jvmti.h:207
JNIEnv jthread jmethodID void * address
Definition: jvmti.h:264
MIIterator i
void utf_sprint_convert_to_latin1(char *buffer, Utf8String u)
Definition: utf8.cpp:584
#define BEGINUSERBRK
Definition: cacaodbg.h:87
JNIEnv jclass jobject loader
Definition: jvmti.h:312
JNIEnv jclass jobject const char jobject jint const unsigned char jint unsigned char ** new_class_data
Definition: jvmti.h:312
void jvmti_NativeMethodBind(jmethodID method, void *address, void **new_address_ptr)
Definition: cacaodbg.c:420
#define COMPILEDMETHODLOADBRK
Definition: cacaodbg.h:85
static void jvmti_cacao_generic_breakpointhandler(int kindofbrk)
Definition: cacaodbg.c:232
void * addr
Definition: cacaodbg.h:93
#define CLASSPREPARERK
Definition: cacaodbg.h:83
jlong jlocation
Definition: jvmti.h:44
jvmtiEvent
Definition: jvmti.h:635
static threadobject * thread_get_current()
Return the threadobject for the current thread.
Definition: thread-none.hpp:56
jint * new_class_data_len
Definition: cacaodbg.h:57
int num
Definition: cacaodbg.h:100
#define MNEW(type, num)
Definition: memory.hpp:96
static void breakpointtable_creator()
Definition: cacaodbg.c:107
unsigned char ** new_class_data
Definition: cacaodbg.h:58
jvmtiEvent ev
Definition: cacaodbg.h:37
void jvmti_set_system_breakpoint(int sysbrk, bool mode)
Definition: cacaodbg.c:134
jlocation location
Definition: cacaodbg.h:92
#define MREALLOC(ptr, type, num1, num2)
Definition: memory.hpp:99
JNIEnv jclass jobject const char jobject jint const unsigned char jint * new_class_data_len
Definition: jvmti.h:312
JNIEnv jthread jmethodID jlocation location
Definition: jvmti.h:207
#define SETSYSBRKPT
Definition: cacaodbg.h:76
JNIEnv jclass jobject const char jobject jint const unsigned char * class_data
Definition: jvmti.h:312
void jvmti_MonitorWaiting(bool wait, jobject obj, jlong timeout)
Definition: cacaodbg.c:385
#define log_text(s)
Definition: logging.hpp:170
cacaodbgcommunication * dbgcom
Definition: cacaodbg.h:112
#define MFREE(ptr, type, num)
Definition: memory.hpp:97
jobject protection_domain
Definition: cacaodbg.h:53
jmethodID method
Definition: cacaodbg.h:40