Создание PE-файла с помощью IMetaDataEmit::Save(/ToMemory/toStream)

#winapi #clr #cil #clr-profiling-api

#winapi #clr #cil #clr-profiling-api

Вопрос:

Я пишу собственный профилировщик CLR, который выполняет тяжелую перезапись IL. При разработке новой функции мы иногда сталкиваемся с ошибкой проверки CLR. Для небольших методов довольно легко сравнить байты до и после, просмотрев различные элементы (заголовок метода, подпись, локальные файлы, код и таблицу исключений, в основном) и найти ошибку. Иногда это может быть связано с огромными методами, и процесс может занять некоторое время. Я пытаюсь сбросить текущий модуль в файл, чтобы его можно было легко запустить peverify.exe (и https://github.com/dotnet/corert/tree/master/src/ILVerify ). Я нашел IMetaDataEmit::Save, который выглядит идеально на бумаге (мы постоянно используем IMetaDataEmit для перезаписи IL). Я могу сбросить свой модуль, открыть его в шестнадцатеричном просмотрщике и просмотреть внесенные изменения. Однако он только сбрасывает модуль (the .Сетевой каталог внутри PE). Как я могу создать полный PE (dll / exe) из этого модуля, предпочтительно программно?

Комментарии:

1. Я не знаю ни о каких готовых системных компонентах, которые позволяют вам собирать PE-образ (если только в DbgHelp API что-то не скрыто). Тот факт, что проект Roslyn реализует свой собственный PEWriter , похоже, поддерживает это. Возможно, это может послужить отправной точкой для реализации вашего собственного, либо в неуправляемом, либо в управляемом коде.

2. Система. Отражение. Пространство имен PortableExecutable , похоже, обеспечивает достаточную поддержку PE-образов. Я не уверен, что вы можете с этим сделать. И это только для .NET Core, если это имеет значение.

3. @IInspectable, обратным вызовам профилировщика не разрешается повторно вводить управляемый код. (обратные вызовы профилировщика выполняются в процессе, поэтому плохие вещи случаются, если, например, необходимо выполнить jit-обратные вызовы или GC-обратные вызовы для выделения управляемой памяти.)

4. However, it only dumps the module (the .Net directory inside the PE). модуль является PE-файлом. Если у вас многомодульная сборка, то эта сборка будет охватывать несколько PE-файлов. Чего именно не хватает при использовании IMetaDataEmit::Save* .

5. @bri: Как я понимаю, IMetaDataEmit::Save* просто сериализует содержимое того, что называется разделом в PE-образе. Он не будет записывать полный PE-образ. Вам все еще необходимо собрать это воедино, включая заглушку DOS и PE-заголовок, а также заголовки разделов. Если я не неправильно понял.