Руководство пользователя

(руководство описывает сборку 080215)

Разрешение проблем

Существуют следующие категории отказа:

  1. аварийный отказ или нарушение прав доступа
  2. внутренний отказ проверки на непротиворечивость (interr)
  3. отказ декомпиляции функции без нарушения работоспособности
  4. неправильный выходной текст
  5. неэффективный/неясный/неоптимальный выходной текст

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

Декомпилятор использует обширный набор внутренних проверок и суждений. Например, он не производит код, который разыменовывает пустой указатель - "void *". С другой стороны, произведенный код, как предполагается, не является компилируемым, и много компиляторов будут жаловаться на это. Это - преднамеренный выбор создания не компилируемого на 100 % вывода, потому что цель состоит не в том, чтобы перекомпилировать код, но проанализировать его.

Декомпилятор использует некоторые конструкции языка C++ в синтезируемом тексте. Их использование ограничено конструкциями, которые не могут быть представлены на Cи (самый известный пример - это передача структур в функции по значению).

Внутренние ошибки

Когда декомпилятор обнаруживает внутреннюю несогласованность, он отображает окно сообщения с кодом ошибки. Он также предлагает Вам выслать базу данных на сервер hex-rays.com:

Действительно трудно (почти невозможно) воспроизвести ошибки без типовой базы данных, так что, пожалуйста, вышлите её на сервер. Для упрощения задачи, декомпилятор сохраняет свое внутреннее состояние в базе данных, которая действительно удобна, если ошибка происходит после нескольких часов декомпиляции.

Невозможно что-нибудь декомпилировать после внутренней ошибки. Пожалуйста, перезагрузите базу данных, или, лучше, перезапустите IDA.

Отказы без нарушения работоспособности

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

Пожалуйста, читайте раздел Разрешение проблем о возможных действиях.

can not convert to microcode (рус. не могу преобразовать в микрокод)

Эта ошибка означает, что декомпилятор не смог транслировать машинную команду по указанному адресу в микрокод. Пожалуйста, проверьте машинную команду и её длину. Если похоже, что это обычная  машинная команда, используемая в коде сгенерированном компилятором, и её длина верна, то вышлите сообщение об ошибке.

not enough memory (рус. недостаточно памяти)

Сообщение об ошибке самоочевидно. В то время, как она не должна случаться очень часто, она всё ещё может быть замечена при функциях с огромными стеками. Нет никакой необходимости сообщать об этой ошибке. Мы надеемся, что следующая версия будет обрабатывать функции с огромным стеком более эффективно.

invalid basic block (рус. недопустимый базисный блок)

Это - самая частая причина отказа декомпилятора. Она означает, что в указанном адресе есть базисный блок, который не заканчивается должным образом. Например, переход из функции, завершение с немашинной командой, или, просто, наличие мусора. Если Вы можете, попытайтесь исправить ситуацию, изменяя границы функции, создавая команды, или играя с хвостами функции. Обычно эта ошибка случается с уродливыми функциями.

Если ошибка случается при вызове, который не возвращает, поможет пометка вызванной функции как "noret". Если вызов является косвенным, поможет, также, добавление ссылки на "noret"-функцию.

Если эта ошибка происходит в базе данных, созданной старой версией IDA, попытайтесь повторно проанализировать программу прежде, чем декомпилировать её. Вообще, чтобы создать базы данных для декомпиляции, лучше использовать IDA 5.1.

К этому отказу также приводят нераспознанные таблицы переходов. Пожалуйста не сообщайте об этом отказе как об ошибке. Мы скоро введём решение для таблиц переходов.

positive sp value has been found (рус. найдено позитивное значение указателя вершины стека)

Указатель вершины стека по указанному адресу выше чем начальный указатель вершины стека. Функции, ведущие себя так странно, не могут быть декомпилированы. Если Вы видите, что значения указателя вершины стека являются неправильными, измените их при помощи команды Alt-K (Edit, Functions, Change stack pointer (рус. Правка, Функции, Изменить указатель вершины стека)) в IDA.

prolog analysis failed (рус. анализ пролога потерпел неудачу)

Анализ пролога функции потерпел неудачу. В настоящее время Вы не можете сделать очень много, но Вы не будете видеть эту ошибку очень часто. Декомпилятор попытается произвести код с командами пролога вместо остановки из-за этого отказа.

switch analysis failed (рус. анализ переключателя потерпел неудачу)

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

Если эта ошибка происходит в базе данных, созданной старой версией IDA, попытайтесь удалить бракованную машинную команду и обновить базу. Выполнение этого повторно анализа базы данных могло бы исправить ошибку, потому что IDA 5.1 обрабатывает переключатели намного лучше чем предыдущие версии.

exception analysis failed (рус. анализ особой ситуации потерпел неудачу)

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

stack frame is too big (рус. фрейм стека слишком большой)

Так как анализ стека требует большого количества памяти, декомпилятор откажется обработать любую функцию со стеком, больше чем 1 МБ. Анализ стека будет переписан в будущем, но мы должны жить пока с этим ограничением.

local variable allocation failed (рус. выделение локальной переменной потерпело неудачу)

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

16bit functions are not supported (рус. 16-разрядные функции не поддерживаются)

Обо всём говорит текст сообщения. В то время, как декомпилятор может быть прекрасно настроен для декомпиляции 16-битного кода, это пока не приоритетная задача. Может быть, в будущем, он будет поддерживать 16-битный код.

