obfuz/Plugins/dnlib/DotNet/ModuleLoader.cs

932 lines
19 KiB
C#

// dnlib: See LICENSE.txt for more info
using System;
using System.Collections.Generic;
using System.Diagnostics;
using dnlib.DotNet.Emit;
using dnlib.DotNet.MD;
using dnlib.DotNet.Pdb;
using dnlib.PE;
using dnlib.Threading;
using dnlib.W32Resources;
namespace dnlib.DotNet {
readonly struct ModuleLoader {
readonly ModuleDef module;
readonly ICancellationToken cancellationToken;
readonly Dictionary<object, bool> seen;
readonly Stack<object> stack;
ModuleLoader(ModuleDef module, ICancellationToken cancellationToken) {
const int CAPACITY = 0x4000;
this.module = module;
this.cancellationToken = cancellationToken;
seen = new Dictionary<object, bool>(CAPACITY);
stack = new Stack<object>(CAPACITY);
}
public static void LoadAll(ModuleDef module, ICancellationToken cancellationToken) =>
new ModuleLoader(module, cancellationToken).Load();
void Add(UTF8String a) { }
void Add(Guid? a) { }
void Add(ushort a) { }
void Add(AssemblyHashAlgorithm a) { }
void Add(Version a) { }
void Add(AssemblyAttributes a) { }
void Add(PublicKeyBase a) { }
void Add(RVA a) { }
void Add(IManagedEntryPoint a) { }
void Add(string a) { }
void Add(WinMDStatus a) { }
void Add(TypeAttributes a) { }
void Add(FieldAttributes a) { }
void Add(uint? a) { }
void Add(byte[] a) { }
void Add(MethodImplAttributes a) { }
void Add(MethodAttributes a) { }
void Add(MethodSemanticsAttributes a) { }
void Add(ParamAttributes a) { }
void Add(ElementType a) { }
void Add(SecurityAction a) { }
void Add(EventAttributes a) { }
void Add(PropertyAttributes a) { }
void Add(PInvokeAttributes a) { }
void Add(FileAttributes a) { }
void Add(ManifestResourceAttributes a) { }
void Add(GenericParamAttributes a) { }
void Add(NativeType a) { }
void Load() {
LoadAllTables();
Load(module);
Process();
}
void Process() {
while (stack.Count != 0) {
if (cancellationToken is not null)
cancellationToken.ThrowIfCancellationRequested();
var o = stack.Pop();
LoadObj(o);
}
}
void LoadAllTables() {
var resolver = module as ITokenResolver;
if (resolver is null)
return;
for (Table tbl = 0; tbl <= Table.GenericParamConstraint; tbl++) {
for (uint rid = 1; ; rid++) {
var o = resolver.ResolveToken(new MDToken(tbl, rid).Raw, new GenericParamContext());
if (o is null)
break;
Add(o);
Process();
}
}
}
void LoadObj(object o) {
if (o is TypeSig ts) {
Load(ts);
return;
}
if (o is IMDTokenProvider mdt) {
Load(mdt);
return;
}
if (o is CustomAttribute ca) {
Load(ca);
return;
}
if (o is SecurityAttribute sa) {
Load(sa);
return;
}
if (o is CANamedArgument na) {
Load(na);
return;
}
if (o is Parameter p) {
Load(p);
return;
}
if (o is PdbMethod pdbMethod) {
Load(pdbMethod);
return;
}
if (o is ResourceDirectory rd) {
Load(rd);
return;
}
if (o is ResourceData rdata) {
Load(rdata);
return;
}
Debug.Fail("Unknown type");
}
void Load(TypeSig ts) {
if (ts is null)
return;
Add(ts.Next);
switch (ts.ElementType) {
case ElementType.Void:
case ElementType.Boolean:
case ElementType.Char:
case ElementType.I1:
case ElementType.U1:
case ElementType.I2:
case ElementType.U2:
case ElementType.I4:
case ElementType.U4:
case ElementType.I8:
case ElementType.U8:
case ElementType.R4:
case ElementType.R8:
case ElementType.String:
case ElementType.ValueType:
case ElementType.Class:
case ElementType.TypedByRef:
case ElementType.I:
case ElementType.U:
case ElementType.Object:
Add(((TypeDefOrRefSig)ts).TypeDefOrRef);
break;
case ElementType.Var:
case ElementType.MVar:
var vsig = (GenericSig)ts;
Add(vsig.OwnerType);
Add(vsig.OwnerMethod);
break;
case ElementType.GenericInst:
var gis = (GenericInstSig)ts;
Add(gis.GenericType);
Add(gis.GenericArguments);
break;
case ElementType.FnPtr:
var fpsig = (FnPtrSig)ts;
Add(fpsig.Signature);
break;
case ElementType.CModReqd:
case ElementType.CModOpt:
var cmod = (ModifierSig)ts;
Add(cmod.Modifier);
break;
case ElementType.End:
case ElementType.Ptr:
case ElementType.ByRef:
case ElementType.Array:
case ElementType.ValueArray:
case ElementType.SZArray:
case ElementType.Module:
case ElementType.Pinned:
case ElementType.Sentinel:
case ElementType.R:
case ElementType.Internal:
default:
break;
}
}
void Load(IMDTokenProvider mdt) {
if (mdt is null)
return;
switch (mdt.MDToken.Table) {
case Table.Module: Load((ModuleDef)mdt); break;
case Table.TypeRef: Load((TypeRef)mdt); break;
case Table.TypeDef: Load((TypeDef)mdt); break;
case Table.Field: Load((FieldDef)mdt); break;
case Table.Method: Load((MethodDef)mdt); break;
case Table.Param: Load((ParamDef)mdt); break;
case Table.InterfaceImpl: Load((InterfaceImpl)mdt); break;
case Table.MemberRef: Load((MemberRef)mdt); break;
case Table.Constant: Load((Constant)mdt); break;
case Table.DeclSecurity: Load((DeclSecurity)mdt); break;
case Table.ClassLayout: Load((ClassLayout)mdt); break;
case Table.StandAloneSig: Load((StandAloneSig)mdt); break;
case Table.Event: Load((EventDef)mdt); break;
case Table.Property: Load((PropertyDef)mdt); break;
case Table.ModuleRef: Load((ModuleRef)mdt); break;
case Table.TypeSpec: Load((TypeSpec)mdt); break;
case Table.ImplMap: Load((ImplMap)mdt); break;
case Table.Assembly: Load((AssemblyDef)mdt); break;
case Table.AssemblyRef: Load((AssemblyRef)mdt); break;
case Table.File: Load((FileDef)mdt); break;
case Table.ExportedType: Load((ExportedType)mdt); break;
case Table.GenericParam: Load((GenericParam)mdt); break;
case Table.MethodSpec: Load((MethodSpec)mdt); break;
case Table.GenericParamConstraint: Load((GenericParamConstraint)mdt); break;
case Table.ManifestResource:
var rsrc = mdt as Resource;
if (rsrc is not null) {
Load(rsrc);
break;
}
var mr = mdt as ManifestResource;
if (mr is not null) {
Load(mr);
break;
}
Debug.Fail("Unknown ManifestResource");
break;
case Table.FieldPtr:
case Table.MethodPtr:
case Table.ParamPtr:
case Table.CustomAttribute:
case Table.FieldMarshal:
case Table.FieldLayout:
case Table.EventMap:
case Table.EventPtr:
case Table.PropertyMap:
case Table.PropertyPtr:
case Table.MethodSemantics:
case Table.MethodImpl:
case Table.FieldRVA:
case Table.ENCLog:
case Table.ENCMap:
case Table.AssemblyProcessor:
case Table.AssemblyOS:
case Table.AssemblyRefProcessor:
case Table.AssemblyRefOS:
case Table.NestedClass:
case Table.Document:
case Table.MethodDebugInformation:
case Table.LocalScope:
case Table.LocalVariable:
case Table.LocalConstant:
case Table.ImportScope:
case Table.StateMachineMethod:
case Table.CustomDebugInformation:
break;
default:
Debug.Fail("Unknown type");
break;
}
}
void Load(ModuleDef obj) {
if (obj is null || obj != module)
return;
Add(obj.Generation);
Add(obj.Name);
Add(obj.Mvid);
Add(obj.EncId);
Add(obj.EncBaseId);
Add(obj.CustomAttributes);
Add(obj.Assembly);
Add(obj.Types);
Add(obj.ExportedTypes);
Add(obj.NativeEntryPoint);
Add(obj.ManagedEntryPoint);
Add(obj.Resources);
Add(obj.VTableFixups);
Add(obj.Location);
Add(obj.Win32Resources);
Add(obj.RuntimeVersion);
Add(obj.WinMDStatus);
Add(obj.RuntimeVersionWinMD);
Add(obj.WinMDVersion);
Add(obj.PdbState);
}
void Load(TypeRef obj) {
if (obj is null)
return;
Add(obj.ResolutionScope);
Add(obj.Name);
Add(obj.Namespace);
Add(obj.CustomAttributes);
}
void Load(TypeDef obj) {
if (obj is null)
return;
Add(obj.Module2);
Add(obj.Attributes);
Add(obj.Name);
Add(obj.Namespace);
Add(obj.BaseType);
Add(obj.Fields);
Add(obj.Methods);
Add(obj.GenericParameters);
Add(obj.Interfaces);
Add(obj.DeclSecurities);
Add(obj.ClassLayout);
Add(obj.DeclaringType);
Add(obj.DeclaringType2);
Add(obj.NestedTypes);
Add(obj.Events);
Add(obj.Properties);
Add(obj.CustomAttributes);
}
void Load(FieldDef obj) {
if (obj is null)
return;
Add(obj.CustomAttributes);
Add(obj.Attributes);
Add(obj.Name);
Add(obj.Signature);
Add(obj.FieldOffset);
Add(obj.MarshalType);
Add(obj.RVA);
Add(obj.InitialValue);
Add(obj.ImplMap);
Add(obj.Constant);
Add(obj.DeclaringType);
}
void Load(MethodDef obj) {
if (obj is null)
return;
Add(obj.RVA);
Add(obj.ImplAttributes);
Add(obj.Attributes);
Add(obj.Name);
Add(obj.Signature);
Add(obj.ParamDefs);
Add(obj.GenericParameters);
Add(obj.DeclSecurities);
Add(obj.ImplMap);
Add(obj.MethodBody);
Add(obj.CustomAttributes);
Add(obj.Overrides);
Add(obj.DeclaringType);
Add(obj.Parameters);
Add(obj.SemanticsAttributes);
}
void Load(ParamDef obj) {
if (obj is null)
return;
Add(obj.DeclaringMethod);
Add(obj.Attributes);
Add(obj.Sequence);
Add(obj.Name);
Add(obj.MarshalType);
Add(obj.Constant);
Add(obj.CustomAttributes);
}
void Load(InterfaceImpl obj) {
if (obj is null)
return;
Add(obj.Interface);
Add(obj.CustomAttributes);
}
void Load(MemberRef obj) {
if (obj is null)
return;
Add(obj.Class);
Add(obj.Name);
Add(obj.Signature);
Add(obj.CustomAttributes);
}
void Load(Constant obj) {
if (obj is null)
return;
Add(obj.Type);
var o = obj.Value;
}
void Load(DeclSecurity obj) {
if (obj is null)
return;
Add(obj.Action);
Add(obj.SecurityAttributes);
Add(obj.CustomAttributes);
obj.GetBlob();
}
void Load(ClassLayout obj) {
if (obj is null)
return;
Add(obj.PackingSize);
Add(obj.ClassSize);
}
void Load(StandAloneSig obj) {
if (obj is null)
return;
Add(obj.Signature);
Add(obj.CustomAttributes);
}
void Load(EventDef obj) {
if (obj is null)
return;
Add(obj.Attributes);
Add(obj.Name);
Add(obj.EventType);
Add(obj.CustomAttributes);
Add(obj.AddMethod);
Add(obj.InvokeMethod);
Add(obj.RemoveMethod);
Add(obj.OtherMethods);
Add(obj.DeclaringType);
}
void Load(PropertyDef obj) {
if (obj is null)
return;
Add(obj.Attributes);
Add(obj.Name);
Add(obj.Type);
Add(obj.Constant);
Add(obj.CustomAttributes);
Add(obj.GetMethods);
Add(obj.SetMethods);
Add(obj.OtherMethods);
Add(obj.DeclaringType);
}
void Load(ModuleRef obj) {
if (obj is null)
return;
Add(obj.Name);
Add(obj.CustomAttributes);
}
void Load(TypeSpec obj) {
if (obj is null)
return;
Add(obj.TypeSig);
Add(obj.ExtraData);
Add(obj.CustomAttributes);
}
void Load(ImplMap obj) {
if (obj is null)
return;
Add(obj.Attributes);
Add(obj.Name);
Add(obj.Module);
}
void Load(AssemblyDef obj) {
if (obj is null)
return;
if (obj.ManifestModule != module)
return;
Add(obj.HashAlgorithm);
Add(obj.Version);
Add(obj.Attributes);
Add(obj.PublicKey);
Add(obj.Name);
Add(obj.Culture);
Add(obj.DeclSecurities);
Add(obj.Modules);
Add(obj.CustomAttributes);
}
void Load(AssemblyRef obj) {
if (obj is null)
return;
Add(obj.Version);
Add(obj.Attributes);
Add(obj.PublicKeyOrToken);
Add(obj.Name);
Add(obj.Culture);
Add(obj.Hash);
Add(obj.CustomAttributes);
}
void Load(FileDef obj) {
if (obj is null)
return;
Add(obj.Flags);
Add(obj.Name);
Add(obj.HashValue);
Add(obj.CustomAttributes);
}
void Load(ExportedType obj) {
if (obj is null)
return;
Add(obj.CustomAttributes);
Add(obj.Attributes);
Add(obj.TypeDefId);
Add(obj.TypeName);
Add(obj.TypeNamespace);
Add(obj.Implementation);
}
void Load(Resource obj) {
if (obj is null)
return;
Add(obj.Offset);
Add(obj.Name);
Add(obj.Attributes);
Add(obj.CustomAttributes);
switch (obj.ResourceType) {
case ResourceType.Embedded:
break;
case ResourceType.AssemblyLinked:
var ar = (AssemblyLinkedResource)obj;
Add(ar.Assembly);
break;
case ResourceType.Linked:
var lr = (LinkedResource)obj;
Add(lr.File);
Add(lr.Hash);
break;
default:
Debug.Fail("Unknown resource");
break;
}
}
void Load(ManifestResource obj) {
if (obj is null)
return;
Add(obj.Offset);
Add(obj.Flags);
Add(obj.Name);
Add(obj.Implementation);
Add(obj.CustomAttributes);
}
void Load(GenericParam obj) {
if (obj is null)
return;
Add(obj.Owner);
Add(obj.Number);
Add(obj.Flags);
Add(obj.Name);
Add(obj.Kind);
Add(obj.GenericParamConstraints);
Add(obj.CustomAttributes);
}
void Load(MethodSpec obj) {
if (obj is null)
return;
Add(obj.Method);
Add(obj.Instantiation);
Add(obj.CustomAttributes);
}
void Load(GenericParamConstraint obj) {
if (obj is null)
return;
Add(obj.Owner);
Add(obj.Constraint);
Add(obj.CustomAttributes);
}
void Load(CANamedArgument obj) {
if (obj is null)
return;
Add(obj.Type);
Add(obj.Name);
Load(obj.Argument);
}
void Load(Parameter obj) {
if (obj is null)
return;
Add(obj.Type);
}
void Load(SecurityAttribute obj) {
if (obj is null)
return;
Add(obj.AttributeType);
Add(obj.NamedArguments);
}
void Load(CustomAttribute obj) {
if (obj is null)
return;
Add(obj.Constructor);
Add(obj.RawData);
Add(obj.ConstructorArguments);
Add(obj.NamedArguments);
}
void Load(MethodOverride obj) {
Add(obj.MethodBody);
Add(obj.MethodDeclaration);
}
void AddCAValue(object obj) {
if (obj is CAArgument) {
Load((CAArgument)obj);
return;
}
if (obj is IList<CAArgument> list) {
Add(list);
return;
}
if (obj is IMDTokenProvider md) {
Add(md);
return;
}
}
void Load(CAArgument obj) {
Add(obj.Type);
AddCAValue(obj.Value);
}
void Load(PdbMethod obj) { }
void Load(ResourceDirectory obj) {
if (obj is null)
return;
Add(obj.Directories);
Add(obj.Data);
}
void Load(ResourceData obj) { }
void AddToStack<T>(T t) where T : class {
if (t is null)
return;
if (seen.ContainsKey(t))
return;
seen[t] = true;
stack.Push(t);
}
void Add(CustomAttribute obj) => AddToStack(obj);
void Add(SecurityAttribute obj) => AddToStack(obj);
void Add(CANamedArgument obj) => AddToStack(obj);
void Add(Parameter obj) => AddToStack(obj);
void Add(IMDTokenProvider o) => AddToStack(o);
void Add(PdbMethod pdbMethod) { }
void Add(TypeSig ts) => AddToStack(ts);
void Add(ResourceDirectory rd) => AddToStack(rd);
void Add(ResourceData rd) => AddToStack(rd);
void Add<T>(IList<T> list) where T : IMDTokenProvider {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<TypeSig> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<CustomAttribute> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<SecurityAttribute> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<MethodOverride> list) {
if (list is null)
return;
foreach (var item in list)
Load(item);
}
void Add(IList<CAArgument> list) {
if (list is null)
return;
foreach (var item in list)
Load(item);
}
void Add(IList<CANamedArgument> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(ParameterList list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<Instruction> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<ExceptionHandler> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<Local> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<ResourceDirectory> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(IList<ResourceData> list) {
if (list is null)
return;
foreach (var item in list)
Add(item);
}
void Add(VTableFixups vtf) {
if (vtf is null)
return;
foreach (var fixup in vtf) {
foreach (var method in fixup)
Add(method);
}
}
void Add(Win32Resources vtf) {
if (vtf is null)
return;
Add(vtf.Root);
}
void Add(CallingConventionSig sig) {
if (sig is MethodBaseSig msig) {
Add(msig);
return;
}
if (sig is FieldSig fsig) {
Add(fsig);
return;
}
if (sig is LocalSig lsig) {
Add(lsig);
return;
}
if (sig is GenericInstMethodSig gsig) {
Add(gsig);
return;
}
Debug.Assert(sig is null);
}
void Add(MethodBaseSig msig) {
if (msig is null)
return;
Add(msig.ExtraData);
Add(msig.RetType);
Add(msig.Params);
Add(msig.ParamsAfterSentinel);
}
void Add(FieldSig fsig) {
if (fsig is null)
return;
Add(fsig.ExtraData);
Add(fsig.Type);
}
void Add(LocalSig lsig) {
if (lsig is null)
return;
Add(lsig.ExtraData);
Add(lsig.Locals);
}
void Add(GenericInstMethodSig gsig) {
if (gsig is null)
return;
Add(gsig.ExtraData);
Add(gsig.GenericArguments);
}
void Add(MarshalType mt) {
if (mt is null)
return;
Add(mt.NativeType);
}
void Add(MethodBody mb) {
if (mb is CilBody cilBody) {
Add(cilBody);
return;
}
if (mb is NativeMethodBody nb) {
Add(nb);
return;
}
Debug.Assert(mb is null, "Unknown method body");
}
void Add(NativeMethodBody body) {
if (body is null)
return;
Add(body.RVA);
}
void Add(CilBody body) {
if (body is null)
return;
Add(body.Instructions);
Add(body.ExceptionHandlers);
Add(body.Variables);
Add(body.PdbMethod);
}
void Add(Instruction instr) {
if (instr is null)
return;
if (instr.Operand is IMDTokenProvider mdt) {
Add(mdt);
return;
}
if (instr.Operand is Parameter p) {
Add(p);
return;
}
if (instr.Operand is Local l) {
Add(l);
return;
}
if (instr.Operand is CallingConventionSig csig) {
Add(csig);
return;
}
}
void Add(ExceptionHandler eh) {
if (eh is null)
return;
Add(eh.CatchType);
}
void Add(Local local) {
if (local is null)
return;
Add(local.Type);
}
void Add(PdbState state) {
if (state is null)
return;
Add(state.UserEntryPoint);
}
}
}