GetILAsByteArray to Method

Ты че баклан, дефективный?
Пользователь
Статус
Оффлайн
Регистрация
18 Мар 2019
Сообщения
756
Реакции[?]
64
Поинты[?]
2K
Посмотреть вложение 140787
Тут скорее твоя невнимательность. Я не думаю, что визулка не подсказала бы тебе о рекурсивном вызове
System.Reflection.TargetInvocationException: "Адресат вызова создал исключение."
BadImageFormatException: Индекс не найден. (Исключение из HRESULT: 0x80131124)

при invoke теперь
 
Ты че баклан, дефективный?
Пользователь
Статус
Оффлайн
Регистрация
18 Мар 2019
Сообщения
756
Реакции[?]
64
Поинты[?]
2K
ldloc.s <d0t.net> stloc.s <Reversed>
Пользователь
Статус
Оффлайн
Регистрация
21 Окт 2018
Сообщения
214
Реакции[?]
337
Поинты[?]
1K
К сожалению, телепатических способностей у меня нет, поэтому не могу сказать, что у тебя там не выполняется. Вот код с илгенератором, который генерирует метод типа void (с лок. переменной типа Int32)
C#:
class Program
    {
        static void Main(string[] args)
        {
            var gen = BuildDynType();
            gen.InvokeMember("DoAdd", // название метода, который создал
                BindingFlags.InvokeMethod, // биндинг на вызов
                null, // биндер здесь не нужен
                gen, // тип, в котором метод
                new object[]{5, 6}); // передача аргументов в метод (должны совпадать типы 1к1)
        }

        public static Type BuildDynType() {
     
            Type addType = null;

            AppDomain currentDom = Thread.GetDomain();

            AssemblyName myAsmName = new AssemblyName();
            myAsmName.Name = "MyDynamicAssembly";

            AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
                myAsmName,
                AssemblyBuilderAccess.RunAndSave);

            // The dynamic assembly space has been created.  Next, create a module
            // within it.  The type Point will be reflected into this module.

            ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");

            TypeBuilder myTypeBldr =  myModuleBldr.DefineType("Adder");

            MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("DoAdd",
                MethodAttributes.Public |
                MethodAttributes.Static,
                typeof(void),
                new Type[]
                {typeof(int), typeof(int)});
         
            var il = myMthdBldr.GetILGenerator();
         
            il.DeclareLocal(typeof(int));
         
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_1);
            il.Emit(OpCodes.Ret);

            addType = myTypeBldr.CreateType();

            return addType;
        }
    }
Результат:
1617204634672.png
 
Ты че баклан, дефективный?
Пользователь
Статус
Оффлайн
Регистрация
18 Мар 2019
Сообщения
756
Реакции[?]
64
Поинты[?]
2K
К сожалению, телепатических способностей у меня нет, поэтому не могу сказать, что у тебя там не выполняется. Вот код с илгенератором, который генерирует метод типа void (с лок. переменной типа Int32)
C#:
class Program
    {
        static void Main(string[] args)
        {
            var gen = BuildDynType();
            gen.InvokeMember("DoAdd", // название метода, который создал
                BindingFlags.InvokeMethod, // биндинг на вызов
                null, // биндер здесь не нужен
                gen, // тип, в котором метод
                new object[]{5, 6}); // передача аргументов в метод (должны совпадать типы 1к1)
        }

        public static Type BuildDynType() {
   
            Type addType = null;

            AppDomain currentDom = Thread.GetDomain();

            AssemblyName myAsmName = new AssemblyName();
            myAsmName.Name = "MyDynamicAssembly";

            AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
                myAsmName,
                AssemblyBuilderAccess.RunAndSave);

            // The dynamic assembly space has been created.  Next, create a module
            // within it.  The type Point will be reflected into this module.

            ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");

            TypeBuilder myTypeBldr =  myModuleBldr.DefineType("Adder");

            MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("DoAdd",
                MethodAttributes.Public |
                MethodAttributes.Static,
                typeof(void),
                new Type[]
                {typeof(int), typeof(int)});
       
            var il = myMthdBldr.GetILGenerator();
       
            il.DeclareLocal(typeof(int));
       
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            il.Emit(OpCodes.Add);
            il.Emit(OpCodes.Stloc_1);
            il.Emit(OpCodes.Ret);

            addType = myTypeBldr.CreateType();

            return addType;
        }
    }
