Я пишу concolic engine для Python с использованием функциональности sys.settrace()
.
Основная задача при выполнении такого рода - записать ограничения на входные переменные. Ограничения - это не что иное, как условия операторов if, которые создают две ветви (ветвь then и else).
Когда выполнение завершено, механизм выбирает ограничение и находит подходящие значения для входных данных, чтобы выполнение пошло вниз по другой ветви (при выполнении x оно переходит в ветвь then, при выполнении x + 1 он идет вдоль ветви "else").
Это немного контекста о том, почему я делаю то, что пытаюсь сделать ...
Комбинируя settrace()
и модуль dis
, я вижу байт-код каждой строки исходного кода непосредственно перед его выполнением. Таким образом, я легко могу записать условия if, которые появляются во время выполнения.
Но тогда у меня есть большая проблема. Мне нужно знать, в какую сторону пошла if, какую ветку взяла на себя казнь. Так что, если мой код что-то вроде:
if x > a:
print x
else:
print a
в определенный момент моя трассирующая вещь увидит:
t: if x > 0:
тогда интерпретатор python выполнит if и прыгнет (или нет) куда-нибудь. И я увижу:
t + 1: print x
Так есть ли инструкция t + 1
в ветви "then" или в ветви "else"? Помните, что функция трассировки видит только некоторый байт-код в текущем блоке.
Я знаю два способа сделать это. Одним из них является оценка состояния, чтобы точно определить, является ли оно истинным или ложным. Это работает, только если нет побочных эффектов.
Другой способ - попытаться посмотреть на указатель инструкции на t + 1
и попытаться понять, где мы находимся в коде. Это способ, которым я сейчас пользуюсь, но он очень деликатный, потому что на t + 1
я могу оказаться в другом месте (другой модуль, встроенная функция и т. Д.).
Итак, наконец, у меня возник вопрос: есть ли способ получить из самого Python или из модуля / расширения C / чего-либо еще результат последнего условного перехода?
В качестве альтернативы, есть ли более точные параметры трассировки? Что-то вроде выполнения байт-кода по одному коду операции за раз. С функциональностью settrace()
максимальное разрешение, которое я получаю - это целые строки исходного кода.
В худшем случае, я думаю, я могу изменить интерпретатор Python для предоставления такой информации, но я бы оставил это в качестве крайней меры по очевидным причинам.