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