Есть ли способ перечислить, какие функции изменились между двумя исполняемыми файлами? - PullRequest
0 голосов
/ 26 января 2019

TLDR / сводка : есть ли способ, если предоставить два исполняемых файла (оба скомпилированы из C ++, с отладочной информацией и из идентичного или почти идентичного исходного кода) ) перечислить только функции, отличающиеся в одном относительно другого?

Предпосылки / мотивация : В конце каждого спринта наша инженерная команда передает сборку «герой» нашей команде QA в качестве кандидата на релиз. Затем команда SQA проводит несколько человеко-недель, тестируя кандидата на релиз, чтобы убедиться, что он работает правильно. (Они автоматизировали как можно большую часть тестирования, но есть некоторые части, которые нелегко автоматизировать, следовательно, трудоемкое ручное тестирование / проверка). Неизбежно, они сталкиваются с одним или несколькими сбоями в кандидате на выпуск, после чего регистрируется отчет об ошибке, и инженерия исправляет ошибки и генерирует нового кандидата на выпуск.

На этом этапе команда SQA должна принять решение: перезапускают ли все тестирование с нуля, или они предполагают, что новый релиз-кандидат идентичен предыдущему релиз-кандидату, за исключением запрошенных исправлений - т.е. что в других частях программы не было введено никаких регрессий?

Первый вариант («перезапустить с нуля») безопаснее, но дороже и вызывает значительное отставание от графика. Второй вариант («просто продолжайте тестирование, как и раньше, но с новой сборкой») более быстрый, но рискует, что регрессия проскользнет к пользователю, если какие-либо недавно обнаруженные ошибки появятся в частях программы, которые уже были протестированы с использованием старая сборка.

Поэтому, когда SQA просит у меня совета относительно этого решения, я в настоящее время делаю «svn diff» между двумя датами сборки, чтобы точно проверить, какой код C ++ изменился между двумя сборками, и использовать его для оценки уровня риска делает полный повторный тест. Однако некоторые из наших сотрудников SQA не доверяют нашему процессу сборки так сильно, как я, и неохотно делают предположение, что только из-за того, что исходный код почти не изменился, это означает, что исполняемый файл практически не изменился. (то есть они говорят «но что, если на сборочной машине были изменены какие-то настройки, о которых мы не знаем?»; я могу лишь обратиться к их вере в человечество, что никто не будет делать такие вещи)

Поэтому, чтобы успокоить страхи SQA (и мои собственные), было бы очень полезно, если бы я мог взять новый исполняемый файл release-кандидата и сделать с ним «diff» (по сравнению со старым / частично протестированным исполняемым файлом release -андидата). ) и посмотреть, какие именно функции отличаются, а какие остаются без изменений. (Очевидно, я мог бы просто использовать для этого контрольные суммы бинарных различий или MD5, но они только скажут мне, что эти два исполняемых файла различны; они не скажут мне, какие функции различны, и это то, что я действительно хочу знать - например, после того, как я исправил опечатку в поле About, функции основной бизнес-логики в исполняемом файле не изменились по сравнению с тем, что было проверено ранее)

Я понимаю, что ответ на этот вопрос, скорее всего, зависит от ОС; однако мы компилируем под Linux, MacOS / X и Linux, так что приветствуется любая идея для любой из этих трех ОС.

1 Ответ

0 голосов
/ 26 января 2019

Ответ на этот вопрос, по-видимому, заключается в том, что нет, таких инструментов не существует (по крайней мере, вне сообщества по защите от вредоносных программ).

Поэтому, просто чтобы посмотреть, можно ли это сделать, я написал простую проверочную концепцию executetable_diff , которая делает более или менее то, что я искал. Он работает под Linux и MacOS / X, и при запуске он запускает каждый из двух исполняемых файлов через дизассемблер («otool» в MacOS / X, «objdump» в Linux), затем сканирует текст дизассемблирования, чтобы увидеть, какие функции в тексте -сегмент (или строки в сегменте .rodata) отличаются между одним исполняемым файлом и следующим.

Затем распечатывает список функций, которые не идентичны своим аналогам в другом исполняемом файле, а также записывает файл, содержащий фактические различия, на случай, если пользователь захочет увидеть как функции разные.

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

Как отметили комментаторы по этому вопросу, отличающиеся исполняемые файлы не заменяют использование контроля версий и отслеживания номера репозитория-ревизии, связанного с каждым встроенным исполняемым файлом, так что вы можете вместо этого делать свои сравнения на уровне исходного кода. , Я написал это только для того, чтобы увидеть, можно ли это сделать, и в качестве учебного упражнения, чтобы больше узнать о том, как изменения в исходном коде отражаются в полученных двоичных файлах. executetable_diff следует рассматривать только как грубую эвристику, поскольку в некоторых случаях он, несомненно, будет давать ложноположительные результаты и ошибочно игнорировать значимые изменения в других.

...