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