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