Skip to content

Commit 3a3d953

Browse files
authored
Merge 88fc1e4 into b4a67cb
2 parents b4a67cb + 88fc1e4 commit 3a3d953

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1046
-106
lines changed

Confuser.Core/Utils.cs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.IO;
4+
using System.Linq;
45
using System.Security.Cryptography;
56
using System.Text;
67

@@ -223,13 +224,25 @@ public static IList<T> RemoveWhere<T>(this IList<T> self, Predicate<T> match) {
223224
/// <param name="logger">The logger.</param>
224225
/// <returns>A wrapper of the list.</returns>
225226
public static IEnumerable<T> WithProgress<T>(this IEnumerable<T> enumerable, ILogger logger) {
226-
var list = new List<T>(enumerable);
227-
int i;
228-
for (i = 0; i < list.Count; i++) {
229-
logger.Progress(i, list.Count);
230-
yield return list[i];
227+
switch (enumerable) {
228+
case IReadOnlyCollection<T> readOnlyCollection:
229+
return WithProgress(enumerable, readOnlyCollection.Count, logger);
230+
case ICollection<T> collection:
231+
return WithProgress(enumerable, collection.Count, logger);
232+
default:
233+
var buffered = enumerable.ToList();
234+
return WithProgress(buffered, buffered.Count, logger);
231235
}
232-
logger.Progress(i, list.Count);
236+
}
237+
238+
public static IEnumerable<T> WithProgress<T>(this IEnumerable<T> enumerable, int totalCount, ILogger logger) {
239+
var counter = 0;
240+
foreach (var obj in enumerable) {
241+
logger.Progress(counter, totalCount);
242+
yield return obj;
243+
counter++;
244+
}
245+
logger.Progress(totalCount, totalCount);
233246
logger.EndProgress();
234247
}
235248
}

Confuser.Renamer/AnalyzePhase.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,6 @@ void Analyze(NameService service, ConfuserContext context, ProtectionParameters
239239
else if (property.IsRuntimeSpecialName)
240240
service.SetCanRename(property, false);
241241

242-
else if (property.IsExplicitlyImplementedInterfaceMember())
243-
service.SetCanRename(property, false);
244-
245242
else if (parameters.GetParameter(context, property, "forceRen", false))
246243
return;
247244

@@ -250,9 +247,6 @@ void Analyze(NameService service, ConfuserContext context, ProtectionParameters
250247

251248
else if (property.DeclaringType.Name.String.Contains("AnonymousType"))
252249
service.SetCanRename(property, false);
253-
254-
else if (property.IsAbstract())
255-
service.SetCanRename(property, false);
256250
}
257251

258252
void Analyze(NameService service, ConfuserContext context, ProtectionParameters parameters, EventDef evt) {
@@ -263,12 +257,6 @@ void Analyze(NameService service, ConfuserContext context, ProtectionParameters
263257

264258
else if (evt.IsRuntimeSpecialName)
265259
service.SetCanRename(evt, false);
266-
267-
else if (evt.IsExplicitlyImplementedInterfaceMember())
268-
service.SetCanRename(evt, false);
269-
270-
else if (evt.IsAbstract())
271-
service.SetCanRename(evt, false);
272260
}
273261
}
274262
}

Confuser.Renamer/Analyzers/InterReferenceAnalyzer.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void ProcessMemberRef(ConfuserContext context, INameService service, ModuleDefMD
5353

5454
TypeDef declType = memberRef.DeclaringType.ResolveTypeDefThrow();
5555
if (declType.Module != module && context.Modules.Contains((ModuleDefMD)declType.Module)) {
56-
var memberDef = (IDnlibDef)declType.ResolveThrow(memberRef);
56+
var memberDef = (IMemberDef)declType.ResolveThrow(memberRef);
5757
service.AddReference(memberDef, new MemberRefReference(memberRef, memberDef));
5858
}
5959
}
@@ -67,4 +67,4 @@ public void PostRename(ConfuserContext context, INameService service, Protection
6767
//
6868
}
6969
}
70-
}
70+
}

Confuser.Renamer/Analyzers/ReflectionAnalyzer.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Confuser.Core;
55
using Confuser.Core.Services;
66
using Confuser.Renamer.Properties;
7+
using Confuser.Renamer.References;
78
using dnlib.DotNet;
89
using dnlib.DotNet.Emit;
910
using ILogger = Confuser.Core.ILogger;
@@ -57,8 +58,13 @@ MethodTrace GetMethodTrace() {
5758
if (!types.Any())
5859
types = moduleDefs.SelectMany(m => m.GetTypes()).ToArray();
5960

60-
foreach (var possibleMethod in types.SelectMany(getMember).Where(m => names.Contains(m.Name))) {
61-
nameService.SetCanRename(possibleMethod, false);
61+
foreach (var possibleMember in types.SelectMany(GetTypeAndBaseTypes).SelectMany(getMember).Where(m => names.Contains(m.Name))) {
62+
nameService.SetCanRename(possibleMember, false);
63+
if (!(possibleMember is IMethod) && !(possibleMember is PropertyDef) && !(possibleMember is EventDef)) continue;
64+
65+
foreach (var reference in nameService.GetReferences(possibleMember).OfType<MemberOverrideReference>()) {
66+
nameService.SetCanRename(reference.BaseMemberDef, false);
67+
}
6268
}
6369
}
6470
}
@@ -67,6 +73,14 @@ MethodTrace GetMethodTrace() {
6773
}
6874
}
6975

76+
private static IEnumerable<TypeDef> GetTypeAndBaseTypes(TypeDef typeDef) {
77+
var currentType = typeDef;
78+
while (currentType != null) {
79+
yield return currentType;
80+
currentType = currentType.BaseType.ResolveTypeDef();
81+
}
82+
}
83+
7084
/// <summary>
7185
/// This method is used to determine the types that are load onto the stack at the referenced instruction.
7286
/// In case the method is unable to determine all the types reliable, it will return a empty list.

Confuser.Renamer/Analyzers/TypeBlobAnalyzer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private static void AnalyzeMemberRef(ICollection<ModuleDefMD> modules, INameServ
164164
memberRef.IsArrayAccessors())
165165
return;
166166

167-
IDnlibDef member;
167+
IMemberDef member;
168168
if (memberRef.IsFieldRef) member = memberRef.ResolveFieldThrow();
169169
else if (memberRef.IsMethodRef) member = memberRef.ResolveMethodThrow();
170170
else throw new UnreachableException();

Confuser.Renamer/Analyzers/VTableAnalyzer.cs

Lines changed: 157 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,54 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
4949
return;
5050

5151
var vTbl = service.GetVTables()[method.DeclaringType];
52-
VTableSignature sig = VTableSignature.FromMethod(method);
53-
var slots = vTbl.FindSlots(method);
52+
var slots = vTbl.FindSlots(method).ToArray();
53+
54+
IMemberDef discoveredBaseMemberDef = null;
55+
MethodDef discoveredBaseMethodDef = null;
56+
57+
bool doesOverridePropertyOrEvent = false;
58+
var methodProp = method.DeclaringType.Properties.Where(p => BelongsToProperty(p, method));
59+
foreach (var prop in methodProp) {
60+
foreach (var baseMethodDef in FindBaseDeclarations(service, method)) {
61+
var basePropDef = baseMethodDef.DeclaringType.Properties.
62+
FirstOrDefault(p => BelongsToProperty(p, baseMethodDef) && String.Equals(p.Name, prop.Name, StringComparison.Ordinal));
63+
64+
if (basePropDef is null) continue;
65+
66+
// Name of property has to line up.
67+
CreateOverrideReference(service, prop, basePropDef);
68+
CreateSiblingReference(basePropDef, ref discoveredBaseMemberDef, service);
69+
70+
// Method names have to line up as well (otherwise inheriting attributes does not work).
71+
CreateOverrideReference(service, method, baseMethodDef);
72+
CreateSiblingReference(baseMethodDef, ref discoveredBaseMethodDef, service);
73+
74+
doesOverridePropertyOrEvent = true;
75+
}
76+
}
77+
78+
discoveredBaseMemberDef = null;
79+
discoveredBaseMethodDef = null;
80+
81+
var methodEvent = method.DeclaringType.Events.Where(e => BelongsToEvent(e, method));
82+
foreach (var evt in methodEvent) {
83+
foreach (var baseMethodDef in FindBaseDeclarations(service, method)) {
84+
var baseEventDef = baseMethodDef.DeclaringType.Events.
85+
FirstOrDefault(e => BelongsToEvent(e, baseMethodDef) && String.Equals(e.Name, evt.Name, StringComparison.Ordinal));
86+
87+
if (baseEventDef is null) continue;
88+
89+
// Name of event has to line up.
90+
CreateOverrideReference(service, evt, baseEventDef);
91+
CreateSiblingReference(baseEventDef, ref discoveredBaseMemberDef, service);
92+
93+
// Method names have to line up as well (otherwise inheriting attributes does not work).
94+
CreateOverrideReference(service, method, baseMethodDef);
95+
CreateSiblingReference(baseMethodDef, ref discoveredBaseMethodDef, service);
96+
97+
doesOverridePropertyOrEvent = true;
98+
}
99+
}
54100