Результат:
Посмотреть вложение 140926
вот тут у меня и была в самом начале загвостка - передать все опкоды с метода в Emit.Метод не 1 просто - есть ли какой конвертер или парсер?
 
ldloc.s <d0t.net> stloc.s <Reversed>
Пользователь
Статус
Оффлайн
Регистрация
21 Окт 2018
Сообщения
214
Реакции[?]
337
Поинты[?]
1K
вот тут у меня и была в самом начале загвостка - передать все опкоды с метода в Emit.Метод не 1 просто - есть ли какой конвертер или парсер?
Не понял проблему. Какой конвертер? Пишешь метод -> открываешь в dnSpy метод -> смотришь MSIL -> эмиттишь их
 
Ты че баклан, дефективный?
Пользователь
Статус
Оффлайн
Регистрация
18 Мар 2019
Сообщения
756
Реакции[?]
64
Поинты[?]
2K
Не понял проблему. Какой конвертер? Пишешь метод -> открываешь в dnSpy метод -> смотришь MSIL -> эмиттишь их
ну это каждый метод - а если он будит меняться?При том, что методов больше 50
 
ldloc.s <d0t.net> stloc.s <Reversed>
Пользователь
Статус
Оффлайн
Регистрация
21 Окт 2018
Сообщения
214
Реакции[?]
337
Поинты[?]
1K
Так, пока было время, накидал тебе то, что нужно. Проблема скорее всего у тебя была в том, что ты забыл про директиву .maxstack (а если ты про нее забыл, то она равна нулю), поэтому джиттить метод нельзя было, т.к. при вычислениях произошла ошибка. (не влезли бы в стек переменные). Чтобы это исправить, нужно вместо
.CreateMethodBody(...) использовать .SetMethodBody(...), где ты явно будешь указывать величину вместимости. Ну и посмотри, как работает метод. Рабочий код ниже:
C#:
class Program
    {
        static void Main(string[] args)
        {
            var gen = BuildDynType();
            var genInst = Activator.CreateInstance(gen, new object[0]);
           
            gen.InvokeMember("DoAdd", // название метода, который создал
                BindingFlags.InvokeMethod, // биндинг на вызов
                null, // биндер здесь не нужен
                genInst, // тип, в котором метод
                new object[]{5, 6}); // передача аргументов в метод (должны совпадать типы 1к1)
        }

        public static Type BuildDynType() {
       
            Type addType = null;

            AppDomain currentDom = Thread.GetDomain();

            AssemblyName myAsmName = new AssemblyName();
            myAsmName.Name = "MyDynamicAssembly";

            AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
                myAsmName,
                AssemblyBuilderAccess.RunAndSave);

            // The dynamic assembly space has been created.  Next, create a module
            // within it.  The type Point will be reflected into this module.

            ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");

            TypeBuilder myTypeBldr =  myModuleBldr.DefineType("Adder");

            MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("DoAdd",
                MethodAttributes.Public |
                MethodAttributes.Static,
                typeof(void),
                new Type[]
                    {typeof(int), typeof(int)});
            // Build the array of Bytes holding the MSIL instructions.
            var ILGen = myMthdBldr.GetILGenerator();
            byte[] ILcodes = new byte[] {
                0x02,   /* 02h is the opcode for ldarg.0 */
                0x03,   /* 03h is the opcode for ldarg.1 */
                0x58,   /* 58h is the opcode for add     */
                0x0A,   /* 0Ah is the opcode for stloc.0 */
                0x2A    /* 2Ah is the opcode for ret     */
            };
           
            var localSig = SignatureHelper.GetLocalVarSigHelper(myModuleBldr);
            localSig.AddArgument(typeof(int));
            var localSigArray = localSig.GetSignature();
            ILGen.DeclareLocal(typeof(Int32));
            myMthdBldr.SetMethodBody(ILcodes, 8, localSigArray, null, null);
            addType = myTypeBldr.CreateType();

            return addType;
        }
    }
 
