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

Split Split Close
Expand all
Collapse all
          --- old/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
          +++ new/hotspot/agent/src/share/classes/sun/jvm/hotspot/HotSpotTypeDataBase.java
↓ open down ↓ 43 lines elided ↑ open up ↑
  44   44   */
  45   45  
  46   46  public class HotSpotTypeDataBase extends BasicTypeDataBase {
  47   47    private Debugger symbolLookup;
  48   48    private String[] jvmLibNames;
  49   49    private static final int UNINITIALIZED_SIZE = -1;
  50   50    private static final int C_INT8_SIZE  = 1;
  51   51    private static final int C_INT32_SIZE = 4;
  52   52    private static final int C_INT64_SIZE = 8;
  53   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;
  54   57  
  55   58    private static final boolean DEBUG;
  56   59    static {
  57   60      DEBUG = System.getProperty("sun.jvm.hotspot.HotSpotTypeDataBase.DEBUG")
  58   61              != null;
  59   62    }
  60   63  
  61   64    /** <P> This requires a SymbolLookup mechanism as well as the
  62   65        MachineDescription. Note that we do not need a NameMangler since
  63   66        we use the vmStructs mechanism to avoid looking up C++
↓ open down ↓ 95 lines elided ↑ open up ↑
 159  162      }
 160  163  
 161  164      typeEntryTypeNameOffset       = getLongValueFromProcess("gHotSpotVMTypeEntryTypeNameOffset");
 162  165      typeEntrySuperclassNameOffset = getLongValueFromProcess("gHotSpotVMTypeEntrySuperclassNameOffset");
 163  166      typeEntryIsOopTypeOffset      = getLongValueFromProcess("gHotSpotVMTypeEntryIsOopTypeOffset");
 164  167      typeEntryIsIntegerTypeOffset  = getLongValueFromProcess("gHotSpotVMTypeEntryIsIntegerTypeOffset");
 165  168      typeEntryIsUnsignedOffset     = getLongValueFromProcess("gHotSpotVMTypeEntryIsUnsignedOffset");
 166  169      typeEntrySizeOffset           = getLongValueFromProcess("gHotSpotVMTypeEntrySizeOffset");
 167  170      typeEntryArrayStride          = getLongValueFromProcess("gHotSpotVMTypeEntryArrayStride");
 168  171  
      172 +    if (typeEntryArrayStride == 0L) {
      173 +      throw new RuntimeException("zero stride: cannot read types.");
      174 +    }
      175 +
 169  176      // Start iterating down it until we find an entry with no name
 170  177      Address typeNameAddr = null;
 171  178      do {
 172  179        // Fetch the type name first
 173  180        typeNameAddr = entryAddr.getAddressAt(typeEntryTypeNameOffset);
 174  181        if (typeNameAddr != null) {
 175  182          String typeName = CStringUtilities.getString(typeNameAddr);
 176  183  
 177  184          String superclassName = null;
 178  185          Address superclassNameAddr = entryAddr.getAddressAt(typeEntrySuperclassNameOffset);
↓ open down ↓ 6 lines elided ↑ open up ↑
 185  192          boolean isUnsigned    = (entryAddr.getCIntegerAt(typeEntryIsUnsignedOffset, C_INT32_SIZE, false) != 0);
 186  193          long size             = entryAddr.getCIntegerAt(typeEntrySizeOffset, C_INT64_SIZE, true);
 187  194  
 188  195          createType(typeName, superclassName, isOopType, isIntegerType, isUnsigned, size);
 189  196          if (pointerSize == UNINITIALIZED_SIZE && typeName.equals("void*")) {
 190  197            pointerSize = (int)size;
 191  198          }
 192  199        }
 193  200  
 194  201        entryAddr = entryAddr.addOffsetTo(typeEntryArrayStride);
 195      -    } while (typeNameAddr != null);
      202 +    } while (typeNameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
      203 +
      204 +    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      205 +      throw new RuntimeException("too many duplicate definitions");
      206 +    }
 196  207    }
 197  208  
 198  209    private void initializePrimitiveTypes() {
 199  210      // Look up the needed primitive types by name...they had better be present
 200  211      setJBooleanType(lookupPrimitiveType("jboolean"));
 201  212      setJByteType   (lookupPrimitiveType("jbyte"));
 202  213      setJCharType   (lookupPrimitiveType("jchar"));
 203  214      setJDoubleType (lookupPrimitiveType("jdouble"));
 204  215      setJFloatType  (lookupPrimitiveType("jfloat"));
 205  216      setJIntType    (lookupPrimitiveType("jint"));
↓ open down ↓ 182 lines elided ↑ open up ↑
 388  399      long structEntryArrayStride;
 389  400  
 390  401      structEntryTypeNameOffset     = getLongValueFromProcess("gHotSpotVMStructEntryTypeNameOffset");
 391  402      structEntryFieldNameOffset    = getLongValueFromProcess("gHotSpotVMStructEntryFieldNameOffset");
 392  403      structEntryTypeStringOffset   = getLongValueFromProcess("gHotSpotVMStructEntryTypeStringOffset");
 393  404      structEntryIsStaticOffset     = getLongValueFromProcess("gHotSpotVMStructEntryIsStaticOffset");
 394  405      structEntryOffsetOffset       = getLongValueFromProcess("gHotSpotVMStructEntryOffsetOffset");
 395  406      structEntryAddressOffset      = getLongValueFromProcess("gHotSpotVMStructEntryAddressOffset");
 396  407      structEntryArrayStride        = getLongValueFromProcess("gHotSpotVMStructEntryArrayStride");
 397  408  
      409 +    if (structEntryArrayStride == 0L) {
      410 +      throw new RuntimeException("zero stride: cannot read types.");
      411 +    }
      412 +
 398  413      // Fetch the address of the VMStructEntry*
 399  414      Address entryAddr = lookupInProcess("gHotSpotVMStructs");
 400  415      // Dereference this once to get the pointer to the first VMStructEntry
 401  416      entryAddr = entryAddr.getAddressAt(0);
 402  417      if (entryAddr == null) {
 403  418        throw new RuntimeException("gHotSpotVMStructs was not initialized properly in the remote process; can not continue");
 404  419      }
 405  420  
 406  421      // Start iterating down it until we find an entry with no name
 407  422      Address fieldNameAddr = null;
↓ open down ↓ 57 lines elided ↑ open up ↑
 465  480    private void readVMIntConstants() {
 466  481      // Get the variables we need in order to traverse the VMIntConstantEntry[]
 467  482      long intConstantEntryNameOffset;
 468  483      long intConstantEntryValueOffset;
 469  484      long intConstantEntryArrayStride;
 470  485  
 471  486      intConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMIntConstantEntryNameOffset");
 472  487      intConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMIntConstantEntryValueOffset");
 473  488      intConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMIntConstantEntryArrayStride");
 474  489  
      490 +    if (intConstantEntryArrayStride == 0L) {
      491 +      throw new RuntimeException("zero stride: cannot read types.");
      492 +    }
      493 +
      494 +
 475  495      // Fetch the address of the VMIntConstantEntry*
 476  496      Address entryAddr = lookupInProcess("gHotSpotVMIntConstants");
 477  497      // Dereference this once to get the pointer to the first VMIntConstantEntry
 478  498      entryAddr = entryAddr.getAddressAt(0);
 479  499      if (entryAddr == null) {
 480  500        throw new RuntimeException("gHotSpotVMIntConstants was not initialized properly in the remote process; can not continue");
 481  501      }
 482  502  
 483  503      // Start iterating down it until we find an entry with no name
 484  504      Address nameAddr = null;
↓ open down ↓ 9 lines elided ↑ open up ↑
 494  514          if (oldValue == null) {
 495  515            addIntConstant(name, value);
 496  516          } else {
 497  517            if (oldValue.intValue() != value) {
 498  518              throw new RuntimeException("Error: the integer constant \"" + name +
 499  519                                         "\" had its value redefined (old was " + oldValue +
 500  520                                         ", new is " + value + ". Aborting.");
 501  521            } else {
 502  522              System.err.println("Warning: the int constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMIntConstants) " +
 503  523                                 "had its value declared as " + value + " twice. Continuing.");
      524 +            duplicateDefCount++;
 504  525            }
 505  526          }
 506  527        }
 507  528  
 508  529        entryAddr = entryAddr.addOffsetTo(intConstantEntryArrayStride);
 509      -    } while (nameAddr != null);
      530 +    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
      531 +
      532 +    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      533 +      throw new RuntimeException("too many duplicate definitions");
      534 +    }
 510  535    }
 511  536  
 512  537    private void readVMLongConstants() {
 513  538      // Get the variables we need in order to traverse the VMLongConstantEntry[]
 514  539      long longConstantEntryNameOffset;
 515  540      long longConstantEntryValueOffset;
 516  541      long longConstantEntryArrayStride;
 517  542  
 518  543      longConstantEntryNameOffset  = getLongValueFromProcess("gHotSpotVMLongConstantEntryNameOffset");
 519  544      longConstantEntryValueOffset = getLongValueFromProcess("gHotSpotVMLongConstantEntryValueOffset");
 520  545      longConstantEntryArrayStride = getLongValueFromProcess("gHotSpotVMLongConstantEntryArrayStride");
 521  546  
      547 +    if (longConstantEntryArrayStride == 0L) {
      548 +      throw new RuntimeException("zero stride: cannot read types.");
      549 +    }
      550 +
 522  551      // Fetch the address of the VMLongConstantEntry*
 523  552      Address entryAddr = lookupInProcess("gHotSpotVMLongConstants");
 524  553      // Dereference this once to get the pointer to the first VMLongConstantEntry
 525  554      entryAddr = entryAddr.getAddressAt(0);
 526  555      if (entryAddr == null) {
 527  556        throw new RuntimeException("gHotSpotVMLongConstants was not initialized properly in the remote process; can not continue");
 528  557      }
 529  558  
 530  559      // Start iterating down it until we find an entry with no name
 531  560      Address nameAddr = null;
↓ open down ↓ 9 lines elided ↑ open up ↑
 541  570          if (oldValue == null) {
 542  571            addLongConstant(name, value);
 543  572          } else {
 544  573            if (oldValue.longValue() != value) {
 545  574              throw new RuntimeException("Error: the long constant \"" + name +
 546  575                                         "\" had its value redefined (old was " + oldValue +
 547  576                                         ", new is " + value + ". Aborting.");
 548  577            } else {
 549  578              System.err.println("Warning: the long constant \"" + name + "\" (declared in the remote VM in VMStructs::localHotSpotVMLongConstants) " +
 550  579                                 "had its value declared as " + value + " twice. Continuing.");
      580 +            duplicateDefCount++;
 551  581            }
 552  582          }
 553  583        }
 554  584  
 555  585        entryAddr = entryAddr.addOffsetTo(longConstantEntryArrayStride);
 556      -    } while (nameAddr != null);
      586 +    } while (nameAddr != null && duplicateDefCount < MAX_DUPLICATE_DEFINITIONS);
      587 +
      588 +    if (duplicateDefCount >= MAX_DUPLICATE_DEFINITIONS) {
      589 +      throw new RuntimeException("too many duplicate definitions.");
      590 +    }
 557  591    }
 558  592  
 559  593    private BasicType lookupOrFail(String typeName) {
 560  594      BasicType type = (BasicType) lookupType(typeName, false);
 561  595      if (type == null) {
 562  596        throw new RuntimeException("Type \"" + typeName + "\", referenced in VMStructs::localHotSpotVMStructs in the remote VM, " +
 563  597                                   "was not present in the remote VMStructs::localHotSpotVMTypes table (should have been caught " +
 564  598                                   "in the debug build of that VM). Can not continue.");
 565  599      }
 566  600      return type;
↓ open down ↓ 166 lines elided ↑ open up ↑
 733  767          // Set size if necessary.
 734  768          if (curType.getSize() == UNINITIALIZED_SIZE || curType.getSize() == 0) {
 735  769              curType.setSize(size);
 736  770          } else {
 737  771              if (curType.getSize() != size) {
 738  772                  throw new RuntimeException("Error: the type \"" + typeName + "\" (declared in the remote VM in VMStructs::localHotSpotVMTypes) " +
 739  773                                             "had its size redefined (old was " + curType.getSize() + ", new is " + size + ").");
 740  774              }
 741  775  
 742  776              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      -        }
      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 +            }
 746  781          }
 747  782  
 748  783      }
 749  784  
 750  785      /** "Virtual constructor" for fields based on type */
 751  786      public void createField(BasicType containingType,
 752  787                              String name, Type type, boolean isStatic,
 753  788                              long offset, Address staticFieldAddress) {
 754  789          // Add field to containing type
 755  790          containingType.addField(internalCreateField(containingType, name, type, isStatic, offset, staticFieldAddress));
↓ open down ↓ 78 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX