2025-04-05 21:47:28 +08:00
|
|
|
using dnlib.DotNet;
|
2025-05-04 19:55:10 +08:00
|
|
|
using Obfuz.ObfusPasses.SymbolObfus;
|
2025-05-05 12:38:52 +08:00
|
|
|
using Obfuz.ObfusPasses.SymbolObfus.NameMakers;
|
|
|
|
using Obfuz.ObfusPasses.SymbolObfus.Policies;
|
2025-05-05 09:09:53 +08:00
|
|
|
using Obfuz.Settings;
|
2025-04-28 11:37:48 +08:00
|
|
|
using Obfuz.Utils;
|
2025-04-07 23:38:11 +08:00
|
|
|
using System;
|
2025-04-05 19:02:50 +08:00
|
|
|
using System.Collections;
|
|
|
|
using System.Collections.Generic;
|
2025-04-07 23:38:11 +08:00
|
|
|
using System.Data.OleDb;
|
2025-04-16 13:12:21 +08:00
|
|
|
using System.IO;
|
2025-04-07 15:14:27 +08:00
|
|
|
using System.Linq;
|
2025-04-05 21:47:28 +08:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using UnityEditor.SceneManagement;
|
2025-04-05 19:02:50 +08:00
|
|
|
using UnityEngine;
|
2025-04-15 11:08:44 +08:00
|
|
|
using UnityEngine.Assertions;
|
2025-04-05 19:02:50 +08:00
|
|
|
|
2025-05-04 19:55:10 +08:00
|
|
|
namespace Obfuz.ObfusPasses.SymbolObfus
|
2025-04-05 19:02:50 +08:00
|
|
|
{
|
|
|
|
public class SymbolRename
|
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
class AssemblyReferenceInfo
|
|
|
|
{
|
|
|
|
public string name;
|
|
|
|
|
|
|
|
public bool needObfuscated;
|
|
|
|
|
|
|
|
public ModuleDef module;
|
|
|
|
|
|
|
|
public List<AssemblyReferenceInfo> referenceMeAssemblies;
|
|
|
|
}
|
|
|
|
|
2025-05-05 10:33:46 +08:00
|
|
|
private readonly bool _useConsistentNamespaceObfuscation;
|
2025-05-03 21:43:50 +08:00
|
|
|
private readonly List<string> _obfuscationRuleFiles;
|
2025-04-16 23:03:41 +08:00
|
|
|
private readonly string _mappingXmlPath;
|
2025-05-03 21:43:50 +08:00
|
|
|
|
|
|
|
private AssemblyCache _assemblyCache;
|
2025-05-03 23:23:16 +08:00
|
|
|
|
|
|
|
private List<ModuleDef> _toObfuscatedModules;
|
|
|
|
private List<ModuleDef> _obfuscatedAndNotObfuscatedModules;
|
|
|
|
private List<AssemblyReferenceInfo> _obfuzAssemblies;
|
|
|
|
private HashSet<ModuleDef> _toObfuscatedModuleSet;
|
2025-05-05 12:38:52 +08:00
|
|
|
private IObfuscationPolicy _renamePolicy;
|
2025-05-03 21:43:50 +08:00
|
|
|
private INameMaker _nameMaker;
|
2025-04-07 15:14:27 +08:00
|
|
|
private readonly Dictionary<ModuleDef, List<CustomAttributeInfo>> _customAttributeArgumentsWithTypeByMods = new Dictionary<ModuleDef, List<CustomAttributeInfo>>();
|
2025-04-16 13:12:21 +08:00
|
|
|
private readonly RenameRecordMap _renameRecordMap;
|
2025-05-03 21:43:50 +08:00
|
|
|
private readonly VirtualMethodGroupCalculator _virtualMethodGroupCalculator;
|
2025-04-07 15:14:27 +08:00
|
|
|
|
|
|
|
class CustomAttributeInfo
|
|
|
|
{
|
|
|
|
public CustomAttributeCollection customAttributes;
|
|
|
|
public int index;
|
|
|
|
public List<CAArgument> arguments;
|
|
|
|
public List<CANamedArgument> namedArguments;
|
|
|
|
}
|
2025-04-16 23:03:41 +08:00
|
|
|
|
2025-05-05 09:09:53 +08:00
|
|
|
public SymbolRename(SymbolObfusSettings settings)
|
2025-05-03 21:43:50 +08:00
|
|
|
{
|
2025-05-05 10:33:46 +08:00
|
|
|
_useConsistentNamespaceObfuscation = settings.useConsistentNamespaceObfuscation;
|
2025-05-05 09:09:53 +08:00
|
|
|
_mappingXmlPath = settings.mappingFile;
|
|
|
|
_obfuscationRuleFiles = settings.ruleFiles.ToList();
|
|
|
|
_renameRecordMap = new RenameRecordMap(settings.mappingFile);
|
2025-05-03 21:43:50 +08:00
|
|
|
_virtualMethodGroupCalculator = new VirtualMethodGroupCalculator();
|
2025-05-05 10:24:13 +08:00
|
|
|
_nameMaker = settings.debug ? NameMakerFactory.CreateDebugNameMaker() : NameMakerFactory.CreateNameMakerBaseASCIICharSet(settings.obfuscatedNamePrefix);
|
2025-05-03 21:43:50 +08:00
|
|
|
}
|
|
|
|
|
2025-05-04 19:24:14 +08:00
|
|
|
public void Init(ObfuscationPassContext ctx)
|
2025-04-05 19:02:50 +08:00
|
|
|
{
|
2025-04-15 17:16:47 +08:00
|
|
|
_assemblyCache = ctx.assemblyCache;
|
2025-05-03 23:23:16 +08:00
|
|
|
_toObfuscatedModules = ctx.toObfuscatedModules;
|
|
|
|
_obfuscatedAndNotObfuscatedModules = ctx.obfuscatedAndNotObfuscatedModules;
|
|
|
|
_toObfuscatedModuleSet = ctx.toObfuscatedModules.ToHashSet();
|
|
|
|
_obfuzAssemblies = BuildAssemblyReferenceInfos(ctx);
|
2025-05-08 12:36:06 +08:00
|
|
|
var obfuscateRuleConfig = new ConfigurableRenamePolicy(ctx.toObfuscatedAssemblyNames, _obfuscationRuleFiles);
|
2025-05-05 12:38:52 +08:00
|
|
|
_renamePolicy = new CacheRenamePolicy(new CombineRenamePolicy(new SystemRenamePolicy(), new UnityRenamePolicy(), obfuscateRuleConfig));
|
2025-05-03 23:23:16 +08:00
|
|
|
BuildCustomAttributeArguments();
|
|
|
|
}
|
2025-04-13 22:41:09 +08:00
|
|
|
|
2025-05-04 19:24:14 +08:00
|
|
|
private static List<AssemblyReferenceInfo> BuildAssemblyReferenceInfos(ObfuscationPassContext ctx)
|
2025-05-03 23:23:16 +08:00
|
|
|
{
|
|
|
|
var obfuzAssemblies = new List<AssemblyReferenceInfo>();
|
|
|
|
foreach (ModuleDef mod in ctx.obfuscatedAndNotObfuscatedModules)
|
2025-04-13 22:41:09 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
var obfuzAsm = new AssemblyReferenceInfo
|
|
|
|
{
|
|
|
|
name = mod.Assembly.Name,
|
|
|
|
needObfuscated = ctx.toObfuscatedModules.Contains(mod),
|
|
|
|
module = mod,
|
|
|
|
referenceMeAssemblies = new List<AssemblyReferenceInfo>(),
|
|
|
|
};
|
|
|
|
obfuzAsm.referenceMeAssemblies.Add(obfuzAsm);
|
|
|
|
obfuzAssemblies.Add(obfuzAsm);
|
2025-04-13 22:41:09 +08:00
|
|
|
}
|
2025-05-03 23:23:16 +08:00
|
|
|
|
|
|
|
var assByName = obfuzAssemblies.ToDictionary(x => x.name);
|
|
|
|
foreach (var ass in obfuzAssemblies)
|
|
|
|
{
|
|
|
|
foreach (var refAss in ass.module.GetAssemblyRefs())
|
|
|
|
{
|
|
|
|
string refAssName = refAss.Name;
|
|
|
|
if (assByName.TryGetValue(refAssName, out var refAssembly))
|
|
|
|
{
|
|
|
|
//UnityEngine.Debug.Log($"assembly:{ass.name} reference to {refAssName}");
|
|
|
|
refAssembly.referenceMeAssemblies.Add(ass);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return obfuzAssemblies;
|
2025-04-07 15:14:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void CollectCArgumentWithTypeOf(IHasCustomAttribute meta, List<CustomAttributeInfo> customAttributes)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
foreach (CustomAttribute ca in meta.CustomAttributes)
|
|
|
|
{
|
|
|
|
List<CAArgument> arguments = null;
|
2025-04-13 21:20:58 +08:00
|
|
|
if (ca.ConstructorArguments.Any(a => MetaUtil.MayRenameCustomDataType(a.Type.ElementType)))
|
2025-04-07 15:14:27 +08:00
|
|
|
{
|
|
|
|
arguments = ca.ConstructorArguments.ToList();
|
|
|
|
}
|
|
|
|
List<CANamedArgument> namedArguments = null;
|
2025-04-13 21:20:58 +08:00
|
|
|
if (ca.NamedArguments.Any(a => MetaUtil.MayRenameCustomDataType(a.Type.ElementType)))
|
2025-04-07 15:14:27 +08:00
|
|
|
{
|
|
|
|
namedArguments = ca.NamedArguments.ToList();
|
|
|
|
}
|
|
|
|
if (arguments != null | namedArguments != null)
|
|
|
|
{
|
|
|
|
customAttributes.Add(new CustomAttributeInfo
|
|
|
|
{
|
|
|
|
customAttributes = meta.CustomAttributes,
|
|
|
|
index = index,
|
|
|
|
arguments = arguments,
|
|
|
|
namedArguments = namedArguments
|
|
|
|
});
|
|
|
|
}
|
|
|
|
++index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildCustomAttributeArguments()
|
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules)
|
2025-04-07 15:14:27 +08:00
|
|
|
{
|
|
|
|
var customAttributes = new List<CustomAttributeInfo>();
|
2025-05-03 23:23:16 +08:00
|
|
|
CollectCArgumentWithTypeOf(mod, customAttributes);
|
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-07 15:14:27 +08:00
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf(type, customAttributes);
|
|
|
|
foreach (FieldDef field in type.Fields)
|
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf(field, customAttributes);
|
|
|
|
}
|
|
|
|
foreach (MethodDef method in type.Methods)
|
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf(method, customAttributes);
|
|
|
|
foreach (Parameter param in method.Parameters)
|
|
|
|
{
|
|
|
|
if (param.ParamDef != null)
|
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf(param.ParamDef, customAttributes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach (PropertyDef property in type.Properties)
|
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf(property, customAttributes);
|
|
|
|
}
|
|
|
|
foreach (EventDef eventDef in type.Events)
|
|
|
|
{
|
|
|
|
CollectCArgumentWithTypeOf (eventDef, customAttributes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-03 23:23:16 +08:00
|
|
|
_customAttributeArgumentsWithTypeByMods.Add(mod, customAttributes);
|
2025-04-07 15:14:27 +08:00
|
|
|
}
|
2025-04-05 19:02:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Process()
|
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
_renameRecordMap.Init(_toObfuscatedModules, _nameMaker);
|
2025-05-05 09:14:40 +08:00
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
RenameTypes();
|
|
|
|
RenameFields();
|
|
|
|
RenameMethods();
|
|
|
|
RenameProperties();
|
|
|
|
RenameEvents();
|
|
|
|
}
|
|
|
|
|
2025-04-15 11:08:44 +08:00
|
|
|
class RefTypeDefMetas
|
|
|
|
{
|
|
|
|
public readonly List<TypeRef> typeRefs = new List<TypeRef>();
|
|
|
|
|
|
|
|
public readonly List<CustomAttribute> customAttributes = new List<CustomAttribute>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildRefTypeDefMetasMap(Dictionary<TypeDef, RefTypeDefMetas> refTypeDefMetasMap)
|
|
|
|
{
|
2025-05-12 09:42:58 +08:00
|
|
|
foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules)
|
2025-04-15 11:08:44 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeRef typeRef in mod.GetTypeRefs())
|
2025-04-15 11:08:44 +08:00
|
|
|
{
|
2025-05-12 09:42:58 +08:00
|
|
|
if (typeRef.DefinitionAssembly.IsCorLib())
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2025-04-15 11:08:44 +08:00
|
|
|
TypeDef typeDef = typeRef.ResolveThrow();
|
|
|
|
if (!refTypeDefMetasMap.TryGetValue(typeDef, out var typeDefMetas))
|
|
|
|
{
|
|
|
|
typeDefMetas = new RefTypeDefMetas();
|
|
|
|
refTypeDefMetasMap.Add(typeDef, typeDefMetas);
|
|
|
|
}
|
|
|
|
typeDefMetas.typeRefs.Add(typeRef);
|
|
|
|
}
|
|
|
|
}
|
2025-04-15 12:36:10 +08:00
|
|
|
|
|
|
|
foreach (CustomAttributeInfo cai in _customAttributeArgumentsWithTypeByMods.Values.SelectMany(cas => cas))
|
|
|
|
{
|
|
|
|
CustomAttribute ca = cai.customAttributes[cai.index];
|
|
|
|
TypeDef typeDef = MetaUtil.GetTypeDefOrGenericTypeBaseThrowException(ca.Constructor.DeclaringType);
|
|
|
|
if (!refTypeDefMetasMap.TryGetValue(typeDef, out var typeDefMetas))
|
|
|
|
{
|
|
|
|
typeDefMetas = new RefTypeDefMetas();
|
|
|
|
refTypeDefMetasMap.Add(typeDef, typeDefMetas);
|
|
|
|
}
|
|
|
|
typeDefMetas.customAttributes.Add(ca);
|
|
|
|
}
|
2025-04-15 11:08:44 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 11:36:13 +08:00
|
|
|
private void RetargetTypeRefInCustomAttributes()
|
|
|
|
{
|
|
|
|
foreach (CustomAttributeInfo cai in _customAttributeArgumentsWithTypeByMods.Values.SelectMany(cas => cas))
|
|
|
|
{
|
|
|
|
CustomAttribute ca = cai.customAttributes[cai.index];
|
|
|
|
bool anyChange = false;
|
|
|
|
if (cai.arguments != null)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < cai.arguments.Count; i++)
|
|
|
|
{
|
|
|
|
CAArgument oldArg = cai.arguments[i];
|
|
|
|
if (MetaUtil.TryRetargetTypeRefInArgument(oldArg, out CAArgument newArg))
|
|
|
|
{
|
|
|
|
anyChange = true;
|
|
|
|
cai.arguments[i] = newArg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cai.namedArguments != null)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < cai.namedArguments.Count; i++)
|
|
|
|
{
|
|
|
|
if (MetaUtil.TryRetargetTypeRefInNamedArgument(cai.namedArguments[i]))
|
|
|
|
{
|
|
|
|
anyChange = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (anyChange)
|
|
|
|
{
|
|
|
|
cai.customAttributes[cai.index] = new CustomAttribute(ca.Constructor,
|
|
|
|
cai.arguments != null ? cai.arguments : ca.ConstructorArguments,
|
|
|
|
cai.namedArguments != null ? cai.namedArguments : ca.NamedArguments);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-15 12:36:10 +08:00
|
|
|
private readonly Dictionary<TypeDef, RefTypeDefMetas> _refTypeRefMetasMap = new Dictionary<TypeDef, RefTypeDefMetas>();
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
private void RenameTypes()
|
|
|
|
{
|
|
|
|
Debug.Log("RenameTypes begin");
|
2025-04-15 11:08:44 +08:00
|
|
|
|
2025-04-15 11:36:13 +08:00
|
|
|
RetargetTypeRefInCustomAttributes();
|
|
|
|
|
2025-04-15 12:36:10 +08:00
|
|
|
BuildRefTypeDefMetasMap(_refTypeRefMetasMap);
|
2025-04-15 17:16:47 +08:00
|
|
|
_assemblyCache.EnableTypeDefCache = false;
|
2025-04-15 11:08:44 +08:00
|
|
|
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _toObfuscatedModules)
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-13 21:20:58 +08:00
|
|
|
if (_renamePolicy.NeedRename(type))
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-16 18:05:21 +08:00
|
|
|
Rename(type, _refTypeRefMetasMap.GetValueOrDefault(type));
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
2025-04-15 09:52:28 +08:00
|
|
|
}
|
|
|
|
}
|
2025-04-15 11:36:13 +08:00
|
|
|
|
|
|
|
// clean cache
|
2025-04-15 17:16:47 +08:00
|
|
|
_assemblyCache.EnableTypeDefCache = true;
|
2025-04-15 09:52:28 +08:00
|
|
|
Debug.Log("Rename Types end");
|
|
|
|
}
|
|
|
|
|
2025-04-15 12:36:10 +08:00
|
|
|
|
|
|
|
class RefFieldMetas
|
|
|
|
{
|
|
|
|
public readonly List<MemberRef> fieldRefs = new List<MemberRef>();
|
|
|
|
public readonly List<CustomAttribute> customAttributes = new List<CustomAttribute>();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void BuildHierarchyFields(TypeDef type, List<FieldDef> fields)
|
|
|
|
{
|
|
|
|
while (type != null)
|
|
|
|
{
|
|
|
|
fields.AddRange(type.Fields);
|
|
|
|
type = MetaUtil.GetBaseTypeDef(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildRefFieldMetasMap(Dictionary<FieldDef, RefFieldMetas> refFieldMetasMap)
|
|
|
|
{
|
2025-05-12 10:55:31 +08:00
|
|
|
foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules)
|
2025-04-15 12:36:10 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (MemberRef memberRef in mod.GetMemberRefs())
|
2025-04-15 12:36:10 +08:00
|
|
|
{
|
|
|
|
if (!memberRef.IsFieldRef)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMemberRefParent parent = memberRef.Class;
|
|
|
|
TypeDef parentTypeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(parent);
|
|
|
|
if (parentTypeDef == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach (FieldDef field in parentTypeDef.Fields)
|
|
|
|
{
|
|
|
|
if (field.Name == memberRef.Name && TypeEqualityComparer.Instance.Equals(field.FieldSig.Type, memberRef.FieldSig.Type))
|
|
|
|
{
|
|
|
|
if (!refFieldMetasMap.TryGetValue(field, out var fieldMetas))
|
|
|
|
{
|
|
|
|
fieldMetas = new RefFieldMetas();
|
|
|
|
refFieldMetasMap.Add(field, fieldMetas);
|
|
|
|
}
|
|
|
|
fieldMetas.fieldRefs.Add(memberRef);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach (var e in _refTypeRefMetasMap)
|
|
|
|
{
|
|
|
|
TypeDef typeDef = e.Key;
|
|
|
|
var hierarchyFields = new List<FieldDef>();
|
|
|
|
BuildHierarchyFields(typeDef, hierarchyFields);
|
|
|
|
RefTypeDefMetas typeDefMetas = e.Value;
|
|
|
|
foreach (CustomAttribute ca in typeDefMetas.customAttributes)
|
|
|
|
{
|
|
|
|
foreach (var arg in ca.NamedArguments)
|
|
|
|
{
|
|
|
|
if (arg.IsProperty)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach (FieldDef field in hierarchyFields)
|
|
|
|
{
|
2025-04-15 17:49:02 +08:00
|
|
|
// FIXME. field of Generic Base Type may not be same
|
|
|
|
if (field.Name == arg.Name && TypeEqualityComparer.Instance.Equals(field.FieldType, arg.Type))
|
2025-04-15 12:36:10 +08:00
|
|
|
{
|
|
|
|
if (!refFieldMetasMap.TryGetValue(field, out var fieldMetas))
|
|
|
|
{
|
|
|
|
fieldMetas = new RefFieldMetas();
|
|
|
|
refFieldMetasMap.Add(field, fieldMetas);
|
|
|
|
}
|
|
|
|
fieldMetas.customAttributes.Add(ca);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
private void RenameFields()
|
|
|
|
{
|
|
|
|
Debug.Log("Rename fields begin");
|
2025-04-15 12:36:10 +08:00
|
|
|
var refFieldMetasMap = new Dictionary<FieldDef, RefFieldMetas>();
|
|
|
|
BuildRefFieldMetasMap(refFieldMetasMap);
|
|
|
|
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _toObfuscatedModules)
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-04-05 21:47:28 +08:00
|
|
|
foreach (FieldDef field in type.Fields)
|
|
|
|
{
|
|
|
|
if (_renamePolicy.NeedRename(field))
|
|
|
|
{
|
2025-04-16 18:05:21 +08:00
|
|
|
Rename(field, refFieldMetasMap.GetValueOrDefault(field));
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
}
|
2025-04-15 09:52:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Debug.Log("Rename fields end");
|
|
|
|
}
|
|
|
|
|
2025-04-15 17:16:47 +08:00
|
|
|
class RefMethodMetas
|
|
|
|
{
|
|
|
|
public readonly List<MemberRef> memberRefs = new List<MemberRef>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildRefMethodMetasMap(Dictionary<MethodDef, RefMethodMetas> refMethodMetasMap)
|
|
|
|
{
|
2025-05-12 10:55:31 +08:00
|
|
|
foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules)
|
2025-04-15 17:16:47 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (MemberRef memberRef in mod.GetMemberRefs())
|
2025-04-15 17:16:47 +08:00
|
|
|
{
|
|
|
|
if (!memberRef.IsMethodRef)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
IMemberRefParent parent = memberRef.Class;
|
|
|
|
TypeDef parentTypeDef = MetaUtil.GetMemberRefTypeDefParentOrNull(parent);
|
|
|
|
if (parentTypeDef == null)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach (MethodDef method in parentTypeDef.Methods)
|
|
|
|
{
|
|
|
|
if (method.Name == memberRef.Name && new SigComparer(default).Equals(method.MethodSig, memberRef.MethodSig))
|
|
|
|
{
|
|
|
|
if (!refMethodMetasMap.TryGetValue(method, out var refMethodMetas))
|
|
|
|
{
|
|
|
|
refMethodMetas = new RefMethodMetas();
|
|
|
|
refMethodMetasMap.Add(method, refMethodMetas);
|
|
|
|
}
|
|
|
|
refMethodMetas.memberRefs.Add(memberRef);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
private void RenameMethods()
|
|
|
|
{
|
|
|
|
Debug.Log("Rename methods begin");
|
|
|
|
Debug.Log("Rename not virtual methods begin");
|
|
|
|
var virtualMethods = new List<MethodDef>();
|
2025-04-15 17:16:47 +08:00
|
|
|
var refMethodMetasMap = new Dictionary<MethodDef, RefMethodMetas>();
|
|
|
|
BuildRefMethodMetasMap(refMethodMetasMap);
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _toObfuscatedModules)
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-04-05 21:47:28 +08:00
|
|
|
foreach (MethodDef method in type.Methods)
|
|
|
|
{
|
2025-04-13 22:41:09 +08:00
|
|
|
if (method.IsVirtual)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2025-04-05 21:47:28 +08:00
|
|
|
if (_renamePolicy.NeedRename(method))
|
|
|
|
{
|
2025-04-16 18:05:21 +08:00
|
|
|
Rename(method, refMethodMetasMap.GetValueOrDefault(method));
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-05-12 11:26:00 +08:00
|
|
|
|
|
|
|
foreach (ModuleDef mod in _obfuscatedAndNotObfuscatedModules)
|
|
|
|
{
|
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
|
|
|
{
|
|
|
|
_virtualMethodGroupCalculator.CalculateType(type);
|
|
|
|
foreach (MethodDef method in type.Methods)
|
|
|
|
{
|
|
|
|
if (method.IsVirtual)
|
|
|
|
{
|
|
|
|
virtualMethods.Add(method);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
Debug.Log("Rename not virtual methods end");
|
|
|
|
|
2025-04-13 22:41:09 +08:00
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
Debug.Log("Rename virtual methods begin");
|
2025-04-13 22:41:09 +08:00
|
|
|
var visitedVirtualMethods = new HashSet<MethodDef>();
|
|
|
|
var groupNeedRenames = new Dictionary<VirtualMethodGroup, bool>();
|
|
|
|
foreach (var method in virtualMethods)
|
|
|
|
{
|
|
|
|
if (!visitedVirtualMethods.Add(method))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
VirtualMethodGroup group = _virtualMethodGroupCalculator.GetMethodGroup(method);
|
|
|
|
if (!groupNeedRenames.TryGetValue(group, out var needRename))
|
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
needRename = group.methods.All(m => _toObfuscatedModuleSet.Contains(m.DeclaringType.Module) && _renamePolicy.NeedRename(m));
|
2025-04-13 22:41:09 +08:00
|
|
|
groupNeedRenames.Add(group, needRename);
|
|
|
|
if (needRename)
|
|
|
|
{
|
2025-04-16 18:30:51 +08:00
|
|
|
_renameRecordMap.InitAndAddRename(group, _renameRecordMap.TryGetExistRenameMapping(method, out var nn) ? nn : _nameMaker.GetNewName(method, method.Name));
|
2025-04-13 22:41:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!needRename)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2025-04-16 13:34:53 +08:00
|
|
|
if (_renameRecordMap.TryGetRename(group, out var newName))
|
2025-04-13 22:41:09 +08:00
|
|
|
{
|
2025-04-16 18:05:21 +08:00
|
|
|
Rename(method, refMethodMetasMap.GetValueOrDefault(method), newName);
|
2025-04-13 22:41:09 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw new Exception($"group:{group} method:{method} not found in rename record map");
|
|
|
|
}
|
|
|
|
}
|
2025-04-15 09:52:28 +08:00
|
|
|
Debug.Log("Rename virtual methods end");
|
|
|
|
Debug.Log("Rename methods end");
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 12:42:09 +08:00
|
|
|
class RefPropertyMetas
|
|
|
|
{
|
|
|
|
public List<CustomAttribute> customAttributes = new List<CustomAttribute>();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildHierarchyProperties(TypeDef type, List<PropertyDef> properties)
|
|
|
|
{
|
|
|
|
while (type != null)
|
|
|
|
{
|
|
|
|
properties.AddRange(type.Properties);
|
|
|
|
type = MetaUtil.GetBaseTypeDef(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void BuildRefPropertyMetasMap(Dictionary<PropertyDef, RefPropertyMetas> refPropertyMetasMap)
|
|
|
|
{
|
|
|
|
foreach (var e in _refTypeRefMetasMap)
|
|
|
|
{
|
|
|
|
TypeDef typeDef = e.Key;
|
|
|
|
var hierarchyProperties = new List<PropertyDef>();
|
|
|
|
BuildHierarchyProperties(typeDef, hierarchyProperties);
|
|
|
|
RefTypeDefMetas typeDefMetas = e.Value;
|
|
|
|
foreach (CustomAttribute ca in typeDefMetas.customAttributes)
|
|
|
|
{
|
|
|
|
foreach (var arg in ca.NamedArguments)
|
|
|
|
{
|
|
|
|
if (arg.IsField)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
foreach (PropertyDef field in hierarchyProperties)
|
|
|
|
{
|
2025-04-15 17:49:02 +08:00
|
|
|
// FIXME. field of Generic Base Type may not be same
|
|
|
|
if (field.Name == arg.Name && TypeEqualityComparer.Instance.Equals(arg.Type, field.PropertySig.RetType))
|
2025-04-15 12:42:09 +08:00
|
|
|
{
|
|
|
|
if (!refPropertyMetasMap.TryGetValue(field, out var fieldMetas))
|
|
|
|
{
|
|
|
|
fieldMetas = new RefPropertyMetas();
|
|
|
|
refPropertyMetasMap.Add(field, fieldMetas);
|
|
|
|
}
|
|
|
|
fieldMetas.customAttributes.Add(ca);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
private void RenameProperties()
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-15 09:52:28 +08:00
|
|
|
Debug.Log("Rename properties begin");
|
2025-04-15 12:42:09 +08:00
|
|
|
var refPropertyMetasMap = new Dictionary<PropertyDef, RefPropertyMetas>();
|
|
|
|
BuildRefPropertyMetasMap(refPropertyMetasMap);
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _toObfuscatedModules)
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
|
|
|
foreach (PropertyDef property in type.Properties)
|
|
|
|
{
|
|
|
|
if (_renamePolicy.NeedRename(property))
|
|
|
|
{
|
2025-04-16 18:05:21 +08:00
|
|
|
Rename(property, refPropertyMetasMap.GetValueOrDefault(property));
|
2025-04-15 09:52:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Debug.Log("Rename properties end");
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RenameEvents()
|
|
|
|
{
|
|
|
|
Debug.Log("Rename events begin");
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (ModuleDef mod in _toObfuscatedModules)
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
2025-05-03 23:23:16 +08:00
|
|
|
foreach (TypeDef type in mod.GetTypes())
|
2025-04-15 09:52:28 +08:00
|
|
|
{
|
|
|
|
foreach (EventDef eventDef in type.Events)
|
|
|
|
{
|
|
|
|
if (_renamePolicy.NeedRename(eventDef))
|
|
|
|
{
|
|
|
|
Rename(eventDef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Debug.Log("Rename events begin");
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
|
2025-05-05 09:31:18 +08:00
|
|
|
//private void Rename(ModuleDef mod)
|
|
|
|
//{
|
|
|
|
// string oldName = mod.Assembly.Name;
|
|
|
|
// string newName = _renameRecordMap.TryGetExistRenameMapping(mod, out var n) ? n : _nameMaker.GetNewName(mod, oldName);
|
|
|
|
// _renameRecordMap.AddRename(mod, newName);
|
|
|
|
// mod.Assembly.Name = newName;
|
|
|
|
// mod.Name = $"{newName}.dll";
|
|
|
|
// //Debug.Log($"rename module. oldName:{oldName} newName:{newName}");
|
|
|
|
// foreach (AssemblyReferenceInfo ass in GetReferenceMeAssemblies(mod))
|
|
|
|
// {
|
|
|
|
// foreach (AssemblyRef assRef in ass.module.GetAssemblyRefs())
|
|
|
|
// {
|
|
|
|
// if (assRef.Name == oldName)
|
|
|
|
// {
|
|
|
|
// _renameRecordMap.AddRename(mod, newName);
|
|
|
|
// assRef.Name = newName;
|
|
|
|
// // Debug.Log($"rename assembly:{ass.name} ref oldName:{oldName} newName:{newName}");
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//}
|
2025-04-05 21:47:28 +08:00
|
|
|
|
2025-04-15 11:08:44 +08:00
|
|
|
private void Rename(TypeDef type, RefTypeDefMetas refTypeDefMeta)
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-05 23:21:24 +08:00
|
|
|
string moduleName = MetaUtil.GetModuleNameWithoutExt(type.Module.Name);
|
|
|
|
string oldFullName = type.FullName;
|
|
|
|
string oldNamespace = type.Namespace;
|
2025-04-16 18:30:51 +08:00
|
|
|
|
|
|
|
string oldName = type.Name;
|
|
|
|
|
2025-04-05 23:21:24 +08:00
|
|
|
string newNamespace;
|
2025-04-16 18:30:51 +08:00
|
|
|
string newName;
|
|
|
|
if (_renameRecordMap.TryGetExistRenameMapping(type, out var nns, out var nn))
|
2025-04-05 23:21:24 +08:00
|
|
|
{
|
2025-04-16 18:30:51 +08:00
|
|
|
newNamespace = nns;
|
|
|
|
newName = nn;
|
2025-04-05 23:21:24 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2025-05-05 10:33:46 +08:00
|
|
|
newNamespace = _nameMaker.GetNewNamespace(type, oldNamespace, _useConsistentNamespaceObfuscation);
|
2025-04-16 18:30:51 +08:00
|
|
|
newName = _nameMaker.GetNewName(type, oldName);
|
2025-04-05 23:21:24 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 11:08:44 +08:00
|
|
|
if (refTypeDefMeta != null)
|
2025-04-05 23:21:24 +08:00
|
|
|
{
|
2025-04-15 11:08:44 +08:00
|
|
|
foreach (TypeRef typeRef in refTypeDefMeta.typeRefs)
|
2025-04-05 23:21:24 +08:00
|
|
|
{
|
2025-04-15 11:08:44 +08:00
|
|
|
Assert.AreEqual(typeRef.FullName, oldFullName);
|
|
|
|
Assert.IsTrue(typeRef.DefinitionAssembly.Name == moduleName);
|
2025-04-05 23:21:24 +08:00
|
|
|
if (!string.IsNullOrEmpty(oldNamespace))
|
|
|
|
{
|
|
|
|
typeRef.Namespace = newNamespace;
|
|
|
|
}
|
|
|
|
typeRef.Name = newName;
|
2025-04-16 13:12:21 +08:00
|
|
|
//Debug.Log($"rename assembly:{typeRef.Module.Name} reference {oldFullName} => {typeRef.FullName}");
|
2025-04-05 23:21:24 +08:00
|
|
|
}
|
|
|
|
}
|
2025-04-07 15:14:27 +08:00
|
|
|
type.Name = newName;
|
2025-04-16 18:30:51 +08:00
|
|
|
type.Namespace = newNamespace;
|
2025-04-07 15:14:27 +08:00
|
|
|
string newFullName = type.FullName;
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(type, newFullName);
|
2025-04-16 13:12:21 +08:00
|
|
|
//Debug.Log($"rename typedef. assembly:{type.Module.Name} oldName:{oldFullName} => newName:{newFullName}");
|
2025-04-07 15:14:27 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 12:36:10 +08:00
|
|
|
private void Rename(FieldDef field, RefFieldMetas fieldMetas)
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-07 08:04:29 +08:00
|
|
|
string oldName = field.Name;
|
2025-04-16 18:30:51 +08:00
|
|
|
string newName = _renameRecordMap.TryGetExistRenameMapping(field, out var nn) ? nn : _nameMaker.GetNewName(field, oldName);
|
2025-04-15 12:36:10 +08:00
|
|
|
if (fieldMetas != null)
|
2025-04-07 08:04:29 +08:00
|
|
|
{
|
2025-04-15 12:36:10 +08:00
|
|
|
foreach (var memberRef in fieldMetas.fieldRefs)
|
2025-04-07 08:04:29 +08:00
|
|
|
{
|
2025-04-15 12:36:10 +08:00
|
|
|
memberRef.Name = newName;
|
2025-04-16 13:12:21 +08:00
|
|
|
//Debug.Log($"rename assembly:{memberRef.Module.Name} reference {field.FullName} => {memberRef.FullName}");
|
2025-04-15 12:36:10 +08:00
|
|
|
}
|
|
|
|
foreach (var ca in fieldMetas.customAttributes)
|
|
|
|
{
|
|
|
|
foreach (var arg in ca.NamedArguments)
|
2025-04-07 08:04:29 +08:00
|
|
|
{
|
2025-04-15 12:36:10 +08:00
|
|
|
if (arg.Name == oldName)
|
2025-04-07 08:04:29 +08:00
|
|
|
{
|
2025-04-15 12:36:10 +08:00
|
|
|
arg.Name = newName;
|
2025-04-07 08:04:29 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-04-16 13:12:21 +08:00
|
|
|
//Debug.Log($"rename field. {field} => {newName}");
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(field, newName);
|
2025-04-07 08:04:29 +08:00
|
|
|
field.Name = newName;
|
2025-04-13 10:31:55 +08:00
|
|
|
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
2025-04-05 19:02:50 +08:00
|
|
|
|
2025-04-15 17:16:47 +08:00
|
|
|
private void Rename(MethodDef method, RefMethodMetas refMethodMetas)
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-13 11:18:34 +08:00
|
|
|
string oldName = method.Name;
|
2025-04-16 18:30:51 +08:00
|
|
|
string newName = _renameRecordMap.TryGetExistRenameMapping(method, out var nn) ? nn : _nameMaker.GetNewName(method, oldName);
|
2025-04-16 13:34:53 +08:00
|
|
|
Rename(method, refMethodMetas, newName);
|
2025-04-13 22:41:09 +08:00
|
|
|
}
|
|
|
|
|
2025-04-16 13:34:53 +08:00
|
|
|
private void Rename(MethodDef method, RefMethodMetas refMethodMetas, string newName)
|
2025-04-13 22:41:09 +08:00
|
|
|
{
|
2025-04-13 11:18:34 +08:00
|
|
|
ModuleDefMD mod = (ModuleDefMD)method.DeclaringType.Module;
|
2025-04-15 09:52:28 +08:00
|
|
|
RenameMethodParams(method);
|
2025-04-13 11:18:34 +08:00
|
|
|
RenameMethodBody(method);
|
2025-04-15 17:16:47 +08:00
|
|
|
if (refMethodMetas != null)
|
2025-04-13 11:18:34 +08:00
|
|
|
{
|
2025-04-15 17:16:47 +08:00
|
|
|
foreach (MemberRef memberRef in refMethodMetas.memberRefs)
|
2025-04-13 11:18:34 +08:00
|
|
|
{
|
|
|
|
string oldMethodFullName = memberRef.ToString();
|
|
|
|
memberRef.Name = newName;
|
2025-04-16 13:12:21 +08:00
|
|
|
//Debug.Log($"rename assembly:{memberRef.Module.Name} method:{oldMethodFullName} => {memberRef}");
|
2025-04-13 11:18:34 +08:00
|
|
|
}
|
|
|
|
}
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(method, newName);
|
2025-04-13 11:18:34 +08:00
|
|
|
method.Name = newName;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void RenameMethodBody(MethodDef method)
|
|
|
|
{
|
|
|
|
if (method.Body == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 09:52:28 +08:00
|
|
|
private void RenameMethodParams(MethodDef method)
|
|
|
|
{
|
|
|
|
foreach (Parameter param in method.Parameters)
|
|
|
|
{
|
|
|
|
if (param.ParamDef != null)
|
|
|
|
{
|
|
|
|
Rename(param.ParamDef);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-04-05 21:47:28 +08:00
|
|
|
private void Rename(ParamDef param)
|
|
|
|
{
|
2025-04-15 17:16:47 +08:00
|
|
|
if (_renamePolicy.NeedRename(param))
|
|
|
|
{
|
2025-04-16 13:12:21 +08:00
|
|
|
string newName = _nameMaker.GetNewName(param, param.Name);
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(param, newName);
|
2025-04-16 13:12:21 +08:00
|
|
|
param.Name = newName;
|
|
|
|
}
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
private void Rename(EventDef eventDef)
|
|
|
|
{
|
2025-04-13 21:20:58 +08:00
|
|
|
string oldName = eventDef.Name;
|
2025-04-16 18:30:51 +08:00
|
|
|
string newName = _renameRecordMap.TryGetExistRenameMapping(eventDef, out var nn) ? nn : _nameMaker.GetNewName(eventDef, eventDef.Name);
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(eventDef, newName);
|
2025-04-13 21:20:58 +08:00
|
|
|
eventDef.Name = newName;
|
2025-04-05 21:47:28 +08:00
|
|
|
}
|
|
|
|
|
2025-04-15 12:42:09 +08:00
|
|
|
private void Rename(PropertyDef property, RefPropertyMetas refPropertyMetas)
|
2025-04-05 21:47:28 +08:00
|
|
|
{
|
2025-04-13 10:31:55 +08:00
|
|
|
string oldName = property.Name;
|
2025-04-16 18:30:51 +08:00
|
|
|
string newName = _renameRecordMap.TryGetExistRenameMapping(property, out var nn) ? nn : _nameMaker.GetNewName(property, oldName);
|
2025-04-15 12:42:09 +08:00
|
|
|
|
|
|
|
if (refPropertyMetas != null)
|
2025-04-13 10:31:55 +08:00
|
|
|
{
|
2025-04-15 12:42:09 +08:00
|
|
|
foreach (var ca in refPropertyMetas.customAttributes)
|
|
|
|
{
|
|
|
|
foreach (var arg in ca.NamedArguments)
|
|
|
|
{
|
|
|
|
if (arg.Name == oldName)
|
|
|
|
{
|
|
|
|
arg.Name = newName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-04-13 10:31:55 +08:00
|
|
|
}
|
2025-04-16 13:34:53 +08:00
|
|
|
_renameRecordMap.AddRename(property, newName);
|
2025-04-15 10:46:03 +08:00
|
|
|
property.Name = newName;
|
2025-04-16 13:12:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
public void Save()
|
|
|
|
{
|
2025-04-16 23:03:41 +08:00
|
|
|
Directory.CreateDirectory(Path.GetDirectoryName(_mappingXmlPath));
|
2025-04-16 13:12:21 +08:00
|
|
|
_renameRecordMap.WriteXmlMappingFile();
|
2025-04-05 19:02:50 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|