1 /* 2 * Copyright (c) 2000, 2011, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package sun.jvm.hotspot; 26 27 import java.io.*; 28 import java.util.*; 29 import sun.jvm.hotspot.debugger.*; 30 import sun.jvm.hotspot.types.*; 31 import sun.jvm.hotspot.types.basic.*; 32 import sun.jvm.hotspot.utilities.*; 33 34 /** <P> This is the cross-platform TypeDataBase used by the Oop 35 hierarchy. The decision was made to make this cross-platform by 36 having the VM export the necessary symbols via a built-in table; 37 see src/share/vm/runtime/vmStructs.[ch]pp for more details. </P> 38 39 <P> <B>WARNING</B>: clients should refer to this class through the 40 TypeDataBase interface and not directly to the HotSpotTypeDataBase 41 type. </P> 42 43 <P> NOTE: since we are fetching the sizes of the Java primitive types 44 */ 45 46 public class HotSpotTypeDataBase extends BasicTypeDataBase { 47 private Debugger symbolLookup; 48 private String[] jvmLibNames; 49 private static final int UNINITIALIZED_SIZE = -1; 50 private static final int C_INT8_SIZE = 1; 51 private static final int C_INT32_SIZE = 4; 52 private static final int C_INT64_SIZE = 8; 53 54 private static final boolean DEBUG; 55 static { 56 DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG") 57 != null; 58 } 59 60 /** <P> This requires a SymbolLookup mechanism as well as the 61 MachineDescription. Note that we do not need a NameMangler since 62 we use the vmStructs mechanism to avoid looking up C++ 63 symbols. </P> 64 65 <P> NOTE that it is guaranteed that this constructor will not 66 attempt to fetch any Java values from the remote process, only C 67 integers and addresses. This is required because we are fetching 68 the sizes of the Java primitive types from the remote process, 69 implying that attempting to fetch them before their sizes are 70 known is illegal. </P> 71 72 <P> Throws NoSuchSymbolException if a problem occurred while 73 looking up one of the bootstrapping symbols related to the 74 VMStructs table in the remote VM; this may indicate that the 75 remote process is not actually a HotSpot VM. </P> 76 */ 77 public HotSpotTypeDataBase(MachineDescription machDesc, 78 VtblAccess vtblAccess, 79 Debugger symbolLookup, 80 String[] jvmLibNames) throws NoSuchSymbolException { 81 super(machDesc, vtblAccess); 82 this.symbolLookup = symbolLookup; 83 this.jvmLibNames = jvmLibNames; 84 85 readVMTypes(); 86 initializePrimitiveTypes(); 87 readVMStructs(); 88 readVMIntConstants(); 89 readVMLongConstants(); 90 } 91 92 public Type lookupType(String cTypeName, boolean throwException) { 93 Type fieldType = super.lookupType(cTypeName, false); 94 if (fieldType == null && cTypeName.startsWith("const ")) { 95 fieldType = (BasicType)lookupType(cTypeName.substring(6), false); 96 } 97 if (fieldType == null && cTypeName.endsWith(" const")) { 98 fieldType = (BasicType)lookupType(cTypeName.substring(0, cTypeName.length() - 6), false); 99 } 100 if (fieldType == null) { 101 if (cTypeName.startsWith("GrowableArray<") && cTypeName.endsWith(">*")) { 102 String ttype = cTypeName.substring("GrowableArray<".length(), 103 cTypeName.length() - 2); 104 Type templateType = lookupType(ttype, false); 105 if (templateType == null && typeNameIsPointerType(ttype)) { 106 templateType = recursiveCreateBasicPointerType(ttype); 107 } 108 if (templateType == null) { 109 lookupOrFail(ttype); 110 } 111 fieldType = recursiveCreateBasicPointerType(cTypeName); 112 } 113 } 114 if (fieldType == null && typeNameIsPointerType(cTypeName)) { 115 fieldType = recursiveCreateBasicPointerType(cTypeName); 116 } 117 if (fieldType == null && throwException) { 118 super.lookupType(cTypeName, true); 119 } 120 return fieldType; 121 } 122 123 private void readVMTypes() { 124 // Get the variables we need in order to traverse the VMTypeEntry[] 125 long typeEntryTypeNameOffset; 126 long typeEntrySuperclassNameOffset; 127 long typeEntryIsOopTypeOffset; 128 long typeEntryIsIntegerTypeOffset; 129 long typeEntryIsUnsignedOffset; 130 long typeEntrySizeOffset; 131 long typeEntryArrayStride; 132 133 // Fetch the address of the VMTypeEntry*. We get this symbol first 134 // and try to use it to make sure that symbol lookup is working. 135 Address entryAddr = lookupInProcess("gHotSpotVMTypes"); 136 // System.err.println("gHotSpotVMTypes address = " + entryAddr); 137 // Dereference this once to get the pointer to the first VMTypeEntry 138 // dumpMemory(entryAddr, 80); 139 entryAddr = entryAddr.getAddressAt(0); 140 141 if (entryAddr == null) { 142 throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue"); 143 } 144 145 typeEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset"); 146 typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset"); 147 typeEntryIsOopTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset"); 148 typeEntryIsIntegerTypeOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset"); 149 typeEntryIsUnsignedOffset = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset"); 150 typeEntrySizeOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset"); 151 typeEntryArrayStride = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride"); 152 153 // Start iterating down it until we find an entry with no name 154 Address typeNameAddr = null; 155 do { 156 // Fetch the type name first 157 typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset); 158 if (typeNameAddr != null) { 159 String typeName = CStringUtilities.getString(typeNameAddr); 160 161 String superclassName = null; 162 Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset); 163 if (superclassNameAddr != null) { 164 superclassName = CStringUtilities.getString(superclassNameAddr); 165 } 166 167 boolean isOopType = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0); 168 boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0); 169 boolean isUnsigned = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0); 170 long size = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true); 171 172 createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size); 173 } 174 175 entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride); 176 } while (typeNameAddr != null); 177 } 178 179 private void initializePrimitiveTypes() { 180 // Look up the needed primitive types by name...they had better be present 181 setJBooleanType(lookupPrimitiveType("jboolean")); 182 setJByteType (lookupPrimitiveType("jbyte")); 183 setJCharType (lookupPrimitiveType("jchar")); 184 setJDoubleType (lookupPrimitiveType("jdouble")); 185 setJFloatType (lookupPrimitiveType("jfloat")); 186 setJIntType (lookupPrimitiveType("jint")); 187 setJLongType (lookupPrimitiveType("jlong")); 188 setJShortType (lookupPrimitiveType("jshort")); 189 190 // Indicate that these are the Java primitive types 191 ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true); 192 ((BasicType) getJByteType()).setIsJavaPrimitiveType(true); 193 ((BasicType) getJCharType()).setIsJavaPrimitiveType(true); 194 ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true); 195 ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true); 196 ((BasicType) getJIntType()).setIsJavaPrimitiveType(true); 197 ((BasicType) getJLongType()).setIsJavaPrimitiveType(true); 198 ((BasicType) getJShortType()).setIsJavaPrimitiveType(true); 199 } 200 201 private Type lookupPrimitiveType(String typeName) { 202 Type type = lookupType(typeName, false); 203 if (type == null) { 204 throw new RuntimeException("Error initializing the HotSpotDataBase: could not find the primitive type \"" + 205 typeName + "\" in the remote VM's VMStructs table. This type is required in " + 206 "order to determine the size of Java primitive types. Can not continue."); 207 } 208 return type; 209 } 210 211 private void readVMStructs() { 212 // Get the variables we need in order to traverse the VMStructEntry[] 213 long structEntryTypeNameOffset; 214 long structEntryFieldNameOffset; 215 long structEntryTypeStringOffset; 216 long structEntryIsStaticOffset; 217 long structEntryOffsetOffset; 218 long structEntryAddressOffset; 219 long structEntryArrayStride; 220 221 structEntryTypeNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset"); 222 structEntryFieldNameOffset = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset"); 223 structEntryTypeStringOffset = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset"); 224 structEntryIsStaticOffset = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset"); 225 structEntryOffsetOffset = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset"); 226 structEntryAddressOffset = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset"); 227 structEntryArrayStride = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride"); 228 229 // Fetch the address of the VMStructEntry* 230 Address entryAddr = lookupInProcess("gHotSpotVMStructs"); 231 // Dereference this once to get the pointer to the first VMStructEntry 232 entryAddr = entryAddr.getAddressAt(0); 233 if (entryAddr == null) { 234 throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue"); 235 } 236 237 // Start iterating down it until we find an entry with no name 238 Address fieldNameAddr = null; 239 String typeName = null; 240 String fieldName = null; 241 String typeString = null; 242 boolean isStatic = false; 243 long offset = 0; 244 Address staticFieldAddr = null; 245 long size = 0; 246 long index = 0; 247 String opaqueName = "<opaque>"; 248 lookupOrCreateClass(opaqueName, false, false, false); 249 250 do { 251 // Fetch the field name first 252 fieldNameAddr = entryAddr.getAddressAt(structEntryFieldNameOffset); 253 if (fieldNameAddr != null) { 254 fieldName = CStringUtilities.getString(fieldNameAddr); 255 256 // Now the rest of the names. Keep in mind that the type name 257 // may be NULL, indicating that the type is opaque. 258 Address addr = entryAddr.getAddressAt(structEntryTypeNameOffset); 259 if (addr == null) { 260 throw new RuntimeException("gHotSpotVMStructs unexpectedly had a NULL type name at index " + index); 261 } 262 typeName = CStringUtilities.getString(addr); 263 264 addr = entryAddr.getAddressAt(structEntryTypeStringOffset); 265 if (addr == null) { 266 typeString = opaqueName; 267 } else { 268 typeString = CStringUtilities.getString(addr); 269 } 270 271 isStatic = !(entryAddr.getCIntegerAt(structEntryIsStaticOffset, C_INT32_SIZE, false) == 0); 272 if (isStatic) { 273 staticFieldAddr = entryAddr.getAddressAt(structEntryAddressOffset); 274 offset = 0; 275 } else { 276 offset = entryAddr.getCIntegerAt(structEntryOffsetOffset, C_INT64_SIZE, true); 277 staticFieldAddr = null; 278 } 279 280 // The containing Type must already be in the database -- no exceptions 281 BasicType containingType = lookupOrFail(typeName); 282 283 // The field's Type must already be in the database -- no exceptions 284 BasicType fieldType = (BasicType)lookupType(typeString); 285 286 // Create field by type 287 createField(containingType, fieldName, fieldType, 288 isStatic, offset, staticFieldAddr); 289 } 290 291 ++index; 292 entryAddr = entryAddr.addOffsetTo(structEntryArrayStride); 293 } while (fieldNameAddr != null); 294 } 295 296 private void readVMIntConstants() { 297 // Get the variables we need in order to traverse the VMIntConstantEntry[] 298 long intConstantEntryNameOffset; 299 long intConstantEntryValueOffset; 300 long intConstantEntryArrayStride; 301 302 intConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset"); 303 intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset"); 304 intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride"); 305 306 // Fetch the address of the VMIntConstantEntry* 307 Address entryAddr = lookupInProcess("gHotSpotVMIntConstants"); 308 // Dereference this once to get the pointer to the first VMIntConstantEntry 309 entryAddr = entryAddr.getAddressAt(0); 310 if (entryAddr == null) { 311 throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue"); 312 } 313 314 // Start iterating down it until we find an entry with no name 315 Address nameAddr = null; 316 do { 317 // Fetch the type name first 318 nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset); 319 if (nameAddr != null) { 320 String name = CStringUtilities.getString(nameAddr); 321 int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false); 322 323 // Be a little resilient 324 Integer oldValue = lookupIntConstant(name, false); 325 if (oldValue == null) { 326 addIntConstant(name, value); 327 } else { 328 if (oldValue.intValue() != value) { 329 throw new RuntimeException("Error: the integer constant \"" + name + 330 "\" had its value redefined (old was " + oldValue + 331 ", new is " + value + ". Aborting."); 332 } else { 333 System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " + 334 "had its value declared as " + value + " twice. Continuing."); 335 } 336 } 337 } 338 339 entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride); 340 } while (nameAddr != null); 341 } 342 343 private void readVMLongConstants() { 344 // Get the variables we need in order to traverse the VMLongConstantEntry[] 345 long longConstantEntryNameOffset; 346 long longConstantEntryValueOffset; 347 long longConstantEntryArrayStride; 348 349 longConstantEntryNameOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset"); 350 longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset"); 351 longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride"); 352 353 // Fetch the address of the VMLongConstantEntry* 354 Address entryAddr = lookupInProcess("gHotSpotVMLongConstants"); 355 // Dereference this once to get the pointer to the first VMLongConstantEntry 356 entryAddr = entryAddr.getAddressAt(0); 357 if (entryAddr == null) { 358 throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue"); 359 } 360 361 // Start iterating down it until we find an entry with no name 362 Address nameAddr = null; 363 do { 364 // Fetch the type name first 365 nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset); 366 if (nameAddr != null) { 367 String name = CStringUtilities.getString(nameAddr); 368 int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true); 369 370 // Be a little resilient 371 Long oldValue = lookupLongConstant(name, false); 372 if (oldValue == null) { 373 addLongConstant(name, value); 374 } else { 375 if (oldValue.longValue() != value) { 376 throw new RuntimeException("Error: the long constant \"" + name + 377 "\" had its value redefined (old was " + oldValue + 378 ", new is " + value + ". Aborting."); 379 } else { 380 System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " + 381 "had its value declared as " + value + " twice. Continuing."); 382 } 383 } 384 } 385 386 entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride); 387 } while (nameAddr != null); 388 } 389 390 private BasicType lookupOrFail(String typeName) { 391 BasicType type = (BasicType) lookupType(typeName, false); 392 if (type == null) { 393 throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " + 394 "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " + 395 "in the debug build of that VM). Can not continue."); 396 } 397 return type; 398 } 399 400 private long getLongValueFromProcess(String symbol) { 401 return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true); 402 } 403 404 private Address lookupInProcess(String symbol) throws NoSuchSymbolException { 405 // FIXME: abstract away the loadobject name 406 for (int i = 0; i < jvmLibNames.length; i++) { 407 Address addr = symbolLookup.lookup(jvmLibNames[i], symbol); 408 if (addr != null) { 409 return addr; 410 } 411 } 412 String errStr = "("; 413 for (int i = 0; i < jvmLibNames.length; i++) { 414 errStr += jvmLibNames[i]; 415 if (i < jvmLibNames.length - 1) { 416 errStr += ", "; 417 } 418 } 419 errStr += ")"; 420 throw new NoSuchSymbolException(symbol, 421 "Could not find symbol \"" + symbol + 422 "\" in any of the known library names " + 423 errStr); 424 } 425 426 private BasicType lookupOrCreateClass(String typeName, boolean isOopType, 427 boolean isIntegerType, boolean isUnsigned) { 428 BasicType type = (BasicType) lookupType(typeName, false); 429 if (type == null) { 430 // Create a new type 431 type = createBasicType(typeName, isOopType, isIntegerType, isUnsigned); 432 } 433 return type; 434 } 435 436 /** Creates a new BasicType, initializes its size to -1 so we can 437 test to ensure that all types' sizes are initialized by VMTypes, 438 and adds it to the database. Takes care of initializing integer 439 and oop types properly. */ 440 private BasicType createBasicType(String typeName, boolean isOopType, 441 boolean isIntegerType, boolean isUnsigned) { 442 443 BasicType type = null; 444 445 if (isIntegerType) { 446 type = new BasicCIntegerType(this, typeName, isUnsigned); 447 } else { 448 if (typeNameIsPointerType(typeName)) { 449 type = recursiveCreateBasicPointerType(typeName); 450 } else { 451 type = new BasicType(this, typeName); 452 } 453 454 if (isOopType) { 455 // HACK: turn markOop into a C integer type. This allows 456 // proper handling of it in the Serviceability Agent. (FIXME 457 // -- consider doing something different here) 458 if (typeName.equals("markOop")) { 459 type = new BasicCIntegerType(this, typeName, true); 460 } else { 461 type.setIsOopType(true); 462 } 463 } 464 } 465 466 type.setSize(UNINITIALIZED_SIZE); 467 addType(type); 468 return type; 469 } 470 471 /** Recursively creates a PointerType from the string representation 472 of the type's name. Note that this currently needs some 473 workarounds due to incomplete information in the VMStructs 474 database. */ 475 private BasicPointerType recursiveCreateBasicPointerType(String typeName) { 476 BasicPointerType result = (BasicPointerType)super.lookupType(typeName, false); 477 if (result != null) { 478 return result; 479 } 480 String targetTypeName = typeName.substring(0, typeName.lastIndexOf('*')).trim(); 481 Type targetType = null; 482 if (typeNameIsPointerType(targetTypeName)) { 483 targetType = lookupType(targetTypeName, false); 484 if (targetType == null) { 485 targetType = recursiveCreateBasicPointerType(targetTypeName); 486 } 487 } else { 488 targetType = lookupType(targetTypeName, false); 489 if (targetType == null) { 490 // Workaround for missing C integer types in database. 491 // Also looks like we can't throw an exception for other 492 // missing target types because there are some in old 493 // VMStructs tables that didn't have the target type declared. 494 // For this case, we create basic types that never get filled 495 // in. 496 497 if (targetTypeName.equals("char") || 498 targetTypeName.equals("const char")) { 499 // We don't have a representation of const-ness of C types in the SA 500 BasicType basicTargetType = createBasicType(targetTypeName, false, true, false); 501 basicTargetType.setSize(1); 502 targetType = basicTargetType; 503 } else if (targetTypeName.equals("u_char")) { 504 BasicType basicTargetType = createBasicType(targetTypeName, false, true, true); 505 basicTargetType.setSize(1); 506 targetType = basicTargetType; 507 } else if (targetTypeName.startsWith("GrowableArray<")) { 508 BasicType basicTargetType = createBasicType(targetTypeName, false, false, false); 509 510 // transfer fields from GenericGrowableArray to template instance 511 BasicType generic = lookupOrFail("GenericGrowableArray"); 512 basicTargetType.setSize(generic.getSize()); 513 Iterator fields = generic.getFields(); 514 while (fields.hasNext()) { 515 Field f = (Field)fields.next(); 516 basicTargetType.addField(internalCreateField(basicTargetType, f.getName(), 517 f.getType(), f.isStatic(), 518 f.getOffset(), null)); 519 } 520 targetType = basicTargetType; 521 } else { 522 if (DEBUG) { 523 System.err.println("WARNING: missing target type \"" + targetTypeName + "\" for pointer type \"" + typeName + "\""); 524 } 525 targetType = createBasicType(targetTypeName, false, false, false); 526 } 527 } 528 } 529 result = new BasicPointerType(this, typeName, targetType); 530 result.setSize(UNINITIALIZED_SIZE); 531 addType(result); 532 return result; 533 } 534 535 private boolean typeNameIsPointerType(String typeName) { 536 int i = typeName.length() - 1; 537 while (i >= 0 && Character.isWhitespace(typeName.charAt(i))) { 538 --i; 539 } 540 if (i >= 0 && typeName.charAt(i) == '*') { 541 return true; 542 } 543 return false; 544 } 545 546 public void createType(String typeName, String superclassName, 547 boolean isOopType, boolean isIntegerType, 548 boolean isUnsigned, long size) { 549 // See whether we have a superclass 550 BasicType superclass = null; 551 if (superclassName != null) { 552 // Fetch or create it (FIXME: would get oop types wrong if 553 // they had a hierarchy; consider using lookupOrFail) 554 superclass = lookupOrCreateClass(superclassName, false, false, false); 555 } 556 557 // Lookup or create the current type 558 BasicType curType = lookupOrCreateClass(typeName, isOopType, isIntegerType, isUnsigned); 559 // Set superclass and/or ensure it's correct 560 if (superclass != null) { 561 if (curType.getSuperclass() == null) { 562 // Set the superclass in the current type 563 curType.setSuperclass(superclass); 564 } 565 566 if (curType.getSuperclass() != superclass) { 567 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 568 "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " + 569 superclass.getName() + ")."); 570 } 571 } 572 573 // Classes are created with a size of UNINITIALIZED_SIZE. 574 // Set size if necessary. 575 if (curType.getSize() == UNINITIALIZED_SIZE) { 576 curType.setSize(size); 577 } else { 578 if (curType.getSize() != size) { 579 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 580 "had its size redefined (old was " + curType.getSize() + ", new is " + size + ")."); 581 } 582 583 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " + 584 "had its size declared as " + size + " twice. Continuing."); 585 } 586 587 } 588 589 /** "Virtual constructor" for fields based on type */ 590 public void createField(BasicType containingType, 591 String name, Type type, boolean isStatic, 592 long offset, Address staticFieldAddress) { 593 // Add field to containing type 594 containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress)); 595 } 596 597 Field internalCreateField(BasicType containingType, 598 String name, Type type, boolean isStatic, 599 long offset, Address staticFieldAddress) { 600 // "Virtual constructor" based on type 601 if (type.isOopType()) { 602 return new BasicOopField(this, containingType, name, type, 603 isStatic, offset, staticFieldAddress); 604 } 605 606 if (type instanceof CIntegerType) { 607 return new BasicCIntegerField(this, containingType, name, type, 608 isStatic, offset, staticFieldAddress); 609 } 610 611 if (type.equals(getJBooleanType())) { 612 return new BasicJBooleanField(this, containingType, name, type, 613 isStatic, offset, staticFieldAddress); 614 } 615 616 if (type.equals(getJByteType())) { 617 return new BasicJByteField(this, containingType, name, type, 618 isStatic, offset, staticFieldAddress); 619 } 620 621 if (type.equals(getJCharType())) { 622 return new BasicJCharField(this, containingType, name, type, 623 isStatic, offset, staticFieldAddress); 624 } 625 626 if (type.equals(getJDoubleType())) { 627 return new BasicJDoubleField(this, containingType, name, type, 628 isStatic, offset, staticFieldAddress); 629 } 630 631 if (type.equals(getJFloatType())) { 632 return new BasicJFloatField(this, containingType, name, type, 633 isStatic, offset, staticFieldAddress); 634 } 635 636 if (type.equals(getJIntType())) { 637 return new BasicJIntField(this, containingType, name, type, 638 isStatic, offset, staticFieldAddress); 639 } 640 641 if (type.equals(getJLongType())) { 642 return new BasicJLongField(this, containingType, name, type, 643 isStatic, offset, staticFieldAddress); 644 } 645 646 if (type.equals(getJShortType())) { 647 return new BasicJShortField(this, containingType, name, type, 648 isStatic, offset, staticFieldAddress); 649 } 650 651 // Unknown ("opaque") type. Instantiate ordinary Field. 652 return new BasicField(this, containingType, name, type, 653 isStatic, offset, staticFieldAddress); 654 } 655 656 // For debugging 657 private void dumpMemory(Address addr, int len) { 658 int i = 0; 659 while (i < len) { 660 System.err.print(addr.addOffsetTo(i) + ":"); 661 for (int j = 0; j < 8 && i < len; i++, j++) { 662 String s = Long.toHexString(addr.getCIntegerAt(i, 1, true)); 663 System.err.print(" 0x"); 664 for (int k = 0; k < 2 - s.length(); k++) { 665 System.err.print("0"); 666 } 667 System.err.print(s); 668 } 669 System.err.println(); 670 } 671 } 672 }