четверг, 20 января 2011 г.

typedVar

При разработке pykd мы старались не трансиловать механически функционал из Debug Engine, а реализвать API, удобный при повседневной работе в windbg. А что делает пользователь в отладчике чаще всего? Конечно, просматривает значение переменных! Соответственно, для автоматизации его работу в первую очередь нужна функция для удобной и быстрой работы с переменными. Для этого мы реализовали функцию typedVar.

Вот ее прототип:

typedVar( string moduleName, string typeName, long address )


moduleName - имя модуля, содержащего тип
typeName - имя типа переменной
address - виртуальный адрес переменной

Функция создает объект типа typedVarClass и динамически добавляет ему аттрибуты, с именами соответствующими именам полей структуры заданного типа. Если поле является сложным типом - операция повторяется рекурсивно. В результате, мы в python е получаем объект, с которым можем работать в той же манере, как и в Си:

p = typedVar( "nt", "_ETHREAD", threadAddr )
print "Wait time: %d" % p.Tcb.WaitTime

Данный код выведет значение счетчика ожидания потока, адрес которого задан в переменной threadAddr. Массивы тоже будут корректно обработаны. Обращаться к элементу массива можно также в стиле Си:

print p.Tcb.Alerted[1]

В работе часто приходится иметь дело с связанными списками структур. Конечно, можно в цикле вызвать ф. typedVar для получения значений списка. В pykd для этого реализована специальная функция: typedVarList.

Вот ее прототип:

typedVarList( long head_address, string moduleName, string typeName, fieldName)


head_address - адрес головы списка
moduleName - имя модуля, содержащего тип элемента списка
typeName - имя типа элемента списка
fieldName - имя поля, содержащего указатель на следующий элемент списка.

Функция возвращает питоновский лист, каждый элемент которого имеет тип typedVarClass. Соответственно, для элементов этого списка справедливо все, что сказано выше. Проиллюстрируем на примере, как это работает:

nt = loadModule( "nt" )
processList = typedVarList( nt.PsActiveProcessHead, "nt", "_EPROCESS", "ActiveProcessLinks" )
for process in processList:
dprintln( "".join( [ chr(i) for i in process.ImageFileName.values() ] ) )

Данный код выведет на экран список процессов

Третья полезная функция для работы с переменными: containingRecord. Это аналог макроса CONTAINING_RECORD.

Вот ее прототип:

containingRecord( long field_address, string moduleName, string typeName, fieldName)


field_address - адрес поля структуры.
moduleName - имя модуля, содержащего тип
typeName - имя типа элемента списка
fieldName - имя поля, адрес которого задан переменной field_address

Битовые поля

Функция typedVar не поддерживает работу с битовымии полями в полном объеме. Если в структуре объявлено битовое поле:

struct A {
int a : 10;
int b : 20;
};

Мы в питоне получим, что obj.a = obj.b. Т.е структура битового поля не сохраняется и придется дополнительно накладывать битовые маски. Интересно, что команда dt в windbg правильно отображает битовые поля. Так что тут есть над чем поработать!

Комментариев нет:

Отправить комментарий