Как стать автором
Обновить
52
0
Pavel Romash @ZloyChert

C# & .NET Monk

Отправить сообщение

В первых своих исследованиях я использовал winDbg, но там надо учитывать, что для начала надо дождаться, пока функция вызовется хоть раз (до этого JIT ее просто не скомпелит) или предкомпелить. Разумеется, windbg очень мощный, но для таких примеров слишком громоздкий.
И не так давно один добрый человек мне подсказал сайт https://sharplab.io. Я сверял с windbg (к нему было доверие), все совпадает. Так что для небольших примеров пользуюсь им.

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

Виртуальные методы вызываются по смещению в таблице методов. На этом и основана вся эта статья.
И благодаря этому при вызове метода CompareTo на CustomClass, вызывается метод строки. Это же и объясняет поведение при замене виртуального свойства на клон Equals. Заглушка действительно генерируется(для всех методов), но ради последующей компиляции JITом(имеет единсвеннную инструкцию на тригеринг JITа), которая потом затирается и изменяется на jmp в нужное место памяти, где расположен скомпилированный метод.

Могу высказать текущую гипотезу. Во-первых: при проецировании на Equals, параметр внуть метода строки передается null, скорее всего это связано с тем, что данный параметр передается через регистры, и значение в регистре при вызове метода соответсвет null. Второе — при этом метод возвращает false, то бишь нули (память). Которые интерпритируются как null в случае ссылочных типов, как 0 в случае int и тд.
Это звучит довольно дико для шарпа. И я не утвержаю, а лишь предполагаю. Возможно, это послужит толчком для дальнейших исследований (моих или ваших).
На самом деле вопрос действительно сложный.
Весь этот пример основан лишь на смещениях. Например, в смещении метода CompareTo я уверен, он совпадает с моим CompareTo. Однако свойство, когда идет первым, проецируется на другой метод. В моем случае это Equals. Попробуйте сделать вместо данного свойства аналог метода Equals. А далее попробуйте передать такую-же строку («4564» в моем случае), или другую. Результаты будут ожидаемыми для метода Equals (true и false соотвественно).
Причина же по которой возвращаемое значение становится null (строго говоря, дефолтным, для int будет 0) мною не разгадана. Если вам интересно, попробуйте подебажить в dnSpy, там можно своими глазами увидеть, в какой метод переходит выполнение. Порядок методов в таблице методов не тривиален. Есть правила, по которым располагаются методы, но я предпочитаю видеть точно.

Не пробовал и, если честно, не хотелось бы.
Я думал о возможностях использования, но возможность отстрела ноги слишком велика. Представляет интерес скорее с научной точки зрения.

Согласен, целью рефлексии, разумеется, не является нарушение инкапсуляции. Однако это не отменяет того факта, что с ее помощью (при желании), нарушение инкапсуляции легче некуда.
2

Информация

В рейтинге
Не участвует
Откуда
Украина
Зарегистрирован
Активность