call analysis failed (рус. анализ вызова потерпел неудачу)

Это - самое болезненное сообщение об ошибках, но оно, также, говорит кое о чём, что Вы можете сделать. Короче говоря, это сообщение означает, что декомпилятор не смог определить соглашение о вызовах и их параметры. Если это - прямой вызов функции без переменного количества аргументов, Вы можете исправить это, определяя тип вызываемой функции: только перейдите к вызываемой функции и нажмите Y, чтобы определить её тип. Для функций с переменным числом параметров это также хорошая идея - определить их тип, но анализ вызова может всё ещё потерпеть неудачу, потому что декомпилятор должен знать фактическое число параметров в вызове. Мы рекомендовали бы начать с проврки указателя вершины стека во всей функции. Избавьтесь от любых неправильных значений указателя вершины стека. Во-вторых, проверьте типы всех вызванных функций. Если тип вызванной функции является неправильным, он может столкнуться с другими вызовами и привести к отказу. Вот маленький пример:

push eax push edx push eax call f1 call f2

Если f1 будет определена как функция с соглашением о вызове __stdcall, с 3-мя параметрами, и f2 - функция с 1-м параметром, то анализ вызова потерпит неудачу, так как была необходимость в использовании всех 4-х параметров, и только 3 из них помещены в стек.

Если ошибка происходит при косвенном вызове, пожалуйста добавьте таблицу перекрестных ссылок на функции требуемого типа. Декомпилятор будет использовать тип функции, на которую ссылаются.

Если все входные типы и значения указателя вершины стека верны, но декомпилятор всё ещё терпит неудачу, пожалуйста вышлите сообщение об ошибке.
function frame is wrong (рус. неверный фрейм функции)
Это - редкое сообщение об ошибках. Оно означает, что что-что неправильно во фрейме функции. Самая вероятная причина состоит в том, что во фрейме отсутствует область адреса возврата, или ему не соответствует дальность функции (far/near).
undefined type (рус. неопределенный тип)
Эта ошибка может произойти, если сделана ссылка на зарегистрированный тип (typedef), но он неопределё. Наиболее распространённый случай это - когда выгружена библиотека типа (например, vc6win.til). Это делает все ссылки на все определенные в ней типы недействительными.
inconsistent database information (рус. непоследовательная информация базы данных)
В настоящее время эта ошибка означает, что информация об участке памяти функции является неверной. Попытайтесь переопределить функцию (удалить и воссоздать).

Разрешение проблем

Когда декомпилятор терпит неудачу, пожалуйста проверьте следующие условия: 

  • границы функции. Здесь не должно быть никаких "диких" переходов, выходящих из функции в ничто. Функция должна заканчиваться должным образом: машинной командой возвращения или переходом к началу другой функции. Если она заканчивается после вызова невозвратной функции, вызываемая функция должна быть отмечена как non-returning (рус. невозвратная).
  • значения указателя вершины стека. Используйте команду Options, General, Stack pointer (рус. Настройка, Общие, Указатель вершины стека), чтобы отобразить их в столбце сразу после адресов в представлении дизассемблированного кода. Если значение указателя вершины стека является неверным в каком-либо месте функции, то декомпиляция может потерпеть неудачу. Чтобы исправить значения указателя вершины стека, используйте команду Edit, Functions, Change stack pointer (рус. Правка, Функции, Изменить указатель вершины стека).
  • тип функции. Соглашение о вызовах, количестве и типах их параметров должны быть верными. Если тип функции не будет определён, то декомпилятор попытается вывести его. В некоторых редких случаях это будет терпеть неудачу. Если функция ожидает свой ввод в нестандартных регистрах или возвращает результат в нестандартном регистре, Вы должны будете сообщить об этом декомпилятору. В настоящее время он выдаёт хорошие предположения о нестандартных местах входа, но не может обработать нестандартные места возврата.
  • типы вызываемых функций и элементов данных, на которые они ссылаются. Неправильный тип может очень легко нанести ущерб. Используйте вызывающую клавишу F для отображения типа текущего элемента в окне сообщений. Для функций, переместите курсор в её начало и нажмите F. Если тип неверный, измените его командой Edit, Functions, Set function type (рус. Правка, Функции, Установить тип функции) (вызывающая клавиша Y). Эта команда работает не только для функций но, также, и для данных и членов структур.
  • Если тип ссылается на неопределенный тип, декомпиляция может потерпеть неудачу.
  • используйте базу данных, созданную IDA 5.1, потому что она анализирует файлы лучше чем её предыдущие версии.

У будущих версий будет больше корректирующих команд, но мы должны понять, в каких командах мы нуждаемся.

Сообщения об ошибках

Чтобы оказаться полезным, сообщение об ошибке должно содержать достаточно информации, чтобы для её воспроизведения. Команда send database (рус. выслать базу данных) - предпочтительный способ отправки сообщения об ошибках, потому что он сохраняет всю соответствующую информацию в базе данных. Некоторые ошибки невозможно воспроизвести без этой команды.

База данных передаётся в сжатой форме, в целях сохранения полосы пропускания. Для передачи используется подключение SSL.

Если Ваша база данных/входной файл является конфиденциальной, и Вы не можете выслать её, попытайтесь найти похожий файл, для иллюстрации проблемы. Спасибо.

Мы обрабатываем Ваши базы данных конфиденциально (как всегда в прошлом).