Инъекции CLR: замена методов во время выполнения - Пример кода

ОГЛАВЛЕНИЕ

Пример кода

В нашем образце кода коде мы будем использовать несколько вещей - мы заменим статический метод одного из классов статическим методом другого класса. Мы сделаем то же самое с экземпляром метода, а также заменим статический метод DynamicMethod. Некоторые из наших тестовых методов будут подключены к режиму Release. Нам понадобилось добавить атрибуты MethodImpl к некоторым методам чтобы предотвратить подключение.

Если вы пройдетесь по коду, то заметите, что Visual Studio просто обманут. После замены метода Visual Studio вступит в новый метод вместо старого метода.

Далее мы приведем результаты наших тестов:

Enabling JIT debugging.
        JIT :   0x10720a8 Program.StaticTests
        JIT :   0x107217b Program.TestStaticReplaceJited
Replacing StaticClassA.A() with StaticClassB.A()
        JIT :   0x71ac205c MethodUtil.ReplaceMethod
        JIT :   0x71ac2270 MethodUtil.MethodSignaturesEqual
        JIT :   0x71ac231c MethodUtil.GetMethodReturnType
        JIT :   0x71ac20e4 MethodUtil.GetMethodAddress
        JIT :   0x10723e6 StaticClassB.A
        JIT :   0x71ac2094 MethodUtil.ReplaceMethod
        JIT :   0x1072426 StaticClassA.A
Call StaticClassA.A() from a  method that has already been jited
StaticClassA.A
Call StaticClassA.A() from a  method that has not been jited
        JIT :   0x1072172 Program.TestStaticReplace
StaticClassB.A
        JIT :   0x1072190 Program.InstanceTests
        JIT :   0x1072284 Program.TestInstanceReplaceJited
Replacing InstanceClassA.A() with InstanceClassB.A()
        JIT :   0x10723c2 InstanceClassB.A
        JIT :   0x1072402 InstanceClassA.A
Call InstanceClassA.A() from a  method that has already been jited
        JIT :   0x107241e InstanceClassA..ctor
InstanceClassA.A
Call InstanceClassA.A() from a  method that has not been jited
        JIT :   0x1072268 Program.TestInstanceReplace
InstanceClassB.A
        JIT :   0x10722a0 Program.DynamicTests
        JIT :   0x1072344 Program.CreateTestMethod
Created new dynamic metbod StaticClassA.C
        JIT :   0x107232e Program.TestDynamicReplaceJited
Replacing StaticClassA.B() with dynamic StaticClassA.C()
        JIT :   0x71ac2210 MethodUtil.GetDynamicMethodRuntimeHandle
        JIT :   0x1072434 StaticClassA.B
Call StaticClassA.B() from a  method that has already been jited
StaticClassA.B
Call StaticClassA.B() from a  method that has not been jited
        JIT :   0x1072325 Program.TestDynamicReplace
        JIT :   0x10c318 DynamicClass.C
StaticClassA.C

Выводы

Практичность использования данного кода ограничена. Если вы хотите изменить библиотеку, и у вас нет доступа к исходному коду, и вы не хотите детранслировать, перекомпилировать или использовать редактор шестнадцатеричных файлов, то это, скорее всего, вам поможет. Можно создать некоторую библиотеку AOP , которая модифицирует существующие типы во время выполнения, вместо того, чтобы создавать оболочки или другие подходы во время сборки.

Существуют некоторые ограничения для данного кода. Заметим, что как только метод скомпилирован при помощи JIT, он не будет более ссылаться на адрес таблицы методов, который мы изменяем. Замена должна производиться до того, как вызываемый метод будет скомпилирован JIT. Вдобавок, это не было протестировано на станциях архитектуры x86-64. Сборки Zap или NGen также не работают.

Нам необходимо помнить, что мы напрямую манипулируем памятью CLR не рекомендуемыми способами. Этот код может не сработать с более новыми версиями .NET Framework. Работа выполнялась на .NET 3.5 и ОС Vista x86, поэтому код может не сработать на других компьютерах. Неплохо было бы написать класс, который смог бы определить свойства процессора и создать более оптимальную версию, которая будет использовать более совершенные технологии, такие как SIMD. .
Обновление

Распределение памяти было изменено в .NET версии 2.0 SP2, которую приходится установить при установке .NET версии 3.5 SP1. Код был обновлен таким образом, чтобы он определял структуру и действовал соответственно.

Скачать исходный код

Ziad Elmalki