Связывание интерфейсов среды TrEx со скриптовым языком
В качестве инструментального языка, при разработке среды TrEx был использован язык С++, что позволило добиться в критических местах кода должного уровня производительности. Однако с точки зрения пользователя среды она является «монолитом», обладающим фиксированным набором возможностей, и предоставляющим их средствами графического интерфейса. Разработка и встраивание собственных модулей-расширений способна решить эту проблему, однако такой подход сопряжен со значительными временными задержками, не приемлемыми для пользователя. Подходящим решением в данной ситуации является встраивание в среду интерпретатора скриптового языка, обеспеченного привязкой к методам и классам Common API.
В качестве кандидата на встраивание рассматривались следующие языки: Lua, Ch, Java/Javascript, Perl, Ruby. Были сформулированы следующие обязательные требования, которым должен удовлетворять скриптовый язык и его окружение.
- Возможность удобной работы с классами языка C++.
- Поддержка шаблонов.
- Перехват исключительных ситуаций.
- Наличие средств автоматизации для построения привязки.
В результате рассмотрения была выбрана связка Lua/SWIG. Ключевыми достоинствами выбранного решения является: открытый код, наличие сообщества, занимающегося развитием этих программных средств, малые накладные расходы на встраивание при использовании генератора кода привязки SWIG.
Возможность выполнения Lua-скриптов обеспечивается скриптовой консолью, совмещенной с окном вывода информационных сообщений среды. Применяемый интерпретатор Lua, по сравнению со стандартным, обладает следующими отличиями.
- Тип number, соответствующий в стандартном Lua C-типу double, в TrEx является 64-битным знаковым целым.
- Формат ввода чисел соответствует стандартному: число «10» воспринимается как десятичное 10, число «0x10» как десятичное 16, число «010» как восьмеричное 8. Формат вывода чисел всегда шестнадцатеричный, без префикса «0x».
- Операция возведения в степень в силу слабой применимости для целых чисел заменена на «исключающее или».
- Набор стандартных библиотек сохранен без изменений, за исключением библиотеки math, которая отключена по причине переопределения типа number.
При открытии трассы в ее контексте автоматически выполняется скрипт autoload.lua, расположенный в каталоге TrEx. Предоставляемый скрипт создает окружение, позволяющее получить доступ к элементам трассы в более простом виде, нежели при использовании C++-интерфейсов напрямую.
В стандартном окружении определен набор таблиц, используемых для ввода-вывода и работы с моделью и трассой.
Таблица TrEx.Util содержит следующие два поля.
- TrEx.Util.loggerInstance хранит ссылку на объект Logger, позволяющий выводить сообщения в консоль и файл журнала.
- TrEx.Util.traceContext хранит ссылку на объект TraceContext открытой трассы.
Таблица TrEx.Model используется для работы с регистровым файлом архитектуры, соответствующей открытой трассе. По ключу, соответствующему имени регистра (в нижнерегистровом или верхнерегистровом написании) или его числовому коду таблица позволяет получить описание регистра в виде структуры NamedElement.
Таблица TrEx.Trace содержит механизмы для работы с шагами трассы. Помимо получения количества шагов в трассе по ключу n, она позволяет обратиться к отдельному шагу по ключу, соответствующему его порядковому номеру. Помимо того, через ключ TrEx.Trace.position доступен номер выбранного пользователем шага.
Для доступа к декомпозиции на зависимости используется поле Dep объекта шага трассы, например TrEx.Trace[0].Dep. Данная таблица содержит количество зависимостей в ключе n, а также сами зависимости в виде объектов класса Dep по числовым ключам с 0 до n - 1.
Разбор на зависимости управляется флагами, содержащимися в TrEx.Trace.depFlags. В начальном состоянии флаги устанавливаются в значение 15, соответствующее наиболее полному набору флагов.
Рассмотрим пример использования TrEx.Trace.Dep: выводим все зависимости инструкции в шаге stepIndex (Рис. 2).
Таблица TrEx.Notepad предоставляет расширенные возможности вывода для скриптов с использованием окон «блокнотов». В каждом из таких блокнотов может содержаться список шагов и сопоставленной им текстовой информации с возможностью перехода к соответствующему шагу в трассе по двойному клику.
Для создания нового или доступа к уже существующему блокноту применяется индексированный доступ к таблице по имени блокнота (имя может являться произвольной строкой). Пример работы с блокнотом показан на Рис. 3.
local dumpDeps = function(stepIndex) local i
-- Цикл по зависимостям. for i = 0, TrEx.Trace[stepIndex].Dep.n - 1 do -- Выводим номер зависимости и ее текстовый вид. print(i, TrEx.Trace[stepIndex].Dep[i]) end end
Рис. 2. Работа с зависимостями в Lua-скрипте
for i = 0, TrEx.Trace.n - 1 do -- Проверяем eax. if 0 == TrEx.Trace[i].eax then -- Добавляем в блокнот "Zero EAX". TrEx.Notepad["Zero EAX"]:print(i, "На этом шаге eax == 0") end
-- Проверяем ebx. if 0 == TrEx.Trace[i].ebx then -- Добавляем в блокнот "Zero EBX". TrEx.Notepad["Zero EBX"]:print(i, "На этом шаге ebx == 0") end
-- Если на каком-то шаге eax и ebx равны нулю одновременно, добавляем текст в оба блокнота -- и выделяем его красным (0x0000FF) цветом. if (0 == TrEx.Trace[i].eax) and (0 == TrEx.Trace[i].ebx) then -- Добавляем в оба блокнота красный текст. TrEx.Notepad["Zero EAX"]:cprint(i, "Причем ebx тоже 0!", 0x0000FF) TrEx.Notepad["Zero EBX"]:cprint(i, "Причем eax тоже 0!", 0x0000FF) end end
Рис. 3. Пример использования TrEx.Trace и TrEx.Notepad для поиска шагов, где eax == 0 или ebx == 0.
В блокноте, таким образом, определены два метода: print(stepIndex, message) и cprint(stepIndex, message, color). В качестве color могут использоваться произвольные RGB-цвета.