author | clanger |
Tue, 12 Dec 2017 09:16:12 +0100 | |
changeset 48242 | 61e60548c0cf |
parent 47216 | 71c04702a3d5 |
child 49440 | 396ea30afbd5 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
48242 | 2 |
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
#include <string.h> |
|
26 |
||
27 |
#include "jdwpTransport.h" |
|
28 |
#include "shmemBase.h" |
|
29 |
#include "sysShmem.h" |
|
30 |
#include "sys.h" |
|
31 |
||
32 |
/* |
|
33 |
* The Shared Memory Transport Library. |
|
34 |
* |
|
35 |
* This module is an implementation of the Java Debug Wire Protocol Transport |
|
36 |
* Service Provider Interface - see src/share/javavm/export/jdwpTransport.h. |
|
37 |
*/ |
|
38 |
||
39 |
static SharedMemoryTransport *transport = NULL; /* maximum of 1 transport */ |
|
40 |
static SharedMemoryConnection *connection = NULL; /* maximum of 1 connection */ |
|
41 |
static jdwpTransportCallback *callbacks; |
|
42 |
static jboolean initialized; |
|
43 |
static struct jdwpTransportNativeInterface_ interface; |
|
44 |
static jdwpTransportEnv single_env = (jdwpTransportEnv)&interface; |
|
45 |
||
46 |
/* |
|
47 |
* Thread-local index to the per-thread error message |
|
48 |
*/ |
|
49 |
static int tlsIndex; |
|
50 |
||
51 |
/* |
|
52 |
* Return an error and record the error message associated with |
|
53 |
* the error. Note the if (1==1) { } usage here is to avoid |
|
54 |
* compilers complaining that a statement isn't reached which |
|
55 |
* will arise if the semicolon (;) appears after the macro, |
|
56 |
*/ |
|
57 |
#define RETURN_ERROR(err, msg) \ |
|
58 |
if (1==1) { \ |
|
59 |
setLastError(err, msg); \ |
|
60 |
return err; \ |
|
61 |
} |
|
62 |
||
63 |
/* |
|
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); |
|
67 |
||
68 |
||
69 |
/* |
|
70 |
* Set the error message for this thread. If the error is an I/O |
|
71 |
* error then augment the supplied error message with the textual |
|
72 |
* representation of the I/O error. |
|
73 |
*/ |
|
74 |
static void |
|
75 |
setLastError(int err, char *newmsg) { |
|
76 |
char buf[255]; |
|
77 |
char *msg; |
|
78 |
||
79 |
/* get any I/O first in case any system calls override errno */ |
|
80 |
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) { |
|
81 |
if (shmemBase_getlasterror(buf, sizeof(buf)) != SYS_OK) { |
|
82 |
buf[0] = '\0'; |
|
83 |
} |
|
84 |
} |
|
85 |
||
86 |
/* free any current error */ |
|
87 |
msg = (char *)sysTlsGet(tlsIndex); |
|
88 |
if (msg != NULL) { |
|
89 |
(*callbacks->free)(msg); |
|
90 |
} |
|
91 |
||
92 |
/* |
|
93 |
* For I/O errors append the I/O error message with to the |
|
94 |
* supplied message. For all other errors just use the supplied |
|
95 |
* message. |
|
96 |
*/ |
|
97 |
if (err == JDWPTRANSPORT_ERROR_IO_ERROR) { |
|
98 |
char *join_str = ": "; |
|
896
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
99 |
int msg_len = (int)strlen(newmsg) + (int)strlen(join_str) + |
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
100 |
(int)strlen(buf) + 3; |
2 | 101 |
msg = (*callbacks->alloc)(msg_len); |
102 |
if (msg != NULL) { |
|
103 |
strcpy(msg, newmsg); |
|
104 |
strcat(msg, join_str); |
|
105 |
strcat(msg, buf); |
|
106 |
} |
|
107 |
} else { |
|
896
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
108 |
msg = (*callbacks->alloc)((int)strlen(newmsg)+1); |
2 | 109 |
if (msg != NULL) { |
110 |
strcpy(msg, newmsg); |
|
111 |
} |
|
112 |
} |
|
113 |
||
114 |
/* Put a pointer to the message in TLS */ |
|
115 |
sysTlsPut(tlsIndex, msg); |
|
116 |
} |
|
117 |
||
118 |
static jdwpTransportError |
|
119 |
handshake() |
|
120 |
{ |
|
121 |
char *hello = "JDWP-Handshake"; |
|
122 |
unsigned int i; |
|
123 |
||
124 |
for (i=0; i<strlen(hello); i++) { |
|
125 |
jbyte b; |
|
126 |
int rv = shmemBase_receiveByte(connection, &b); |
|
127 |
if (rv != 0) { |
|
128 |
RETURN_IO_ERROR("receive failed during handshake"); |
|
129 |
} |
|
130 |
if ((char)b != hello[i]) { |
|
131 |
RETURN_IO_ERROR("handshake failed - debugger sent unexpected message"); |
|
132 |
} |
|
133 |
} |
|
134 |
||
135 |
for (i=0; i<strlen(hello); i++) { |
|
136 |
int rv = shmemBase_sendByte(connection, (jbyte)hello[i]); |
|
137 |
if (rv != 0) { |
|
138 |
RETURN_IO_ERROR("write failed during handshake"); |
|
139 |
} |
|
140 |
} |
|
141 |
||
142 |
return JDWPTRANSPORT_ERROR_NONE; |
|
143 |
} |
|
144 |
||
145 |
||
146 |
/* |
|
147 |
* Return the capabilities of the shared memory transport. The shared |
|
148 |
* memory transport supports both the attach and accept timeouts but |
|
149 |
* doesn't support a handshake timeout. |
|
150 |
*/ |
|
151 |
static jdwpTransportError JNICALL |
|
152 |
shmemGetCapabilities(jdwpTransportEnv* env, JDWPTransportCapabilities *capabilitiesPtr) |
|
153 |
{ |
|
154 |
JDWPTransportCapabilities result; |
|
155 |
||
156 |
memset(&result, 0, sizeof(result)); |
|
157 |
result.can_timeout_attach = JNI_TRUE; |
|
158 |
result.can_timeout_accept = JNI_TRUE; |
|
159 |
result.can_timeout_handshake = JNI_FALSE; |
|
160 |
||
161 |
*capabilitiesPtr = result; |
|
162 |
||
163 |
return JDWPTRANSPORT_ERROR_NONE; |
|
164 |
} |
|
165 |
||
166 |
||
167 |
static jdwpTransportError JNICALL |
|
168 |
shmemStartListening(jdwpTransportEnv* env, const char *address, char **actualAddress) |
|
169 |
{ |
|
170 |
jint rc; |
|
171 |
||
172 |
if (connection != NULL || transport != NULL) { |
|
173 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected or already listening"); |
|
174 |
} |
|
175 |
||
176 |
rc = shmemBase_listen(address, &transport); |
|
177 |
||
178 |
/* |
|
179 |
* If a name was selected by the function above, find it and return |
|
180 |
* it in place of the original arg. |
|
181 |
*/ |
|
182 |
if (rc == SYS_OK) { |
|
183 |
char *name; |
|
184 |
char *name2; |
|
185 |
rc = shmemBase_name(transport, &name); |
|
186 |
if (rc == SYS_OK) { |
|
896
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
187 |
name2 = (callbacks->alloc)((int)strlen(name) + 1); |
2 | 188 |
if (name2 == NULL) { |
189 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory"); |
|
190 |
} else { |
|
191 |
strcpy(name2, name); |
|
192 |
*actualAddress = name2; |
|
193 |
} |
|
194 |
} |
|
195 |
} else { |
|
196 |
RETURN_IO_ERROR("failed to create shared memory listener"); |
|
197 |
} |
|
198 |
return JDWPTRANSPORT_ERROR_NONE; |
|
199 |
} |
|
200 |
||
201 |
static jdwpTransportError JNICALL |
|
202 |
shmemAccept(jdwpTransportEnv* env, jlong acceptTimeout, jlong handshakeTimeout) |
|
203 |
{ |
|
204 |
jint rc; |
|
205 |
||
206 |
if (connection != NULL) { |
|
207 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected"); |
|
208 |
} |
|
209 |
if (transport == NULL) { |
|
210 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "transport not listening"); |
|
211 |
} |
|
212 |
||
213 |
rc = shmemBase_accept(transport, (long)acceptTimeout, &connection); |
|
214 |
if (rc != SYS_OK) { |
|
215 |
if (rc == SYS_TIMEOUT) { |
|
216 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "Timed out waiting for connection"); |
|
217 |
} else { |
|
218 |
RETURN_IO_ERROR("failed to accept shared memory connection"); |
|
219 |
} |
|
220 |
} |
|
221 |
||
222 |
rc = handshake(); |
|
223 |
if (rc != JDWPTRANSPORT_ERROR_NONE) { |
|
224 |
shmemBase_closeConnection(connection); |
|
225 |
connection = NULL; |
|
226 |
} |
|
227 |
return rc; |
|
228 |
} |
|
229 |
||
230 |
static jdwpTransportError JNICALL |
|
231 |
shmemStopListening(jdwpTransportEnv* env) |
|
232 |
{ |
|
233 |
if (transport != NULL) { |
|
234 |
shmemBase_closeTransport(transport); |
|
235 |
transport = NULL; |
|
236 |
} |
|
237 |
return JDWPTRANSPORT_ERROR_NONE; |
|
238 |
} |
|
239 |
||
240 |
static jdwpTransportError JNICALL |
|
241 |
shmemAttach(jdwpTransportEnv* env, const char *address, jlong attachTimeout, jlong handshakeTimeout) |
|
242 |
{ |
|
243 |
jint rc; |
|
244 |
||
245 |
if (connection != NULL) { |
|
246 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "already connected"); |
|
247 |
} |
|
248 |
rc = shmemBase_attach(address, (long)attachTimeout, &connection); |
|
249 |
if (rc != SYS_OK) { |
|
250 |
if (rc == SYS_NOMEM) { |
|
251 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_OUT_OF_MEMORY, "out of memory"); |
|
252 |
} |
|
253 |
if (rc == SYS_TIMEOUT) { |
|
254 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "Timed out waiting to attach"); |
|
255 |
} |
|
256 |
RETURN_IO_ERROR("failed to attach to shared memory connection"); |
|
257 |
} |
|
258 |
||
259 |
rc = handshake(); |
|
260 |
if (rc != JDWPTRANSPORT_ERROR_NONE) { |
|
261 |
shmemBase_closeConnection(connection); |
|
262 |
connection = NULL; |
|
263 |
} |
|
264 |
return rc; |
|
265 |
} |
|
266 |
||
267 |
static jdwpTransportError JNICALL |
|
268 |
shmemWritePacket(jdwpTransportEnv* env, const jdwpPacket *packet) |
|
269 |
{ |
|
270 |
if (packet == NULL) { |
|
271 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null"); |
|
272 |
} |
|
48242 | 273 |
if (packet->type.cmd.len < JDWP_HEADER_SIZE) { |
2 | 274 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "invalid length"); |
275 |
} |
|
276 |
if (connection == NULL) { |
|
277 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "not connected"); |
|
278 |
} |
|
279 |
if (shmemBase_sendPacket(connection, packet) == SYS_OK) { |
|
280 |
return JDWPTRANSPORT_ERROR_NONE; |
|
281 |
} else { |
|
282 |
RETURN_IO_ERROR("write packet failed"); |
|
283 |
} |
|
284 |
} |
|
285 |
||
286 |
static jdwpTransportError JNICALL |
|
287 |
shmemReadPacket(jdwpTransportEnv* env, jdwpPacket *packet) |
|
288 |
{ |
|
289 |
if (packet == NULL) { |
|
290 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_ARGUMENT, "packet is null"); |
|
291 |
} |
|
292 |
if (connection == NULL) { |
|
293 |
RETURN_ERROR(JDWPTRANSPORT_ERROR_ILLEGAL_STATE, "not connected"); |
|
294 |
} |
|
295 |
if (shmemBase_receivePacket(connection, packet) == SYS_OK) { |
|
296 |
return JDWPTRANSPORT_ERROR_NONE; |
|
297 |
} else { |
|
298 |
RETURN_IO_ERROR("receive packet failed"); |
|
299 |
} |
|
300 |
} |
|
301 |
||
302 |
static jboolean JNICALL |
|
303 |
shmemIsOpen(jdwpTransportEnv* env) |
|
304 |
{ |
|
305 |
if (connection != NULL) { |
|
306 |
return JNI_TRUE; |
|
307 |
} else { |
|
308 |
return JNI_FALSE; |
|
309 |
} |
|
310 |
} |
|
311 |
||
312 |
static jdwpTransportError JNICALL |
|
313 |
shmemClose(jdwpTransportEnv* env) |
|
314 |
{ |
|
315 |
SharedMemoryConnection* current_connection = connection; |
|
316 |
if (current_connection != NULL) { |
|
317 |
connection = NULL; |
|
318 |
shmemBase_closeConnection(current_connection); |
|
319 |
} |
|
320 |
return JDWPTRANSPORT_ERROR_NONE; |
|
321 |
} |
|
322 |
||
323 |
/* |
|
324 |
* Return the error message for this thread. |
|
325 |
*/ |
|
326 |
static jdwpTransportError JNICALL |
|
327 |
shmemGetLastError(jdwpTransportEnv* env, char **msgP) |
|
328 |
{ |
|
329 |
char *msg = (char *)sysTlsGet(tlsIndex); |
|
330 |
if (msg == NULL) { |
|
331 |
return JDWPTRANSPORT_ERROR_MSG_NOT_AVAILABLE; |
|
332 |
} |
|
896
5c02031316bf
6725543: Compiler warnings in serviceability native code
ohair
parents:
2
diff
changeset
|
333 |
*msgP = (*callbacks->alloc)((int)strlen(msg)+1); |
2 | 334 |
if (*msgP == NULL) { |
335 |
return JDWPTRANSPORT_ERROR_OUT_OF_MEMORY; |
|
336 |
} |
|
337 |
strcpy(*msgP, msg); |
|
338 |
return JDWPTRANSPORT_ERROR_NONE; |
|
339 |
} |
|
340 |
||
36134 | 341 |
jint JNICALL |
2 | 342 |
jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, |
343 |
jint version, jdwpTransportEnv** result) |
|
344 |
{ |
|
345 |
if (version != JDWPTRANSPORT_VERSION_1_0) { |
|
346 |
return JNI_EVERSION; |
|
347 |
} |
|
348 |
if (initialized) { |
|
349 |
/* |
|
350 |
* This library doesn't support multiple environments (yet) |
|
351 |
*/ |
|
352 |
return JNI_EEXIST; |
|
353 |
} |
|
354 |
initialized = JNI_TRUE; |
|
355 |
||
356 |
/* initialize base shared memory system */ |
|
357 |
(void) shmemBase_initialize(vm, cbTablePtr); |
|
358 |
||
359 |
/* save callbacks */ |
|
360 |
callbacks = cbTablePtr; |
|
361 |
||
362 |
/* initialize interface table */ |
|
363 |
interface.GetCapabilities = &shmemGetCapabilities; |
|
364 |
interface.Attach = &shmemAttach; |
|
365 |
interface.StartListening = &shmemStartListening; |
|
366 |
interface.StopListening = &shmemStopListening; |
|
367 |
interface.Accept = &shmemAccept; |
|
368 |
interface.IsOpen = &shmemIsOpen; |
|
369 |
interface.Close = &shmemClose; |
|
370 |
interface.ReadPacket = &shmemReadPacket; |
|
371 |
interface.WritePacket = &shmemWritePacket; |
|
372 |
interface.GetLastError = &shmemGetLastError; |
|
373 |
*result = &single_env; |
|
374 |
||
375 |
/* initialized TLS */ |
|
376 |
tlsIndex = sysTlsAlloc(); |
|
377 |
||
378 |
return JNI_OK; |
|
379 |
} |