1 /*
2  * Copyright (c) 1998, 2017, 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 package com.sun.tools.jdi;
27 
28 import java.io.ByteArrayOutputStream;
29 import java.util.ArrayList;
30 import java.util.List;
31 
32 import com.sun.jdi.BooleanValue;
33 import com.sun.jdi.ByteValue;
34 import com.sun.jdi.CharValue;
35 import com.sun.jdi.ClassType;
36 import com.sun.jdi.DoubleValue;
37 import com.sun.jdi.Field;
38 import com.sun.jdi.FloatValue;
39 import com.sun.jdi.IntegerValue;
40 import com.sun.jdi.InterfaceType;
41 import com.sun.jdi.InternalException;
42 import com.sun.jdi.InvalidTypeException;
43 import com.sun.jdi.Location;
44 import com.sun.jdi.LongValue;
45 import com.sun.jdi.ObjectReference;
46 import com.sun.jdi.PrimitiveValue;
47 import com.sun.jdi.ShortValue;
48 import com.sun.jdi.Value;
49 
50 class PacketStream {
51     final VirtualMachineImpl vm;
52     private int inCursor = 0;
53     final Packet pkt;
54     private ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
55     private boolean isCommitted = false;
56 
PacketStream(VirtualMachineImpl vm, int cmdSet, int cmd)57     PacketStream(VirtualMachineImpl vm, int cmdSet, int cmd) {
58         this.vm = vm;
59         this.pkt = new Packet();
60         pkt.cmdSet = (short)cmdSet;
61         pkt.cmd = (short)cmd;
62     }
63 
PacketStream(VirtualMachineImpl vm, Packet pkt)64     PacketStream(VirtualMachineImpl vm, Packet pkt) {
65         this.vm = vm;
66         this.pkt = pkt;
67         this.isCommitted = true; /* read only stream */
68     }
69 
id()70     int id() {
71         return pkt.id;
72     }
73 
send()74     void send() {
75         if (!isCommitted) {
76             pkt.data = dataStream.toByteArray();
77             vm.sendToTarget(pkt);
78             isCommitted = true;
79         }
80     }
81 
waitForReply()82     void waitForReply() throws JDWPException {
83         if (!isCommitted) {
84             throw new InternalException("waitForReply without send");
85         }
86 
87         vm.waitForTargetReply(pkt);
88 
89         if (pkt.errorCode != Packet.ReplyNoError) {
90             throw new JDWPException(pkt.errorCode);
91         }
92     }
93 
writeBoolean(boolean data)94     void writeBoolean(boolean data) {
95         if(data) {
96             dataStream.write( 1 );
97         } else {
98             dataStream.write( 0 );
99         }
100     }
101 
writeByte(byte data)102     void writeByte(byte data) {
103         dataStream.write( data );
104     }
105 
writeChar(char data)106     void writeChar(char data) {
107         dataStream.write( (byte)((data >>> 8) & 0xFF) );
108         dataStream.write( (byte)((data >>> 0) & 0xFF) );
109     }
110 
writeShort(short data)111     void writeShort(short data) {
112         dataStream.write( (byte)((data >>> 8) & 0xFF) );
113         dataStream.write( (byte)((data >>> 0) & 0xFF) );
114     }
115 
writeInt(int data)116     void writeInt(int data) {
117         dataStream.write( (byte)((data >>> 24) & 0xFF) );
118         dataStream.write( (byte)((data >>> 16) & 0xFF) );
119         dataStream.write( (byte)((data >>> 8) & 0xFF) );
120         dataStream.write( (byte)((data >>> 0) & 0xFF) );
121     }
122 
writeLong(long data)123     void writeLong(long data) {
124         dataStream.write( (byte)((data >>> 56) & 0xFF) );
125         dataStream.write( (byte)((data >>> 48) & 0xFF) );
126         dataStream.write( (byte)((data >>> 40) & 0xFF) );
127         dataStream.write( (byte)((data >>> 32) & 0xFF) );
128 
129         dataStream.write( (byte)((data >>> 24) & 0xFF) );
130         dataStream.write( (byte)((data >>> 16) & 0xFF) );
131         dataStream.write( (byte)((data >>> 8) & 0xFF) );
132         dataStream.write( (byte)((data >>> 0) & 0xFF) );
133     }
134 
writeFloat(float data)135     void writeFloat(float data) {
136         writeInt(Float.floatToIntBits(data));
137     }
138 
writeDouble(double data)139     void writeDouble(double data) {
140         writeLong(Double.doubleToLongBits(data));
141     }
142 
writeID(int size, long data)143     void writeID(int size, long data) {
144         switch (size) {
145             case 8:
146                 writeLong(data);
147                 break;
148             case 4:
149                 writeInt((int)data);
150                 break;
151             case 2:
152                 writeShort((short)data);
153                 break;
154             default:
155                 throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);
156         }
157     }
158 
writeNullObjectRef()159     void writeNullObjectRef() {
160         writeObjectRef(0);
161     }
162 
writeObjectRef(long data)163     void writeObjectRef(long data) {
164         writeID(vm.sizeofObjectRef, data);
165     }
166 
writeClassRef(long data)167     void writeClassRef(long data) {
168         writeID(vm.sizeofClassRef, data);
169     }
170 
writeMethodRef(long data)171     void writeMethodRef(long data) {
172         writeID(vm.sizeofMethodRef, data);
173     }
174 
writeModuleRef(long data)175     void writeModuleRef(long data) {
176         writeID(vm.sizeofModuleRef, data);
177     }
178 
writeFieldRef(long data)179     void writeFieldRef(long data) {
180         writeID(vm.sizeofFieldRef, data);
181     }
182 
writeFrameRef(long data)183     void writeFrameRef(long data) {
184         writeID(vm.sizeofFrameRef, data);
185     }
186 
writeByteArray(byte[] data)187     void writeByteArray(byte[] data) {
188         dataStream.write(data, 0, data.length);
189     }
190 
writeString(String string)191     void writeString(String string) {
192         try {
193             byte[] stringBytes = string.getBytes("UTF8");
194             writeInt(stringBytes.length);
195             writeByteArray(stringBytes);
196         } catch (java.io.UnsupportedEncodingException e) {
197             throw new InternalException("Cannot convert string to UTF8 bytes");
198         }
199     }
200 
writeLocation(Location location)201     void writeLocation(Location location) {
202         ReferenceTypeImpl refType = (ReferenceTypeImpl)location.declaringType();
203         byte tag;
204         if (refType instanceof ClassType) {
205             tag = JDWP.TypeTag.CLASS;
206         } else if (refType instanceof InterfaceType) {
207             // It's possible to have executable code in an interface
208             tag = JDWP.TypeTag.INTERFACE;
209         } else {
210             throw new InternalException("Invalid Location");
211         }
212         writeByte(tag);
213         writeClassRef(refType.ref());
214         writeMethodRef(((MethodImpl)location.method()).ref());
215         writeLong(location.codeIndex());
216     }
217 
writeValue(Value val)218     void writeValue(Value val) {
219         try {
220             writeValueChecked(val);
221         } catch (InvalidTypeException exc) {  // should never happen
222             throw new RuntimeException(
223                 "Internal error: Invalid Tag/Type pair");
224         }
225     }
226 
writeValueChecked(Value val)227     void writeValueChecked(Value val) throws InvalidTypeException {
228         writeByte(ValueImpl.typeValueKey(val));
229         writeUntaggedValue(val);
230     }
231 
writeUntaggedValue(Value val)232     void writeUntaggedValue(Value val) {
233         try {
234             writeUntaggedValueChecked(val);
235         } catch (InvalidTypeException exc) {  // should never happen
236             throw new RuntimeException(
237                 "Internal error: Invalid Tag/Type pair");
238         }
239     }
240 
writeUntaggedValueChecked(Value val)241     void writeUntaggedValueChecked(Value val) throws InvalidTypeException {
242         byte tag = ValueImpl.typeValueKey(val);
243         if (isObjectTag(tag)) {
244             if (val == null) {
245                  writeObjectRef(0);
246             } else {
247                 if (!(val instanceof ObjectReference)) {
248                     throw new InvalidTypeException();
249                 }
250                 writeObjectRef(((ObjectReferenceImpl)val).ref());
251             }
252         } else {
253             switch (tag) {
254                 case JDWP.Tag.BYTE:
255                     if(!(val instanceof ByteValue))
256                         throw new InvalidTypeException();
257 
258                     writeByte(((PrimitiveValue)val).byteValue());
259                     break;
260 
261                 case JDWP.Tag.CHAR:
262                     if(!(val instanceof CharValue))
263                         throw new InvalidTypeException();
264 
265                     writeChar(((PrimitiveValue)val).charValue());
266                     break;
267 
268                 case JDWP.Tag.FLOAT:
269                     if(!(val instanceof FloatValue))
270                         throw new InvalidTypeException();
271 
272                     writeFloat(((PrimitiveValue)val).floatValue());
273                     break;
274 
275                 case JDWP.Tag.DOUBLE:
276                     if(!(val instanceof DoubleValue))
277                         throw new InvalidTypeException();
278 
279                     writeDouble(((PrimitiveValue)val).doubleValue());
280                     break;
281 
282                 case JDWP.Tag.INT:
283                     if(!(val instanceof IntegerValue))
284                         throw new InvalidTypeException();
285 
286                     writeInt(((PrimitiveValue)val).intValue());
287                     break;
288 
289                 case JDWP.Tag.LONG:
290                     if(!(val instanceof LongValue))
291                         throw new InvalidTypeException();
292 
293                     writeLong(((PrimitiveValue)val).longValue());
294                     break;
295 
296                 case JDWP.Tag.SHORT:
297                     if(!(val instanceof ShortValue))
298                         throw new InvalidTypeException();
299 
300                     writeShort(((PrimitiveValue)val).shortValue());
301                     break;
302 
303                 case JDWP.Tag.BOOLEAN:
304                     if(!(val instanceof BooleanValue))
305                         throw new InvalidTypeException();
306 
307                     writeBoolean(((PrimitiveValue)val).booleanValue());
308                     break;
309             }
310         }
311     }
312 
313     /**
314      * Read byte represented as one bytes.
315      */
readByte()316     byte readByte() {
317         byte ret = pkt.data[inCursor];
318         inCursor += 1;
319         return ret;
320     }
321 
322     /**
323      * Read boolean represented as one byte.
324      */
readBoolean()325     boolean readBoolean() {
326         byte ret = readByte();
327         return (ret != 0);
328     }
329 
330     /**
331      * Read char represented as two bytes.
332      */
readChar()333     char readChar() {
334         int b1, b2;
335 
336         b1 = pkt.data[inCursor++] & 0xff;
337         b2 = pkt.data[inCursor++] & 0xff;
338 
339         return (char)((b1 << 8) + b2);
340     }
341 
342     /**
343      * Read short represented as two bytes.
344      */
readShort()345     short readShort() {
346         int b1, b2;
347 
348         b1 = pkt.data[inCursor++] & 0xff;
349         b2 = pkt.data[inCursor++] & 0xff;
350 
351         return (short)((b1 << 8) + b2);
352     }
353 
354     /**
355      * Read int represented as four bytes.
356      */
readInt()357     int readInt() {
358         int b1,b2,b3,b4;
359 
360         b1 = pkt.data[inCursor++] & 0xff;
361         b2 = pkt.data[inCursor++] & 0xff;
362         b3 = pkt.data[inCursor++] & 0xff;
363         b4 = pkt.data[inCursor++] & 0xff;
364 
365         return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
366     }
367 
368     /**
369      * Read long represented as eight bytes.
370      */
readLong()371     long readLong() {
372         long b1,b2,b3,b4;
373         long b5,b6,b7,b8;
374 
375         b1 = pkt.data[inCursor++] & 0xff;
376         b2 = pkt.data[inCursor++] & 0xff;
377         b3 = pkt.data[inCursor++] & 0xff;
378         b4 = pkt.data[inCursor++] & 0xff;
379 
380         b5 = pkt.data[inCursor++] & 0xff;
381         b6 = pkt.data[inCursor++] & 0xff;
382         b7 = pkt.data[inCursor++] & 0xff;
383         b8 = pkt.data[inCursor++] & 0xff;
384 
385         return ((b1 << 56) + (b2 << 48) + (b3 << 40) + (b4 << 32)
386                 + (b5 << 24) + (b6 << 16) + (b7 << 8) + b8);
387     }
388 
389     /**
390      * Read float represented as four bytes.
391      */
readFloat()392     float readFloat() {
393         return Float.intBitsToFloat(readInt());
394     }
395 
396     /**
397      * Read double represented as eight bytes.
398      */
readDouble()399     double readDouble() {
400         return Double.longBitsToDouble(readLong());
401     }
402 
403     /**
404      * Read string represented as four byte length followed by
405      * characters of the string.
406      */
readString()407     String readString() {
408         String ret;
409         int len = readInt();
410 
411         try {
412             ret = new String(pkt.data, inCursor, len, "UTF8");
413         } catch(java.io.UnsupportedEncodingException e) {
414             System.err.println(e);
415             ret = "Conversion error!";
416         }
417         inCursor += len;
418         return ret;
419     }
420 
readID(int size)421     private long readID(int size) {
422         switch (size) {
423           case 8:
424               return readLong();
425           case 4:
426               return readInt();
427           case 2:
428               return readShort();
429           default:
430               throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);
431         }
432     }
433 
434     /**
435      * Read object represented as vm specific byte sequence.
436      */
readObjectRef()437     long readObjectRef() {
438         return readID(vm.sizeofObjectRef);
439     }
440 
readClassRef()441     long readClassRef() {
442         return readID(vm.sizeofClassRef);
443     }
444 
readTaggedObjectReference()445     ObjectReferenceImpl readTaggedObjectReference() {
446         byte typeKey = readByte();
447         return vm.objectMirror(readObjectRef(), typeKey);
448     }
449 
readObjectReference()450     ObjectReferenceImpl readObjectReference() {
451         return vm.objectMirror(readObjectRef());
452     }
453 
readStringReference()454     StringReferenceImpl readStringReference() {
455         long ref = readObjectRef();
456         return vm.stringMirror(ref);
457     }
458 
readArrayReference()459     ArrayReferenceImpl readArrayReference() {
460         long ref = readObjectRef();
461         return vm.arrayMirror(ref);
462     }
463 
readThreadReference()464     ThreadReferenceImpl readThreadReference() {
465         long ref = readObjectRef();
466         return vm.threadMirror(ref);
467     }
468 
readThreadGroupReference()469     ThreadGroupReferenceImpl readThreadGroupReference() {
470         long ref = readObjectRef();
471         return vm.threadGroupMirror(ref);
472     }
473 
readClassLoaderReference()474     ClassLoaderReferenceImpl readClassLoaderReference() {
475         long ref = readObjectRef();
476         return vm.classLoaderMirror(ref);
477     }
478 
readClassObjectReference()479     ClassObjectReferenceImpl readClassObjectReference() {
480         long ref = readObjectRef();
481         return vm.classObjectMirror(ref);
482     }
483 
readReferenceType()484     ReferenceTypeImpl readReferenceType() {
485         byte tag = readByte();
486         long ref = readObjectRef();
487         return vm.referenceType(ref, tag);
488     }
489 
readModule()490     ModuleReferenceImpl readModule() {
491         long ref = readModuleRef();
492         return vm.moduleMirror(ref);
493     }
494 
495     /**
496      * Read method reference represented as vm specific byte sequence.
497      */
readMethodRef()498     long readMethodRef() {
499         return readID(vm.sizeofMethodRef);
500     }
501 
502     /**
503      * Read module reference represented as vm specific byte sequence.
504      */
readModuleRef()505     long readModuleRef() {
506         return readID(vm.sizeofModuleRef);
507     }
508 
509     /**
510      * Read field reference represented as vm specific byte sequence.
511      */
readFieldRef()512     long readFieldRef() {
513         return readID(vm.sizeofFieldRef);
514     }
515 
516     /**
517      * Read field represented as vm specific byte sequence.
518      */
readField()519     Field readField() {
520         ReferenceTypeImpl refType = readReferenceType();
521         long fieldRef = readFieldRef();
522         return refType.getFieldMirror(fieldRef);
523     }
524 
525     /**
526      * Read frame represented as vm specific byte sequence.
527      */
readFrameRef()528     long readFrameRef() {
529         return readID(vm.sizeofFrameRef);
530     }
531 
532     /**
533      * Read a value, first byte describes type of value to read.
534      */
readValue()535     ValueImpl readValue() {
536         byte typeKey = readByte();
537         return readUntaggedValue(typeKey);
538     }
539 
readUntaggedValue(byte typeKey)540     ValueImpl readUntaggedValue(byte typeKey) {
541         ValueImpl val = null;
542 
543         if (isObjectTag(typeKey)) {
544             val = vm.objectMirror(readObjectRef(), typeKey);
545         } else {
546             switch(typeKey) {
547                 case JDWP.Tag.BYTE:
548                     val = new ByteValueImpl(vm, readByte());
549                     break;
550 
551                 case JDWP.Tag.CHAR:
552                     val = new CharValueImpl(vm, readChar());
553                     break;
554 
555                 case JDWP.Tag.FLOAT:
556                     val = new FloatValueImpl(vm, readFloat());
557                     break;
558 
559                 case JDWP.Tag.DOUBLE:
560                     val = new DoubleValueImpl(vm, readDouble());
561                     break;
562 
563                 case JDWP.Tag.INT:
564                     val = new IntegerValueImpl(vm, readInt());
565                     break;
566 
567                 case JDWP.Tag.LONG:
568                     val = new LongValueImpl(vm, readLong());
569                     break;
570 
571                 case JDWP.Tag.SHORT:
572                     val = new ShortValueImpl(vm, readShort());
573                     break;
574 
575                 case JDWP.Tag.BOOLEAN:
576                     val = new BooleanValueImpl(vm, readBoolean());
577                     break;
578 
579                 case JDWP.Tag.VOID:
580                     val = new VoidValueImpl(vm);
581                     break;
582             }
583         }
584         return val;
585     }
586 
587     /**
588      * Read location represented as vm specific byte sequence.
589      */
readLocation()590     Location readLocation() {
591         byte tag = readByte();
592         long classRef = readObjectRef();
593         long methodRef = readMethodRef();
594         long codeIndex = readLong();
595         if (classRef != 0) {
596             /* Valid location */
597             ReferenceTypeImpl refType = vm.referenceType(classRef, tag);
598             return new LocationImpl(vm, refType, methodRef, codeIndex);
599         } else {
600             /* Null location (example: uncaught exception) */
601            return null;
602         }
603     }
604 
readByteArray(int length)605     byte[] readByteArray(int length) {
606         byte[] array = new byte[length];
607         System.arraycopy(pkt.data, inCursor, array, 0, length);
608         inCursor += length;
609         return array;
610     }
611 
readArrayRegion()612     List<Value> readArrayRegion() {
613         byte typeKey = readByte();
614         int length = readInt();
615         List<Value> list = new ArrayList<>(length);
616         boolean gettingObjects = isObjectTag(typeKey);
617         for (int i = 0; i < length; i++) {
618             /*
619              * Each object comes back with a type key which might
620              * identify a more specific type than the type key we
621              * passed in, so we use it in the decodeValue call.
622              * (For primitives, we just use the original one)
623              */
624             if (gettingObjects) {
625                 typeKey = readByte();
626             }
627             Value value = readUntaggedValue(typeKey);
628             list.add(value);
629         }
630 
631         return list;
632     }
633 
writeArrayRegion(List<Value> srcValues)634     void writeArrayRegion(List<Value> srcValues) {
635         writeInt(srcValues.size());
636         for (int i = 0; i < srcValues.size(); i++) {
637             Value value = srcValues.get(i);
638             writeUntaggedValue(value);
639         }
640     }
641 
skipBytes(int n)642     int skipBytes(int n) {
643         inCursor += n;
644         return n;
645     }
646 
command()647     byte command() {
648         return (byte)pkt.cmd;
649     }
650 
isObjectTag(byte tag)651     static boolean isObjectTag(byte tag) {
652         return (tag == JDWP.Tag.OBJECT) ||
653                (tag == JDWP.Tag.ARRAY) ||
654                (tag == JDWP.Tag.STRING) ||
655                (tag == JDWP.Tag.THREAD) ||
656                (tag == JDWP.Tag.THREAD_GROUP) ||
657                (tag == JDWP.Tag.CLASS_LOADER) ||
658                (tag == JDWP.Tag.CLASS_OBJECT);
659     }
660 }
661