Трассировка Python и условные переходы

Я пишу 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, чтобы предоставлять такую ​​информацию, но я бы оставил это как последнее средство по очевидным причинам.

6
задан agf 4 August 2011 в 15:18
поделиться