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);
|