1 /* 2 * Copyright (c) 1998, 2014, 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 "util.h" 27 #include "utf_util.h" 28 #include "transport.h" 29 #include "debugLoop.h" 30 #include "sys.h" 31 32 static jdwpTransportEnv *transport; 33 static jrawMonitorID listenerLock; 34 static jrawMonitorID sendLock; 35 36 /* 37 * data structure used for passing transport info from thread to thread 38 */ 39 typedef struct TransportInfo { 40 char *name; 41 jdwpTransportEnv *transport; 42 char *address; 43 long timeout; 44 } TransportInfo; 45 46 static struct jdwpTransportCallback callback = {jvmtiAllocate, jvmtiDeallocate}; 47 48 /* 49 * Print the last transport error 50 */ 51 static void 52 printLastError(jdwpTransportEnv *t, jdwpTransportError err) 53 { 54 char *msg; 55 jbyte *utf8msg; 56 jdwpTransportError rv; 57 58 msg = NULL; 59 utf8msg = NULL; 60 rv = (*t)->GetLastError(t, &msg); /* This is a platform encoded string */ 61 if ( msg != NULL ) { 62 int len; 63 int maxlen; 64 65 /* Convert this string to UTF8 */ 66 len = (int)strlen(msg); 67 maxlen = len+len/2+2; /* Should allow for plenty of room */ 68 utf8msg = (jbyte*)jvmtiAllocate(maxlen+1); 69 if (utf8msg != NULL) { 70 (void)utf8FromPlatform(msg, len, utf8msg, maxlen); 71 utf8msg[maxlen] = 0; 72 } 73 } 74 if (rv == JDWPTRANSPORT_ERROR_NONE) { 75 ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); 76 } else if ( msg!=NULL ) { 77 ERROR_MESSAGE(("transport error %d: %s",err, utf8msg)); 78 } else { 79 ERROR_MESSAGE(("transport error %d: %s",err, "UNKNOWN")); 80 } 81 jvmtiDeallocate(msg); 82 jvmtiDeallocate(utf8msg); 83 } 84 85 /* Find OnLoad symbol */ 86 static jdwpTransport_OnLoad_t 87 findTransportOnLoad(void *handle) 88 { 89 jdwpTransport_OnLoad_t onLoad; 90 91 onLoad = (jdwpTransport_OnLoad_t)NULL; 92 if (handle == NULL) { 93 return onLoad; 94 } 95 onLoad = (jdwpTransport_OnLoad_t) 96 dbgsysFindLibraryEntry(handle, "jdwpTransport_OnLoad"); 97 return onLoad; 98 } 99 100 /* Load transport library (directory=="" means do system search) */ 101 static void * 102 loadTransportLibrary(const char *libdir, const char *name) 103 { 104 void *handle; 105 char libname[MAXPATHLEN+2]; 106 char buf[MAXPATHLEN*2+100]; 107 const char *plibdir; 108 109 /* Convert libdir from UTF-8 to platform encoding */ 110 plibdir = NULL; 111 if ( libdir != NULL ) { 112 int len; 113 114 len = (int)strlen(libdir); 115 (void)utf8ToPlatform((jbyte*)libdir, len, buf, (int)sizeof(buf)); 116 plibdir = buf; 117 } 118 119 /* Construct library name (simple name or full path) */ 120 dbgsysBuildLibName(libname, sizeof(libname), plibdir, name); 121 if (strlen(libname) == 0) { 122 return NULL; 123 } 124 125 /* dlopen (unix) / LoadLibrary (windows) the transport library */ 126 handle = dbgsysLoadLibrary(libname, buf, sizeof(buf)); 127 return handle; 128 } 129 130 /* 131 * loadTransport() is adapted from loadJVMHelperLib() in 132 * JDK 1.2 javai.c v1.61 133 */ 134 static jdwpError 135 loadTransport(const char *name, jdwpTransportEnv **transportPtr) 136 { 137 JNIEnv *env; 138 jdwpTransport_OnLoad_t onLoad; 139 void *handle; 140 const char *libdir; 141 142 /* Make sure library name is not empty */ 143 if (name == NULL) { 144 ERROR_MESSAGE(("library name is empty")); 145 return JDWP_ERROR(TRANSPORT_LOAD); 146 } 147 148 /* First, look in sun.boot.library.path. This should find the standard 149 * dt_socket and dt_shmem transport libraries, or any library 150 * that was delivered with the J2SE. 151 * Note: Since 6819213 fixed, Java property sun.boot.library.path can 152 * contain multiple paths. Dll_dir is the first entry and 153 * -Dsun.boot.library.path entries are appended. 154 */ 155 libdir = gdata->property_sun_boot_library_path; 156 if (libdir == NULL) { 157 ERROR_MESSAGE(("Java property sun.boot.library.path is not set")); 158 return JDWP_ERROR(TRANSPORT_LOAD); 159 } 160 handle = loadTransportLibrary(libdir, name); 161 if (handle == NULL) { 162 /* Second, look along the path used by the native dlopen/LoadLibrary 163 * functions. This should effectively try and load the simple 164 * library name, which will cause the default system library 165 * search technique to happen. 166 * We should only reach here if the transport library wasn't found 167 * in the J2SE directory, e.g. it's a custom transport library 168 * not installed in the J2SE like dt_socket and dt_shmem is. 169 * 170 * Note: Why not use java.library.path? Several reasons: 171 * a) This matches existing agentlib search 172 * b) These are technically not JNI libraries 173 */ 174 handle = loadTransportLibrary("", name); 175 } 176 177 /* See if a library was found with this name */ 178 if (handle == NULL) { 179 ERROR_MESSAGE(("transport library not found: %s", name)); 180 return JDWP_ERROR(TRANSPORT_LOAD); 181 } 182 183 /* Find the onLoad address */ 184 onLoad = findTransportOnLoad(handle); 185 if (onLoad == NULL) { 186 ERROR_MESSAGE(("transport library missing onLoad entry: %s", name)); 187 return JDWP_ERROR(TRANSPORT_LOAD); 188 } 189 190 /* Get transport interface */ 191 env = getEnv(); 192 if ( env != NULL ) { 193 jdwpTransportEnv *t; 194 JavaVM *jvm; 195 jint ver; 196 197 JNI_FUNC_PTR(env,GetJavaVM)(env, &jvm); 198 ver = (*onLoad)(jvm, &callback, JDWPTRANSPORT_VERSION_1_0, &t); 199 if (ver != JNI_OK) { 200 switch (ver) { 201 case JNI_ENOMEM : 202 ERROR_MESSAGE(("insufficient memory to complete initialization")); 203 break; 204 205 case JNI_EVERSION : 206 ERROR_MESSAGE(("transport doesn't recognize version %x", 207 JDWPTRANSPORT_VERSION_1_0)); 208 break; 209 210 case JNI_EEXIST : 211 ERROR_MESSAGE(("transport doesn't support multiple environments")); 212 break; 213 214 default: 215 ERROR_MESSAGE(("unrecognized error %d from transport", ver)); 216 break; 217 } 218 219 return JDWP_ERROR(TRANSPORT_INIT); 220 } 221 *transportPtr = t; 222 } else { 223 return JDWP_ERROR(TRANSPORT_LOAD); 224 } 225 226 return JDWP_ERROR(NONE); 227 } 228 229 static void 230 connectionInitiated(jdwpTransportEnv *t) 231 { 232 jint isValid = JNI_FALSE; 233 234 debugMonitorEnter(listenerLock); 235 236 /* 237 * Don't allow a connection until initialization is complete 238 */ 239 debugInit_waitInitComplete(); 240 241 /* Are we the first transport to get a connection? */ 242 243 if (transport == NULL) { 244 transport = t; 245 isValid = JNI_TRUE; 246 } else { 247 if (transport == t) { 248 /* connected with the same transport as before */ 249 isValid = JNI_TRUE; 250 } else { 251 /* 252 * Another transport got a connection - multiple transports 253 * not fully supported yet so shouldn't get here. 254 */ 255 (*t)->Close(t); 256 JDI_ASSERT(JNI_FALSE); 257 } 258 } 259 260 if (isValid) { 261 debugMonitorNotifyAll(listenerLock); 262 } 263 264 debugMonitorExit(listenerLock); 265 266 if (isValid) { 267 debugLoop_run(); 268 } 269 270 } 271 272 /* 273 * Set the transport property (sun.jdwp.listenerAddress) to the 274 * specified value. 275 */ 276 static void 277 setTransportProperty(JNIEnv* env, char* value) { 278 char* prop_value = (value == NULL) ? "" : value; 279 setAgentPropertyValue(env, "sun.jdwp.listenerAddress", prop_value); 280 } 281 282 void 283 transport_waitForConnection(void) 284 { 285 /* 286 * If the VM is suspended on debugger initialization, we wait 287 * for a connection before continuing. This ensures that all 288 * events are delivered to the debugger. (We might as well do this 289 * this since the VM won't continue until a remote debugger attaches 290 * and resumes it.) If not suspending on initialization, we must 291 * just drop any packets (i.e. events) so that the VM can continue 292 * to run. The debugger may not attach until much later. 293 */ 294 if (debugInit_suspendOnInit()) { 295 debugMonitorEnter(listenerLock); 296 while (transport == NULL) { 297 debugMonitorWait(listenerLock); 298 } 299 debugMonitorExit(listenerLock); 300 } 301 } 302 303 static void JNICALL 304 acceptThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) 305 { 306 TransportInfo *info; 307 jdwpTransportEnv *t; 308 jdwpTransportError rc; 309 310 LOG_MISC(("Begin accept thread")); 311 312 info = (TransportInfo*)(void*)arg; 313 t = info->transport; 314 315 rc = (*t)->Accept(t, info->timeout, 0); 316 317 /* System property no longer needed */ 318 setTransportProperty(jni_env, NULL); 319 320 if (rc != JDWPTRANSPORT_ERROR_NONE) { 321 /* 322 * If accept fails it probably means a timeout, or another fatal error 323 * We thus exit the VM after stopping the listener. 324 */ 325 printLastError(t, rc); 326 (*t)->StopListening(t); 327 EXIT_ERROR(JVMTI_ERROR_NONE, "could not connect, timeout or fatal error"); 328 } else { 329 (*t)->StopListening(t); 330 connectionInitiated(t); 331 } 332 333 LOG_MISC(("End accept thread")); 334 } 335 336 static void JNICALL 337 attachThread(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg) 338 { 339 LOG_MISC(("Begin attach thread")); 340 connectionInitiated((jdwpTransportEnv *)(void*)arg); 341 LOG_MISC(("End attach thread")); 342 } 343 344 void 345 transport_initialize(void) 346 { 347 transport = NULL; 348 listenerLock = debugMonitorCreate("JDWP Transport Listener Monitor"); 349 sendLock = debugMonitorCreate("JDWP Transport Send Monitor"); 350 } 351 352 void 353 transport_reset(void) 354 { 355 /* 356 * Reset the transport by closing any listener (will silently fail 357 * with JDWPTRANSPORT_ERROR_ILLEGAL_STATE if not listening), and 358 * closing any connection (will also fail silently if not 359 * connected). 360 * 361 * Note: There's an assumption here that we don't yet support 362 * multiple transports. When we do then we need a clear transition 363 * from the current transport to the new transport. 364 */ 365 if (transport != NULL) { 366 setTransportProperty(getEnv(), NULL); 367 (*transport)->StopListening(transport); 368 (*transport)->Close(transport); 369 } 370 } 371 372 static jdwpError 373 launch(char *command, char *name, char *address) 374 { 375 jint rc; 376 char *buf; 377 char *commandLine; 378 int len; 379 380 /* Construct complete command line (all in UTF-8) */ 381 commandLine = jvmtiAllocate((int)strlen(command) + 382 (int)strlen(name) + 383 (int)strlen(address) + 3); 384 if (commandLine == NULL) { 385 return JDWP_ERROR(OUT_OF_MEMORY); 386 } 387 (void)strcpy(commandLine, command); 388 (void)strcat(commandLine, " "); 389 (void)strcat(commandLine, name); 390 (void)strcat(commandLine, " "); 391 (void)strcat(commandLine, address); 392 393 /* Convert commandLine from UTF-8 to platform encoding */ 394 len = (int)strlen(commandLine); 395 buf = jvmtiAllocate(len*3+3); 396 if (buf == NULL) { 397 jvmtiDeallocate(commandLine); 398 return JDWP_ERROR(OUT_OF_MEMORY); 399 } 400 (void)utf8ToPlatform((jbyte*)commandLine, len, buf, len*3+3); 401 402 /* Exec commandLine */ 403 rc = dbgsysExec(buf); 404 405 /* Free up buffers */ 406 jvmtiDeallocate(buf); 407 jvmtiDeallocate(commandLine); 408 409 /* And non-zero exit status means we had an error */ 410 if (rc != SYS_OK) { 411 return JDWP_ERROR(TRANSPORT_INIT); 412 } 413 return JDWP_ERROR(NONE); 414 } 415 416 jdwpError 417 transport_startTransport(jboolean isServer, char *name, char *address, 418 long timeout) 419 { 420 jvmtiStartFunction func; 421 jdwpTransportEnv *trans; 422 char threadName[MAXPATHLEN + 100]; 423 jint err; 424 jdwpError serror; 425 426 /* 427 * If the transport is already loaded then use it 428 * Note: We're assuming here that we don't support multiple 429 * transports - when we do then we need to handle the case 430 * where the transport library only supports a single environment. 431 * That probably means we have a bag a transport environments 432 * to correspond to the transports bag. 433 */ 434 if (transport != NULL) { 435 trans = transport; 436 } else { 437 serror = loadTransport(name, &trans); 438 if (serror != JDWP_ERROR(NONE)) { 439 return serror; 440 } 441 } 442 443 if (isServer) { 444 445 char *retAddress; 446 char *launchCommand; 447 TransportInfo *info; 448 jvmtiError error; 449 int len; 450 char* prop_value; 451 452 info = jvmtiAllocate(sizeof(*info)); 453 if (info == NULL) { 454 return JDWP_ERROR(OUT_OF_MEMORY); 455 } 456 info->timeout = timeout; 457 458 info->name = jvmtiAllocate((int)strlen(name)+1); 459 if (info->name == NULL) { 460 serror = JDWP_ERROR(OUT_OF_MEMORY); 461 goto handleError; 462 } 463 (void)strcpy(info->name, name); 464 465 info->address = NULL; 466 if (address != NULL) { 467 info->address = jvmtiAllocate((int)strlen(address)+1); 468 if (info->address == NULL) { 469 serror = JDWP_ERROR(OUT_OF_MEMORY); 470 goto handleError; 471 } 472 (void)strcpy(info->address, address); 473 } 474 475 info->transport = trans; 476 477 err = (*trans)->StartListening(trans, address, &retAddress); 478 if (err != JDWPTRANSPORT_ERROR_NONE) { 479 printLastError(trans, err); 480 serror = JDWP_ERROR(TRANSPORT_INIT); 481 goto handleError; 482 } 483 484 /* 485 * Record listener address in a system property 486 */ 487 len = (int)strlen(name) + (int)strlen(retAddress) + 2; /* ':' and '\0' */ 488 prop_value = (char*)jvmtiAllocate(len); 489 if (prop_value == NULL) { 490 serror = JDWP_ERROR(OUT_OF_MEMORY); 491 goto handleError; 492 } 493 strcpy(prop_value, name); 494 strcat(prop_value, ":"); 495 strcat(prop_value, retAddress); 496 setTransportProperty(getEnv(), prop_value); 497 jvmtiDeallocate(prop_value); 498 499 500 (void)strcpy(threadName, "JDWP Transport Listener: "); 501 (void)strcat(threadName, name); 502 503 func = &acceptThread; 504 error = spawnNewThread(func, (void*)info, threadName); 505 if (error != JVMTI_ERROR_NONE) { 506 serror = map2jdwpError(error); 507 goto handleError; 508 } 509 510 launchCommand = debugInit_launchOnInit(); 511 if (launchCommand != NULL) { 512 serror = launch(launchCommand, name, retAddress); 513 if (serror != JDWP_ERROR(NONE)) { 514 goto handleError; 515 } 516 } else { 517 if ( ! gdata->quiet ) { 518 TTY_MESSAGE(("Listening for transport %s at address: %s", 519 name, retAddress)); 520 } 521 } 522 return JDWP_ERROR(NONE); 523 524 handleError: 525 jvmtiDeallocate(info->name); 526 jvmtiDeallocate(info->address); 527 jvmtiDeallocate(info); 528 } else { 529 /* 530 * Note that we don't attempt to do a launch here. Launching 531 * is currently supported only in server mode. 532 */ 533 534 /* 535 * If we're connecting to another process, there shouldn't be 536 * any concurrent listens, so its ok if we block here in this 537 * thread, waiting for the attach to finish. 538 */ 539 err = (*trans)->Attach(trans, address, timeout, 0); 540 if (err != JDWPTRANSPORT_ERROR_NONE) { 541 printLastError(trans, err); 542 serror = JDWP_ERROR(TRANSPORT_INIT); 543 return serror; 544 } 545 546 /* 547 * Start the transport loop in a separate thread 548 */ 549 (void)strcpy(threadName, "JDWP Transport Listener: "); 550 (void)strcat(threadName, name); 551 552 func = &attachThread; 553 err = spawnNewThread(func, (void*)trans, threadName); 554 serror = map2jdwpError(err); 555 } 556 return serror; 557 } 558 559 void 560 transport_close(void) 561 { 562 if ( transport != NULL ) { 563 (*transport)->Close(transport); 564 } 565 } 566 567 jboolean 568 transport_is_open(void) 569 { 570 jboolean is_open = JNI_FALSE; 571 572 if ( transport != NULL ) { 573 is_open = (*transport)->IsOpen(transport); 574 } 575 return is_open; 576 } 577 578 jint 579 transport_sendPacket(jdwpPacket *packet) 580 { 581 jdwpTransportError err = JDWPTRANSPORT_ERROR_NONE; 582 jint rc = 0; 583 584 if (transport != NULL) { 585 if ( (*transport)->IsOpen(transport) ) { 586 debugMonitorEnter(sendLock); 587 err = (*transport)->WritePacket(transport, packet); 588 debugMonitorExit(sendLock); 589 } 590 if (err != JDWPTRANSPORT_ERROR_NONE) { 591 if ((*transport)->IsOpen(transport)) { 592 printLastError(transport, err); 593 } 594 595 /* 596 * The users of transport_sendPacket except 0 for 597 * success; non-0 otherwise. 598 */ 599 rc = (jint)-1; 600 } 601 602 } /* else, bit bucket */ 603 604 return rc; 605 } 606 607 jint 608 transport_receivePacket(jdwpPacket *packet) 609 { 610 jdwpTransportError err; 611 612 err = (*transport)->ReadPacket(transport, packet); 613 if (err != JDWPTRANSPORT_ERROR_NONE) { 614 /* 615 * If transport has been closed return EOF 616 */ 617 if (!(*transport)->IsOpen(transport)) { 618 packet->type.cmd.len = 0; 619 return 0; 620 } 621 622 printLastError(transport, err); 623 624 /* 625 * Users of transport_receivePacket expect 0 for success, 626 * non-0 otherwise. 627 */ 628 return (jint)-1; 629 } 630 return 0; 631 }