Code Monkey home page Code Monkey logo

Comments (11)

 avatar commented on July 25, 2024

Have you tried peverify on the created assembly? What does it tell you is wrong with it?

method.Parameters is built from the MethodSig so when you update the MethodSig.Params you must call method.Parameters.UpdateParameterTypes(). The MethodSig doesn't know about method or method.Parameters so it can't do it automatically. If however you write a new MethodSig to method.MethodSig, the MethodDef will call this method for you. It's only when you update the existing MethodSig that you must call method.Parameters.UpdateParameterTypes().

You only need to call CreateParamDef() if you want a ParamDef column for that parameter (i.e., if you want to name it). It's not used by the CLR at runtime.

from dnlib.

asdfgasdfsafgsdfa avatar asdfgasdfsafgsdfa commented on July 25, 2024

Thanks for the information!
I really appreciate the information about the parameters.
Peverify is a good idea. I will try it.
Thanks again.

from dnlib.

asdfgasdfsafgsdfa avatar asdfgasdfsafgsdfa commented on July 25, 2024

For now I'm just trying to remove a parameter from a constructor. It takes an int and I want to change it so it takes no parameter.
I know how to deal with the methodbody and the callsites later on! But for now I want to focus on getting peverify to run through without errors.

I'm using this code to change the method sig. I'm not doing anything else atm.

ctor.MethodSig = new MethodSig(ctor.MethodSig.CallingConvention, (uint)ctor.GenericParameters.Count, ctor.MethodSig.RetType);

One thing I immediately noticed is that passing ctor.CallingConvention instead of ctor.MethodSig.CallingConvention will cause another error:
"Method is not marked static but calling convention =0x0000000 is not marked HASTHIS"

The next error after fixing this is the following:

"[MD]: Error: Parameter has sequence number exceeding number of arguments (parameter: 0; seq.num: 1; num.args: 0). [Token:0x0600010E]"

ctor.MethodSig.Params does not contain the hidden this parameter so I don't know how I can adjust the index. I tried to access it trough Parameters, MethodSig.Params and ParamDef (though that doesn't seem to be the right property anyway)

Shouldn't dnlib handle changing the seq.num? If not then how do I change it myself??

from dnlib.

 avatar commented on July 25, 2024

You're not showing any of your code, so I can only guess what the problem is.

Here's a sample that will create .ctors and call them. It will hopefully fix your .ctor problem:

using dnlib.DotNet;
using dnlib.DotNet.Emit;

...

var mod = new ModuleDefUser("ctor-test");
mod.Kind = ModuleKind.Console;
new AssemblyDefUser("ctor-test", new Version(1, 2, 3, 4)).Modules.Add(mod);

CilBody body;
var main = new TypeDefUser("Ctor.Test", "Main", mod.CorLibTypes.Object.TypeDefOrRef);
mod.Types.Add(main);
var entryPoint = new MethodDefUser("Main", MethodSig.CreateStatic(mod.CorLibTypes.Void),
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                MethodAttributes.Public | MethodAttributes.Static);
mod.EntryPoint = entryPoint;
main.Methods.Add(entryPoint);

var systemConsole = mod.CorLibTypes.GetTypeRef("System", "Console");
var writeLine2 = new MemberRefUser(mod, "WriteLine",
                MethodSig.CreateStatic(mod.CorLibTypes.Void, mod.CorLibTypes.String,
                                    mod.CorLibTypes.Object),
                systemConsole);
var objectCtor = new MemberRefUser(mod, ".ctor",
                MethodSig.CreateInstance(mod.CorLibTypes.Void),
                mod.CorLibTypes.Object.TypeDefOrRef);

var ctor0 = new MethodDefUser(".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void),
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                MethodAttributes.Public |
                MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
main.Methods.Add(ctor0);
ctor0.Body = body = new CilBody();
body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction());
body.Instructions.Add(OpCodes.Call.ToInstruction(objectCtor));
body.Instructions.Add(OpCodes.Ldstr.ToInstruction("Default .ctor called"));
body.Instructions.Add(OpCodes.Ldnull.ToInstruction());
body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2));
body.Instructions.Add(OpCodes.Ret.ToInstruction());

