From caf7cbe040ae0c174438e4cae2a10e583fa8454b Mon Sep 17 00:00:00 2001 From: walon Date: Wed, 16 Apr 2025 13:12:21 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=B8=AD=E9=97=B4=E6=94=B9?= =?UTF-8?q?=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/Obfuscator.cs | 22 +- Editor/ObfuscatorContext.cs | 2 + Editor/Rename/RenameRecordMap.cs | 426 ++++++++++++++++++++++++++++++- Editor/Rename/SymbolRename.cs | 43 ++-- Editor/TypeSigUtil.cs | 191 ++++++++++++++ 5 files changed, 655 insertions(+), 29 deletions(-) create mode 100644 Editor/TypeSigUtil.cs diff --git a/Editor/Obfuscator.cs b/Editor/Obfuscator.cs index 1efd4f6..084bd62 100644 --- a/Editor/Obfuscator.cs +++ b/Editor/Obfuscator.cs @@ -28,6 +28,7 @@ namespace Obfuz private readonly IRenamePolicy _renamePolicy; private readonly INameMaker _nameMaker; + private readonly SymbolRename _symbolRename; public Obfuscator(Options options) { @@ -36,6 +37,16 @@ namespace Obfuz _renamePolicy = new CombineRenamePolicy(new SystemRenamePolicy(), new UnityRenamePolicy(), new XmlConfigRenamePolicy()); //_nameMaker = new TestNameMaker(); _nameMaker = NameMakerFactory.CreateNameMakerBaseASCIICharSet(); + + var ctx = new ObfuscatorContext + { + assemblyCache = _assemblyCache, + assemblies = _obfuzAssemblies, + renamePolicy = _renamePolicy, + nameMaker = _nameMaker, + outputDir = _options.outputDir, + }; + _symbolRename = new SymbolRename(ctx); } public void DoIt() @@ -77,21 +88,14 @@ namespace Obfuz private void Rename() { - var ctx = new ObfuscatorContext - { - assemblyCache = _assemblyCache, - assemblies = _obfuzAssemblies, - renamePolicy = _renamePolicy, - nameMaker = _nameMaker, - }; - var sr = new SymbolRename(ctx); - sr.Process(); + _symbolRename.Process(); } private void Save() { string outputDir = _options.outputDir; FileUtil.RecreateDir(outputDir); + _symbolRename.Save(); foreach (var ass in _obfuzAssemblies) { string outputFile = $"{outputDir}/{ass.module.Name}"; diff --git a/Editor/ObfuscatorContext.cs b/Editor/ObfuscatorContext.cs index fa8e2d3..72c923c 100644 --- a/Editor/ObfuscatorContext.cs +++ b/Editor/ObfuscatorContext.cs @@ -26,5 +26,7 @@ namespace Obfuz public IRenamePolicy renamePolicy; public INameMaker nameMaker; + + public string outputDir; } } diff --git a/Editor/Rename/RenameRecordMap.cs b/Editor/Rename/RenameRecordMap.cs index 283bc1f..8602d34 100644 --- a/Editor/Rename/RenameRecordMap.cs +++ b/Editor/Rename/RenameRecordMap.cs @@ -1,9 +1,15 @@ using dnlib.DotNet; using Obfuz.Rename; using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; +using System.Xml.Linq; +using UnityEngine; namespace Obfuz { + public class RenameRecordMap { private enum RenameStatus @@ -15,24 +21,399 @@ namespace Obfuz private class RenameRecord { public RenameStatus status; + public string signature; public string oldName; public string newName; } + private class RenameMappingField + { + public RenameStatus status; + public string signature; + public string newName; + } + + private class RenameMappingMethod + { + public RenameStatus status; + public string signature; + public string newName; + + public List parameters = new List(); + } + + private class RenameMappingMethodParam + { + public RenameStatus status; + public int index; + public string newName; + } + + private class RenameMappingProperty + { + public RenameStatus status; + public string signature; + public string newName; + } + + private class RenameMappingEvent + { + public RenameStatus status; + public string signature; + public string newName; + } + + private class RenameMappingType + { + public RenameStatus status; + public string oldFullName; + public string newFullName; + + public Dictionary fields = new Dictionary(); + public Dictionary methods = new Dictionary(); + public Dictionary properties = new Dictionary(); + public Dictionary events = new Dictionary(); + } + + private class RenameMappingAssembly + { + public RenameStatus status; + public string oldAssName; + public string newAssName; + + public Dictionary types = new Dictionary(); + } + + private readonly string _mappingFile; + private readonly Dictionary _assemblies = new Dictionary(); + + private readonly Dictionary _modRenames = new Dictionary(); private readonly Dictionary _typeRenames = new Dictionary(); private readonly Dictionary _methodRenames = new Dictionary(); + private readonly Dictionary _paramRenames = new Dictionary(); private readonly Dictionary _fieldRenames = new Dictionary(); private readonly Dictionary _propertyRenames = new Dictionary(); private readonly Dictionary _eventRenames = new Dictionary(); private readonly Dictionary _virtualMethodGroups = new Dictionary(); + public RenameRecordMap(string mappingFile) + { + _mappingFile = mappingFile; + LoadXmlMappingFile(mappingFile); + } + + + public void Init(List assemblies) + { + foreach (var ObfuzAssemblyInfo in assemblies) + { + ModuleDefMD mod = ObfuzAssemblyInfo.module; + string name = mod.Assembly.Name; + _modRenames.Add(mod, new RenameRecord + { + status = RenameStatus.NotRenamed, + signature = name, + oldName = name, + newName = null, + }); + _modRenames.Add(mod, new RenameRecord + { + status = RenameStatus.NotRenamed, + signature = mod.Assembly.Name, + oldName = mod.Assembly.Name, + newName = null, + }); + } + } + + private void LoadXmlMappingFile(string mappingFile) + { + if (!File.Exists(mappingFile)) + { + return; + } + var doc = new XmlDocument(); + doc.Load(mappingFile); + var root = doc.DocumentElement; + foreach (XmlNode node in root.ChildNodes) + { + if (node is not XmlElement element) + { + continue; + } + LoadAssemblyMapping(element); + } + } + + + + private void LoadAssemblyMapping(XmlElement ele) + { + if (ele.Name != "assembly") + { + throw new System.Exception($"Invalid node name: {ele.Name}. Expected 'assembly'."); + } + + var assemblyName = ele.Attributes["name"].Value; + var newAssemblyName = ele.Attributes["newName"].Value; + var rma = new RenameMappingAssembly + { + oldAssName = assemblyName, + newAssName = newAssemblyName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + foreach (XmlNode node in ele.ChildNodes) + { + if (node is not XmlElement element) + { + continue; + } + if (element.Name != "type") + { + throw new System.Exception($"Invalid node name: {element.Name}. Expected 'type'."); + } + LoadTypeMapping(element, rma); + } + _assemblies.Add(assemblyName, rma); + } + + private void LoadTypeMapping(XmlElement ele, RenameMappingAssembly ass) + { + var typeName = ele.Attributes["fullName"].Value; + var newTypeName = ele.Attributes["newFullName"].Value; + var rmt = new RenameMappingType + { + oldFullName = typeName, + newFullName = newTypeName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + foreach (XmlNode node in ele.ChildNodes) + { + if (node is not XmlElement c) + { + continue; + } + switch (node.Name) + { + case "field": LoadFieldMapping(c, rmt); break; + case "event": LoadEventMapping(c, rmt); break; + case "property": LoadPropertyMapping(c, rmt); break; + case "method": LoadMethodMapping(c, rmt); break; + default: throw new System.Exception($"Invalid node name:{node.Name}"); + } + } + ass.types.Add(typeName, rmt); + } + + private void LoadMethodMapping(XmlElement ele, RenameMappingType type) + { + string signature = ele.Attributes["signature"].Value; + string newName = ele.Attributes["newName"].Value; + var rmm = new RenameMappingMethod + { + signature = signature, + newName = newName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + foreach (XmlNode node in ele.ChildNodes) + { + if (node is not XmlElement c) + { + continue; + } + switch (node.Name) + { + case "param": LoadMethodParamMapping(c, rmm); break; + default: throw new System.Exception($"unknown node name:{node.Name}, expect 'param'"); + } + } + type.methods.Add(signature, rmm); + } + + private void LoadMethodParamMapping(XmlElement ele, RenameMappingMethod method) + { + string index = ele.Attributes["index"].Value; + string newName = ele.Attributes["newName"].Value; + var rmp = new RenameMappingMethodParam + { + index = int.Parse(index), + newName = newName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + method.parameters.Add(rmp); + } + + private void LoadFieldMapping(XmlElement ele, RenameMappingType type) + { + string signature = ele.Attributes["signature"].Value; + string newName = ele.Attributes["newName"].Value; + var rmf = new RenameMappingField + { + signature = signature, + newName = newName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + type.fields.Add(signature, rmf); + } + + private void LoadPropertyMapping(XmlElement ele, RenameMappingType type) + { + string signature = ele.Attributes["signature"].Value; + string newName = ele.Attributes["newName"].Value; + var rmp = new RenameMappingProperty + { + signature = signature, + newName = newName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + type.properties.Add(signature, rmp); + } + + private void LoadEventMapping(XmlElement ele, RenameMappingType type) + { + string signature = ele.Attributes["signature"].Value; + string newName = ele.Attributes["newName"].Value; + var rme = new RenameMappingEvent + { + signature = signature, + newName = newName, + status = System.Enum.Parse(ele.Attributes["status"].Value), + }; + type.events.Add(signature, rme); + } + + public void WriteXmlMappingFile() + { + var doc = new XmlDocument(); + var root = doc.CreateElement("mapping"); + doc.AppendChild(root); + foreach (var kvp in _modRenames) + { + ModuleDefMD mod = kvp.Key; + RenameRecord record = kvp.Value; + var assemblyNode = doc.CreateElement("assembly"); + assemblyNode.SetAttribute("name", mod.Assembly.Name); + assemblyNode.SetAttribute("newName", record.status == RenameStatus.Renamed ? record.newName : ""); + assemblyNode.SetAttribute("status", record.status.ToString()); + foreach (TypeDef type in mod.GetTypes()) + { + WriteTypeMapping(assemblyNode, type); + } + root.AppendChild(assemblyNode); + } + doc.Save(_mappingFile); + Debug.Log($"Mapping file saved to {Path.GetFullPath(_mappingFile)}"); + } + + private void WriteTypeMapping(XmlElement assNode, TypeDef type) + { + _typeRenames.TryGetValue(type, out var record); + var typeNode = assNode.OwnerDocument.CreateElement("type"); + typeNode.SetAttribute("fullName", record?.signature ?? type.FullName); + typeNode.SetAttribute("newFullName", record != null && record.status == RenameStatus.Renamed ? record.newName : ""); + typeNode.SetAttribute("status", record != null ? record.status.ToString() : RenameStatus.NotRenamed.ToString()); + + foreach (FieldDef field in type.Fields) + { + WriteFieldMapping(typeNode, field); + } + foreach (PropertyDef property in type.Properties) + { + WritePropertyMapping(typeNode, property); + } + foreach (EventDef eventDef in type.Events) + { + WriteEventMapping(typeNode, eventDef); + } + foreach (MethodDef method in type.Methods) + { + WriteMethodMapping(typeNode, method); + } + if ((record != null && record.status == RenameStatus.Renamed) || typeNode.ChildNodes.Count > 0) + { + assNode.AppendChild(typeNode); + } + } + + private void WriteFieldMapping(XmlElement typeEle, FieldDef field) + { + if (!_fieldRenames.TryGetValue(field, out var record) || record.status == RenameStatus.NotRenamed) + { + return; + } + var fieldNode = typeEle.OwnerDocument.CreateElement("field"); + fieldNode.SetAttribute("signature", record?.signature); + fieldNode.SetAttribute("newName", record.newName); + //fieldNode.SetAttribute("status", record.status.ToString()); + typeEle.AppendChild(fieldNode); + } + + private void WritePropertyMapping(XmlElement typeEle, PropertyDef property) + { + if (!_propertyRenames.TryGetValue(property, out var record) || record.status == RenameStatus.NotRenamed) + { + return; + } + var propertyNode = typeEle.OwnerDocument.CreateElement("property"); + propertyNode.SetAttribute("signature", record.signature); + propertyNode.SetAttribute("newName", record.newName); + //propertyNode.SetAttribute("status", record.status.ToString()); + typeEle.AppendChild(propertyNode); + } + + private void WriteEventMapping(XmlElement typeEle, EventDef eventDef) + { + if (!_eventRenames.TryGetValue(eventDef, out var record) || record.status == RenameStatus.NotRenamed) + { + return; + } + var eventNode = typeEle.OwnerDocument.CreateElement("event"); + eventNode.SetAttribute("signature", record.signature); + eventNode.SetAttribute("newName", record.newName); + typeEle.AppendChild(eventNode); + } + + private void WriteMethodMapping(XmlElement typeEle, MethodDef method) + { + if (!_methodRenames.TryGetValue(method, out var record) || record.status == RenameStatus.NotRenamed) + { + return; + } + var methodNode = typeEle.OwnerDocument.CreateElement("method"); + methodNode.SetAttribute("signature", record.signature); + methodNode.SetAttribute("newName", record.newName); + //methodNode.SetAttribute("status", record != null ? record.status.ToString() : RenameStatus.NotRenamed.ToString()); + foreach (Parameter param in method.Parameters) + { + if (param.ParamDef != null) + { + WriteMethodParamMapping(methodNode, param.ParamDef); + } + } + typeEle.AppendChild(methodNode); + } + + private void WriteMethodParamMapping(XmlElement methodEle, ParamDef param) + { + if (!_paramRenames.TryGetValue(param, out var record) || record.status == RenameStatus.NotRenamed) + { + return; + } + var paramNode = methodEle.OwnerDocument.CreateElement("param"); + paramNode.SetAttribute("index", param.Sequence.ToString()); + paramNode.SetAttribute("newName", record.newName); + //paramNode.SetAttribute("status", record.status.ToString()); + methodEle.AppendChild(paramNode); + } + public void AddRenameRecord(ModuleDefMD mod, string oldName, string newName) { _modRenames.Add(mod, new RenameRecord { status = RenameStatus.Renamed, + signature = oldName, oldName = oldName, newName = newName }); @@ -43,26 +424,40 @@ namespace Obfuz _typeRenames.Add(type, new RenameRecord { status = RenameStatus.Renamed, + signature = oldName, oldName = oldName, newName = newName }); } - public void AddRenameRecord(MethodDef method, string oldName, string newName) + public void AddRenameRecord(MethodDef method, string signature, string oldName, string newName) { _methodRenames.Add(method, new RenameRecord { status = RenameStatus.Renamed, + signature = signature, oldName = oldName, newName = newName }); } - public void AddRenameRecord(VirtualMethodGroup methodGroup, string oldName, string newName) + public void AddRenameRecord(ParamDef paramDef, string oldName, string newName) + { + _paramRenames.Add(paramDef, new RenameRecord + { + status = RenameStatus.Renamed, + signature = oldName, + oldName = oldName, + newName = newName + }); + } + + public void AddRenameRecord(VirtualMethodGroup methodGroup, string signature, string oldName, string newName) { _virtualMethodGroups.Add(methodGroup, new RenameRecord { status = RenameStatus.Renamed, + signature = signature, oldName = oldName, newName = newName }); @@ -81,31 +476,34 @@ namespace Obfuz return false; } - public void AddRenameRecord(FieldDef field, string oldName, string newName) + public void AddRenameRecord(FieldDef field, string signature, string oldName, string newName) { _fieldRenames.Add(field, new RenameRecord { status = RenameStatus.Renamed, + signature = signature, oldName = oldName, newName = newName }); } - public void AddRenameRecord(PropertyDef property, string oldName, string newName) + public void AddRenameRecord(PropertyDef property, string signature, string oldName, string newName) { _propertyRenames.Add(property, new RenameRecord { status = RenameStatus.Renamed, + signature = signature, oldName = oldName, newName = newName }); } - public void AddRenameRecord(EventDef eventDef, string oldName, string newName) + public void AddRenameRecord(EventDef eventDef, string signature, string oldName, string newName) { _eventRenames.Add(eventDef, new RenameRecord { status = RenameStatus.Renamed, + signature = signature, oldName = oldName, newName = newName }); @@ -116,6 +514,7 @@ namespace Obfuz _modRenames.Add(mod, new RenameRecord { status = RenameStatus.NotRenamed, + signature = mod.Assembly.Name, oldName = mod.Assembly.Name, newName = null, }); @@ -126,6 +525,7 @@ namespace Obfuz _typeRenames.Add(typeDef, new RenameRecord { status = RenameStatus.NotRenamed, + signature = typeDef.FullName, oldName = typeDef.FullName, newName = null, }); @@ -136,16 +536,29 @@ namespace Obfuz _methodRenames.Add(methodDef, new RenameRecord { status = RenameStatus.NotRenamed, + signature = methodDef.FullName, oldName = methodDef.Name, newName = null, }); } + public void AddUnRenameRecord(ParamDef paramDef) + { + _paramRenames.Add(paramDef, new RenameRecord + { + status = RenameStatus.NotRenamed, + signature = paramDef.Name, + oldName = paramDef.Name, + newName = null, + }); + } + public void AddUnRenameRecord(VirtualMethodGroup methodGroup) { _virtualMethodGroups.Add(methodGroup, new RenameRecord { status = RenameStatus.NotRenamed, + signature = methodGroup.methods[0].FullName, oldName = methodGroup.methods[0].Name, newName = null, }); @@ -156,6 +569,7 @@ namespace Obfuz _fieldRenames.Add(fieldDef, new RenameRecord { status = RenameStatus.NotRenamed, + signature = fieldDef.FullName, oldName = fieldDef.Name, newName = null, }); @@ -166,6 +580,7 @@ namespace Obfuz _propertyRenames.Add(propertyDef, new RenameRecord { status = RenameStatus.NotRenamed, + signature = propertyDef.FullName, oldName = propertyDef.Name, newName = null, }); @@ -176,6 +591,7 @@ namespace Obfuz _eventRenames.Add(eventDef, new RenameRecord { status = RenameStatus.NotRenamed, + signature = eventDef.FullName, oldName = eventDef.Name, newName = null, }); diff --git a/Editor/Rename/SymbolRename.cs b/Editor/Rename/SymbolRename.cs index ae8440c..a6d9b65 100644 --- a/Editor/Rename/SymbolRename.cs +++ b/Editor/Rename/SymbolRename.cs @@ -4,6 +4,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Data.OleDb; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using UnityEditor.SceneManagement; @@ -22,7 +23,7 @@ namespace Obfuz private readonly IRenamePolicy _renamePolicy; private readonly INameMaker _nameMaker; private readonly Dictionary> _customAttributeArgumentsWithTypeByMods = new Dictionary>(); - private readonly RenameRecordMap _renameRecordMap = new RenameRecordMap(); + private readonly RenameRecordMap _renameRecordMap; private readonly VirtualMethodGroupCalculator _virtualMethodGroupCalculator = new VirtualMethodGroupCalculator(); class CustomAttributeInfo @@ -44,6 +45,8 @@ namespace Obfuz _obfuscatedModules.Add(mod.module); } BuildCustomAttributeArguments(); + + _renameRecordMap = new RenameRecordMap(Path.Combine(ctx.outputDir, "mapping.xml")); } private void CollectCArgumentWithTypeOf(IHasCustomAttribute meta, List customAttributes) @@ -446,7 +449,7 @@ namespace Obfuz groupNeedRenames.Add(group, needRename); if (needRename) { - _renameRecordMap.AddRenameRecord(group, method.Name, _nameMaker.GetNewName(method, method.Name)); + _renameRecordMap.AddRenameRecord(group, method.FullName, method.Name, _nameMaker.GetNewName(method, method.Name)); } else { @@ -574,7 +577,7 @@ namespace Obfuz string newName = _nameMaker.GetNewName(mod, oldName); _renameRecordMap.AddRenameRecord(mod, oldName, newName); mod.Name = $"{newName}.dll"; - Debug.Log($"rename module. oldName:{oldName} newName:{newName}"); + //Debug.Log($"rename module. oldName:{oldName} newName:{newName}"); foreach (ObfuzAssemblyInfo ass in GetReferenceMeAssemblies(mod)) { foreach (AssemblyRef assRef in ass.module.GetAssemblyRefs()) @@ -582,7 +585,7 @@ namespace Obfuz if (assRef.Name == oldName) { assRef.Name = newName; - Debug.Log($"rename assembly:{ass.name} ref oldName:{oldName} newName:{newName}"); + // Debug.Log($"rename assembly:{ass.name} ref oldName:{oldName} newName:{newName}"); } } } @@ -618,13 +621,13 @@ namespace Obfuz typeRef.Namespace = newNamespace; } typeRef.Name = newName; - Debug.Log($"rename assembly:{typeRef.Module.Name} reference {oldFullName} => {typeRef.FullName}"); + //Debug.Log($"rename assembly:{typeRef.Module.Name} reference {oldFullName} => {typeRef.FullName}"); } } type.Name = newName; string newFullName = type.FullName; _renameRecordMap.AddRenameRecord(type, oldFullName, newFullName); - Debug.Log($"rename typedef. assembly:{type.Module.Name} oldName:{oldFullName} => newName:{newFullName}"); + //Debug.Log($"rename typedef. assembly:{type.Module.Name} oldName:{oldFullName} => newName:{newFullName}"); } private void Rename(FieldDef field, RefFieldMetas fieldMetas) @@ -636,7 +639,7 @@ namespace Obfuz foreach (var memberRef in fieldMetas.fieldRefs) { memberRef.Name = newName; - Debug.Log($"rename assembly:{memberRef.Module.Name} reference {field.FullName} => {memberRef.FullName}"); + //Debug.Log($"rename assembly:{memberRef.Module.Name} reference {field.FullName} => {memberRef.FullName}"); } foreach (var ca in fieldMetas.customAttributes) { @@ -649,9 +652,9 @@ namespace Obfuz } } } - Debug.Log($"rename field. {field} => {newName}"); + //Debug.Log($"rename field. {field} => {newName}"); + _renameRecordMap.AddRenameRecord(field, field.FullName, oldName, newName); field.Name = newName; - _renameRecordMap.AddRenameRecord(field, oldName, newName); } @@ -674,12 +677,11 @@ namespace Obfuz { string oldMethodFullName = memberRef.ToString(); memberRef.Name = newName; - Debug.Log($"rename assembly:{memberRef.Module.Name} method:{oldMethodFullName} => {memberRef}"); + //Debug.Log($"rename assembly:{memberRef.Module.Name} method:{oldMethodFullName} => {memberRef}"); } } + _renameRecordMap.AddRenameRecord(method, method.FullName, oldName, newName); method.Name = newName; - _renameRecordMap.AddRenameRecord(method, oldName, newName); - } private void RenameMethodBody(MethodDef method) @@ -705,7 +707,13 @@ namespace Obfuz { if (_renamePolicy.NeedRename(param)) { - param.Name = _nameMaker.GetNewName(param, param.Name); + string newName = _nameMaker.GetNewName(param, param.Name); + _renameRecordMap.AddRenameRecord(param, param.Name, newName); + param.Name = newName; + } + else + { + _renameRecordMap.AddUnRenameRecord(param); } } @@ -713,8 +721,8 @@ namespace Obfuz { string oldName = eventDef.Name; string newName = _nameMaker.GetNewName(eventDef, eventDef.Name); + _renameRecordMap.AddRenameRecord(eventDef, eventDef.FullName, oldName, newName); eventDef.Name = newName; - _renameRecordMap.AddRenameRecord(eventDef, oldName, newName); } private void Rename(PropertyDef property, RefPropertyMetas refPropertyMetas) @@ -735,8 +743,13 @@ namespace Obfuz } } } + _renameRecordMap.AddRenameRecord(property, property.FullName, oldName, newName); property.Name = newName; - _renameRecordMap.AddRenameRecord(property, oldName, newName); + } + + public void Save() + { + _renameRecordMap.WriteXmlMappingFile(); } } } diff --git a/Editor/TypeSigUtil.cs b/Editor/TypeSigUtil.cs new file mode 100644 index 0000000..ec65b36 --- /dev/null +++ b/Editor/TypeSigUtil.cs @@ -0,0 +1,191 @@ +using dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Obfuz +{ + public static class TypeSigUtil + { + public static string ComputeTypeDefSignature(TypeDef type) + { + return type.FullName; + } + + public static string ComputeMethodDefSignature(MethodDef method) + { + var result = new StringBuilder(); + ComputeTypeSigName(method.MethodSig.RetType, result); + result.Append(" "); + result.Append(method.DeclaringType.FullName); + result.Append("::"); + result.Append(method.Name); + result.Append("("); + for (int i = 0; i < method.Parameters.Count; i++) + { + if (i > 0) + { + result.Append(", "); + } + ComputeTypeSigName(method.Parameters[i].Type, result); + } + result.Append(")"); + return result.ToString(); + } + + public static string ComputeFieldDefSignature(FieldDef field) + { + var result = new StringBuilder(); + ComputeTypeSigName(field.FieldSig.Type, result); + result.Append(" "); + result.Append(field.Name); + return result.ToString(); + } + + public static string ComputePropertyDefSignature(PropertyDef property) + { + var result = new StringBuilder(); + ComputeTypeSigName(property.PropertySig.RetType, result); + result.Append(" "); + result.Append(property.Name); + return result.ToString(); + } + + public static string ComputeEventDefSignature(EventDef eventDef) + { + var result = new StringBuilder(); + ComputeTypeSigName(eventDef.EventType.ToTypeSig(), result); + result.Append(" "); + result.Append(eventDef.Name); + return result.ToString(); + } + + public static string ComputeMethodSpecSignature(TypeSig type) + { + var sb = new StringBuilder(); + ComputeTypeSigName(type, sb); + return sb.ToString(); + } + + public static void ComputeTypeSigName(TypeSig type, StringBuilder result) + { + type = type.RemovePinnedAndModifiers(); + switch (type.ElementType) + { + case ElementType.Void: result.Append("void"); break; + case ElementType.Boolean: result.Append("bool"); break; + case ElementType.Char: result.Append("char"); break; + case ElementType.I1: result.Append("sbyte"); break; + case ElementType.U1: result.Append("byte"); break; + case ElementType.I2: result.Append("short"); break; + case ElementType.U2: result.Append("ushort"); break; + case ElementType.I4: result.Append("int"); break; + case ElementType.U4: result.Append("uint"); break; + case ElementType.I8: result.Append("long"); break; + case ElementType.U8: result.Append("ulong"); break; + case ElementType.R4: result.Append("float"); break; + case ElementType.R8: result.Append("double"); break; + case ElementType.String: result.Append("string"); break; + case ElementType.Ptr: + ComputeTypeSigName(((PtrSig)type).Next, result); + result.Append("*"); + break; + case ElementType.ByRef: + ComputeTypeSigName(((ByRefSig)type).Next, result); + result.Append("&"); + break; + case ElementType.ValueType: + case ElementType.Class: + { + var valueOrClassType = type.ToClassOrValueTypeSig(); + var typeDef = valueOrClassType.ToTypeDefOrRef().ResolveTypeDefThrow(); + result.Append($"[{typeDef.Module.Assembly.Name}]"); + result.Append(typeDef.FullName); + break; + } + case ElementType.GenericInst: + { + var genInst = (GenericInstSig)type; + ComputeTypeSigName(genInst.GenericType, result); + result.Append("<"); + for (int i = 0; i < genInst.GenericArguments.Count; i++) + { + if (i > 0) + { + result.Append(","); + } + ComputeTypeSigName(genInst.GenericArguments[i], result); + } + result.Append(">"); + break; + } + case ElementType.SZArray: + ComputeTypeSigName(((SZArraySig)type).Next, result); + result.Append("[]"); + break; + case ElementType.Array: + { + var arraySig = (ArraySig)type; + ComputeTypeSigName(arraySig.Next, result); + result.Append("["); + for (int i = 0; i < arraySig.Rank; i++) + { + if (i > 0) + { + result.Append(","); + } + //result.Append(arraySig.Sizes[i]); + } + result.Append("]"); + break; + } + case ElementType.FnPtr: + { + var fnPtr = (FnPtrSig)type; + result.Append("("); + MethodSig ms = fnPtr.MethodSig; + ComputeTypeSigName(ms.RetType, result); + result.Append("("); + for (int i = 0; i < ms.Params.Count; i++) + { + if (i > 0) + { + result.Append(","); + } + ComputeTypeSigName(ms.Params[i], result); + } + result.Append(")*"); + break; + } + case ElementType.TypedByRef: + result.Append("typedref"); + break; + case ElementType.I: + result.Append("nint"); + break; + case ElementType.U: + result.Append("nuint"); + break; + case ElementType.Object: + result.Append("object"); + break; + case ElementType.Var: + { + var var = (GenericVar)type; + result.Append($"!{var.Number}"); + break; + } + case ElementType.MVar: + { + var mvar = (GenericMVar)type; + result.Append($"!!{mvar.Number}"); + break; + } + default: throw new NotSupportedException($"[ComputeTypeSigName] not support :{type}"); + + } + } + } +}