public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary<VTableSignature, List<VTableSlot>>(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) ret.Inherit(ifaceVTbl, slotDict); } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) ret.Inherit(baseVTbl, slotDict); List<MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet<MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) ret.Finals.Add(slot); else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } } return ret; }
static void CheckKeyExist <TKey, TValue>(VTableStorage storage, IDictionary <TKey, TValue> dictionary, TKey key, string name) { if (!dictionary.ContainsKey(key)) { storage.GetLogger().ErrorFormat("{0} not found: {1}", name, key); foreach (TKey k in dictionary.Keys) { storage.GetLogger().ErrorFormat(" {0}", k); } } }
static void CheckKeyExist <TKey, TValue>(VTableStorage storage, ILookup <TKey, TValue> lookup, TKey key, string name) { if (!lookup.Contains(key)) { storage.GetLogger().ErrorFormat("{0} not found: {1}", name, key); foreach (var k in lookup.Select(g => g.Key)) { storage.GetLogger().ErrorFormat(" {0}", k); } } }
public NameService(ConfuserContext context) { this.context = context; storage = new VTableStorage(context.Logger); random = context.Registry.GetService <IRandomService>().GetRandomGenerator(NameProtection._FullId); nameSeed = random.NextBytes(20); Renamers = new List <IRenamer> { new InterReferenceAnalyzer(), new VTableAnalyzer(), new TypeBlobAnalyzer(), new ResourceAnalyzer(), new LdtokenEnumAnalyzer() }; }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary<VTableSignature, List<VTableSlot>>(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) ret.Inherit(ifaceVTbl, slotDict); } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) ret.Inherit(baseVTbl, slotDict); List<MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet<MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { foreach (var remainingSlot in slotDict.Keys.Where(key => key.InterfaceType != null)) { // If there is a remaining slot for an interface method which has the same name and signature as an unprocessed method, // allow the method to override the slot. // This is necessary because public methods which implement interface methods do not have an InterfaceType in their signature, // but the keys of "slotDict" which were added for interface methods *do* have InterfaceType in their signature. Therefore, // these slots are not filled by the "Normal override" loop above. if (new SigComparer().Equals(remainingSlot.MethodSig, method.MethodSig) && remainingSlot.Name.Equals(method.Name, StringComparison.Ordinal)) { var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), remainingSlot); ret.Override(slotDict, remainingSlot, methodSlot); methodsProcessed.Add(method); goto next; } } var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) ret.Finals.Add(slot); else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } next: continue; } return ret; }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef.ToTypeSig()); var virtualMethods = typeDef.Methods .Where(method => method.IsVirtual) .ToDictionary( method => VTableSignature.FromMethod(method), method => method ); // See Partition II 12.2 for implementation algorithm var vTbl = new VTableConstruction(); // Inherits base type's slots VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) { Inherits(vTbl, baseVTbl); } // Explicit interface implementation foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) { Implements(vTbl, virtualMethods, ifaceVTbl, iface.Interface.ToTypeSig()); } } // Normal interface implementation if (!typeDef.IsInterface) { // Interface methods cannot implements base interface methods. foreach (Dictionary <VTableSignature, VTableSlot> iface in vTbl.InterfaceSlots.Values) { foreach (KeyValuePair <VTableSignature, VTableSlot> entry in iface.ToList()) { if (!entry.Value.MethodDef.DeclaringType.IsInterface) { continue; } if (virtualMethods.TryGetValue(entry.Key, out MethodDef impl)) { iface[entry.Key] = entry.Value.OverridedBy(impl); } else if (vTbl.SlotsMap.TryGetValue(entry.Key, out VTableSlot implSlot)) { iface[entry.Key] = entry.Value.OverridedBy(implSlot.MethodDef); } } } } // Normal overrides foreach (KeyValuePair <VTableSignature, MethodDef> method in virtualMethods) { VTableSlot slot; if (method.Value.IsNewSlot) { slot = new VTableSlot(method.Value, typeDef.ToTypeSig(), method.Key); } else { if (vTbl.SlotsMap.TryGetValue(method.Key, out slot)) { Debug.Assert(!slot.MethodDef.IsFinal); slot = slot.OverridedBy(method.Value); } else { slot = new VTableSlot(method.Value, typeDef.ToTypeSig(), method.Key); } } vTbl.SlotsMap[method.Key] = slot; vTbl.AllSlots.Add(slot); } // MethodImpls foreach (KeyValuePair <VTableSignature, MethodDef> method in virtualMethods) { foreach (MethodOverride impl in method.Value.Overrides) { Debug.Assert(impl.MethodBody == method.Value); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); if (targetMethod.DeclaringType.IsInterface) { var iface = impl.MethodDeclaration.DeclaringType.ToTypeSig(); CheckKeyExist(storage, vTbl.InterfaceSlots, iface, "MethodImpl Iface"); Dictionary <VTableSignature, VTableSlot> ifaceVTbl = vTbl.InterfaceSlots[iface]; var signature = VTableSignature.FromMethod(impl.MethodDeclaration); CheckKeyExist(storage, ifaceVTbl, signature, "MethodImpl Iface Sig"); VTableSlot targetSlot = ifaceVTbl[signature]; // The Overrides of interface slots should directly points to the root interface slot while (targetSlot.Overrides != null) { targetSlot = targetSlot.Overrides; } Debug.Assert(targetSlot.MethodDef.DeclaringType.IsInterface); ifaceVTbl[targetSlot.Signature] = targetSlot.OverridedBy(method.Value); } else { VTableSlot targetSlot = vTbl.AllSlots.Single(slot => slot.MethodDef == targetMethod); CheckKeyExist(storage, vTbl.SlotsMap, targetSlot.Signature, "MethodImpl Normal Sig"); targetSlot = vTbl.SlotsMap[targetSlot.Signature]; // Use the most derived slot // Maybe implemented by above processes --- this process should take priority while (targetSlot.MethodDef.DeclaringType == typeDef) { targetSlot = targetSlot.Overrides; } vTbl.SlotsMap[targetSlot.Signature] = targetSlot.OverridedBy(method.Value); } } } // Populate result V-table ret.InterfaceSlots = vTbl.InterfaceSlots.ToDictionary( kvp => kvp.Key, kvp => (IList <VTableSlot>)kvp.Value.Values.ToList()); foreach (VTableSlot slot in vTbl.AllSlots) { ret.Slots.Add(slot); } return(ret); }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef); var slotDict = new Dictionary <VTableSignature, List <VTableSlot> >(); // Partition II 12.2 // Interfaces foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) { ret.Inherit(ifaceVTbl, slotDict); } } // Base type VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) { ret.Inherit(baseVTbl, slotDict); } List <MethodDef> virtualMethods = typeDef.Methods.Where(method => method.IsVirtual).ToList(); var methodsProcessed = new HashSet <MethodDef>(); // MethodImpls (Partition II 22.27) foreach (MethodDef method in virtualMethods) { foreach (MethodOverride impl in method.Overrides) { Debug.Assert(impl.MethodBody == method); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); VTableSignature sig = VTableSignature.FromMethod(impl.MethodDeclaration); Debug.Assert(slotDict.ContainsKey(sig)); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot, targetMethod); methodsProcessed.Add(method); } } } // Normal override foreach (MethodDef method in virtualMethods) { VTableSignature sig = VTableSignature.FromMethod(method); var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), sig); if (slotDict.ContainsKey(sig) && slotDict[sig].Count > 0) { ret.Override(slotDict, sig, methodSlot); methodsProcessed.Add(method); } } // Remaining methods foreach (MethodDef method in typeDef.Methods.Where(method => method.IsVirtual).Except(methodsProcessed)) { foreach (var remainingSlot in slotDict.Keys.Where(key => key.InterfaceType != null)) { // If there is a remaining slot for an interface method which has the same name and signature as an unprocessed method, // allow the method to override the slot. // This is necessary because public methods which implement interface methods do not have an InterfaceType in their signature, // but the keys of "slotDict" which were added for interface methods *do* have InterfaceType in their signature. Therefore, // these slots are not filled by the "Normal override" loop above. if (new SigComparer().Equals(remainingSlot.MethodSig, method.MethodSig) && remainingSlot.Name.Equals(method.Name, StringComparison.Ordinal)) { var methodSlot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), remainingSlot); ret.Override(slotDict, remainingSlot, methodSlot); methodsProcessed.Add(method); goto next; } } var slot = new VTableSlot(ret, method, method.DeclaringType.ToTypeSig(), VTableSignature.FromMethod(method)); if (method.IsFinal) { ret.Finals.Add(slot); } else { Debug.Assert(!ret.Slots.Any(s => s.MethodDef == method)); ret.Slots.Add(slot); } next: continue; } return(ret); }
public static VTable ConstructVTable(TypeDef typeDef, VTableStorage storage) { var ret = new VTable(typeDef.ToTypeSig()); var virtualMethods = typeDef.Methods .Where(method => method.IsVirtual) .ToDictionary( method => VTableSignature.FromMethod(method), method => method ); // See Partition II 12.2 for implementation algorithm VTableConstruction vTbl = new VTableConstruction(); // Inherits base type's slots VTable baseVTbl = storage.GetVTable(typeDef.GetBaseTypeThrow()); if (baseVTbl != null) { Inherits(vTbl, baseVTbl); } // Explicit interface implementation foreach (InterfaceImpl iface in typeDef.Interfaces) { VTable ifaceVTbl = storage.GetVTable(iface.Interface); if (ifaceVTbl != null) { Implements(vTbl, virtualMethods, ifaceVTbl, iface.Interface.ToTypeSig()); } } // Normal interface implementation if (!typeDef.IsInterface) { // Interface methods cannot implements base interface methods. foreach (var interfaceTypeSig in vTbl.InterfaceSlots.Keys.ToList()) { var slots = vTbl.InterfaceSlots[interfaceTypeSig]; if (slots.Select(g => g.Key) .Any(sig => virtualMethods.ContainsKey(sig) || vTbl.SlotsMap.ContainsKey(sig))) { // Something has a new signature. We need to rewrite the whole thing. // This is the step 1 of 12.2 algorithm -- find implementation for still empty slots. // Note that it seems we should include newslot methods as well, despite what the standard said. slots = slots .SelectMany(g => g.Select(slot => (g.Key, Slot: slot))) .ToLookup(t => t.Key, t => { if (!t.Slot.MethodDef.DeclaringType.IsInterface) { return(t.Slot); } if (virtualMethods.TryGetValue(t.Key, out var impl)) { return(t.Slot.OverridedBy(impl)); } if (vTbl.SlotsMap.TryGetValue(t.Key, out var implSlot)) { return(t.Slot.OverridedBy(implSlot.MethodDef)); } return(t.Slot); }); vTbl.InterfaceSlots[interfaceTypeSig] = slots; } } } // Normal overrides foreach (var method in virtualMethods) { VTableSlot slot; if (method.Value.IsNewSlot) { slot = new VTableSlot(method.Value, typeDef.ToTypeSig(), method.Key); } else { if (vTbl.SlotsMap.TryGetValue(method.Key, out slot)) { Debug.Assert(!slot.MethodDef.IsFinal); slot = slot.OverridedBy(method.Value); } else { slot = new VTableSlot(method.Value, typeDef.ToTypeSig(), method.Key); } } vTbl.SlotsMap[method.Key] = slot; vTbl.AllSlots.Add(slot); } // MethodImpls foreach (var method in virtualMethods) { foreach (var impl in method.Value.Overrides) { Debug.Assert(impl.MethodBody == method.Value); MethodDef targetMethod = impl.MethodDeclaration.ResolveThrow(); if (targetMethod.DeclaringType.IsInterface) { var iface = impl.MethodDeclaration.DeclaringType.ToTypeSig(); CheckKeyExist(storage, vTbl.InterfaceSlots, iface, "MethodImpl Iface"); var ifaceVTbl = vTbl.InterfaceSlots[iface]; var signature = VTableSignature.FromMethod(impl.MethodDeclaration); CheckKeyExist(storage, ifaceVTbl, signature, "MethodImpl Iface Sig"); vTbl.InterfaceSlots[iface] = ifaceVTbl .SelectMany(g => g.Select(slot => (g.Key, Slot: slot))) .ToLookup(t => t.Key, t => { if (!t.Key.Equals(signature)) { return(t.Slot); } var targetSlot = t.Slot; while (targetSlot.Overrides != null) { targetSlot = targetSlot.Overrides; } Debug.Assert(targetSlot.MethodDef.DeclaringType.IsInterface); Debug.Assert(targetSlot.Signature.Equals(t.Slot.Signature)); return(targetSlot.OverridedBy(method.Value)); }); } else { var targetSlot = vTbl.AllSlots.Single(slot => slot.MethodDef == targetMethod); CheckKeyExist(storage, vTbl.SlotsMap, targetSlot.Signature, "MethodImpl Normal Sig"); targetSlot = vTbl.SlotsMap[targetSlot.Signature]; // Use the most derived slot // Maybe implemented by above processes --- this process should take priority while (targetSlot.MethodDef.DeclaringType == typeDef) { targetSlot = targetSlot.Overrides; } vTbl.SlotsMap[targetSlot.Signature] = targetSlot.OverridedBy(method.Value); } } } // Populate result V-table ret.InterfaceSlots = vTbl.InterfaceSlots.ToDictionary( kvp => kvp.Key, kvp => (IList <VTableSlot>)kvp.Value.SelectMany(g => g).ToList(), TypeEqualityComparer.Instance); foreach (var slot in vTbl.AllSlots) { ret.Slots.Add(slot); } return(ret); }