Path: blob/master/src/jdk.jdi/share/classes/com/sun/tools/jdi/PacketStream.java
41161 views
/*1* Copyright (c) 1998, 2017, 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*/2425package com.sun.tools.jdi;2627import java.io.ByteArrayOutputStream;28import java.util.ArrayList;29import java.util.List;3031import com.sun.jdi.BooleanValue;32import com.sun.jdi.ByteValue;33import com.sun.jdi.CharValue;34import com.sun.jdi.ClassType;35import com.sun.jdi.DoubleValue;36import com.sun.jdi.Field;37import com.sun.jdi.FloatValue;38import com.sun.jdi.IntegerValue;39import com.sun.jdi.InterfaceType;40import com.sun.jdi.InternalException;41import com.sun.jdi.InvalidTypeException;42import com.sun.jdi.Location;43import com.sun.jdi.LongValue;44import com.sun.jdi.ObjectReference;45import com.sun.jdi.PrimitiveValue;46import com.sun.jdi.ShortValue;47import com.sun.jdi.Value;4849class PacketStream {50final VirtualMachineImpl vm;51private int inCursor = 0;52final Packet pkt;53private ByteArrayOutputStream dataStream = new ByteArrayOutputStream();54private boolean isCommitted = false;5556PacketStream(VirtualMachineImpl vm, int cmdSet, int cmd) {57this.vm = vm;58this.pkt = new Packet();59pkt.cmdSet = (short)cmdSet;60pkt.cmd = (short)cmd;61}6263PacketStream(VirtualMachineImpl vm, Packet pkt) {64this.vm = vm;65this.pkt = pkt;66this.isCommitted = true; /* read only stream */67}6869int id() {70return pkt.id;71}7273void send() {74if (!isCommitted) {75pkt.data = dataStream.toByteArray();76vm.sendToTarget(pkt);77isCommitted = true;78}79}8081void waitForReply() throws JDWPException {82if (!isCommitted) {83throw new InternalException("waitForReply without send");84}8586vm.waitForTargetReply(pkt);8788if (pkt.errorCode != Packet.ReplyNoError) {89throw new JDWPException(pkt.errorCode);90}91}9293void writeBoolean(boolean data) {94if(data) {95dataStream.write( 1 );96} else {97dataStream.write( 0 );98}99}100101void writeByte(byte data) {102dataStream.write( data );103}104105void writeChar(char data) {106dataStream.write( (byte)((data >>> 8) & 0xFF) );107dataStream.write( (byte)((data >>> 0) & 0xFF) );108}109110void writeShort(short data) {111dataStream.write( (byte)((data >>> 8) & 0xFF) );112dataStream.write( (byte)((data >>> 0) & 0xFF) );113}114115void writeInt(int data) {116dataStream.write( (byte)((data >>> 24) & 0xFF) );117dataStream.write( (byte)((data >>> 16) & 0xFF) );118dataStream.write( (byte)((data >>> 8) & 0xFF) );119dataStream.write( (byte)((data >>> 0) & 0xFF) );120}121122void writeLong(long data) {123dataStream.write( (byte)((data >>> 56) & 0xFF) );124dataStream.write( (byte)((data >>> 48) & 0xFF) );125dataStream.write( (byte)((data >>> 40) & 0xFF) );126dataStream.write( (byte)((data >>> 32) & 0xFF) );127128dataStream.write( (byte)((data >>> 24) & 0xFF) );129dataStream.write( (byte)((data >>> 16) & 0xFF) );130dataStream.write( (byte)((data >>> 8) & 0xFF) );131dataStream.write( (byte)((data >>> 0) & 0xFF) );132}133134void writeFloat(float data) {135writeInt(Float.floatToIntBits(data));136}137138void writeDouble(double data) {139writeLong(Double.doubleToLongBits(data));140}141142void writeID(int size, long data) {143switch (size) {144case 8:145writeLong(data);146break;147case 4:148writeInt((int)data);149break;150case 2:151writeShort((short)data);152break;153default:154throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);155}156}157158void writeNullObjectRef() {159writeObjectRef(0);160}161162void writeObjectRef(long data) {163writeID(vm.sizeofObjectRef, data);164}165166void writeClassRef(long data) {167writeID(vm.sizeofClassRef, data);168}169170void writeMethodRef(long data) {171writeID(vm.sizeofMethodRef, data);172}173174void writeModuleRef(long data) {175writeID(vm.sizeofModuleRef, data);176}177178void writeFieldRef(long data) {179writeID(vm.sizeofFieldRef, data);180}181182void writeFrameRef(long data) {183writeID(vm.sizeofFrameRef, data);184}185186void writeByteArray(byte[] data) {187dataStream.write(data, 0, data.length);188}189190void writeString(String string) {191try {192byte[] stringBytes = string.getBytes("UTF8");193writeInt(stringBytes.length);194writeByteArray(stringBytes);195} catch (java.io.UnsupportedEncodingException e) {196throw new InternalException("Cannot convert string to UTF8 bytes");197}198}199200void writeLocation(Location location) {201ReferenceTypeImpl refType = (ReferenceTypeImpl)location.declaringType();202byte tag;203if (refType instanceof ClassType) {204tag = JDWP.TypeTag.CLASS;205} else if (refType instanceof InterfaceType) {206// It's possible to have executable code in an interface207tag = JDWP.TypeTag.INTERFACE;208} else {209throw new InternalException("Invalid Location");210}211writeByte(tag);212writeClassRef(refType.ref());213writeMethodRef(((MethodImpl)location.method()).ref());214writeLong(location.codeIndex());215}216217void writeValue(Value val) {218try {219writeValueChecked(val);220} catch (InvalidTypeException exc) { // should never happen221throw new RuntimeException(222"Internal error: Invalid Tag/Type pair");223}224}225226void writeValueChecked(Value val) throws InvalidTypeException {227writeByte(ValueImpl.typeValueKey(val));228writeUntaggedValue(val);229}230231void writeUntaggedValue(Value val) {232try {233writeUntaggedValueChecked(val);234} catch (InvalidTypeException exc) { // should never happen235throw new RuntimeException(236"Internal error: Invalid Tag/Type pair");237}238}239240void writeUntaggedValueChecked(Value val) throws InvalidTypeException {241byte tag = ValueImpl.typeValueKey(val);242if (isObjectTag(tag)) {243if (val == null) {244writeObjectRef(0);245} else {246if (!(val instanceof ObjectReference)) {247throw new InvalidTypeException();248}249writeObjectRef(((ObjectReferenceImpl)val).ref());250}251} else {252switch (tag) {253case JDWP.Tag.BYTE:254if(!(val instanceof ByteValue))255throw new InvalidTypeException();256257writeByte(((PrimitiveValue)val).byteValue());258break;259260case JDWP.Tag.CHAR:261if(!(val instanceof CharValue))262throw new InvalidTypeException();263264writeChar(((PrimitiveValue)val).charValue());265break;266267case JDWP.Tag.FLOAT:268if(!(val instanceof FloatValue))269throw new InvalidTypeException();270271writeFloat(((PrimitiveValue)val).floatValue());272break;273274case JDWP.Tag.DOUBLE:275if(!(val instanceof DoubleValue))276throw new InvalidTypeException();277278writeDouble(((PrimitiveValue)val).doubleValue());279break;280281case JDWP.Tag.INT:282if(!(val instanceof IntegerValue))283throw new InvalidTypeException();284285writeInt(((PrimitiveValue)val).intValue());286break;287288case JDWP.Tag.LONG:289if(!(val instanceof LongValue))290throw new InvalidTypeException();291292writeLong(((PrimitiveValue)val).longValue());293break;294295case JDWP.Tag.SHORT:296if(!(val instanceof ShortValue))297throw new InvalidTypeException();298299writeShort(((PrimitiveValue)val).shortValue());300break;301302case JDWP.Tag.BOOLEAN:303if(!(val instanceof BooleanValue))304throw new InvalidTypeException();305306writeBoolean(((PrimitiveValue)val).booleanValue());307break;308}309}310}311312/**313* Read byte represented as one bytes.314*/315byte readByte() {316byte ret = pkt.data[inCursor];317inCursor += 1;318return ret;319}320321/**322* Read boolean represented as one byte.323*/324boolean readBoolean() {325byte ret = readByte();326return (ret != 0);327}328329/**330* Read char represented as two bytes.331*/332char readChar() {333int b1, b2;334335b1 = pkt.data[inCursor++] & 0xff;336b2 = pkt.data[inCursor++] & 0xff;337338return (char)((b1 << 8) + b2);339}340341/**342* Read short represented as two bytes.343*/344short readShort() {345int b1, b2;346347b1 = pkt.data[inCursor++] & 0xff;348b2 = pkt.data[inCursor++] & 0xff;349350return (short)((b1 << 8) + b2);351}352353/**354* Read int represented as four bytes.355*/356int readInt() {357int b1,b2,b3,b4;358359b1 = pkt.data[inCursor++] & 0xff;360b2 = pkt.data[inCursor++] & 0xff;361b3 = pkt.data[inCursor++] & 0xff;362b4 = pkt.data[inCursor++] & 0xff;363364return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);365}366367/**368* Read long represented as eight bytes.369*/370long readLong() {371long b1,b2,b3,b4;372long b5,b6,b7,b8;373374b1 = pkt.data[inCursor++] & 0xff;375b2 = pkt.data[inCursor++] & 0xff;376b3 = pkt.data[inCursor++] & 0xff;377b4 = pkt.data[inCursor++] & 0xff;378379b5 = pkt.data[inCursor++] & 0xff;380b6 = pkt.data[inCursor++] & 0xff;381b7 = pkt.data[inCursor++] & 0xff;382b8 = pkt.data[inCursor++] & 0xff;383384return ((b1 << 56) + (b2 << 48) + (b3 << 40) + (b4 << 32)385+ (b5 << 24) + (b6 << 16) + (b7 << 8) + b8);386}387388/**389* Read float represented as four bytes.390*/391float readFloat() {392return Float.intBitsToFloat(readInt());393}394395/**396* Read double represented as eight bytes.397*/398double readDouble() {399return Double.longBitsToDouble(readLong());400}401402/**403* Read string represented as four byte length followed by404* characters of the string.405*/406String readString() {407String ret;408int len = readInt();409410try {411ret = new String(pkt.data, inCursor, len, "UTF8");412} catch(java.io.UnsupportedEncodingException e) {413System.err.println(e);414ret = "Conversion error!";415}416inCursor += len;417return ret;418}419420private long readID(int size) {421switch (size) {422case 8:423return readLong();424case 4:425return readInt();426case 2:427return readShort();428default:429throw new UnsupportedOperationException("JDWP: ID size not supported: " + size);430}431}432433/**434* Read object represented as vm specific byte sequence.435*/436long readObjectRef() {437return readID(vm.sizeofObjectRef);438}439440long readClassRef() {441return readID(vm.sizeofClassRef);442}443444ObjectReferenceImpl readTaggedObjectReference() {445byte typeKey = readByte();446return vm.objectMirror(readObjectRef(), typeKey);447}448449ObjectReferenceImpl readObjectReference() {450return vm.objectMirror(readObjectRef());451}452453StringReferenceImpl readStringReference() {454long ref = readObjectRef();455return vm.stringMirror(ref);456}457458ArrayReferenceImpl readArrayReference() {459long ref = readObjectRef();460return vm.arrayMirror(ref);461}462463ThreadReferenceImpl readThreadReference() {464long ref = readObjectRef();465return vm.threadMirror(ref);466}467468ThreadGroupReferenceImpl readThreadGroupReference() {469long ref = readObjectRef();470return vm.threadGroupMirror(ref);471}472473ClassLoaderReferenceImpl readClassLoaderReference() {474long ref = readObjectRef();475return vm.classLoaderMirror(ref);476}477478ClassObjectReferenceImpl readClassObjectReference() {479long ref = readObjectRef();480return vm.classObjectMirror(ref);481}482483ReferenceTypeImpl readReferenceType() {484byte tag = readByte();485long ref = readObjectRef();486return vm.referenceType(ref, tag);487}488489ModuleReferenceImpl readModule() {490long ref = readModuleRef();491return vm.moduleMirror(ref);492}493494/**495* Read method reference represented as vm specific byte sequence.496*/497long readMethodRef() {498return readID(vm.sizeofMethodRef);499}500501/**502* Read module reference represented as vm specific byte sequence.503*/504long readModuleRef() {505return readID(vm.sizeofModuleRef);506}507508/**509* Read field reference represented as vm specific byte sequence.510*/511long readFieldRef() {512return readID(vm.sizeofFieldRef);513}514515/**516* Read field represented as vm specific byte sequence.517*/518Field readField() {519ReferenceTypeImpl refType = readReferenceType();520long fieldRef = readFieldRef();521return refType.getFieldMirror(fieldRef);522}523524/**525* Read frame represented as vm specific byte sequence.526*/527long readFrameRef() {528return readID(vm.sizeofFrameRef);529}530531/**532* Read a value, first byte describes type of value to read.533*/534ValueImpl readValue() {535byte typeKey = readByte();536return readUntaggedValue(typeKey);537}538539ValueImpl readUntaggedValue(byte typeKey) {540ValueImpl val = null;541542if (isObjectTag(typeKey)) {543val = vm.objectMirror(readObjectRef(), typeKey);544} else {545switch(typeKey) {546case JDWP.Tag.BYTE:547val = new ByteValueImpl(vm, readByte());548break;549550case JDWP.Tag.CHAR:551val = new CharValueImpl(vm, readChar());552break;553554case JDWP.Tag.FLOAT:555val = new FloatValueImpl(vm, readFloat());556break;557558case JDWP.Tag.DOUBLE:559val = new DoubleValueImpl(vm, readDouble());560break;561562case JDWP.Tag.INT:563val = new IntegerValueImpl(vm, readInt());564break;565566case JDWP.Tag.LONG:567val = new LongValueImpl(vm, readLong());568break;569570case JDWP.Tag.SHORT:571val = new ShortValueImpl(vm, readShort());572break;573574case JDWP.Tag.BOOLEAN:575val = new BooleanValueImpl(vm, readBoolean());576break;577578case JDWP.Tag.VOID:579val = new VoidValueImpl(vm);580break;581}582}583return val;584}585586/**587* Read location represented as vm specific byte sequence.588*/589Location readLocation() {590byte tag = readByte();591long classRef = readObjectRef();592long methodRef = readMethodRef();593long codeIndex = readLong();594if (classRef != 0) {595/* Valid location */596ReferenceTypeImpl refType = vm.referenceType(classRef, tag);597return new LocationImpl(vm, refType, methodRef, codeIndex);598} else {599/* Null location (example: uncaught exception) */600return null;601}602}603604byte[] readByteArray(int length) {605byte[] array = new byte[length];606System.arraycopy(pkt.data, inCursor, array, 0, length);607inCursor += length;608return array;609}610611List<Value> readArrayRegion() {612byte typeKey = readByte();613int length = readInt();614List<Value> list = new ArrayList<>(length);615boolean gettingObjects = isObjectTag(typeKey);616for (int i = 0; i < length; i++) {617/*618* Each object comes back with a type key which might619* identify a more specific type than the type key we620* passed in, so we use it in the decodeValue call.621* (For primitives, we just use the original one)622*/623if (gettingObjects) {624typeKey = readByte();625}626Value value = readUntaggedValue(typeKey);627list.add(value);628}629630return list;631}632633void writeArrayRegion(List<Value> srcValues) {634writeInt(srcValues.size());635for (int i = 0; i < srcValues.size(); i++) {636Value value = srcValues.get(i);637writeUntaggedValue(value);638}639}640641int skipBytes(int n) {642inCursor += n;643return n;644}645646byte command() {647return (byte)pkt.cmd;648}649650static boolean isObjectTag(byte tag) {651return (tag == JDWP.Tag.OBJECT) ||652(tag == JDWP.Tag.ARRAY) ||653(tag == JDWP.Tag.STRING) ||654(tag == JDWP.Tag.THREAD) ||655(tag == JDWP.Tag.THREAD_GROUP) ||656(tag == JDWP.Tag.CLASS_LOADER) ||657(tag == JDWP.Tag.CLASS_OBJECT);658}659}660661662