< prev index next >

hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java

Print this page
rev 7149 : 8073688: Infinite loop reading types during jmap attach.
Reviewed-by: dsamersoff, sla


  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   private static int pointerSize = UNINITIALIZED_SIZE;



  54 
  55   private static final boolean DEBUG;
  56   static {
  57     DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG")
  58             != null;
  59   }
  60 
  61   /** <P> This requires a SymbolLookup mechanism as well as the
  62       MachineDescription. Note that we do not need a NameMangler since
  63       we use the vmStructs mechanism to avoid looking up C++
  64       symbols. </P>
  65 
  66       <P> NOTE that it is guaranteed that this constructor will not
  67       attempt to fetch any Java values from the remote process, only C
  68       integers and addresses. This is required because we are fetching
  69       the sizes of the Java primitive types from the remote process,
  70       implying that attempting to fetch them before their sizes are
  71       known is illegal. </P>
  72 
  73       <P> Throws NoSuchSymbolException if a problem occurred while


 149     // Fetch the address of the VMTypeEntry*. We get this symbol first
 150     // and try to use it to make sure that symbol lookup is working.
 151     Address entryAddr = lookupInProcess("gHotSpotVMTypes");
 152     //    System.err.println("gHotSpotVMTypes address = " + entryAddr);
 153     // Dereference this once to get the pointer to the first VMTypeEntry
 154     //    dumpMemory(entryAddr, 80);
 155     entryAddr = entryAddr.getAddressAt(0);
 156 
 157     if (entryAddr == null) {
 158       throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue");
 159     }
 160 
 161     typeEntryTypeNameOffset       = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
 162     typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
 163     typeEntryIsOopTypeOffset      = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
 164     typeEntryIsIntegerTypeOffset  = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
 165     typeEntryIsUnsignedOffset     = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
 166     typeEntrySizeOffset           = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
 167     typeEntryArrayStride          = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
 168 




 169     // Start iterating down it until we find an entry with no name
 170     Address typeNameAddr = null;
 171     do {
 172       // Fetch the type name first
 173       typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset);
 174       if (typeNameAddr != null) {
 175         String typeName = CStringUtilities.getString(typeNameAddr);
 176 
 177         String superclassName = null;
 178         Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset);
 179         if (superclassNameAddr != null) {
 180           superclassName = CStringUtilities.getString(superclassNameAddr);
 181         }
 182 
 183         boolean isOopType     = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0);
 184         boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0);
 185         boolean isUnsigned    = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0);
 186         long size             = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true);
 187 
 188         createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size);
 189         if (pointerSize == UNINITIALIZED_SIZE && typeName.equals("void*")) {
 190           pointerSize = (int)size;
 191         }
 192       }
 193 
 194       entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
 195     } while (typeNameAddr != null);




 196   }
 197 
 198   private void initializePrimitiveTypes() {
 199     // Look up the needed primitive types by name...they had better be present
 200     setJBooleanType(lookupPrimitiveType("jboolean"));
 201     setJByteType   (lookupPrimitiveType("jbyte"));
 202     setJCharType   (lookupPrimitiveType("jchar"));
 203     setJDoubleType (lookupPrimitiveType("jdouble"));
 204     setJFloatType  (lookupPrimitiveType("jfloat"));
 205     setJIntType    (lookupPrimitiveType("jint"));
 206     setJLongType   (lookupPrimitiveType("jlong"));
 207     setJShortType  (lookupPrimitiveType("jshort"));
 208 
 209     // Indicate that these are the Java primitive types
 210     ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true);
 211     ((BasicType) getJByteType()).setIsJavaPrimitiveType(true);
 212     ((BasicType) getJCharType()).setIsJavaPrimitiveType(true);
 213     ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true);
 214     ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true);
 215     ((BasicType) getJIntType()).setIsJavaPrimitiveType(true);


 378   }
 379 
 380   private void readVMStructs() {
 381     // Get the variables we need in order to traverse the VMStructEntry[]
 382     long structEntryTypeNameOffset;
 383     long structEntryFieldNameOffset;
 384     long structEntryTypeStringOffset;
 385     long structEntryIsStaticOffset;
 386     long structEntryOffsetOffset;
 387     long structEntryAddressOffset;
 388     long structEntryArrayStride;
 389 
 390     structEntryTypeNameOffset     = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset");
 391     structEntryFieldNameOffset    = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset");
 392     structEntryTypeStringOffset   = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset");
 393     structEntryIsStaticOffset     = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset");
 394     structEntryOffsetOffset       = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset");
 395     structEntryAddressOffset      = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
 396     structEntryArrayStride        = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");
 397 




 398     // Fetch the address of the VMStructEntry*
 399     Address entryAddr = lookupInProcess("gHotSpotVMStructs");
 400     // Dereference this once to get the pointer to the first VMStructEntry
 401     entryAddr = entryAddr.getAddressAt(0);
 402     if (entryAddr == null) {
 403       throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue");
 404     }
 405 
 406     // Start iterating down it until we find an entry with no name
 407     Address fieldNameAddr = null;
 408     String typeName = null;
 409     String fieldName = null;
 410     String typeString = null;
 411     boolean isStatic = false;
 412     long offset = 0;
 413     Address staticFieldAddr = null;
 414     long size = 0;
 415     long index = 0;
 416     String opaqueName = "<opaque>";
 417     lookupOrCreateClass(opaqueName, false, false, false);


 455         // Create field by type
 456         createField(containingType, fieldName, fieldType,
 457                     isStatic, offset, staticFieldAddr);
 458       }
 459 
 460       ++index;
 461       entryAddr = entryAddr.addOffsetTo(structEntryArrayStride);
 462     } while (fieldNameAddr != null);
 463   }
 464 
 465   private void readVMIntConstants() {
 466     // Get the variables we need in order to traverse the VMIntConstantEntry[]
 467     long intConstantEntryNameOffset;
 468     long intConstantEntryValueOffset;
 469     long intConstantEntryArrayStride;
 470 
 471     intConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset");
 472     intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
 473     intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");
 474 





 475     // Fetch the address of the VMIntConstantEntry*
 476     Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
 477     // Dereference this once to get the pointer to the first VMIntConstantEntry
 478     entryAddr = entryAddr.getAddressAt(0);
 479     if (entryAddr == null) {
 480       throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue");
 481     }
 482 
 483     // Start iterating down it until we find an entry with no name
 484     Address nameAddr = null;
 485     do {
 486       // Fetch the type name first
 487       nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset);
 488       if (nameAddr != null) {
 489         String name = CStringUtilities.getString(nameAddr);
 490         int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false);
 491 
 492         // Be a little resilient
 493         Integer oldValue = lookupIntConstant(name, false);
 494         if (oldValue == null) {
 495           addIntConstant(name, value);
 496         } else {
 497           if (oldValue.intValue() != value) {
 498             throw new RuntimeException("Error: the integer constant \"" + name +
 499                                        "\" had its value redefined (old was " + oldValue +
 500                                        ", new is " + value + ". Aborting.");
 501           } else {
 502             System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
 503                                "had its value declared as " + value + " twice. Continuing.");

 504           }
 505         }
 506       }
 507 
 508       entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
 509     } while (nameAddr != null);




 510   }
 511 
 512   private void readVMLongConstants() {
 513     // Get the variables we need in order to traverse the VMLongConstantEntry[]
 514     long longConstantEntryNameOffset;
 515     long longConstantEntryValueOffset;
 516     long longConstantEntryArrayStride;
 517 
 518     longConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset");
 519     longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
 520     longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");
 521 




 522     // Fetch the address of the VMLongConstantEntry*
 523     Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
 524     // Dereference this once to get the pointer to the first VMLongConstantEntry
 525     entryAddr = entryAddr.getAddressAt(0);
 526     if (entryAddr == null) {
 527       throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue");
 528     }
 529 
 530     // Start iterating down it until we find an entry with no name
 531     Address nameAddr = null;
 532     do {
 533       // Fetch the type name first
 534       nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset);
 535       if (nameAddr != null) {
 536         String name = CStringUtilities.getString(nameAddr);
 537         int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true);
 538 
 539         // Be a little resilient
 540         Long oldValue = lookupLongConstant(name, false);
 541         if (oldValue == null) {
 542           addLongConstant(name, value);
 543         } else {
 544           if (oldValue.longValue() != value) {
 545             throw new RuntimeException("Error: the long constant \"" + name +
 546                                        "\" had its value redefined (old was " + oldValue +
 547                                        ", new is " + value + ". Aborting.");
 548           } else {
 549             System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
 550                                "had its value declared as " + value + " twice. Continuing.");

 551           }
 552         }
 553       }
 554 
 555       entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
 556     } while (nameAddr != null);




 557   }
 558 
 559   private BasicType lookupOrFail(String typeName) {
 560     BasicType type = (BasicType) lookupType(typeName, false);
 561     if (type == null) {
 562       throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " +
 563                                  "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " +
 564                                  "in the debug build of that VM). Can not continue.");
 565     }
 566     return type;
 567   }
 568 
 569   private long getLongValueFromProcess(String symbol) {
 570     return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true);
 571   }
 572 
 573   private Address lookupInProcess(String symbol) throws NoSuchSymbolException {
 574     // FIXME: abstract away the loadobject name
 575     for (int i = 0; i < jvmLibNames.length; i++) {
 576       Address addr = symbolLookup.lookup(jvmLibNames[i], symbol);


 725             if (curType.getSuperclass() != superclass) {
 726                 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 727                                            "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " +
 728                                            superclass.getName() + ").");
 729             }
 730         }
 731 
 732         // Classes are created with a size of UNINITIALIZED_SIZE.
 733         // Set size if necessary.
 734         if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) {
 735             curType.setSize(size);
 736         } else {
 737             if (curType.getSize() != size) {
 738                 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 739                                            "had its size redefined (old was " + curType.getSize() + ", new is " + size + ").");
 740             }
 741 
 742             if (!typeNameIsPointerType(typeName)) {
 743             System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 744                                "had its size declared as " + size + " twice. Continuing.");

 745         }
 746         }
 747 
 748     }
 749 
 750     /** "Virtual constructor" for fields based on type */
 751     public void createField(BasicType containingType,
 752                             String name, Type type, boolean isStatic,
 753                             long offset, Address staticFieldAddress) {
 754         // Add field to containing type
 755         containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress));
 756     }
 757 
 758     Field internalCreateField(BasicType containingType,
 759                               String name, Type type, boolean isStatic,
 760                               long offset, Address staticFieldAddress) {
 761     // "Virtual constructor" based on type
 762     if (type.isOopType()) {
 763       return new BasicOopField(this, containingType, name, type,
 764                                isStatic, offset, staticFieldAddress);




  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   private static int pointerSize = UNINITIALIZED_SIZE;
  54   // Counter to ensure read loops terminate:
  55   private static final int MAX_DUPLICATE_DEFINITIONS = 100;
  56   private int duplicateDefCount = 0;
  57 
  58   private static final boolean DEBUG;
  59   static {
  60     DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG")
  61             != null;
  62   }
  63 
  64   /** <P> This requires a SymbolLookup mechanism as well as the
  65       MachineDescription. Note that we do not need a NameMangler since
  66       we use the vmStructs mechanism to avoid looking up C++
  67       symbols. </P>
  68 
  69       <P> NOTE that it is guaranteed that this constructor will not
  70       attempt to fetch any Java values from the remote process, only C
  71       integers and addresses. This is required because we are fetching
  72       the sizes of the Java primitive types from the remote process,
  73       implying that attempting to fetch them before their sizes are
  74       known is illegal. </P>
  75 
  76       <P> Throws NoSuchSymbolException if a problem occurred while


 152     // Fetch the address of the VMTypeEntry*. We get this symbol first
 153     // and try to use it to make sure that symbol lookup is working.
 154     Address entryAddr = lookupInProcess("gHotSpotVMTypes");
 155     //    System.err.println("gHotSpotVMTypes address = " + entryAddr);
 156     // Dereference this once to get the pointer to the first VMTypeEntry
 157     //    dumpMemory(entryAddr, 80);
 158     entryAddr = entryAddr.getAddressAt(0);
 159 
 160     if (entryAddr == null) {
 161       throw new RuntimeException("gHotSpotVMTypes was not initialized properly in the remote process; can not continue");
 162     }
 163 
 164     typeEntryTypeNameOffset       = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
 165     typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
 166     typeEntryIsOopTypeOffset      = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
 167     typeEntryIsIntegerTypeOffset  = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
 168     typeEntryIsUnsignedOffset     = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
 169     typeEntrySizeOffset           = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
 170     typeEntryArrayStride          = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
 171 
 172     if (typeEntryArrayStride == 0L) {
 173       throw new RuntimeException("zero stride: cannot read types.");
 174     }
 175 
 176     // Start iterating down it until we find an entry with no name
 177     Address typeNameAddr = null;
 178     do {
 179       // Fetch the type name first
 180       typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset);
 181       if (typeNameAddr != null) {
 182         String typeName = CStringUtilities.getString(typeNameAddr);
 183 
 184         String superclassName = null;
 185         Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset);
 186         if (superclassNameAddr != null) {
 187           superclassName = CStringUtilities.getString(superclassNameAddr);
 188         }
 189 
 190         boolean isOopType     = (entryAddr.getCIntegerAt(typeEntryIsOopTypeOffset, C_INT32_SIZE, false) != 0);
 191         boolean isIntegerType = (entryAddr.getCIntegerAt(typeEntryIsIntegerTypeOffset, C_INT32_SIZE, false) != 0);
 192         boolean isUnsigned    = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0);
 193         long size             = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true);
 194 
 195         createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size);
 196         if (pointerSize == UNINITIALIZED_SIZE && typeName.equals("void*")) {
 197           pointerSize = (int)size;
 198         }
 199       }
 200 
 201       entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
 202     } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
 203 
 204     if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
 205       throw new RuntimeException("too many duplicate definitions");
 206     }
 207   }
 208 
 209   private void initializePrimitiveTypes() {
 210     // Look up the needed primitive types by name...they had better be present
 211     setJBooleanType(lookupPrimitiveType("jboolean"));
 212     setJByteType   (lookupPrimitiveType("jbyte"));
 213     setJCharType   (lookupPrimitiveType("jchar"));
 214     setJDoubleType (lookupPrimitiveType("jdouble"));
 215     setJFloatType  (lookupPrimitiveType("jfloat"));
 216     setJIntType    (lookupPrimitiveType("jint"));
 217     setJLongType   (lookupPrimitiveType("jlong"));
 218     setJShortType  (lookupPrimitiveType("jshort"));
 219 
 220     // Indicate that these are the Java primitive types
 221     ((BasicType) getJBooleanType()).setIsJavaPrimitiveType(true);
 222     ((BasicType) getJByteType()).setIsJavaPrimitiveType(true);
 223     ((BasicType) getJCharType()).setIsJavaPrimitiveType(true);
 224     ((BasicType) getJDoubleType()).setIsJavaPrimitiveType(true);
 225     ((BasicType) getJFloatType()).setIsJavaPrimitiveType(true);
 226     ((BasicType) getJIntType()).setIsJavaPrimitiveType(true);


 389   }
 390 
 391   private void readVMStructs() {
 392     // Get the variables we need in order to traverse the VMStructEntry[]
 393     long structEntryTypeNameOffset;
 394     long structEntryFieldNameOffset;
 395     long structEntryTypeStringOffset;
 396     long structEntryIsStaticOffset;
 397     long structEntryOffsetOffset;
 398     long structEntryAddressOffset;
 399     long structEntryArrayStride;
 400 
 401     structEntryTypeNameOffset     = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset");
 402     structEntryFieldNameOffset    = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset");
 403     structEntryTypeStringOffset   = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset");
 404     structEntryIsStaticOffset     = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset");
 405     structEntryOffsetOffset       = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset");
 406     structEntryAddressOffset      = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
 407     structEntryArrayStride        = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");
 408 
 409     if (structEntryArrayStride == 0L) {
 410       throw new RuntimeException("zero stride: cannot read types.");
 411     }
 412 
 413     // Fetch the address of the VMStructEntry*
 414     Address entryAddr = lookupInProcess("gHotSpotVMStructs");
 415     // Dereference this once to get the pointer to the first VMStructEntry
 416     entryAddr = entryAddr.getAddressAt(0);
 417     if (entryAddr == null) {
 418       throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue");
 419     }
 420 
 421     // Start iterating down it until we find an entry with no name
 422     Address fieldNameAddr = null;
 423     String typeName = null;
 424     String fieldName = null;
 425     String typeString = null;
 426     boolean isStatic = false;
 427     long offset = 0;
 428     Address staticFieldAddr = null;
 429     long size = 0;
 430     long index = 0;
 431     String opaqueName = "<opaque>";
 432     lookupOrCreateClass(opaqueName, false, false, false);


 470         // Create field by type
 471         createField(containingType, fieldName, fieldType,
 472                     isStatic, offset, staticFieldAddr);
 473       }
 474 
 475       ++index;
 476       entryAddr = entryAddr.addOffsetTo(structEntryArrayStride);
 477     } while (fieldNameAddr != null);
 478   }
 479 
 480   private void readVMIntConstants() {
 481     // Get the variables we need in order to traverse the VMIntConstantEntry[]
 482     long intConstantEntryNameOffset;
 483     long intConstantEntryValueOffset;
 484     long intConstantEntryArrayStride;
 485 
 486     intConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset");
 487     intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
 488     intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");
 489 
 490     if (intConstantEntryArrayStride == 0L) {
 491       throw new RuntimeException("zero stride: cannot read types.");
 492     }
 493 
 494 
 495     // Fetch the address of the VMIntConstantEntry*
 496     Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
 497     // Dereference this once to get the pointer to the first VMIntConstantEntry
 498     entryAddr = entryAddr.getAddressAt(0);
 499     if (entryAddr == null) {
 500       throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue");
 501     }
 502 
 503     // Start iterating down it until we find an entry with no name
 504     Address nameAddr = null;
 505     do {
 506       // Fetch the type name first
 507       nameAddr = entryAddr.getAddressAt(intConstantEntryNameOffset);
 508       if (nameAddr != null) {
 509         String name = CStringUtilities.getString(nameAddr);
 510         int value = (int) entryAddr.getCIntegerAt(intConstantEntryValueOffset, C_INT32_SIZE, false);
 511 
 512         // Be a little resilient
 513         Integer oldValue = lookupIntConstant(name, false);
 514         if (oldValue == null) {
 515           addIntConstant(name, value);
 516         } else {
 517           if (oldValue.intValue() != value) {
 518             throw new RuntimeException("Error: the integer constant \"" + name +
 519                                        "\" had its value redefined (old was " + oldValue +
 520                                        ", new is " + value + ". Aborting.");
 521           } else {
 522             System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
 523                                "had its value declared as " + value + " twice. Continuing.");
 524             duplicateDefCount++;
 525           }
 526         }
 527       }
 528 
 529       entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
 530     } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
 531 
 532     if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
 533       throw new RuntimeException("too many duplicate definitions");
 534     }
 535   }
 536 
 537   private void readVMLongConstants() {
 538     // Get the variables we need in order to traverse the VMLongConstantEntry[]
 539     long longConstantEntryNameOffset;
 540     long longConstantEntryValueOffset;
 541     long longConstantEntryArrayStride;
 542 
 543     longConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset");
 544     longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
 545     longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");
 546 
 547     if (longConstantEntryArrayStride == 0L) {
 548       throw new RuntimeException("zero stride: cannot read types.");
 549     }
 550 
 551     // Fetch the address of the VMLongConstantEntry*
 552     Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
 553     // Dereference this once to get the pointer to the first VMLongConstantEntry
 554     entryAddr = entryAddr.getAddressAt(0);
 555     if (entryAddr == null) {
 556       throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue");
 557     }
 558 
 559     // Start iterating down it until we find an entry with no name
 560     Address nameAddr = null;
 561     do {
 562       // Fetch the type name first
 563       nameAddr = entryAddr.getAddressAt(longConstantEntryNameOffset);
 564       if (nameAddr != null) {
 565         String name = CStringUtilities.getString(nameAddr);
 566         int value = (int) entryAddr.getCIntegerAt(longConstantEntryValueOffset, C_INT64_SIZE, true);
 567 
 568         // Be a little resilient
 569         Long oldValue = lookupLongConstant(name, false);
 570         if (oldValue == null) {
 571           addLongConstant(name, value);
 572         } else {
 573           if (oldValue.longValue() != value) {
 574             throw new RuntimeException("Error: the long constant \"" + name +
 575                                        "\" had its value redefined (old was " + oldValue +
 576                                        ", new is " + value + ". Aborting.");
 577           } else {
 578             System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
 579                                "had its value declared as " + value + " twice. Continuing.");
 580             duplicateDefCount++;
 581           }
 582         }
 583       }
 584 
 585       entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
 586     } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
 587 
 588     if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
 589       throw new RuntimeException("too many duplicate definitions.");
 590     }
 591   }
 592 
 593   private BasicType lookupOrFail(String typeName) {
 594     BasicType type = (BasicType) lookupType(typeName, false);
 595     if (type == null) {
 596       throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " +
 597                                  "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " +
 598                                  "in the debug build of that VM). Can not continue.");
 599     }
 600     return type;
 601   }
 602 
 603   private long getLongValueFromProcess(String symbol) {
 604     return lookupInProcess(symbol).getCIntegerAt(0, C_INT64_SIZE, true);
 605   }
 606 
 607   private Address lookupInProcess(String symbol) throws NoSuchSymbolException {
 608     // FIXME: abstract away the loadobject name
 609     for (int i = 0; i < jvmLibNames.length; i++) {
 610       Address addr = symbolLookup.lookup(jvmLibNames[i], symbol);


 759             if (curType.getSuperclass() != superclass) {
 760                 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 761                                            "had its superclass redefined (old was " + curType.getSuperclass().getName() + ", new is " +
 762                                            superclass.getName() + ").");
 763             }
 764         }
 765 
 766         // Classes are created with a size of UNINITIALIZED_SIZE.
 767         // Set size if necessary.
 768         if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) {
 769             curType.setSize(size);
 770         } else {
 771             if (curType.getSize() != size) {
 772                 throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 773                                            "had its size redefined (old was " + curType.getSize() + ", new is " + size + ").");
 774             }
 775 
 776             if (!typeNameIsPointerType(typeName)) {
 777                 System.err.println("Warning: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 778                                    "had its size declared as " + size + " twice. Continuing.");
 779                 duplicateDefCount++;
 780             }
 781         }
 782 
 783     }
 784 
 785     /** "Virtual constructor" for fields based on type */
 786     public void createField(BasicType containingType,
 787                             String name, Type type, boolean isStatic,
 788                             long offset, Address staticFieldAddress) {
 789         // Add field to containing type
 790         containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress));
 791     }
 792 
 793     Field internalCreateField(BasicType containingType,
 794                               String name, Type type, boolean isStatic,
 795                               long offset, Address staticFieldAddress) {
 796     // "Virtual constructor" based on type
 797     if (type.isOopType()) {
 798       return new BasicOopField(this, containingType, name, type,
 799                                isStatic, offset, staticFieldAddress);


< prev index next >