55101
if (!method.IsAbstract) {
56102
foreach (var slot in slots) {
@@ -60,17 +106,117 @@ public static void Analyze(INameService service, ICollection<ModuleDefMD> module
60106
SetupOverwriteReferences(service, modules, slot, method.Module);
61107
}
62108
}
109+
else if (!doesOverridePropertyOrEvent) {
110+
foreach (var baseMethodDef in FindBaseDeclarations(service, method)) {
111+
CreateOverrideReference(service, method, baseMethodDef);
112+
}
113+
}
114+
}
115+
116+
static void CreateSiblingReference<T>(T basePropDef, ref T discoveredBaseMemberDef, INameService service) where T : class, IMemberDef {
117+
if (discoveredBaseMemberDef is null)
118+
discoveredBaseMemberDef = basePropDef;
119+
else {
120+
var references = service.GetReferences(discoveredBaseMemberDef).OfType<MemberSiblingReference>().ToArray();
121+
if (references.Length > 0) {
122+
discoveredBaseMemberDef = (T)references[0].OldestSiblingDef;
123+
foreach (var siblingRef in references.Skip(1)) {
124+
// Redirect all the siblings to the new oldest reference
125+
RedirectSiblingReferences(siblingRef.OldestSiblingDef, discoveredBaseMemberDef, service);
126+
}
127+
}
128+
129+
service.AddReference(basePropDef, new MemberSiblingReference(basePropDef, discoveredBaseMemberDef));
130+
UpdateOldestSiblingReference(discoveredBaseMemberDef, basePropDef, service);
131+
}
132+
}
133+
134+
static void UpdateOldestSiblingReference(IMemberDef oldestSiblingMemberDef, IMemberDef basePropDef, INameService service) {
135+
var reverseReference = service.GetReferences(oldestSiblingMemberDef).OfType<MemberOldestSiblingReference>()
136+
.SingleOrDefault();
137+
if (reverseReference is null) {
138+
service.AddReference(oldestSiblingMemberDef, new MemberOldestSiblingReference(oldestSiblingMemberDef, basePropDef));
139+
PropagateRenamingRestrictions(service, oldestSiblingMemberDef, basePropDef);
140+
}
141+
else if (!reverseReference.OtherSiblings.Contains(basePropDef)) {
142+
reverseReference.OtherSiblings.Add(basePropDef);
143+
PropagateRenamingRestrictions(service, reverseReference.OtherSiblings);
144+
}
145+
}
146+
147+
static void RedirectSiblingReferences(IMemberDef oldMemberDef, IMemberDef newMemberDef, INameService service) {
148+
if (ReferenceEquals(oldMemberDef, newMemberDef)) return;
149+
150+
var referencesToUpdate = service.GetReferences(oldMemberDef)
151+
.OfType<MemberOldestSiblingReference>()
152+
.SelectMany(r => r.OtherSiblings)
153+
.SelectMany(service.GetReferences)
154+
.OfType<MemberSiblingReference>()
155+
.Where(r => ReferenceEquals(r.OldestSiblingDef, oldMemberDef));
156+
157+
foreach (var reference in referencesToUpdate) {
158+
reference.OldestSiblingDef = newMemberDef;
159+
UpdateOldestSiblingReference(newMemberDef, reference.ThisMemberDef, service);
160+
}
161+
UpdateOldestSiblingReference(newMemberDef, oldMemberDef, service);
162+
}
163+
164+
static void CreateOverrideReference(INameService service, IMemberDef thisMemberDef, IMemberDef baseMemberDef) {
165+
var overrideRef = new MemberOverrideReference(thisMemberDef, baseMemberDef);
166+
service.AddReference(thisMemberDef, overrideRef);
167+
168+
PropagateRenamingRestrictions(service, thisMemberDef, baseMemberDef);
169+
}
170+
171+
static void PropagateRenamingRestrictions(INameService service, params object[] objects) =>
172+
PropagateRenamingRestrictions(service, (IList<object>)objects);
173+
174+
static void PropagateRenamingRestrictions(INameService service, IList<object> objects) {
175+
if (!objects.All(service.CanRename)) {
176+
foreach (var o in objects) {
177+
service.SetCanRename(o, false);
178+
}
179+
}
63180
else {
181+
var minimalRenamingLevel = objects.Max(service.GetRenameMode);
182+
foreach (var o in objects) {
183+
service.ReduceRenameMode(o, minimalRenamingLevel);
184+
}
185+
}
186+
}
187+
188+
private static IEnumerable<MethodDef> FindBaseDeclarations(INameService service, MethodDef method) {
189+
var unprocessed = new Queue<MethodDef>();
190+
unprocessed.Enqueue(method);
191+
192+
var vTables = service.GetVTables();
193+
194+
while (unprocessed.Any()) {
195+
var currentMethod = unprocessed.Dequeue();
196+
197+
var vTbl = vTables[currentMethod.DeclaringType];
198+
var slots = vTbl.FindSlots(currentMethod).Where(s => s.Overrides != null);
199+
200+
bool slotsExists = false;
64201
foreach (var slot in slots) {
65-
if (slot.Overrides == null)
66-
continue;
67-
service.SetCanRename(method, false);
68-
service.SetCanRename(slot.Overrides.MethodDef, false);
202+
unprocessed.Enqueue(slot.Overrides.MethodDef);
203+
slotsExists = true;
69204
}
205+
206+
if (!slotsExists && method != currentMethod)
207+
yield return currentMethod;
70208
}
71209
}
72210

