Анимация
JavaScript
|
Главная Библионтека АРХИТЕКТУРА ПЕРЕЧИСЛЕНИЙ Прежде чем углубляться в технические дебри реализации и архитектуры перечислений, зададимся простым вопросом, - что же по сути представляют собой члены перечислений? Разумеется, это операнды, или еще точнее иная форма представления непосредственных операндов. В главе, посвященной объективной модели IDA уже отмечалось, что один и тот же операнд может быть по-разному отображен на экране дизассемблера. Он может быть не только непосредственным значением, но и смещением, например. Однако, перечисления - это не просто иная форма отображения операнда на экране - с точки зрения IDA это элемент bTree, который может ссылаться на линейный адрес, объекта впрочем, не стоит повторяться, об этом уже писалось выше. Но если каждый сегмент (имя, комментарий, функция) связан только с одним линейным адресом, то одно и то же перечисление может повторяться в десятке разных мест! И поэтому старые методы для него не подходят! Поэтому был использован тот же механизм, который был создан для поддержки структур. Каждый объект ссылался на тег структуры, а операнд указывал на требуемый элемент внутри ее. Точно то же происходит и с перечислениями. Есть список перечислений, на который ссылается объект. Элементы списка просматриваются до тех пор, пока не найдется элемент совпадающий по значению с операндом, объекта. Обратите внимание еще раз на тот факт, что и структура и перечисление связываются не с операндом, а с обладающим им объектом, а точнее линейным адресом его начала. Представление операнда в виде члена структуры или перечисление происходит на втором этапе, - и жесткой связки тут нет, простой поиск на совпадение значений. Но если в структуре смещение каждого члена уникально, то есть никакие два члена не могут быть расположены по одному и тому же смещению, то в перечислениях два разных элемента могут иметь одно и то же значение. Вот, собственно и ответ на вопрос о необходимости поддержки более чем одного списка перечислений, а заодно и тактика группировки элементов. То есть главным критерием должно быть не родственность каких-то признаков, а гарантия непопадающих значений. При этом разумно стремиться к уменьшению числа списков, поскольку, как уже говорилось выше, для представления операнда в виде перечисления достаточно сослаться на список, и IDA самостоятельно подберет нужный элемент! В идеале, если у нас всего один список (что бывает достаточно часто) необходимо перевести курсор на нужную строку и нажать <T>, как IDA все сделает автоматически. Программная работа, в отличие от интерактивной, несколько сложнее. Кроме того, теги списков (это не теги, конечно, но иного названия просто нет, - поэтому будет считать, что это как бы теги) вообще практически не фигурируют. Действительно, все члены связаны с уникальными глобальными идентификаторами, да и имена каждого из них не менее уникальны. МЕТОДЫ
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()
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).
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 |