Ты че баклан, дефективный?
Пользователь
Статус
Оффлайн
Регистрация
18 Мар 2019
Сообщения
756
Реакции[?]
64
Поинты[?]
2K
Так, пока было время, накидал тебе то, что нужно. Проблема скорее всего у тебя была в том, что ты забыл про директиву .maxstack (а если ты про нее забыл, то она равна нулю), поэтому джиттить метод нельзя было, т.к. при вычислениях произошла ошибка. (не влезли бы в стек переменные). Чтобы это исправить, нужно вместо
.CreateMethodBody(...) использовать .SetMethodBody(...), где ты явно будешь указывать величину вместимости. Ну и посмотри, как работает метод. Рабочий код ниже:
C#:
class Program
    {
        static void Main(string[] args)
        {
            var gen = BuildDynType();
            var genInst = Activator.CreateInstance(gen, new object[0]);
          
            gen.InvokeMember("DoAdd", // название метода, который создал
                BindingFlags.InvokeMethod, // биндинг на вызов
                null, // биндер здесь не нужен
                genInst, // тип, в котором метод
                new object[]{5, 6}); // передача аргументов в метод (должны совпадать типы 1к1)
        }

        public static Type BuildDynType() {
      
            Type addType = null;

            AppDomain currentDom = Thread.GetDomain();

            AssemblyName myAsmName = new AssemblyName();
            myAsmName.Name = "MyDynamicAssembly";

            AssemblyBuilder myAsmBldr = currentDom.DefineDynamicAssembly(
                myAsmName,
                AssemblyBuilderAccess.RunAndSave);

            // The dynamic assembly space has been created.  Next, create a module
            // within it.  The type Point will be reflected into this module.

            ModuleBuilder myModuleBldr = myAsmBldr.DefineDynamicModule("MyModule");

            TypeBuilder myTypeBldr =  myModuleBldr.DefineType("Adder");

            MethodBuilder myMthdBldr = myTypeBldr.DefineMethod("DoAdd",
                MethodAttributes.Public |
                MethodAttributes.Static,
                typeof(void),
                new Type[]
                    {typeof(int), typeof(int)});
            // Build the array of Bytes holding the MSIL instructions.
            var ILGen = myMthdBldr.GetILGenerator();
            byte[] ILcodes = new byte[] {
                0x02,   /* 02h is the opcode for ldarg.0 */
                0x03,   /* 03h is the opcode for ldarg.1 */
                0x58,   /* 58h is the opcode for add     */
                0x0A,   /* 0Ah is the opcode for stloc.0 */
                0x2A    /* 2Ah is the opcode for ret     */
            };
          
            var localSig = SignatureHelper.GetLocalVarSigHelper(myModuleBldr);
            localSig.AddArgument(typeof(int));
            var localSigArray = localSig.GetSignature();
            ILGen.DeclareLocal(typeof(Int32));
            myMthdBldr.SetMethodBody(ILcodes, 8, localSigArray, null, null);
            addType = myTypeBldr.CreateType();

            return addType;
        }
    }
вот тут SetMethodBody уже с 4 frame - а мне туда переходить никак не получиться(
 
ldloc.s <d0t.net> stloc.s <Reversed>
Пользователь
Статус
Оффлайн
Регистрация
21 Окт 2018
Сообщения
214
Реакции[?]
337
Поинты[?]
1K
В net 3.5 нету этой функции
Поэтому и добавили в след. версиях .SetMethodBody(..);
По-другому так нельзя сделать. Делай эмит через цикл по каждой инструкции
Или делай сканер памяти по телу метода и патчи 3-ий байт хедера, он отвечает на .maxstack, но это гемор, и вряд ли ты это сделаешь.
 
Сверху Снизу