private void EnumerateRefsOfUnboxedClass(Address objref, int offsetInObject, Action <ulong, int> action) { if (m_fields == null) { return; } for (int i = 0; i < m_fields.Length; i++) { var field = m_fields[i]; var offset = offsetInObject + field.Offset; if (GCRootNames.IsReferenceType(field.m_ComponentType)) { var val = m_heap.FetchIntPtrAt(objref, offset); if (val != 0) { action(val, offset); } } else if (field.m_ComponentType == CorElementType.ELEMENT_TYPE_VALUETYPE) { // We should not have recursive VALUE TYPEs Debug.Assert(field.m_type != this); field.m_type.EnumerateRefsOfUnboxedClass(objref, offset, action); } } }
public override void EnumerateRefsOfObject(Address objRef, Action <Address, int> action) { if (IsArray) { bool isRefType = GCRootNames.IsReferenceType(m_array.componentType); if (isRefType || m_array.componentType == CorElementType.ELEMENT_TYPE_VALUETYPE) { var arrayLength = (int)m_heap.FetchIntPtrAt(objRef, m_array.countOffset); int offset = m_array.firstElementOffset; if (isRefType) { for (int i = 0; i < arrayLength; i++) { var val = m_heap.FetchIntPtrAt(objRef, offset); if (val != 0) { action(val, offset); } offset += m_array.elementSize; } } else { Debug.Assert(m_array.componentType == CorElementType.ELEMENT_TYPE_VALUETYPE); for (int i = 0; i < arrayLength; i++) { m_elementType.EnumerateRefsOfUnboxedClass(objRef, offset, action); offset += m_array.elementSize; } } } } else { // Do the base type's references if (BaseType != null) { BaseType.EnumerateRefsOfObjectCarefully(objRef, action); } // And then my fields. EnumerateRefsOfUnboxedClass(objRef, m_boxOffset, action); } }
private void SetNameModuleAndFields(CorElementType typeKind, COR_TYPEID typeID, int numFields) { // THere is recursion in the definition of primitive types (they have a value field of the primtitive type. // Cut this off here. if (GCRootNames.IsPrimitiveType(typeKind)) { numFields = 0; } var buffer = new StringBuilder(1024); IMetadataImport metaData = null; int bufferSizeRet; // This is getting names. If we fail, we can still plow on .... try { ICorDebugType corType = null; // Console.WriteLine("Calling GetTypeForTypeID {0:x} {1:x}", typeID.token1, typeID.token2); m_heap.m_process5.GetTypeForTypeID(typeID, out corType); string moduleFilePath; m_name = GCRootNames.GetTypeName(corType, out moduleFilePath, out metaData, buffer); m_moduleFilePath = moduleFilePath; } catch (Exception e) { Console.WriteLine("Error: Caught exception for type ID {0:x} {1:x}: {2}", typeID.token1, typeID.token2, e.Message); m_name = string.Format("!ERROR TYPE ID {0:x} {1:x}", typeID.token1, typeID.token2); m_moduleFilePath = Name; } if (numFields > 0) { m_fields = new ICorDebugGCHeapField[numFields]; var corFields = new COR_FIELD[numFields]; int fieldsFetched; m_heap.m_process5.GetTypeFields(typeID, corFields.Length, corFields, out fieldsFetched); Debug.Assert(fieldsFetched == m_fields.Length); for (int i = 0; i < corFields.Length; i++) { int fieldTypeToken, fieldAttr, sigBlobSize, cplusTypeFlab, fieldValSize; IntPtr sigBlob, fieldVal; buffer.Length = 0; if (metaData != null) { metaData.GetFieldProps(corFields[i].token, out fieldTypeToken, buffer, buffer.Capacity, out bufferSizeRet, out fieldAttr, out sigBlob, out sigBlobSize, out cplusTypeFlab, out fieldVal, out fieldValSize); } var fieldName = buffer.ToString(); ICorDebugGCHeapType fieldType = null; // If the type has never been loaded, then you can get a null field type. // TODO FIX NOW, think about this. if (corFields[i].id.token1 != 0 || corFields[i].id.token2 != 0) { // Console.WriteLine("Looking up field {0}.{1} typeId {2:x} {3:x}", Name, fieldName, corFields[i].id.token1, corFields[i].id.token2); Debug.Assert(corFields[i].fieldType != CorElementType.ELEMENT_TYPE_END); // TODO FIX NOW remove the condition if (!GCRootNames.IsReferenceType(corFields[i].fieldType)) { fieldType = m_heap.GetObjectTypeFromID(corFields[i].id); } } else { // Console.WriteLine("Warning, NULL type token for {0}.{1} assuming it is an objectRef", Name, fieldName); // Zero means the type is not loaded. This can only happen if it is a reference type corFields[i].fieldType = CorElementType.ELEMENT_TYPE_CLASS; } // The element types match. (string matches class) #if DEBUG if (fieldType != null) { var fieldTypeKind = fieldType.TypeKind; if (fieldTypeKind == CorElementType.ELEMENT_TYPE_STRING) { fieldTypeKind = CorElementType.ELEMENT_TYPE_CLASS; } if (fieldTypeKind == CorElementType.ELEMENT_TYPE_OBJECT) { fieldTypeKind = CorElementType.ELEMENT_TYPE_CLASS; } Debug.Assert(fieldTypeKind == corFields[i].fieldType); } #endif m_fields[i] = new ICorDebugGCHeapField(fieldName, corFields[i].offset, fieldType, corFields[i].fieldType); } } }