[Add] FishNet
This commit is contained in:
@@ -0,0 +1,449 @@
|
||||
//
|
||||
// Author:
|
||||
// Jb Evain (jbevain@gmail.com)
|
||||
//
|
||||
// Copyright (c) 2008 - 2015 Jb Evain
|
||||
// Copyright (c) 2008 - 2011 Novell, Inc.
|
||||
//
|
||||
// Licensed under the MIT/X11 license.
|
||||
//
|
||||
|
||||
using MonoFN.Cecil.Cil;
|
||||
using MonoFN.Cecil.Metadata;
|
||||
using MonoFN.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace MonoFN.Cecil
|
||||
{
|
||||
internal struct Range
|
||||
{
|
||||
public uint Start;
|
||||
public uint Length;
|
||||
|
||||
public Range(uint index, uint length)
|
||||
{
|
||||
Start = index;
|
||||
Length = length;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class MetadataSystem
|
||||
{
|
||||
internal AssemblyNameReference[] AssemblyReferences;
|
||||
internal ModuleReference[] ModuleReferences;
|
||||
internal TypeDefinition[] Types;
|
||||
internal TypeReference[] TypeReferences;
|
||||
internal FieldDefinition[] Fields;
|
||||
internal MethodDefinition[] Methods;
|
||||
internal MemberReference[] MemberReferences;
|
||||
internal Dictionary<uint, Collection<uint>> NestedTypes;
|
||||
internal Dictionary<uint, uint> ReverseNestedTypes;
|
||||
internal Dictionary<uint, Collection<Row<uint, MetadataToken>>> Interfaces;
|
||||
internal Dictionary<uint, Row<ushort, uint>> ClassLayouts;
|
||||
internal Dictionary<uint, uint> FieldLayouts;
|
||||
internal Dictionary<uint, uint> FieldRVAs;
|
||||
internal Dictionary<MetadataToken, uint> FieldMarshals;
|
||||
internal Dictionary<MetadataToken, Row<ElementType, uint>> Constants;
|
||||
internal Dictionary<uint, Collection<MetadataToken>> Overrides;
|
||||
internal Dictionary<MetadataToken, Range[]> CustomAttributes;
|
||||
internal Dictionary<MetadataToken, Range[]> SecurityDeclarations;
|
||||
internal Dictionary<uint, Range> Events;
|
||||
internal Dictionary<uint, Range> Properties;
|
||||
internal Dictionary<uint, Row<MethodSemanticsAttributes, MetadataToken>> Semantics;
|
||||
internal Dictionary<uint, Row<PInvokeAttributes, uint, uint>> PInvokes;
|
||||
internal Dictionary<MetadataToken, Range[]> GenericParameters;
|
||||
internal Dictionary<uint, Collection<Row<uint, MetadataToken>>> GenericConstraints;
|
||||
internal Document[] Documents;
|
||||
internal Dictionary<uint, Collection<Row<uint, Range, Range, uint, uint, uint>>> LocalScopes;
|
||||
internal ImportDebugInformation[] ImportScopes;
|
||||
internal Dictionary<uint, uint> StateMachineMethods;
|
||||
internal Dictionary<MetadataToken, Row<Guid, uint, uint>[]> CustomDebugInformations;
|
||||
private static Dictionary<string, Row<ElementType, bool>> primitive_value_types;
|
||||
|
||||
private static void InitializePrimitives()
|
||||
{
|
||||
Dictionary<string, Row<ElementType, bool>> types = new(18, StringComparer.Ordinal)
|
||||
{
|
||||
{ "Void", new(ElementType.Void, false) },
|
||||
{ "Boolean", new(ElementType.Boolean, true) },
|
||||
{ "Char", new(ElementType.Char, true) },
|
||||
{ "SByte", new(ElementType.I1, true) },
|
||||
{ "Byte", new(ElementType.U1, true) },
|
||||
{ "Int16", new(ElementType.I2, true) },
|
||||
{ "UInt16", new(ElementType.U2, true) },
|
||||
{ "Int32", new(ElementType.I4, true) },
|
||||
{ "UInt32", new(ElementType.U4, true) },
|
||||
{ "Int64", new(ElementType.I8, true) },
|
||||
{ "UInt64", new(ElementType.U8, true) },
|
||||
{ "Single", new(ElementType.R4, true) },
|
||||
{ "Double", new(ElementType.R8, true) },
|
||||
{ "String", new(ElementType.String, false) },
|
||||
{ "TypedReference", new(ElementType.TypedByRef, false) },
|
||||
{ "IntPtr", new(ElementType.I, true) },
|
||||
{ "UIntPtr", new(ElementType.U, true) },
|
||||
{ "Object", new(ElementType.Object, false) }
|
||||
};
|
||||
|
||||
Interlocked.CompareExchange(ref primitive_value_types, types, null);
|
||||
}
|
||||
|
||||
public static void TryProcessPrimitiveTypeReference(TypeReference type)
|
||||
{
|
||||
if (type.Namespace != "System")
|
||||
return;
|
||||
|
||||
IMetadataScope scope = type.scope;
|
||||
if (scope == null || scope.MetadataScopeType != MetadataScopeType.AssemblyNameReference)
|
||||
return;
|
||||
|
||||
Row<ElementType, bool> primitive_data;
|
||||
if (!TryGetPrimitiveData(type, out primitive_data))
|
||||
return;
|
||||
|
||||
type.etype = primitive_data.Col1;
|
||||
type.IsValueType = primitive_data.Col2;
|
||||
}
|
||||
|
||||
public static bool TryGetPrimitiveElementType(TypeDefinition type, out ElementType etype)
|
||||
{
|
||||
etype = ElementType.None;
|
||||
|
||||
if (type.Namespace != "System")
|
||||
return false;
|
||||
|
||||
Row<ElementType, bool> primitive_data;
|
||||
if (TryGetPrimitiveData(type, out primitive_data))
|
||||
{
|
||||
etype = primitive_data.Col1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryGetPrimitiveData(TypeReference type, out Row<ElementType, bool> primitive_data)
|
||||
{
|
||||
if (primitive_value_types == null)
|
||||
InitializePrimitives();
|
||||
|
||||
return primitive_value_types.TryGetValue(type.Name, out primitive_data);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
if (NestedTypes != null)
|
||||
NestedTypes = new(capacity: 0);
|
||||
if (ReverseNestedTypes != null)
|
||||
ReverseNestedTypes = new(capacity: 0);
|
||||
if (Interfaces != null)
|
||||
Interfaces = new(capacity: 0);
|
||||
if (ClassLayouts != null)
|
||||
ClassLayouts = new(capacity: 0);
|
||||
if (FieldLayouts != null)
|
||||
FieldLayouts = new(capacity: 0);
|
||||
if (FieldRVAs != null)
|
||||
FieldRVAs = new(capacity: 0);
|
||||
if (FieldMarshals != null)
|
||||
FieldMarshals = new(capacity: 0);
|
||||
if (Constants != null)
|
||||
Constants = new(capacity: 0);
|
||||
if (Overrides != null)
|
||||
Overrides = new(capacity: 0);
|
||||
if (CustomAttributes != null)
|
||||
CustomAttributes = new(capacity: 0);
|
||||
if (SecurityDeclarations != null)
|
||||
SecurityDeclarations = new(capacity: 0);
|
||||
if (Events != null)
|
||||
Events = new(capacity: 0);
|
||||
if (Properties != null)
|
||||
Properties = new(capacity: 0);
|
||||
if (Semantics != null)
|
||||
Semantics = new(capacity: 0);
|
||||
if (PInvokes != null)
|
||||
PInvokes = new(capacity: 0);
|
||||
if (GenericParameters != null)
|
||||
GenericParameters = new(capacity: 0);
|
||||
if (GenericConstraints != null)
|
||||
GenericConstraints = new(capacity: 0);
|
||||
|
||||
Documents = Empty<Document>.Array;
|
||||
ImportScopes = Empty<ImportDebugInformation>.Array;
|
||||
if (LocalScopes != null)
|
||||
LocalScopes = new(capacity: 0);
|
||||
if (StateMachineMethods != null)
|
||||
StateMachineMethods = new(capacity: 0);
|
||||
}
|
||||
|
||||
public AssemblyNameReference GetAssemblyNameReference(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > AssemblyReferences.Length)
|
||||
return null;
|
||||
|
||||
return AssemblyReferences[rid - 1];
|
||||
}
|
||||
|
||||
public TypeDefinition GetTypeDefinition(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > Types.Length)
|
||||
return null;
|
||||
|
||||
return Types[rid - 1];
|
||||
}
|
||||
|
||||
public void AddTypeDefinition(TypeDefinition type)
|
||||
{
|
||||
Types[type.token.RID - 1] = type;
|
||||
}
|
||||
|
||||
public TypeReference GetTypeReference(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > TypeReferences.Length)
|
||||
return null;
|
||||
|
||||
return TypeReferences[rid - 1];
|
||||
}
|
||||
|
||||
public void AddTypeReference(TypeReference type)
|
||||
{
|
||||
TypeReferences[type.token.RID - 1] = type;
|
||||
}
|
||||
|
||||
public FieldDefinition GetFieldDefinition(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > Fields.Length)
|
||||
return null;
|
||||
|
||||
return Fields[rid - 1];
|
||||
}
|
||||
|
||||
public void AddFieldDefinition(FieldDefinition field)
|
||||
{
|
||||
Fields[field.token.RID - 1] = field;
|
||||
}
|
||||
|
||||
public MethodDefinition GetMethodDefinition(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > Methods.Length)
|
||||
return null;
|
||||
|
||||
return Methods[rid - 1];
|
||||
}
|
||||
|
||||
public void AddMethodDefinition(MethodDefinition method)
|
||||
{
|
||||
Methods[method.token.RID - 1] = method;
|
||||
}
|
||||
|
||||
public MemberReference GetMemberReference(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > MemberReferences.Length)
|
||||
return null;
|
||||
|
||||
return MemberReferences[rid - 1];
|
||||
}
|
||||
|
||||
public void AddMemberReference(MemberReference member)
|
||||
{
|
||||
MemberReferences[member.token.RID - 1] = member;
|
||||
}
|
||||
|
||||
public bool TryGetNestedTypeMapping(TypeDefinition type, out Collection<uint> mapping)
|
||||
{
|
||||
return NestedTypes.TryGetValue(type.token.RID, out mapping);
|
||||
}
|
||||
|
||||
public void SetNestedTypeMapping(uint type_rid, Collection<uint> mapping)
|
||||
{
|
||||
NestedTypes[type_rid] = mapping;
|
||||
}
|
||||
|
||||
public void RemoveNestedTypeMapping(TypeDefinition type)
|
||||
{
|
||||
NestedTypes.Remove(type.token.RID);
|
||||
}
|
||||
|
||||
public bool TryGetReverseNestedTypeMapping(TypeDefinition type, out uint declaring)
|
||||
{
|
||||
return ReverseNestedTypes.TryGetValue(type.token.RID, out declaring);
|
||||
}
|
||||
|
||||
public void SetReverseNestedTypeMapping(uint nested, uint declaring)
|
||||
{
|
||||
ReverseNestedTypes[nested] = declaring;
|
||||
}
|
||||
|
||||
public void RemoveReverseNestedTypeMapping(TypeDefinition type)
|
||||
{
|
||||
ReverseNestedTypes.Remove(type.token.RID);
|
||||
}
|
||||
|
||||
public bool TryGetInterfaceMapping(TypeDefinition type, out Collection<Row<uint, MetadataToken>> mapping)
|
||||
{
|
||||
return Interfaces.TryGetValue(type.token.RID, out mapping);
|
||||
}
|
||||
|
||||
public void SetInterfaceMapping(uint type_rid, Collection<Row<uint, MetadataToken>> mapping)
|
||||
{
|
||||
Interfaces[type_rid] = mapping;
|
||||
}
|
||||
|
||||
public void RemoveInterfaceMapping(TypeDefinition type)
|
||||
{
|
||||
Interfaces.Remove(type.token.RID);
|
||||
}
|
||||
|
||||
public void AddPropertiesRange(uint type_rid, Range range)
|
||||
{
|
||||
Properties.Add(type_rid, range);
|
||||
}
|
||||
|
||||
public bool TryGetPropertiesRange(TypeDefinition type, out Range range)
|
||||
{
|
||||
return Properties.TryGetValue(type.token.RID, out range);
|
||||
}
|
||||
|
||||
public void RemovePropertiesRange(TypeDefinition type)
|
||||
{
|
||||
Properties.Remove(type.token.RID);
|
||||
}
|
||||
|
||||
public void AddEventsRange(uint type_rid, Range range)
|
||||
{
|
||||
Events.Add(type_rid, range);
|
||||
}
|
||||
|
||||
public bool TryGetEventsRange(TypeDefinition type, out Range range)
|
||||
{
|
||||
return Events.TryGetValue(type.token.RID, out range);
|
||||
}
|
||||
|
||||
public void RemoveEventsRange(TypeDefinition type)
|
||||
{
|
||||
Events.Remove(type.token.RID);
|
||||
}
|
||||
|
||||
public bool TryGetGenericParameterRanges(IGenericParameterProvider owner, out Range[] ranges)
|
||||
{
|
||||
return GenericParameters.TryGetValue(owner.MetadataToken, out ranges);
|
||||
}
|
||||
|
||||
public void RemoveGenericParameterRange(IGenericParameterProvider owner)
|
||||
{
|
||||
GenericParameters.Remove(owner.MetadataToken);
|
||||
}
|
||||
|
||||
public bool TryGetCustomAttributeRanges(ICustomAttributeProvider owner, out Range[] ranges)
|
||||
{
|
||||
return CustomAttributes.TryGetValue(owner.MetadataToken, out ranges);
|
||||
}
|
||||
|
||||
public void RemoveCustomAttributeRange(ICustomAttributeProvider owner)
|
||||
{
|
||||
CustomAttributes.Remove(owner.MetadataToken);
|
||||
}
|
||||
|
||||
public bool TryGetSecurityDeclarationRanges(ISecurityDeclarationProvider owner, out Range[] ranges)
|
||||
{
|
||||
return SecurityDeclarations.TryGetValue(owner.MetadataToken, out ranges);
|
||||
}
|
||||
|
||||
public void RemoveSecurityDeclarationRange(ISecurityDeclarationProvider owner)
|
||||
{
|
||||
SecurityDeclarations.Remove(owner.MetadataToken);
|
||||
}
|
||||
|
||||
public bool TryGetGenericConstraintMapping(GenericParameter generic_parameter, out Collection<Row<uint, MetadataToken>> mapping)
|
||||
{
|
||||
return GenericConstraints.TryGetValue(generic_parameter.token.RID, out mapping);
|
||||
}
|
||||
|
||||
public void SetGenericConstraintMapping(uint gp_rid, Collection<Row<uint, MetadataToken>> mapping)
|
||||
{
|
||||
GenericConstraints[gp_rid] = mapping;
|
||||
}
|
||||
|
||||
public void RemoveGenericConstraintMapping(GenericParameter generic_parameter)
|
||||
{
|
||||
GenericConstraints.Remove(generic_parameter.token.RID);
|
||||
}
|
||||
|
||||
public bool TryGetOverrideMapping(MethodDefinition method, out Collection<MetadataToken> mapping)
|
||||
{
|
||||
return Overrides.TryGetValue(method.token.RID, out mapping);
|
||||
}
|
||||
|
||||
public void SetOverrideMapping(uint rid, Collection<MetadataToken> mapping)
|
||||
{
|
||||
Overrides[rid] = mapping;
|
||||
}
|
||||
|
||||
public void RemoveOverrideMapping(MethodDefinition method)
|
||||
{
|
||||
Overrides.Remove(method.token.RID);
|
||||
}
|
||||
|
||||
public Document GetDocument(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > Documents.Length)
|
||||
return null;
|
||||
|
||||
return Documents[rid - 1];
|
||||
}
|
||||
|
||||
public bool TryGetLocalScopes(MethodDefinition method, out Collection<Row<uint, Range, Range, uint, uint, uint>> scopes)
|
||||
{
|
||||
return LocalScopes.TryGetValue(method.MetadataToken.RID, out scopes);
|
||||
}
|
||||
|
||||
public void SetLocalScopes(uint method_rid, Collection<Row<uint, Range, Range, uint, uint, uint>> records)
|
||||
{
|
||||
LocalScopes[method_rid] = records;
|
||||
}
|
||||
|
||||
public ImportDebugInformation GetImportScope(uint rid)
|
||||
{
|
||||
if (rid < 1 || rid > ImportScopes.Length)
|
||||
return null;
|
||||
|
||||
return ImportScopes[rid - 1];
|
||||
}
|
||||
|
||||
public bool TryGetStateMachineKickOffMethod(MethodDefinition method, out uint rid)
|
||||
{
|
||||
return StateMachineMethods.TryGetValue(method.MetadataToken.RID, out rid);
|
||||
}
|
||||
|
||||
public TypeDefinition GetFieldDeclaringType(uint field_rid)
|
||||
{
|
||||
return BinaryRangeSearch(Types, field_rid, true);
|
||||
}
|
||||
|
||||
public TypeDefinition GetMethodDeclaringType(uint method_rid)
|
||||
{
|
||||
return BinaryRangeSearch(Types, method_rid, false);
|
||||
}
|
||||
|
||||
private static TypeDefinition BinaryRangeSearch(TypeDefinition[] types, uint rid, bool field)
|
||||
{
|
||||
int min = 0;
|
||||
int max = types.Length - 1;
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = min + (max - min) / 2;
|
||||
TypeDefinition type = types[mid];
|
||||
Range range = field ? type.fields_range : type.methods_range;
|
||||
|
||||
if (rid < range.Start)
|
||||
max = mid - 1;
|
||||
else if (rid >= range.Start + range.Length)
|
||||
min = mid + 1;
|
||||
else
|
||||
return type;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user