I tried to write a simple code trimmer, but it fails with generics. So I 
tried to skip them, but it still throws error in Cecil.
Here's my code:

            var a = AssemblyDefinition.ReadAssembly(@"C:\test.exe");
            var mainModule = a.MainModule;

            bool print = false;

            // 1. get a list of all methods
            List<string> AllMethods = new List<string>();
            foreach (var type in mainModule.Types) {
                if (!type.HasMethods) continue;
                if (type.HasGenericParameters || type.IsGenericInstance) 
continue;
               
                foreach(var method in type.Methods) {
                    AllMethods.Add(method.FullName);
                    if (print) Console.WriteLine("> " + method.FullName);
                }
            }

            Console.WriteLine("TOTAL METHODS WITHOUT TRIM: " + 
AllMethods.Count.ToString());

            // 2. get all referenced methods

            foreach (var type in mainModule.Types) {
                if (print) Console.WriteLine(type.FullName);

                foreach (var method in type.Methods) {
                    if (print) Console.WriteLine("\t" + method.FullName);

                    if (method.HasBody) {
                        foreach (var inst in method.Body.Instructions) {
                            if (inst.Operand != null) {
                                string operand = inst.Operand.ToString();

                                if (operand.Contains("(") && 
!operand.Contains("!")) { // "!" for generic argument
                                    if (print) Console.WriteLine("> " + 
operand);
                                    AllMethods.Remove(operand);
                                }
                            }
                            //Console.WriteLine(inst.Operand.ToString());
                        }
                    }
                }
            }

            Console.WriteLine("TOTAL METHODS AFTER TRIM: " + 
AllMethods.Count.ToString());

            // 3. remove all unreferenced

            foreach (var type in mainModule.Types) {
                
                List<MethodDefinition> MethodsToBeRemoved = new 
List<MethodDefinition>();
                foreach (var method in type.Methods) {
                    if (AllMethods.Contains(method.FullName)) {
                        MethodsToBeRemoved.Add(method);
                    }
                }

                foreach (var method in MethodsToBeRemoved) {

                    if (method.FullName.Contains("ctor")) continue;
                    if (method.FullName.Contains("Main")) continue;

                    type.Methods.Remove(method);
                    if (print) Console.WriteLine("REMOVING " + method.FullName);
                }
            }


            a.Write(@"C:\test_out.exe");
            
            Console.WriteLine("DONE");

-------------

Throws exception:

System.NullReferenceException was unhandled
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=Mono.Cecil
  StackTrace:
       at Mono.Cecil.GenericInstanceMethod.get_FullName()
       at Mono.Cecil.MemberReference.ToString()
       at System.Text.StringBuilder.AppendFormat(IFormatProvider provider, 
String format, Object[] args)
       at System.String.Format(IFormatProvider provider, String format, 
Object[] args)
       at System.String.Format(String format, Object arg0)
       at 
Mono.Cecil.MetadataBuilder.CreateForeignMemberException(MemberReference member)
       at Mono.Cecil.MetadataBuilder.LookupToken(IMetadataTokenProvider 
provider)
       at Mono.Cecil.Cil.CodeWriter.WriteOperand(Instruction instruction)
       at Mono.Cecil.Cil.CodeWriter.WriteInstructions()
       at Mono.Cecil.Cil.CodeWriter.WriteResolvedMethodBody(MethodDefinition 
method)
       at Mono.Cecil.Cil.CodeWriter.WriteMethodBody(MethodDefinition method)
       at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
       at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
       at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
       at Mono.Cecil.MetadataBuilder.AddTypeDefs()
       at Mono.Cecil.MetadataBuilder.BuildTypes()
       at Mono.Cecil.MetadataBuilder.BuildModule()
       at Mono.Cecil.MetadataBuilder.BuildMetadata()
       at Mono.Cecil.ModuleWriter.<BuildMetadata>b__0(MetadataBuilder builder, 
MetadataReader _)
       at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
       at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, 
MetadataBuilder metadata)
       at Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Stream 
stream, WriterParameters parameters)
       at Mono.Cecil.ModuleDefinition.Write(Stream stream, WriterParameters 
parameters)
       at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters 
parameters)
       at Mono.Cecil.AssemblyDefinition.Write(String fileName, WriterParameters 
parameters)
       at Mono.Cecil.AssemblyDefinition.Write(String fileName)
       [...]

-----------

Help anyone?

-- 
--
mono-cecil

Reply via email to