void ParseEnum(TypeDefinition enumTypeDef) { // TODO: verify that int32 is the enums storage type for constant read below InspectorEnum ienum = new InspectorEnum(); ienum.Name = metaReader.GetString(enumTypeDef.Name); InspectorEnums[ienum.Name] = ienum; var fields = enumTypeDef.GetFields(); foreach (var fieldHandle in fields) { var inspectorField = new InspectorField(); var fieldDef = metaReader.GetFieldDefinition(fieldHandle); if ((fieldDef.Attributes & FieldAttributes.HasDefault) != 0) { var constantHandle = fieldDef.GetDefaultValue(); var constant = metaReader.GetConstant(constantHandle); BlobReader constantReader = metaReader.GetBlobReader(constant.Value); ienum.Values[metaReader.GetString(fieldDef.Name)] = constantReader.ReadInt32(); } } return; }
private void InspectFields(FieldDefinitionHandleCollection fields) { foreach (var fieldHandle in fields) { var inspectorField = new InspectorField(); var fieldDef = metaReader.GetFieldDefinition(fieldHandle); var customAttr = fieldDef.GetCustomAttributes(); foreach (var caHandle in customAttr) { // Look for InspectorAttribute if (DecodeCustomAttribute(caHandle, inspectorField)) { BlobReader sigReader = metaReader.GetBlobReader(fieldDef.Signature); SignatureHeader header = sigReader.ReadSignatureHeader(); if (header.Kind != SignatureKind.Field) { continue; } var typeCode = sigReader.ReadSignatureTypeCode(); string typeName = typeCode.ToString(); if (typeCode == SignatureTypeCode.SZArray) { inspectorField.IsArray = true; SignatureTypeCode code = sigReader.ReadSignatureTypeCode(); if (code == SignatureTypeCode.TypeHandle) { bool isEnum; DecodeTypeHandleTypeName(sigReader, out typeName, out isEnum); } else { typeName = code.ToString(); } } else if (typeCode == SignatureTypeCode.TypeHandle) { bool isEnum; DecodeTypeHandleTypeName(sigReader, out typeName, out isEnum); inspectorField.IsEnum = isEnum; } inspectorField.TypeName = typeName; inspectorField.Name = metaReader.GetString(fieldDef.Name); _inspectorComponent.Fields[inspectorField.Name] = inspectorField; break; } } } }
private bool DecodeCustomAttribute(CustomAttributeHandle caHandle, InspectorField inspectorField) { // GetCustomAttribute: https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs#L1370 // Custom Attribute var ca = metaReader.GetCustomAttribute(caHandle); // MethodDefinitionHandle or MemberReferenceHandle if (ca.Constructor.Kind != HandleKind.MemberReference) { Console.WriteLine("ca.Constructor.Kind != HandleKind.MemberReference"); return(false); } // constructor of the custom attr which contains the signature var memberRef = metaReader.GetMemberReference((MemberReferenceHandle)ca.Constructor); // parent of the constructor is the TypeReference var parent = memberRef.Parent; if (parent.Kind != HandleKind.TypeReference) { Console.WriteLine("parent.Kind != HandleKind.TypeReference"); return(false); } var parentTypeRef = metaReader.GetTypeReference((TypeReferenceHandle)parent); // check whether we have an InspectorAttribute if (metaReader.GetString(parentTypeRef.Name) != "InspectorAttribute") { //Console.WriteLine("parentTypeRef != InspectorAttribute"); return(false); } // args var argsReader = metaReader.GetBlobReader((BlobHandle)ca.Value); uint prolog = argsReader.ReadUInt16(); if (prolog != 1) { Console.WriteLine("prolog != 1"); return(false); } // sig reader is on constructor BlobReader sigReader = metaReader.GetBlobReader(memberRef.Signature); SignatureHeader header = sigReader.ReadSignatureHeader(); // Get the type parameter count. if (header.IsGeneric && sigReader.ReadCompressedInteger() != 0) { Console.WriteLine("header.IsGeneric && sigReader.ReadCompressedInteger() != 0"); return(false); } // Get the parameter count int paramCount = sigReader.ReadCompressedInteger(); // Get the type return type. var returnTypeCode = sigReader.ReadSignatureTypeCode(); if (returnTypeCode != SignatureTypeCode.Void) { Console.WriteLine("returnTypeCode != SignatureTypeCode.Void"); return(false); } List <SignatureTypeCode> sigTypeCodes = new List <SignatureTypeCode>(); // position args for (int i = 0; i < paramCount; i++) { SignatureTypeCode paramTypeCode = sigReader.ReadSignatureTypeCode(); // support string custom attr for now to simplify things if (paramTypeCode != SignatureTypeCode.String) { return(false); } string value; if (CrackStringInAttributeValue(out value, ref argsReader)) { inspectorField.CustomAttrPositionalArgs.Add(value); } sigTypeCodes.Add(paramTypeCode); } // named args short namedParamCount = argsReader.ReadInt16(); for (short i = 0; i < namedParamCount; i++) { // Ecma-335 23.3 - A NamedArg is simply a FixedArg preceded by information to identify which field or // property it represents. [Note: Recall that the CLI allows fields and properties to have the same name; so // we require a means to disambiguate such situations. end note] FIELD is the single byte 0x53. PROPERTY is // the single byte 0x54. // https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/MetadataReader/MetadataDecoder.cs#L1305 var kind = (CustomAttributeNamedArgumentKind)argsReader.ReadCompressedInteger(); if (kind != CustomAttributeNamedArgumentKind.Field && kind != CustomAttributeNamedArgumentKind.Property) { return(false); } var typeCode = argsReader.ReadSerializationTypeCode(); // support string/int custom attr for now to simplify things if (typeCode != SerializationTypeCode.String && typeCode != SerializationTypeCode.Int32) { return(false); } string name; if (!CrackStringInAttributeValue(out name, ref argsReader)) { return(false); } if (typeCode == SerializationTypeCode.Int32) { int value; value = argsReader.ReadInt32(); inspectorField.CustomAttrNamedArgs[name] = value.ToString(); } else { string value; if (!CrackStringInAttributeValue(out value, ref argsReader)) { return(false); } inspectorField.CustomAttrNamedArgs[name] = value; } } return(true); }
// Inspect a CSComponent derived class internal InspectorComponent Inspect() { var fields = typeDef.GetFields(); foreach (var fieldHandle in fields) { var inspectorField = new InspectorField(); var fieldDef = metaReader.GetFieldDefinition(fieldHandle); var customAttr = fieldDef.GetCustomAttributes(); foreach (var caHandle in customAttr) { // Look for InspectorAttribute if (DecodeCustomAttribute(caHandle, inspectorField)) { BlobReader sigReader = metaReader.GetBlobReader(fieldDef.Signature); SignatureHeader header = sigReader.ReadSignatureHeader(); if (header.Kind != SignatureKind.Field) { continue; } var typeCode = sigReader.ReadSignatureTypeCode(); string typeName = typeCode.ToString(); if (typeCode == SignatureTypeCode.TypeHandle) { EntityHandle token = sigReader.ReadTypeHandle(); HandleKind tokenType = token.Kind; if (tokenType == HandleKind.TypeDefinition) { // can store local enum typedefs // enum initializers are stored as constant value in the IL var typeDef = metaReader.GetTypeDefinition((TypeDefinitionHandle)token); var baseTypeToken = typeDef.BaseType; if (baseTypeToken.Kind != HandleKind.TypeReference) { continue; } var baseTypeRef = metaReader.GetTypeReference((TypeReferenceHandle)baseTypeToken); if (metaReader.GetString(baseTypeRef.Name) != "Enum") { continue; } inspectorField.IsEnum = true; typeName = metaReader.GetString(typeDef.Name); } else if (tokenType == HandleKind.TypeReference) { // TypeReference, ok var typeRef = metaReader.GetTypeReference((TypeReferenceHandle)token); typeName = metaReader.GetString(typeRef.Name); } else { // ??? continue; } } inspectorField.TypeName = typeName; inspectorField.Name = metaReader.GetString(fieldDef.Name); _inspectorComponent.Fields [inspectorField.Name] = inspectorField; break; } } } // There is no way to get the initializer value of a field // other than to inspect the IL code of the constructor var methods = typeDef.GetMethods(); foreach (var methodHandle in methods) { var methodDef = metaReader.GetMethodDefinition(methodHandle); if (metaReader.GetString(methodDef.Name) == ".ctor") { var body = peFile.GetMethodBody(methodDef.RelativeVirtualAddress); var ilBytes = body.GetILContent(); InspectILBlock(ilBytes, ilBytes.Length); } } //Dump (); return(_inspectorComponent); }
void ParseEnum(TypeDefinition enumTypeDef) { // TODO: verify that int32 is the enums storage type for constant read below InspectorEnum ienum = new InspectorEnum (); ienum.Name = metaReader.GetString (enumTypeDef.Name); InspectorEnums [ienum.Name] = ienum; var fields = enumTypeDef.GetFields (); foreach (var fieldHandle in fields) { var inspectorField = new InspectorField (); var fieldDef = metaReader.GetFieldDefinition (fieldHandle); if ((fieldDef.Attributes & FieldAttributes.HasDefault) != 0) { var constantHandle = fieldDef.GetDefaultValue (); var constant = metaReader.GetConstant (constantHandle); BlobReader constantReader = metaReader.GetBlobReader (constant.Value); ienum.Values [metaReader.GetString (fieldDef.Name)] = constantReader.ReadInt32 (); } } return; }
private void InspectFields(FieldDefinitionHandleCollection fields) { foreach (var fieldHandle in fields) { var inspectorField = new InspectorField(); var fieldDef = metaReader.GetFieldDefinition(fieldHandle); var customAttr = fieldDef.GetCustomAttributes(); foreach (var caHandle in customAttr) { // Look for InspectorAttribute if (DecodeCustomAttribute(caHandle, inspectorField)) { BlobReader sigReader = metaReader.GetBlobReader(fieldDef.Signature); SignatureHeader header = sigReader.ReadSignatureHeader(); if (header.Kind != SignatureKind.Field) { continue; } var typeCode = sigReader.ReadSignatureTypeCode(); string typeName = typeCode.ToString(); if (typeCode == SignatureTypeCode.TypeHandle) { EntityHandle token = sigReader.ReadTypeHandle(); HandleKind tokenType = token.Kind; if (tokenType == HandleKind.TypeDefinition) { // can store local enum typedefs // enum initializers are stored as constant value in the IL var typeDef = metaReader.GetTypeDefinition((TypeDefinitionHandle)token); var baseTypeToken = typeDef.BaseType; if (baseTypeToken.Kind != HandleKind.TypeReference) { continue; } var baseTypeRef = metaReader.GetTypeReference((TypeReferenceHandle)baseTypeToken); if (metaReader.GetString(baseTypeRef.Name) != "Enum") { continue; } inspectorField.IsEnum = true; typeName = metaReader.GetString(typeDef.Name); } else if (tokenType == HandleKind.TypeReference) { // TypeReference, ok var typeRef = metaReader.GetTypeReference((TypeReferenceHandle)token); typeName = metaReader.GetString(typeRef.Name); } else { // ??? continue; } } inspectorField.TypeName = typeName; inspectorField.Name = metaReader.GetString(fieldDef.Name); _inspectorComponent.Fields[inspectorField.Name] = inspectorField; break; } } } }