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