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