Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 [ 93 ] 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140

АРХИТЕКТУРА ПЕРЕЧИСЛЕНИЙ

Прежде чем углубляться в технические дебри реализации и архитектуры перечислений, зададимся простым вопросом, - что же по сути представляют собой члены перечислений?

Разумеется, это операнды, или еще точнее иная форма представления непосредственных операндов. В главе, посвященной объективной модели IDA уже отмечалось, что один и тот же операнд может быть по-разному отображен на экране дизассемблера. Он может быть не только непосредственным значением, но и смещением, например.

Однако, перечисления - это не просто иная форма отображения операнда на экране - с точки зрения IDA это элемент bTree, который может ссылаться на линейный адрес, объекта впрочем, не стоит повторяться, об этом уже писалось выше.

Но если каждый сегмент (имя, комментарий, функция) связан только с одним линейным адресом, то одно и то же перечисление может повторяться в десятке разных мест! И поэтому старые методы для него не подходят!

Поэтому был использован тот же механизм, который был создан для поддержки структур. Каждый объект ссылался на тег структуры, а операнд указывал на требуемый элемент внутри ее.

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

Обратите внимание еще раз на тот факт, что и структура и перечисление связываются не с операндом, а с обладающим им объектом, а точнее линейным адресом его начала.

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

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

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

При этом разумно стремиться к уменьшению числа списков, поскольку, как уже говорилось выше, для представления операнда в виде перечисления достаточно сослаться на список, и IDA самостоятельно подберет нужный элемент!

В идеале, если у нас всего один список (что бывает достаточно часто) необходимо перевести курсор на нужную строку и нажать <T>, как IDA все сделает автоматически.

Программная работа, в отличие от интерактивной, несколько сложнее. Кроме того, теги списков (это не теги, конечно, но иного названия просто нет, - поэтому будет считать, что это как бы теги) вообще практически не фигурируют.

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

МЕТОДЫ

Функция

Назначение

long GetEnumQty(void)

Возвращает число типов перечислений

long GetnEnum(long idx)

Возвращает идентификатор перечисления по ее индексу

long GetEnumIdx(long enum id);

Возвращает индекс перечисления по его



идентификатору

long GetEnum(char name)

Возвращает идентификатор перечисления по его имени

char GetEnumName(long enum id)

Возвращает имя перечисления по его идентификатору

char GetEnumCmt(long enum id,long repeatable

Возвращает комментарий перечисления

long GetEnumSize(long enum id)

Возвращает число членов перечисления

long GetEnumFlag(long enum id)

Возвращает флаги, определяющие представление элементов перечисления

long GetConstByName(char name)

Возвращает идентификатор константы по ее имени

long GetConstValue(long const id)

Возвращает значение константы по ее идентификатору

char GetConstName(long const id)

Возвращает имя константы по ее идентификатору

char GetConstName(long const id)

Возвращает комментарий константы по ее идентификатору

long AddEnum(long idx,char name,long flag)

Добавляет новое перечисление

void DelEnum(long enum id)

Удаляет перечисление

success SetEnumIdx(long enum id,long idx)

Задает индекс перечисления в списке

long GetEnumQty(void);

Функция возвращает число типов перечислений. Все они могут быть отображены вызовом списка командой меню ~ View \ Enumerations

FFFFFFFF ; enum enum 1 FFFFFFFF enum 1 0 FFFFFFFF enum 1 2 FFFFFFFF

FFFFFFFF ; ----------------------------

FFFFFFFF

FFFFFFFF ; enum enum 2 FFFFFFFF enum 2 0 FFFFFFFF

= 1 = 2

= 16h



Message("0x%X \n", GetEnumQty()

==return

Пояснения

Return

Число перечислений

Нет ни одного перечисления

long GetnEnum(long idx);

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

В отличие от этого, идентификатор (ID) перечисления представляет собой уникальное 32-битное значение, всегда указывающие на одно и ту же перечисление. Более того, даже если перечисление, связанное с конкретным идентификатором, было удалено, гарантируется, что тот же идентификатор не будет выдан ни одному созданному после этого перечислению.

Это гарантирует непротиворечивость ситуации и позволяет совместно использовать один и тот же идентификатор различным скриптам. Пример использования:

FFFFFFFF enum 1 0

FFFFFFFF enum 1 2 FFFFFFFF

FFFFFFFF ; FFFFFFFF

FFFFFFFF ; enum enum 2 FFFFFFFF enum 2 0

= 1 = 2

= 16h

auto a;

for(a=0;a<GetEnumQty();a++) Message("0x%X 0x%X \n",

a,GetEnumId(a)

0x0 0xFF0000F0 0x1 0xFF0000FE

Идентификатор, как и дескриптор, с точки зрения пользователя являются абстрактным «магическим» числом, интерпретировать которое допускается только операционной системе (в качестве которой выступает в данном случае IDA).

Операнд

Пояснения

index

Индекс перечисления в списке (от нуля до GetEnumQtyO-1)

Return

==return Пояснения



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 [ 93 ] 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140