blob: fbdc576831bdd0518f5d579dbce0542cee4e0ce9 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26#include <ctype.h>
27
28#include "util.h"
29#include "commonRef.h"
30#include "debugDispatch.h"
31#include "eventHandler.h"
32#include "eventHelper.h"
33#include "threadControl.h"
34#include "stepControl.h"
35#include "transport.h"
36#include "classTrack.h"
37#include "debugLoop.h"
38#include "bag.h"
39#include "invoker.h"
40
41/* How the options get to OnLoad: */
42#define XDEBUG "-Xdebug"
43#define XRUN "-Xrunjdwp"
44#define AGENTLIB "-agentlib:jdwp"
45
46/* Debug version defaults */
47#ifdef DEBUG
48 #define DEFAULT_ASSERT_ON JNI_TRUE
49 #define DEFAULT_ASSERT_FATAL JNI_TRUE
50 #define DEFAULT_LOGFILE "jdwp.log"
51#else
52 #define DEFAULT_ASSERT_ON JNI_FALSE
53 #define DEFAULT_ASSERT_FATAL JNI_FALSE
54 #define DEFAULT_LOGFILE NULL
55#endif
56
57static jboolean vmInitialized;
58static jrawMonitorID initMonitor;
59static jboolean initComplete;
60static jbyte currentSessionID;
61
62/*
63 * Options set through the OnLoad options string. All of these values
64 * are set once at VM startup and never reset.
65 */
66static jboolean isServer = JNI_FALSE; /* Listens for connecting debuggers? */
67static jboolean isStrict = JNI_FALSE; /* Unused */
68static jboolean useStandardAlloc = JNI_FALSE; /* Use standard malloc/free? */
69static struct bag *transports; /* of TransportSpec */
70
71static jboolean initOnStartup = JNI_TRUE; /* init immediately */
72static char *initOnException = NULL; /* init when this exception thrown */
73static jboolean initOnUncaught = JNI_FALSE; /* init when uncaught exc thrown */
74
75static char *launchOnInit = NULL; /* launch this app during init */
76static jboolean suspendOnInit = JNI_TRUE; /* suspend all app threads after init */
77static jboolean dopause = JNI_FALSE; /* pause for debugger attach */
78static jboolean docoredump = JNI_FALSE; /* core dump on exit */
79static char *logfile = NULL; /* Name of logfile (if logging) */
80static unsigned logflags = 0; /* Log flags */
81
82static char *names; /* strings derived from OnLoad options */
83
84/*
85 * Elements of the transports bag
86 */
87typedef struct TransportSpec {
88 char *name;
89 char *address;
90 long timeout;
91} TransportSpec;
92
93/*
94 * Forward Refs
95 */
96static void JNICALL cbEarlyVMInit(jvmtiEnv*, JNIEnv *, jthread);
97static void JNICALL cbEarlyVMDeath(jvmtiEnv*, JNIEnv *);
98static void JNICALL cbEarlyException(jvmtiEnv*, JNIEnv *,
99 jthread, jmethodID, jlocation, jobject, jmethodID, jlocation);
100
101static void initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei);
102static jboolean parseOptions(char *str);
103
104/*
105 * Phase 1: Initial load.
106 *
107 * OnLoad is called by the VM immediately after the back-end
108 * library is loaded. We can do very little in this function since
109 * the VM has not completed initialization. So, we parse the JDWP
110 * options and set up a simple initial event callbacks for JVMTI events.
111 * When a triggering event occurs, that callback will begin debugger initialization.
112 */
113
114/* Get a static area to hold the Global Data */
115static BackendGlobalData *
116get_gdata(void)
117{
118 static BackendGlobalData s;
119 (void)memset(&s, 0, sizeof(BackendGlobalData));
120 return &s;
121}
122
123static jvmtiError
124set_event_notification(jvmtiEventMode mode, EventIndex ei)
125{
126 jvmtiError error;
127 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventNotificationMode)
128 (gdata->jvmti, mode, eventIndex2jvmti(ei), NULL);
129 if (error != JVMTI_ERROR_NONE) {
130 ERROR_MESSAGE(("JDWP unable to configure initial JVMTI event %s: %s(%d)",
131 eventText(ei), jvmtiErrorText(error), error));
132 }
133 return error;
134}
135
136/* Logic to determine JVMTI version compatibility */
137static jboolean
138compatible_versions(jint major_runtime, jint minor_runtime,
139 jint major_compiletime, jint minor_compiletime)
140{
141#if 1 /* FIXUP: We allow version 0 to be compatible with anything */
142 /* Special check for FCS of 1.0. */
143 if ( major_runtime == 0 || major_compiletime == 0 ) {
144 return JNI_TRUE;
145 }
146#endif
147 /* Runtime major version must match. */
148 if ( major_runtime != major_compiletime ) {
149 return JNI_FALSE;
150 }
151 /* Runtime minor version must be >= the version compiled with. */
152 if ( minor_runtime < minor_compiletime ) {
153 return JNI_FALSE;
154 }
155 /* Assumed compatible */
156 return JNI_TRUE;
157}
158
159/* OnLoad startup:
160 * Returning JNI_ERR will cause the java_g VM to core dump, be careful.
161 */
162JNIEXPORT jint JNICALL
163Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
164{
165 jvmtiError error;
166 jvmtiCapabilities needed_capabilities;
167 jvmtiCapabilities potential_capabilities;
168 jint jvmtiCompileTimeMajorVersion;
169 jint jvmtiCompileTimeMinorVersion;
170 jint jvmtiCompileTimeMicroVersion;
171
172 /* See if it's already loaded */
173 if ( gdata!=NULL && gdata->isLoaded==JNI_TRUE ) {
174 ERROR_MESSAGE(("Cannot load this JVM TI agent twice, check your java command line for duplicate jdwp options."));
175 return JNI_ERR;
176 }
177
178 /* If gdata is defined and the VM died, why are we here? */
179 if ( gdata!=NULL && gdata->vmDead ) {
180 ERROR_MESSAGE(("JDWP unable to load, VM died"));
181 return JNI_ERR;
182 }
183
184 /* Get global data area */
185 gdata = get_gdata();
186 if (gdata == NULL) {
187 ERROR_MESSAGE(("JDWP unable to allocate memory"));
188 return JNI_ERR;
189 }
190 gdata->isLoaded = JNI_TRUE;
191
192 /* Start filling in gdata */
193 gdata->jvm = vm;
194 vmInitialized = JNI_FALSE;
195 gdata->vmDead = JNI_FALSE;
196
197 /* Npt and Utf function init */
198 NPT_INITIALIZE(&(gdata->npt), NPT_VERSION, NULL);
199 if (gdata->npt == NULL) {
200 ERROR_MESSAGE(("JDWP: unable to initialize NPT library"));
201 return JNI_ERR;
202 }
203 gdata->npt->utf = (gdata->npt->utfInitialize)(NULL);
204 if (gdata->npt->utf == NULL) {
205 ERROR_MESSAGE(("JDWP: UTF function initialization failed"));
206 return JNI_ERR;
207 }
208
209 /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */
210 error = JVM_FUNC_PTR(vm,GetEnv)
211 (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1);
212 if (error != JNI_OK) {
213 ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x),"
214 " is your J2SE a 1.5 or newer version?"
215 " JNIEnv's GetEnv() returned %d",
216 JVMTI_VERSION_1, error));
217 forceExit(1); /* Kill entire process, no core dump */
218 }
219
220 /* Check to make sure the version of jvmti.h we compiled with
221 * matches the runtime version we are using.
222 */
223 jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR )
224 >> JVMTI_VERSION_SHIFT_MAJOR;
225 jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR )
226 >> JVMTI_VERSION_SHIFT_MINOR;
227 jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO )
228 >> JVMTI_VERSION_SHIFT_MICRO;
229
230 /* Check for compatibility */
231 if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(),
232 jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) {
233
234 ERROR_MESSAGE(("This jdwp native library will not work with this VM's "
235 "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].",
236 jvmtiMajorVersion(),
237 jvmtiMinorVersion(),
238 jvmtiMicroVersion(),
239 jvmtiCompileTimeMajorVersion,
240 jvmtiCompileTimeMinorVersion,
241 jvmtiCompileTimeMicroVersion));
242
243 /* Do not let VM get a fatal error, we don't want a core dump here. */
244 forceExit(1); /* Kill entire process, no core dump wanted */
245 }
246
247 /* Parse input options */
248 if (!parseOptions(options)) {
249 /* No message necessary, should have been printed out already */
250 /* Do not let VM get a fatal error, we don't want a core dump here. */
251 forceExit(1); /* Kill entire process, no core dump wanted */
252 }
253
254 LOG_MISC(("Onload: %s", options));
255
256 /* Get potential capabilities */
257 (void)memset(&potential_capabilities,0,sizeof(potential_capabilities));
258 error = JVMTI_FUNC_PTR(gdata->jvmti,GetPotentialCapabilities)
259 (gdata->jvmti, &potential_capabilities);
260 if (error != JVMTI_ERROR_NONE) {
261 ERROR_MESSAGE(("JDWP unable to get potential JVMTI capabilities: %s(%d)",
262 jvmtiErrorText(error), error));
263 return JNI_ERR;
264 }
265
266 /* Fill in ones that we must have */
267 (void)memset(&needed_capabilities,0,sizeof(needed_capabilities));
268 needed_capabilities.can_access_local_variables = 1;
269 needed_capabilities.can_generate_single_step_events = 1;
270 needed_capabilities.can_generate_exception_events = 1;
271 needed_capabilities.can_generate_frame_pop_events = 1;
272 needed_capabilities.can_generate_breakpoint_events = 1;
273 needed_capabilities.can_suspend = 1;
274 needed_capabilities.can_generate_method_entry_events = 1;
275 needed_capabilities.can_generate_method_exit_events = 1;
276 needed_capabilities.can_generate_garbage_collection_events = 1;
277 needed_capabilities.can_maintain_original_method_order = 1;
278 needed_capabilities.can_generate_monitor_events = 1;
279 needed_capabilities.can_tag_objects = 1;
280
281 /* And what potential ones that would be nice to have */
282 needed_capabilities.can_force_early_return
283 = potential_capabilities.can_force_early_return;
284 needed_capabilities.can_generate_field_modification_events
285 = potential_capabilities.can_generate_field_modification_events;
286 needed_capabilities.can_generate_field_access_events
287 = potential_capabilities.can_generate_field_access_events;
288 needed_capabilities.can_get_bytecodes
289 = potential_capabilities.can_get_bytecodes;
290 needed_capabilities.can_get_synthetic_attribute
291 = potential_capabilities.can_get_synthetic_attribute;
292 needed_capabilities.can_get_owned_monitor_info
293 = potential_capabilities.can_get_owned_monitor_info;
294 needed_capabilities.can_get_current_contended_monitor
295 = potential_capabilities.can_get_current_contended_monitor;
296 needed_capabilities.can_get_monitor_info
297 = potential_capabilities.can_get_monitor_info;
298 needed_capabilities.can_pop_frame
299 = potential_capabilities.can_pop_frame;
300 needed_capabilities.can_redefine_classes
301 = potential_capabilities.can_redefine_classes;
302 needed_capabilities.can_redefine_any_class
303 = potential_capabilities.can_redefine_any_class;
304 needed_capabilities.can_get_owned_monitor_stack_depth_info
305 = potential_capabilities.can_get_owned_monitor_stack_depth_info;
306 needed_capabilities.can_get_constant_pool
307 = potential_capabilities.can_get_constant_pool;
308 {
309 needed_capabilities.can_get_source_debug_extension = 1;
310 needed_capabilities.can_get_source_file_name = 1;
311 needed_capabilities.can_get_line_numbers = 1;
312 needed_capabilities.can_signal_thread
313 = potential_capabilities.can_signal_thread;
314 }
315
316 /* Add the capabilities */
317 error = JVMTI_FUNC_PTR(gdata->jvmti,AddCapabilities)
318 (gdata->jvmti, &needed_capabilities);
319 if (error != JVMTI_ERROR_NONE) {
320 ERROR_MESSAGE(("JDWP unable to get necessary JVMTI capabilities."));
321 forceExit(1); /* Kill entire process, no core dump wanted */
322 }
323
324 /* Initialize event number mapping tables */
325 eventIndexInit();
326
327 /* Set the initial JVMTI event notifications */
328 error = set_event_notification(JVMTI_ENABLE, EI_VM_DEATH);
329 if (error != JVMTI_ERROR_NONE) {
330 return JNI_ERR;
331 }
332 error = set_event_notification(JVMTI_ENABLE, EI_VM_INIT);
333 if (error != JVMTI_ERROR_NONE) {
334 return JNI_ERR;
335 }
336 if (initOnUncaught || (initOnException != NULL)) {
337 error = set_event_notification(JVMTI_ENABLE, EI_EXCEPTION);
338 if (error != JVMTI_ERROR_NONE) {
339 return JNI_ERR;
340 }
341 }
342
343 /* Set callbacks just for 3 functions */
344 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
345 gdata->callbacks.VMInit = &cbEarlyVMInit;
346 gdata->callbacks.VMDeath = &cbEarlyVMDeath;
347 gdata->callbacks.Exception = &cbEarlyException;
348 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
349 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
350 if (error != JVMTI_ERROR_NONE) {
351 ERROR_MESSAGE(("JDWP unable to set JVMTI event callbacks: %s(%d)",
352 jvmtiErrorText(error), error));
353 return JNI_ERR;
354 }
355
356 LOG_MISC(("OnLoad: DONE"));
357 return JNI_OK;
358}
359
360JNIEXPORT void JNICALL
361Agent_OnUnload(JavaVM *vm)
362{
363
364 gdata->isLoaded = JNI_FALSE;
365
366 /* Cleanup, but make sure VM is alive before using JNI, and
367 * make sure JVMTI environment is ok before deallocating
368 * memory allocated through JVMTI, which all of it is.
369 */
370
371 /*
372 * Close transport before exit
373 */
374 if (transport_is_open()) {
375 transport_close();
376 }
377}
378
379/*
380 * Phase 2: Initial events. Phase 2 consists of waiting for the
381 * event that triggers full initialization. Under normal circumstances
382 * (initOnStartup == TRUE) this is the JVMTI_EVENT_VM_INIT event.
383 * Otherwise, we delay initialization until the app throws a
384 * particular exception. The triggering event invokes
385 * the bulk of the initialization, including creation of threads and
386 * monitors, transport setup, and installation of a new event callback which
387 * handles the complete set of events.
388 *
389 * Since the triggering event comes in on an application thread, some of the
390 * initialization is difficult to do here. Specifically, this thread along
391 * with all other app threads may need to be suspended until a debugger
392 * connects. These kinds of tasks are left to the third phase which is
393 * invoked by one of the spawned debugger threads, the event handler.
394 */
395
396/*
397 * Wait for a triggering event; then kick off debugger
398 * initialization. A different event callback will be installed by
399 * debugger initialization, and this function will not be called
400 * again.
401 */
402
403 /*
404 * TO DO: Decide whether we need to protect this code with
405 * a lock. It might be too early to create a monitor safely (?).
406 */
407
408static void JNICALL
409cbEarlyVMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread)
410{
411 LOG_CB(("cbEarlyVMInit"));
412 if ( gdata->vmDead ) {
413 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at VM_INIT time");
414 }
415 if (initOnStartup)
416 initialize(env, thread, EI_VM_INIT);
417 vmInitialized = JNI_TRUE;
418 LOG_MISC(("END cbEarlyVMInit"));
419}
420
421static void
422disposeEnvironment(jvmtiEnv *jvmti_env)
423{
424 jvmtiError error;
425
426 error = JVMTI_FUNC_PTR(jvmti_env,DisposeEnvironment)(jvmti_env);
427 if ( error == JVMTI_ERROR_MUST_POSSESS_CAPABILITY )
428 error = JVMTI_ERROR_NONE; /* Hack! FIXUP when JVMTI has disposeEnv */
429 /* What should error return say? */
430 if (error != JVMTI_ERROR_NONE) {
431 ERROR_MESSAGE(("JDWP unable to dispose of JVMTI environment: %s(%d)",
432 jvmtiErrorText(error), error));
433 }
434 gdata->jvmti = NULL;
435}
436
437static void JNICALL
438cbEarlyVMDeath(jvmtiEnv *jvmti_env, JNIEnv *env)
439{
440 LOG_CB(("cbEarlyVMDeath"));
441 if ( gdata->vmDead ) {
442 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM died more than once");
443 }
444 disposeEnvironment(jvmti_env);
445 gdata->jvmti = NULL;
446 gdata->jvm = NULL;
447 gdata->vmDead = JNI_TRUE;
448 LOG_MISC(("END cbEarlyVMDeath"));
449}
450
451static void JNICALL
452cbEarlyException(jvmtiEnv *jvmti_env, JNIEnv *env,
453 jthread thread, jmethodID method, jlocation location,
454 jobject exception,
455 jmethodID catch_method, jlocation catch_location)
456{
457 jvmtiError error;
458 jthrowable currentException;
459
460 LOG_CB(("cbEarlyException: thread=%p", thread));
461
462 if ( gdata->vmDead ) {
463 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initial Exception event");
464 }
465 if (!vmInitialized) {
466 LOG_MISC(("VM is not initialized yet"));
467 return;
468 }
469
470 /*
471 * We want to preserve any current exception that might get wiped
472 * out during event handling (e.g. JNI calls). We have to rely on
473 * space for the local reference on the current frame because
474 * doing a PushLocalFrame here might itself generate an exception.
475 */
476
477 currentException = JNI_FUNC_PTR(env,ExceptionOccurred)(env);
478 JNI_FUNC_PTR(env,ExceptionClear)(env);
479
480 if (initOnUncaught && catch_method == NULL) {
481
482 LOG_MISC(("Initializing on uncaught exception"));
483 initialize(env, thread, EI_EXCEPTION);
484
485 } else if (initOnException != NULL) {
486
487 jclass clazz;
488
489 /* Get class of exception thrown */
490 clazz = JNI_FUNC_PTR(env,GetObjectClass)(env, exception);
491 if ( clazz != NULL ) {
492 char *signature = NULL;
493 /* initing on throw, check */
494 error = classSignature(clazz, &signature, NULL);
495 LOG_MISC(("Checking specific exception: looking for %s, got %s",
496 initOnException, signature));
497 if ( (error==JVMTI_ERROR_NONE) &&
498 (strcmp(signature, initOnException) == 0)) {
499 LOG_MISC(("Initializing on specific exception"));
500 initialize(env, thread, EI_EXCEPTION);
501 } else {
502 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */
503 }
504 if ( signature != NULL ) {
505 jvmtiDeallocate(signature);
506 }
507 } else {
508 error = AGENT_ERROR_INTERNAL; /* Just to cause restore */
509 }
510
511 /* If initialize didn't happen, we need to restore things */
512 if ( error != JVMTI_ERROR_NONE ) {
513 /*
514 * Restore exception state from before callback call
515 */
516 LOG_MISC(("No initialization, didn't find right exception"));
517 if (currentException != NULL) {
518 JNI_FUNC_PTR(env,Throw)(env, currentException);
519 } else {
520 JNI_FUNC_PTR(env,ExceptionClear)(env);
521 }
522 }
523
524 }
525
526 LOG_MISC(("END cbEarlyException"));
527
528}
529
530typedef struct EnumerateArg {
531 jboolean isServer;
532 jdwpError error;
533 jint startCount;
534} EnumerateArg;
535
536static jboolean
537startTransport(void *item, void *arg)
538{
539 TransportSpec *transport = item;
540 EnumerateArg *enumArg = arg;
541 jdwpError serror;
542
543 LOG_MISC(("Begin startTransport"));
544 serror = transport_startTransport(enumArg->isServer, transport->name,
545 transport->address, transport->timeout);
546 if (serror != JDWP_ERROR(NONE)) {
547 ERROR_MESSAGE(("JDWP Transport %s failed to initialize, %s(%d)",
548 transport->name, jdwpErrorText(serror), serror));
549 enumArg->error = serror;
550 } else {
551 /* (Don't overwrite any previous error) */
552
553 enumArg->startCount++;
554 }
555
556 LOG_MISC(("End startTransport"));
557
558 return JNI_TRUE; /* Always continue, even if there was an error */
559}
560
561static void
562signalInitComplete(void)
563{
564 /*
565 * Initialization is complete
566 */
567 LOG_MISC(("signal initialization complete"));
568 debugMonitorEnter(initMonitor);
569 initComplete = JNI_TRUE;
570 debugMonitorNotifyAll(initMonitor);
571 debugMonitorExit(initMonitor);
572}
573
574/*
575 * Determine if initialization is complete.
576 */
577jboolean
578debugInit_isInitComplete(void)
579{
580 return initComplete;
581}
582
583/*
584 * Wait for all initialization to complete.
585 */
586void
587debugInit_waitInitComplete(void)
588{
589 debugMonitorEnter(initMonitor);
590 while (!initComplete) {
591 debugMonitorWait(initMonitor);
592 }
593 debugMonitorExit(initMonitor);
594}
595
596/* All process exit() calls come from here */
597void
598forceExit(int exit_code)
599{
600 /* make sure the transport is closed down before we exit() */
601 transport_close();
602 exit(exit_code);
603}
604
605/* All JVM fatal error exits lead here (e.g. we need to kill the VM). */
606static void
607jniFatalError(JNIEnv *env, const char *msg, jvmtiError error, int exit_code)
608{
609 JavaVM *vm;
610 char buf[512];
611
612 gdata->vmDead = JNI_TRUE;
613 if ( msg==NULL )
614 msg = "UNKNOWN REASON";
615 vm = gdata->jvm;
616 if ( env==NULL && vm!=NULL ) {
617 jint rc = (*((*vm)->GetEnv))(vm, (void **)&env, JNI_VERSION_1_2);
618 if (rc != JNI_OK ) {
619 env = NULL;
620 }
621 }
622 if ( error != JVMTI_ERROR_NONE ) {
623 (void)snprintf(buf, sizeof(buf), "JDWP %s, jvmtiError=%s(%d)",
624 msg, jvmtiErrorText(error), error);
625 } else {
626 (void)snprintf(buf, sizeof(buf), "JDWP %s", buf);
627 }
628 if (env != NULL) {
629 (*((*env)->FatalError))(env, buf);
630 } else {
631 /* Should rarely ever reach here, means VM is really dead */
632 print_message(stderr, "ERROR: JDWP: ", "\n",
633 "Can't call JNI FatalError(NULL, \"%s\")", buf);
634 }
635 forceExit(exit_code);
636}
637
638/*
639 * Initialize debugger back end modules
640 */
641static void
642initialize(JNIEnv *env, jthread thread, EventIndex triggering_ei)
643{
644 jvmtiError error;
645 EnumerateArg arg;
646 jbyte suspendPolicy;
647
648 LOG_MISC(("Begin initialize()"));
649 currentSessionID = 0;
650 initComplete = JNI_FALSE;
651
652 if ( gdata->vmDead ) {
653 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead at initialize() time");
654 }
655
656 /* Turn off the initial JVMTI event notifications */
657 error = set_event_notification(JVMTI_DISABLE, EI_EXCEPTION);
658 if (error != JVMTI_ERROR_NONE) {
659 EXIT_ERROR(error, "unable to disable JVMTI event notification");
660 }
661 error = set_event_notification(JVMTI_DISABLE, EI_VM_INIT);
662 if (error != JVMTI_ERROR_NONE) {
663 EXIT_ERROR(error, "unable to disable JVMTI event notification");
664 }
665 error = set_event_notification(JVMTI_DISABLE, EI_VM_DEATH);
666 if (error != JVMTI_ERROR_NONE) {
667 EXIT_ERROR(error, "unable to disable JVMTI event notification");
668 }
669
670 /* Remove initial event callbacks */
671 (void)memset(&(gdata->callbacks),0,sizeof(gdata->callbacks));
672 error = JVMTI_FUNC_PTR(gdata->jvmti,SetEventCallbacks)
673 (gdata->jvmti, &(gdata->callbacks), sizeof(gdata->callbacks));
674 if (error != JVMTI_ERROR_NONE) {
675 EXIT_ERROR(error, "unable to clear JVMTI callbacks");
676 }
677
678 commonRef_initialize();
679 util_initialize(env);
680 threadControl_initialize();
681 stepControl_initialize();
682 invoker_initialize();
683 debugDispatch_initialize();
684 classTrack_initialize(env);
685 debugLoop_initialize();
686
687 initMonitor = debugMonitorCreate("JDWP Initialization Monitor");
688
689
690 /*
691 * Initialize transports
692 */
693 arg.isServer = isServer;
694 arg.error = JDWP_ERROR(NONE);
695 arg.startCount = 0;
696
697 transport_initialize();
698 (void)bagEnumerateOver(transports, startTransport, &arg);
699
700 /*
701 * Exit with an error only if
702 * 1) none of the transports was successfully started, and
703 * 2) the application has not yet started running
704 */
705 if ((arg.error != JDWP_ERROR(NONE)) &&
706 (arg.startCount == 0) &&
707 initOnStartup) {
708 EXIT_ERROR(map2jvmtiError(arg.error), "No transports initialized");
709 }
710
711 eventHandler_initialize(currentSessionID);
712
713 signalInitComplete();
714
715 transport_waitForConnection();
716
717 suspendPolicy = suspendOnInit ? JDWP_SUSPEND_POLICY(ALL)
718 : JDWP_SUSPEND_POLICY(NONE);
719 if (triggering_ei == EI_VM_INIT) {
720 LOG_MISC(("triggering_ei == EI_VM_INIT"));
721 eventHelper_reportVMInit(env, currentSessionID, thread, suspendPolicy);
722 } else {
723 /*
724 * TO DO: Kludgy way of getting the triggering event to the
725 * just-attached debugger. It would be nice to make this a little
726 * cleaner. There is also a race condition where other events
727 * can get in the queue (from other not-yet-suspended threads)
728 * before this one does. (Also need to handle allocation error below?)
729 */
730 EventInfo info;
731 struct bag *initEventBag;
732 LOG_MISC(("triggering_ei != EI_VM_INIT"));
733 initEventBag = eventHelper_createEventBag();
734 (void)memset(&info,0,sizeof(info));
735 info.ei = triggering_ei;
736 eventHelper_recordEvent(&info, 0, suspendPolicy, initEventBag);
737 (void)eventHelper_reportEvents(currentSessionID, initEventBag);
738 bagDestroyBag(initEventBag);
739 }
740
741 if ( gdata->vmDead ) {
742 EXIT_ERROR(AGENT_ERROR_INTERNAL,"VM dead before initialize() completes");
743 }
744 LOG_MISC(("End initialize()"));
745}
746
747/*
748 * Restore all static data to the initialized state so that another
749 * debugger can connect properly later.
750 */
751void
752debugInit_reset(JNIEnv *env)
753{
754 EnumerateArg arg;
755
756 LOG_MISC(("debugInit_reset() beginning"));
757
758 currentSessionID++;
759 initComplete = JNI_FALSE;
760
761 eventHandler_reset(currentSessionID);
762 transport_reset();
763 debugDispatch_reset();
764 invoker_reset();
765 stepControl_reset();
766 threadControl_reset();
767 util_reset();
768 commonRef_reset(env);
769 classTrack_reset();
770
771 /*
772 * If this is a server, we are now ready to accept another connection.
773 * If it's a client, then we've cleaned up some (more should be added
774 * later) and we're done.
775 */
776 if (isServer) {
777 arg.isServer = JNI_TRUE;
778 arg.error = JDWP_ERROR(NONE);
779 arg.startCount = 0;
780 (void)bagEnumerateOver(transports, startTransport, &arg);
781
782 signalInitComplete();
783
784 transport_waitForConnection();
785 } else {
786 signalInitComplete(); /* Why? */
787 }
788
789 LOG_MISC(("debugInit_reset() completed."));
790}
791
792
793char *
794debugInit_launchOnInit(void)
795{
796 return launchOnInit;
797}
798
799jboolean
800debugInit_suspendOnInit(void)
801{
802 return suspendOnInit;
803}
804
805/*
806 * code below is shamelessly swiped from hprof.
807 */
808
809static int
810get_tok(char **src, char *buf, int buflen, char sep)
811{
812 int i;
813 char *p = *src;
814 for (i = 0; i < buflen; i++) {
815 if (p[i] == 0 || p[i] == sep) {
816 buf[i] = 0;
817 if (p[i] == sep) {
818 i++;
819 }
820 *src += i;
821 return i;
822 }
823 buf[i] = p[i];
824 }
825 /* overflow */
826 return 0;
827}
828
829static void
830printUsage(void)
831{
832 TTY_MESSAGE((
833 " Java Debugger JDWP Agent Library\n"
834 " --------------------------------\n"
835 "\n"
836 " (see http://java.sun.com/products/jpda for more information)\n"
837 "\n"
838 "jdwp usage: java " AGENTLIB "=[help]|[<option>=<value>, ...]\n"
839 "\n"
840 "Option Name and Value Description Default\n"
841 "--------------------- ----------- -------\n"
842 "suspend=y|n wait on startup? y\n"
843 "transport=<name> transport spec none\n"
844 "address=<listen/attach address> transport spec \"\"\n"
845 "server=y|n listen for debugger? n\n"
846 "launch=<command line> run debugger on event none\n"
847 "onthrow=<exception name> debug on throw none\n"
848 "onuncaught=y|n debug on any uncaught? n\n"
849 "timeout=<timeout value> for listen/attach in milliseconds n\n"
850 "mutf8=y|n output modified utf-8 n\n"
851 "quiet=y|n control over terminal messages n\n"
852 "\n"
853 "Obsolete Options\n"
854 "----------------\n"
855 "strict=y|n\n"
856 "stdalloc=y|n\n"
857 "\n"
858 "Examples\n"
859 "--------\n"
860 " - Using sockets connect to a debugger at a specific address:\n"
861 " java " AGENTLIB "=transport=dt_socket,address=localhost:8000 ...\n"
862 " - Using sockets listen for a debugger to attach:\n"
863 " java " AGENTLIB "=transport=dt_socket,server=y,suspend=y ...\n"
864 "\n"
865 "Notes\n"
866 "-----\n"
867 " - A timeout value of 0 (the default) is no timeout.\n"
868 "\n"
869 "Warnings\n"
870 "--------\n"
871 " - The older " XRUN " interface can still be used, but will be removed in\n"
872 " a future release, for example:\n"
873 " java " XDEBUG " " XRUN ":[help]|[<option>=<value>, ...]\n"
874 ));
875
876#ifdef DEBUG
877
878 TTY_MESSAGE((
879 "\n"
880 "Debugging Options Description Default\n"
881 "----------------- ----------- -------\n"
882 "pause=y|n pause to debug PID n\n"
883 "coredump=y|n coredump at exit n\n"
884 "errorexit=y|n exit on any error n\n"
885 "logfile=filename name of log file none\n"
886 "logflags=flags log flags (bitmask) none\n"
887 " JVM calls = 0x001\n"
888 " JNI calls = 0x002\n"
889 " JVMTI calls = 0x004\n"
890 " misc events = 0x008\n"
891 " step logs = 0x010\n"
892 " locations = 0x020\n"
893 " callbacks = 0x040\n"
894 " errors = 0x080\n"
895 " everything = 0xfff\n"
896 "debugflags=flags debug flags (bitmask) none\n"
897 " USE_ITERATE_THROUGH_HEAP 0x01\n"
898 "\n"
899 "Environment Variables\n"
900 "---------------------\n"
901 "_JAVA_JDWP_OPTIONS\n"
902 " Options can be added externally via this environment variable.\n"
903 " Anything contained in it will get a comma prepended to it (if needed),\n"
904 " then it will be added to the end of the options supplied via the\n"
905 " " XRUN " or " AGENTLIB " command line option.\n"
906 ));
907
908#endif
909
910
911
912}
913
914static jboolean checkAddress(void *bagItem, void *arg)
915{
916 TransportSpec *spec = (TransportSpec *)bagItem;
917 if (spec->address == NULL) {
918 ERROR_MESSAGE(("JDWP Non-server transport %s must have a connection "
919 "address specified through the 'address=' option",
920 spec->name));
921 return JNI_FALSE;
922 } else {
923 return JNI_TRUE;
924 }
925}
926
927static char *
928add_to_options(char *options, char *new_options)
929{
930 size_t originalLength;
931 char *combinedOptions;
932
933 /*
934 * Allocate enough space for both strings and
935 * comma in between.
936 */
937 originalLength = strlen(options);
938 combinedOptions = jvmtiAllocate((jint)originalLength + 1 +
939 (jint)strlen(new_options) + 1);
940 if (combinedOptions == NULL) {
941 return NULL;
942 }
943
944 (void)strcpy(combinedOptions, options);
945 (void)strcat(combinedOptions, ",");
946 (void)strcat(combinedOptions, new_options);
947
948 return combinedOptions;
949}
950
951static jboolean
952get_boolean(char **pstr, jboolean *answer)
953{
954 char buf[80];
955 *answer = JNI_FALSE;
956 /*LINTED*/
957 if (get_tok(pstr, buf, (int)sizeof(buf), ',')) {
958 if (strcmp(buf, "y") == 0) {
959 *answer = JNI_TRUE;
960 return JNI_TRUE;
961 } else if (strcmp(buf, "n") == 0) {
962 *answer = JNI_FALSE;
963 return JNI_TRUE;
964 }
965 }
966 return JNI_FALSE;
967}
968
969/* atexit() callback */
970static void
971atexit_finish_logging(void)
972{
973 /* Normal exit(0) (not _exit()) may only reach here */
974 finish_logging(0); /* Only first call matters */
975}
976
977static jboolean
978parseOptions(char *options)
979{
980 TransportSpec *currentTransport = NULL;
981 char *end;
982 char *current;
983 int length;
984 char *str;
985 char *errmsg;
986
987 /* Set defaults */
988 gdata->assertOn = DEFAULT_ASSERT_ON;
989 gdata->assertFatal = DEFAULT_ASSERT_FATAL;
990 logfile = DEFAULT_LOGFILE;
991
992 /* Options being NULL will end up being an error. */
993 if (options == NULL) {
994 options = "";
995 }
996
997 /* Check for "help" BEFORE we add any environmental settings */
998 if ((strcmp(options, "help")) == 0) {
999 printUsage();
1000 forceExit(0); /* Kill entire process, no core dump wanted */
1001 }
1002
1003 /* These buffers are never freed */
1004 {
1005 char *envOptions;
1006
1007 /*
1008 * Add environmentally specified options.
1009 */
1010 envOptions = getenv("_JAVA_JDWP_OPTIONS");
1011 if (envOptions != NULL) {
1012 options = add_to_options(options, envOptions);
1013 if ( options==NULL ) {
1014 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
1015 }
1016 }
1017
1018 /*
1019 * Allocate a buffer for names derived from option strings. It should
1020 * never be longer than the original options string itself.
1021 * Also keep a copy of the options in gdata->options.
1022 */
1023 length = (int)strlen(options);
1024 gdata->options = jvmtiAllocate(length + 1);
1025 if (gdata->options == NULL) {
1026 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
1027 }
1028 (void)strcpy(gdata->options, options);
1029 names = jvmtiAllocate(length + 1);
1030 if (names == NULL) {
1031 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"options");
1032 }
1033
1034 transports = bagCreateBag(sizeof(TransportSpec), 3);
1035 if (transports == NULL) {
1036 EXIT_ERROR(AGENT_ERROR_OUT_OF_MEMORY,"transports");
1037 }
1038
1039 }
1040
1041 current = names;
1042 end = names + length;
1043 str = options;
1044
1045 while (*str) {
1046 char buf[100];
1047 /*LINTED*/
1048 if (!get_tok(&str, buf, (int)sizeof(buf), '=')) {
1049 goto syntax_error;
1050 }
1051 if (strcmp(buf, "transport") == 0) {
1052 currentTransport = bagAdd(transports);
1053 /*LINTED*/
1054 if (!get_tok(&str, current, (int)(end - current), ',')) {
1055 goto syntax_error;
1056 }
1057 currentTransport->name = current;
1058 current += strlen(current) + 1;
1059 } else if (strcmp(buf, "address") == 0) {
1060 if (currentTransport == NULL) {
1061 errmsg = "address specified without transport";
1062 goto bad_option_with_errmsg;
1063 }
1064 /*LINTED*/
1065 if (!get_tok(&str, current, (int)(end - current), ',')) {
1066 goto syntax_error;
1067 }
1068 currentTransport->address = current;
1069 current += strlen(current) + 1;
1070 } else if (strcmp(buf, "timeout") == 0) {
1071 if (currentTransport == NULL) {
1072 errmsg = "timeout specified without transport";
1073 goto bad_option_with_errmsg;
1074 }
1075 /*LINTED*/
1076 if (!get_tok(&str, current, (int)(end - current), ',')) {
1077 goto syntax_error;
1078 }
1079 currentTransport->timeout = atol(current);
1080 current += strlen(current) + 1;
1081 } else if (strcmp(buf, "launch") == 0) {
1082 /*LINTED*/
1083 if (!get_tok(&str, current, (int)(end - current), ',')) {
1084 goto syntax_error;
1085 }
1086 launchOnInit = current;
1087 current += strlen(current) + 1;
1088 } else if (strcmp(buf, "onthrow") == 0) {
1089 /* Read class name and convert in place to a signature */
1090 *current = 'L';
1091 /*LINTED*/
1092 if (!get_tok(&str, current + 1, (int)(end - current - 1), ',')) {
1093 goto syntax_error;
1094 }
1095 initOnException = current;
1096 while (*current != '\0') {
1097 if (*current == '.') {
1098 *current = '/';
1099 }
1100 current++;
1101 }
1102 *current++ = ';';
1103 *current++ = '\0';
1104 } else if (strcmp(buf, "assert") == 0) {
1105 /*LINTED*/
1106 if (!get_tok(&str, current, (int)(end - current), ',')) {
1107 goto syntax_error;
1108 }
1109 if (strcmp(current, "y") == 0) {
1110 gdata->assertOn = JNI_TRUE;
1111 gdata->assertFatal = JNI_FALSE;
1112 } else if (strcmp(current, "fatal") == 0) {
1113 gdata->assertOn = JNI_TRUE;
1114 gdata->assertFatal = JNI_TRUE;
1115 } else if (strcmp(current, "n") == 0) {
1116 gdata->assertOn = JNI_FALSE;
1117 gdata->assertFatal = JNI_FALSE;
1118 } else {
1119 goto syntax_error;
1120 }
1121 current += strlen(current) + 1;
1122 } else if (strcmp(buf, "pause") == 0) {
1123 if ( !get_boolean(&str, &dopause) ) {
1124 goto syntax_error;
1125 }
1126 if ( dopause ) {
1127 do_pause();
1128 }
1129 } else if (strcmp(buf, "coredump") == 0) {
1130 if ( !get_boolean(&str, &docoredump) ) {
1131 goto syntax_error;
1132 }
1133 } else if (strcmp(buf, "errorexit") == 0) {
1134 if ( !get_boolean(&str, &(gdata->doerrorexit)) ) {
1135 goto syntax_error;
1136 }
1137 } else if (strcmp(buf, "exitpause") == 0) {
1138 errmsg = "The exitpause option removed, use -XX:OnError";
1139 goto bad_option_with_errmsg;
1140 } else if (strcmp(buf, "precrash") == 0) {
1141 errmsg = "The precrash option removed, use -XX:OnError";
1142 goto bad_option_with_errmsg;
1143 } else if (strcmp(buf, "logfile") == 0) {
1144 /*LINTED*/
1145 if (!get_tok(&str, current, (int)(end - current), ',')) {
1146 goto syntax_error;
1147 }
1148 logfile = current;
1149 current += strlen(current) + 1;
1150 } else if (strcmp(buf, "logflags") == 0) {
1151 /*LINTED*/
1152 if (!get_tok(&str, current, (int)(end - current), ',')) {
1153 goto syntax_error;
1154 }
1155 /*LINTED*/
1156 logflags = (unsigned)strtol(current, NULL, 0);
1157 } else if (strcmp(buf, "debugflags") == 0) {
1158 /*LINTED*/
1159 if (!get_tok(&str, current, (int)(end - current), ',')) {
1160 goto syntax_error;
1161 }
1162 /*LINTED*/
1163 gdata->debugflags = (unsigned)strtol(current, NULL, 0);
1164 } else if ( strcmp(buf, "suspend")==0 ) {
1165 if ( !get_boolean(&str, &suspendOnInit) ) {
1166 goto syntax_error;
1167 }
1168 } else if ( strcmp(buf, "server")==0 ) {
1169 if ( !get_boolean(&str, &isServer) ) {
1170 goto syntax_error;
1171 }
1172 } else if ( strcmp(buf, "strict")==0 ) { /* Obsolete, but accept it */
1173 if ( !get_boolean(&str, &isStrict) ) {
1174 goto syntax_error;
1175 }
1176 } else if ( strcmp(buf, "quiet")==0 ) {
1177 if ( !get_boolean(&str, &(gdata->quiet)) ) {
1178 goto syntax_error;
1179 }
1180 } else if ( strcmp(buf, "onuncaught")==0 ) {
1181 if ( !get_boolean(&str, &initOnUncaught) ) {
1182 goto syntax_error;
1183 }
1184 } else if ( strcmp(buf, "mutf8")==0 ) {
1185 if ( !get_boolean(&str, &(gdata->modifiedUtf8)) ) {
1186 goto syntax_error;
1187 }
1188 } else if ( strcmp(buf, "stdalloc")==0 ) { /* Obsolete, but accept it */
1189 if ( !get_boolean(&str, &useStandardAlloc) ) {
1190 goto syntax_error;
1191 }
1192 } else {
1193 goto syntax_error;
1194 }
1195 }
1196
1197 /* Setup logging now */
1198 if ( logfile!=NULL ) {
1199 setup_logging(logfile, logflags);
1200 (void)atexit(&atexit_finish_logging);
1201 }
1202
1203 if (bagSize(transports) == 0) {
1204 errmsg = "no transport specified";
1205 goto bad_option_with_errmsg;
1206 }
1207
1208 /*
1209 * TO DO: Remove when multiple transports are allowed. (replace with
1210 * check below.
1211 */
1212 if (bagSize(transports) > 1) {
1213 errmsg = "multiple transports are not supported in this release";
1214 goto bad_option_with_errmsg;
1215 }
1216
1217
1218 if (!isServer) {
1219 jboolean specified = bagEnumerateOver(transports, checkAddress, NULL);
1220 if (!specified) {
1221 /* message already printed */
1222 goto bad_option_no_msg;
1223 }
1224 }
1225
1226 /*
1227 * The user has selected to wait for an exception before init happens
1228 */
1229 if ((initOnException != NULL) || (initOnUncaught)) {
1230 initOnStartup = JNI_FALSE;
1231
1232 if (launchOnInit == NULL) {
1233 /*
1234 * These rely on the launch=/usr/bin/foo
1235 * suboption, so it is an error if user did not
1236 * provide one.
1237 */
1238 errmsg = "Specify launch=<command line> when using onthrow or onuncaught suboption";
1239 goto bad_option_with_errmsg;
1240 }
1241 }
1242
1243 return JNI_TRUE;
1244
1245syntax_error:
1246 ERROR_MESSAGE(("JDWP option syntax error: %s=%s", AGENTLIB, options));
1247 return JNI_FALSE;
1248
1249bad_option_with_errmsg:
1250 ERROR_MESSAGE(("JDWP %s: %s=%s", errmsg, AGENTLIB, options));
1251 return JNI_FALSE;
1252
1253bad_option_no_msg:
1254 ERROR_MESSAGE(("JDWP %s: %s=%s", "invalid option", AGENTLIB, options));
1255 return JNI_FALSE;
1256}
1257
1258/* All normal exit doors lead here */
1259void
1260debugInit_exit(jvmtiError error, const char *msg)
1261{
1262 int exit_code = 0;
1263
1264 /* Pick an error code */
1265 if ( error != JVMTI_ERROR_NONE ) {
1266 exit_code = 1;
1267 if ( docoredump ) {
1268 finish_logging(exit_code);
1269 abort();
1270 }
1271 }
1272 if ( msg==NULL ) {
1273 msg = "";
1274 }
1275
1276 LOG_MISC(("Exiting with error %s(%d): %s", jvmtiErrorText(error), error, msg));
1277
1278 gdata->vmDead = JNI_TRUE;
1279
1280 /* Let's try and cleanup the JVMTI, if we even have one */
1281 if ( gdata->jvmti != NULL ) {
1282 /* Dispose of jvmti (gdata->jvmti becomes NULL) */
1283 disposeEnvironment(gdata->jvmti);
1284 }
1285
1286 /* Finish up logging. We reach here if JDWP is doing the exiting. */
1287 finish_logging(exit_code); /* Only first call matters */
1288
1289 /* Let's give the JNI a FatalError if non-exit 0, which is historic way */
1290 if ( exit_code != 0 ) {
1291 JNIEnv *env = NULL;
1292 jniFatalError(env, msg, error, exit_code);
1293 }
1294
1295 /* Last chance to die, this kills the entire process. */
1296 forceExit(exit_code);
1297}