var ctor1 = new MethodDefUser(".ctor", MethodSig.CreateInstance(mod.CorLibTypes.Void, mod.CorLibTypes.Int32),
                MethodImplAttributes.IL | MethodImplAttributes.Managed,
                MethodAttributes.Public |
                MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
main.Methods.Add(ctor1);
ctor1.Body = body = new CilBody();
body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction());
body.Instructions.Add(OpCodes.Call.ToInstruction(objectCtor));
body.Instructions.Add(OpCodes.Ldstr.ToInstruction(".ctor(Int32) called with arg {0}"));
body.Instructions.Add(OpCodes.Ldarg_1.ToInstruction());
body.Instructions.Add(OpCodes.Box.ToInstruction(mod.CorLibTypes.Int32));
body.Instructions.Add(OpCodes.Call.ToInstruction(writeLine2));
body.Instructions.Add(OpCodes.Ret.ToInstruction());

entryPoint.Body = body = new CilBody();
body.Instructions.Add(OpCodes.Newobj.ToInstruction(ctor0));
body.Instructions.Add(OpCodes.Pop.ToInstruction());
body.Instructions.Add(OpCodes.Ldc_I4.ToInstruction(12345));
body.Instructions.Add(OpCodes.Newobj.ToInstruction(ctor1));
body.Instructions.Add(OpCodes.Pop.ToInstruction());
body.Instructions.Add(OpCodes.Ret.ToInstruction());

mod.Write(@"c:\ctor-test.exe");

output:

C:>c:\ctor-test.exe
Default .ctor called
.ctor(Int32) called with arg 12345

Peverify:

C:>peverify c:\ctor-test.exe /IL /MD

Microsoft (R) .NET Framework PE Verifier.  Version  4.0.30319.1
Copyright (c) Microsoft Corporation.  All rights reserved.

All Classes and Methods in c:\ctor-test.exe Verified.

from dnlib.

 avatar commented on July 25, 2024

BTW, this is the output of ILSpy

using System;
namespace Ctor.Test
{
    internal class Main
    {
        public static void Main()
        {
            new Main();
            new Main(12345);
        }
        public Main()
        {
            Console.WriteLine("Default .ctor called", null);
        }
        public Main(int num)
        {
            Console.WriteLine(".ctor(Int32) called with arg {0}", num);
        }
    }
}

from dnlib.

asdfgasdfsafgsdfa avatar asdfgasdfsafgsdfa commented on July 25, 2024

Thank you, I will change my code so it uses your example.
Why is it needed to call the object .ctor? Can't a default ctor just contain a ret?

from dnlib.

 avatar commented on July 25, 2024

No, one of the base class' ctors must always be called so it can initialize the object. If you don't, peverify will complain. Try removing the calls and see. ;)

from dnlib.

asdfgasdfsafgsdfa avatar asdfgasdfsafgsdfa commented on July 25, 2024

peverify tells me this (translated):
Form1::.ctor][Offset 0x00000001][ ref ('this' ptr) 'Form1' found] Call to ".ctor" is only valid to initialize a pointer in a ".ctor". Use "newobj" instead.

And thats how reflector displays the .ctor
http://i.imgur.com/3T3IkgI.png

Here is the code that creates the new constructor.

                ctor = new MethodDefUser(".ctor", new MethodSig(CallingConvention.Default | CallingConvention.HasThis, 0, method.Module.CorLibTypes.Void));
                ctor.Attributes = MethodAttributes.SpecialName | MethodAttributes.RTSpecialName | MethodAttributes.Public;
                ctor.ImplAttributes = MethodImplAttributes.IL | MethodImplAttributes.Managed;
                method.DeclaringType.Methods.Add(ctor);
                ctor.Body = new CilBody();
                ctor.Body.Instructions.Add(OpCodes.Ldarg_0.ToInstruction());
                ctor.Body.Instructions.Add(OpCodes.Call.ToInstruction(objectCtor));
                ctor.Body.Instructions.Add(OpCodes.Ret.ToInstruction());

                // Change all callsites to use the new ctor
                ctorCalls = ModuleInstructionQuery.FindInstructions(method.Module, null, i => i.OpCode.Code == Code.Newobj && i.Operand == method);
                foreach (var i in ctorCalls)
                {
                    var index = i.Method.Body.Instructions.IndexOf(i.Instruction);
                    i.Method.Body.Instructions[index].Operand = ctor;
                }

from dnlib.

 avatar commented on July 25, 2024

You must call the base class' .ctor. Perhaps this class derives from some other class than System.Object?

from dnlib.

asdfgasdfsafgsdfa avatar asdfgasdfsafgsdfa commented on July 25, 2024

Same thing happens when I call the .ctor of windows.forms.Form

from dnlib.

 avatar commented on July 25, 2024

Are you sure the base class even has the constructor you're calling?

I suggest you take a look at the original code and see what it does.

from dnlib.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.