Path: blob/master/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c
41152 views
/*1* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include <string.h>25#include "jni.h"2627#include "jdwpTransport.h"28#include "shmemBase.h"29#include "sysShmem.h"30#include "sys.h"3132/*33* The Shared Memory Transport Library.34*35* This module is an implementation of the Java Debug Wire Protocol Transport36* Service Provider Interface - see src/share/javavm/export/jdwpTransport.h.37*/3839static SharedMemoryTransport *transport = NULL; /* maximum of 1 transport */40static SharedMemoryConnection *connection = NULL; /* maximum of 1 connection */41static jdwpTransportCallback *callbacks;42static jboolean initialized;43static struct jdwpTransportNativeInterface_ interface;44static jdwpTransportEnv single_env = (jdwpTransportEnv)&interface;4546/*47* Thread-local index to the per-thread error message48*/49static int tlsIndex;5051/*52* Return an error and record the error message associated with53* the error. Note the if (1==1) { } usage here is to avoid54* compilers complaining that a statement isn't reached which55* will arise if the semicolon (;) appears after the macro,56*/57#define RETURN_ERROR(err, msg) \58if (1==1) { \59setLastError(err, msg); \60return err; \61}6263/*64* Return an I/O error and record the error message.65*/66#define RETURN_IO_ERROR(msg) RETURN_ERROR(JDWPTRANSPORT_ERROR_IO_ERROR, msg);676869/*70* Set the error message for this thread. If the error is an I/O71* error then augment the supplied error message with the textual72* representation of the I/O error.73*/74static void75setLastError(int err, char *newmsg) {76char buf[255];77char *msg;7879/* get any I/O first in case any system calls override errno */80if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {81if (shmemBase_getlasterror(buf, sizeof(buf)) != SYS_OK) {82buf[0] = '\0';83}84}8586/* free any current error */87msg = (char *)sysTlsGet(tlsIndex);88if (msg != NULL) {89(*callbacks->free)(msg);90}9192/*93* For I/O errors append the I/O error message with to the94* supplied message. For all other errors just use the supplied95* message.96*/97if (err == JDWPTRANSPORT_ERROR_IO_ERROR) {98char *join_str = ": ";99int msg_len = (int)strlen(newmsg) + (int)strlen(join_str) +100(int)strlen(buf) + 3;101msg = (*callbacks->alloc)(msg_len);102if (msg != NULL) {103strcpy(msg, newmsg);104strcat(msg, join_str);105strcat(msg, buf);106}107} else {108msg = (*callbacks->alloc)((int)strlen(newmsg)+1);109if (msg != NULL) {110strcpy(msg, newmsg);111}112}113114/* Put a pointer to the message in TLS */115sysTlsPut(tlsIndex, msg);116}117118static jdwpTransportError119handshake()120{121char *hello = "JDWP-Handshake";122unsigned int i;123124for (i=0; i<strlen(hello); i++) {125jbyte b;126int rv = shmemBase_receiveByte(connection, &b);127if (rv != 0) {128RETURN_IO_ERROR("receive failed during handshake");129}130if ((char)b != hello[i]) {131RETURN_IO_ERROR("handshake failed - debugger sent unexpected message");132}133}134135for (i=0; i<strlen(hello); i++) {136int rv = shmemBase_sendByte(connection, (jbyte)hello[i]);137if (rv != 0) {138RETURN_IO_ERROR("write failed during handshake");139}140}141142return JDWPTRANSPORT_ERROR_NONE;143}144145146/*147* Return the capabilities of the shared memory transport. The shared148* memory transport supports both the attach and accept timeouts but149* doesn't support a handshake timeout.150*/151static jdwpTransportError JNICALL152shmemGetCapabilities(jdwpTransportEnv* env, JDWPTransportCapabilities *capabilitiesPtr)153{154JDWPTransportCapabilities result;155156memset(&result, 0, sizeof(result));157result.can_timeout_attach = JNI_TRUE;158result.can_timeout_accept = JNI_TRUE;159result.can_timeout_handshake = JNI_FALSE;160161*capabilitiesPtr = result;162163return JDWPTRANSPORT_ERROR_NONE;164}165166167static jdwpTransportError JNICALL168shmemStartListening(jdwpTransportEnv* env, const char *address, char **actualAddress)169{170jint rc;171172if (connection != NULL || transport != NULL) {173RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected or already listening");174}175176rc = shmemBase_listen(address, &transport);177178/*179* If a name was selected by the function above, find it and return180* it in place of the original arg.181*/182if (rc == SYS_OK) {183char *name;184char *name2;185rc = shmemBase_name(transport, &name);186if (rc == SYS_OK) {187name2 = (callbacks->alloc)((int)strlen(name) + 1);188if (name2 == NULL) {189RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");190} else {191strcpy(name2, name);192*actualAddress = name2;193}194}195} else {196RETURN_IO_ERROR("failed to create shared memory listener");197}198return JDWPTRANSPORT_ERROR_NONE;199}200201static jdwpTransportError JNICALL202shmemAccept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout)203{204jint rc;205206if (connection != NULL) {207RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected");208}209if (transport == NULL) {210RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "transport not listening");211}212213rc = shmemBase_accept(transport, (long)acceptTimeout, &connection);214if (rc != SYS_OK) {215if (rc == SYS_TIMEOUT) {216RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "Timed out waiting for connection");217} else {218RETURN_IO_ERROR("failed to accept shared memory connection");219}220}221222rc = handshake();223if (rc != JDWPTRANSPORT_ERROR_NONE) {224shmemBase_closeConnection(connection);225connection = NULL;226}227return rc;228}229230static jdwpTransportError JNICALL231shmemStopListening(jdwpTransportEnv* env)232{233if (transport != NULL) {234shmemBase_closeTransport(transport);235transport = NULL;236}237return JDWPTRANSPORT_ERROR_NONE;238}239240static jdwpTransportError JNICALL241shmemAttach(jdwpTransportEnv* env, const char *address, jlong attachTimeout, jlong handshakeTimeout)242{243jint rc;244245if (connection != NULL) {246RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected");247}248rc = shmemBase_attach(address, (long)attachTimeout, &connection);249if (rc != SYS_OK) {250if (rc == SYS_NOMEM) {251RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory");252}253if (rc == SYS_TIMEOUT) {254RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "Timed out waiting to attach");255}256RETURN_IO_ERROR("failed to attach to shared memory connection");257}258259rc = handshake();260if (rc != JDWPTRANSPORT_ERROR_NONE) {261shmemBase_closeConnection(connection);262connection = NULL;263}264return rc;265}266267static jdwpTransportError JNICALL268shmemWritePacket(jdwpTransportEnv* env, const jdwpPacket *packet)269{270if (packet == NULL) {271RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null");272}273if (packet->type.cmd.len < JDWP_HEADER_SIZE) {274RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid length");275}276if (connection == NULL) {277RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "not connected");278}279if (shmemBase_sendPacket(connection, packet) == SYS_OK) {280return JDWPTRANSPORT_ERROR_NONE;281} else {282RETURN_IO_ERROR("write packet failed");283}284}285286static jdwpTransportError JNICALL287shmemReadPacket(jdwpTransportEnv* env, jdwpPacket *packet)288{289if (packet == NULL) {290RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null");291}292if (connection == NULL) {293RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "not connected");294}295if (shmemBase_receivePacket(connection, packet) == SYS_OK) {296return JDWPTRANSPORT_ERROR_NONE;297} else {298RETURN_IO_ERROR("receive packet failed");299}300}301302static jboolean JNICALL303shmemIsOpen(jdwpTransportEnv* env)304{305if (connection != NULL) {306return JNI_TRUE;307} else {308return JNI_FALSE;309}310}311312static jdwpTransportError JNICALL313shmemClose(jdwpTransportEnv* env)314{315SharedMemoryConnection* current_connection = connection;316if (current_connection != NULL) {317connection = NULL;318shmemBase_closeConnection(current_connection);319}320return JDWPTRANSPORT_ERROR_NONE;321}322323/*324* Return the error message for this thread.325*/326static jdwpTransportError JNICALL327shmemGetLastError(jdwpTransportEnv* env, char **msgP)328{329char *msg = (char *)sysTlsGet(tlsIndex);330if (msg == NULL) {331return JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE;332}333*msgP = (*callbacks->alloc)((int)strlen(msg)+1);334if (*msgP == NULL) {335return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY;336}337strcpy(*msgP, msg);338return JDWPTRANSPORT_ERROR_NONE;339}340341JNIEXPORT jint JNICALL342jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,343jint version, jdwpTransportEnv** result)344{345if (version != JDWPTRANSPORT_VERSION_1_0) {346return JNI_EVERSION;347}348if (initialized) {349/*350* This library doesn't support multiple environments (yet)351*/352return JNI_EEXIST;353}354initialized = JNI_TRUE;355356/* initialize base shared memory system */357(void) shmemBase_initialize(vm, cbTablePtr);358359/* save callbacks */360callbacks = cbTablePtr;361362/* initialize interface table */363interface.GetCapabilities = &shmemGetCapabilities;364interface.Attach = &shmemAttach;365interface.StartListening = &shmemStartListening;366interface.StopListening = &shmemStopListening;367interface.Accept = &shmemAccept;368interface.IsOpen = &shmemIsOpen;369interface.Close = &shmemClose;370interface.ReadPacket = &shmemReadPacket;371interface.WritePacket = &shmemWritePacket;372interface.GetLastError = &shmemGetLastError;373*result = &single_env;374375/* initialized TLS */376tlsIndex = sysTlsAlloc();377378return JNI_OK;379}380381382