73-
private static void AddImportReference(INameService service, ICollection<ModuleDefMD> modules, ModuleDef module, MethodDef method, MemberRef methodRef) {
211+
private static bool BelongsToProperty(PropertyDef propertyDef, MethodDef methodDef) =>
212+
propertyDef.GetMethods.Contains(methodDef) || propertyDef.SetMethods.Contains(methodDef) ||
213+
(propertyDef.HasOtherMethods && propertyDef.OtherMethods.Contains(methodDef));
214+
215+
private static bool BelongsToEvent(EventDef eventDef, MethodDef methodDef) =>
216+
Equals(eventDef.AddMethod, methodDef) || Equals(eventDef.RemoveMethod, methodDef) || Equals(eventDef.InvokeMethod, methodDef) ||
217+
(eventDef.HasOtherMethods && eventDef.OtherMethods.Contains(methodDef));
218+
219+
private static void AddImportReference(INameService service, ICollection<ModuleDefMD> modules, ModuleDef module, MethodDef method, MemberRef methodRef) {
74220
if (method.Module != module && modules.Contains((ModuleDefMD)module)) {
75221
var declType = (TypeRef)methodRef.DeclaringType.ScopeType;
76222
service.AddReference(method.DeclaringType, new TypeRefReference(declType, method.DeclaringType));
@@ -88,8 +234,8 @@ private static void AddImportReference(INameService service, ICollection<ModuleD
88234
private static void SetupTypeReference(INameService service, ICollection<ModuleDefMD> modules, ModuleDef module, ITypeDefOrRef typeDefOrRef) {
89235
if (!(typeDefOrRef is TypeRef typeRef)) return;
90236

91-
var def = typeRef.ResolveTypeDefThrow();
92-
if (def.Module != module && modules.Contains((ModuleDefMD)def.Module))
237+
var def = typeRef.ResolveTypeDef();
238+
if (!(def is null) && def.Module != module && modules.Contains((ModuleDefMD)def.Module))
93239
service.AddReference(def, new TypeRefReference(typeRef, def));
94240
}
95241

@@ -99,7 +245,7 @@ private static GenericInstSig SetupSignatureReferences(INameService service, ICo
99245
return new GenericInstSig(genericType, genericArguments);
100246
}
101247

102-
private static T SetupSignatureReferences<T>(INameService service, ICollection<ModuleDefMD> modules, ModuleDef module, T typeSig) where T : TypeSig {
248+
private static T SetupSignatureReferences<T>(INameService service, ICollection<ModuleDefMD> modules, ModuleDef module, T typeSig) where T : TypeSig {
103249
var asTypeRef = typeSig.TryGetTypeRef();
104250
if (asTypeRef != null) {
105251
SetupTypeReference(service, modules, module, asTypeRef);
@@ -172,22 +318,8 @@ public void PostRename(ConfuserContext context, INameService service, Protection
172318
if (method == null || !method.IsVirtual || method.Overrides.Count == 0)
173319
return;
174320

175-
var methods = new HashSet<IMethodDefOrRef>(MethodDefOrRefComparer.Instance);
176321
method.Overrides
177-
.RemoveWhere(impl => MethodDefOrRefComparer.Instance.Equals(impl.MethodDeclaration, method));
178-
}
179-
180-
class MethodDefOrRefComparer : IEqualityComparer<IMethodDefOrRef> {
181-
public static readonly MethodDefOrRefComparer Instance = new MethodDefOrRefComparer();
182-
MethodDefOrRefComparer() { }
183-
184-
public bool Equals(IMethodDefOrRef x, IMethodDefOrRef y) {
185-
return new SigComparer().Equals(x, y) && new SigComparer().Equals(x.DeclaringType, y.DeclaringType);
186-
}
187-
188-
public int GetHashCode(IMethodDefOrRef obj) {
189-
return new SigComparer().GetHashCode(obj) * 5 + new SigComparer().GetHashCode(obj.DeclaringType);
190-
}
322+
.RemoveWhere(impl => MethodEqualityComparer.CompareDeclaringTypes.Equals(impl.MethodDeclaration, method));
191323
}
192324
}
193325
}

0 commit comments

Comments
 (0)