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