Определите, были ли сборки .NET построены из одного источника
Кто-нибудь знает, как сравнить две сборки .NET, чтобы определить, были ли они созданы из «одинаковых» исходных файлов?
Я знаю, что есть некоторые доступные утилиты для разнесения, такие как плагин для Reflector, но мне не интересно просматривать различия в графическом интерфейсе, я просто хочу автоматизированный способ сравнить коллекцию двоичных файлов, чтобы узнать, были ли они созданы из одинаковые (или эквивалентные) исходные файлы. Я понимаю, что несколько разных исходных файлов могут создавать один и тот же IL и понимать, что процесс будет чувствителен только к различиям в IL, а не к исходному источнику.
Основным препятствием для простого сравнения streamов байтов для двух сборок является то, что .NET включает в себя поле под названием «MVID» (идентификатор версии модуля) сборки. Кажется, что у каждой компиляции другое значение, поэтому, если вы создадите один и тот же код дважды, assembly будет отличаться.
- Сделать муравей тихий без флага -q?
- Как сделать kernel для моего загрузчика?
- Код C ++ для проверки гипотезы Collatz быстрее, чем assembly вручную - почему?
- x86_64 - Условия сборки и выход из строя
- Цикл с вызовом функции быстрее, чем пустой цикл
Связанный с этим вопрос: кто-нибудь знает, как заставить MVID быть одинаковым для каждой компиляции? Это позволит нам избежать процесса сравнения, который нечувствителен к различиям в значении MVID. Согласованный MVID будет предпочтительнее, поскольку это означает, что могут использоваться стандартные контрольные суммы.
Основой этого является то, что сторонняя компания несет ответственность за независимое рассмотрение и отключение наших релизов до того, как нам разрешат выпустить в Production. Это включает в себя проверку исходного кода. Они хотят самостоятельно подтвердить, что исходный код, который мы им даем, соответствует двоичным файлам, которые мы ранее построили, протестировали и в настоящее время планируем развернуть. Мы ищем процесс, который позволяет им самостоятельно строить систему из источника, который мы им поставляем, и сравнивать контрольные суммы с контрольными суммами для бинарных файлов, которые мы тестировали.
КСТАТИ. Обратите внимание, что мы используем непрерывную интеграцию, автоматические сборки, контроль источника и т. Д. Проблема не связана с внутренним отсутствием контроля над исходными файлами в данной сборке. Проблема в том, что третья сторона несет ответственность за проверку того, что источник, который мы им предоставляем, производит те же бинарные файлы, которые мы тестировали, и планируем ввести в Production. Они не должны доверять ни одной из наших внутренних систем или элементов управления, включая сервер сборки или систему управления исходным кодом. Все, о чем они заботятся, это получение источника, связанного с сборкой, выполнение самой сборки и проверка того, что результаты соответствуют тому, что мы говорим, мы развертываем.
Скорость выполнения решения сравнения не имеет особого значения.
благодаря
- Как ссылаться на сборки .NET с помощью PowerShell
- Как вы прокручиваете загруженные в настоящее время сборки?
- .NET Assembly Diff / Compare Tool - Что доступно?
- Почему mulss занимает всего 3 цикла на Хасуэлле, отличном от таблиц инструкций Агнера?
- Как сохранить сборки ASP.NET в AppDomain в живых?
- Как получить вывод ассемблера из источника C / C ++ в gcc?
- Есть ли альтернатива Maven или порт для мира .NET?
- Очень быстро memcpy для обработки изображений?
Нелегко использовать инструменты командной строки для фильтрации MVID и штампов даты из текстового представления IL. Предположим, файлы file1.exe и file2.exe построены из тех же источников:
c: \ temp> ildasm / all / text file1.exe | find / v “Дата штампа:” | find / v “MVID”> file1.txt
c: \ temp> ildasm / all / text file2.exe | find / v “Дата штампа:” | find / v “MVID”> file2.txt
c: \ temp> fc file1.txt file2.txt
Сравнение файлов file1.txt и FILE2.TXT
FC: нет различий
При сравнении библиотек classов с ILDasm v4.0.319.1 кажется, что база изображений не инициализирована. Чтобы избежать несоответствий, используйте пересмотренное решение:
ildasm /all /text assembly.dll | find /v "// Time-date stamp:" | find /v "// MVID:" | find /v "// Checksum:" | find /v "// Image base:" > assembly.dasm
Точка входа (база изображений) – фактически интересная информация для исполняемых сборок и должна быть проверена тщательно. Внедрение новой базы изображений – это общий способ сделать программу чем-то совершенно другим. В моем случае я пытаюсь проверить последовательность многопоточных compilationов, поэтому безопасно пропустить точку входа.
Заметка о производительности: я взял 8 МБ DLL, которая была построена для AnyCPU, и запускала ILDasm. Результирующий файл был размером 251 МБ и потребовалось несколько минут. Размер был составлен примерно в 32 раза.
Я использовал решение Jerry Currry на assemblyх .Net 4 и выяснил, что теперь есть третий элемент, который будет зависеть от каждой сборки: контрольная сумма. Разве не удивительно находить контрольную сумму внутри сборки? Я думаю, что добавление контрольной суммы файла внутри этого файла изменит контрольную сумму …
Во всяком случае, измененная команда:
ildasm /all /text "assembly.dll" | find /v "// Time-date stamp:" | find /v "// MVID:" | find /v "// Checksum:" > assembly.dasm
Обратите внимание, что я также немного изменил строки поиска, добавив косые черты, чтобы избежать непреднамеренных совпадений. Строки этой команды должны запускаться вместе в одной строке, разделенной на читаемость. Имена файлов потребуют двойных кавычек вокруг них, если они содержат пробелы.
Существует несколько способов сделать это в зависимости от объема работы, которую вы готовы сделать, и важности производительности и / или точности. Один из способов, как указал Эрик Дж., – сравнить сборки в двоичном формате, исключая части, которые изменяются при каждой компиляции. Это решение легко и быстро, но может дать вам много ложных негативов. Один лучший способ – развернуть, используя reflection. Если производительность критическая, вы можете начать с сравнения типов и, если они совпадают, перейти к определениям членов. После проверки типов и определений членов, и если все будет равно этой точке, вы можете пойти дальше, исследуя фактический IL каждого метода, GetILAsByteArray
его через метод GetILAsByteArray
. Опять же, вы найдете различия, даже если все одно и то же, но скомпилировано с помощью немного разных флагов или другой версии компилятора. Я бы сказал, что лучшим решением является использование инструментов непрерывной интеграции, которые маркируют сборку с номером набора изменений вашего исходного элемента управления (вы используете один, правильно?).
Связанная статья
вы можете использовать MonoCecil и дать ему небольшую модификацию, чтобы решить проблему. Я сделал это, вы можете прочитать, как здесь: http://groups.google.com/group/mono-cecil/browse_thread/thread/6ab42df05daa3a/49e8b3b279850f13#49e8b3b279850f13
С уважением Флориан
Здесь вы можете использовать Reflector Diff AddIn.
Другое решение:
Информация исходного кода сохраняется, когда двоичные файлы скомпилированы в режиме отладки. Затем вы можете проверить, соответствует ли pdb exe, и если строки pdb соответствуют исходному коду.