В этом документе описаны структура и содержимое файлов .dex, в которых хранятся определения классов и связанные с ними дополнительные данные.
Руководство по типам
| Название | Описание |
|---|---|
| байт | 8-битное целое число со знаком |
| ubyte | 8-битное целое число без знака |
| короткое видео | 16-битное целое число со знаком, младший байт в начале |
| ushort | 16-битное целое число без знака, порядок байтов от младшего к старшему |
| ПРХВ | 32-разрядное целое число со знаком, младший байт в начале |
| uint | 32-разрядное целое число без знака, little-endian |
| long | 64-разрядное целое число со знаком, little-endian |
| улун | 64-разрядное целое число без знака, little-endian |
| sleb128 | signed LEB128, переменная длина (см. ниже) |
| uleb128 | unsigned LEB128, переменная длина (см. ниже) |
| uleb128p1 | беззнаковое LEB128 плюс 1, переменная длина (см. ниже) |
LEB128
LEB128 (Little-Endian Base 128) – это кодировка переменной длины для произвольных целых чисел со знаком или без знака. Формат заимствован из спецификации DWARF3. В файле .dex кодировка LEB128 используется только для 32-битных значений.
Каждое значение, закодированное с помощью LEB128, состоит из одного–пяти байтов, которые вместе представляют одно 32-битное значение. У каждого байта установлен старший бит, за исключением последнего байта в последовательности, у которого старший бит очищен. Остальные семь битов каждого байта содержат полезную нагрузку: семь младших битов – в первом байте, следующие семь – во втором и т. д. В случае с LEB128 со знаком (sleb128) старший бит полезной нагрузки последнего байта в последовательности расширяется до знака, чтобы получить конечное значение. В случае без знака (uleb128) любые биты, не представленные явно, интерпретируются как 0.
| Побитовая диаграмма двухбайтового значения LEB128 | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Первый байт | Второй байт | ||||||||||||||
1 |
бит 6 | bit5 | bit4 | bit3 | bit2 | бит1 | bit0 | 0 |
bit13 | bit12 | bit11 | bit10 | bit9 | bit8 | bit7 |
Вариант uleb128p1 используется для представления значения со знаком, где значение плюс один закодировано как uleb128. Это позволяет закодировать -1 (или 0xffffffff) одним байтом, но не другие отрицательные числа. Это полезно в тех случаях, когда представляемое число должно быть неотрицательным или равным -1 (или 0xffffffff) и когда другие отрицательные значения недопустимы (или когда вряд ли понадобятся большие неотрицательные значения).
Вот несколько примеров:
| Закодированная последовательность | Как sleb128 |
Как uleb128 |
Как uleb128p1 |
|---|---|---|---|
| 00 | 0 | 0 | -1 |
| 01 | 1 | 1 | 0 |
| 7f | -1 | 127 | 126 |
| 80 7f | -128 | 16256 | 16255 |
Макет файла
| Название | Формат | Описание |
|---|---|---|
| заголовок | header_item | заголовок; |
| string_ids | string_id_item[] | список идентификаторов строк. Это идентификаторы всех строк, используемых в файле, как для внутреннего именования (например, дескрипторов типов), так и в качестве постоянных объектов, на которые ссылается код. Этот список должен быть отсортирован по содержимому строк с использованием значений кодовых точек UTF-16 (без учета локали) и не должен содержать повторяющихся записей. |
| type_ids | type_id_item[] | список идентификаторов типов. Идентификаторы всех типов (классов, массивов или примитивных типов), на которые ссылается этот файл, независимо от того, определены они в файле или нет. Список должен быть отсортирован по индексу string_id и не содержать повторяющихся записей.
|
| proto_ids | proto_id_item[] | список идентификаторов прототипов методов. Идентификаторы всех прототипов, на которые ссылается этот файл. Этот список должен быть отсортирован по типу возвращаемого значения (по индексу type_id) в порядке убывания, а затем по списку аргументов (в лексикографическом порядке, отдельные аргументы упорядочены по индексу type_id). Список не должен содержать повторяющихся записей.
|
| field_ids | field_id_item[] | список идентификаторов полей. Это идентификаторы всех полей, на которые ссылается файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован по определяющему типу (индекс type_id), названию поля (индекс string_id) и типу (индекс type_id). В списке не должно быть повторяющихся записей.
|
| method_ids | method_id_item[] | список идентификаторов методов. Это идентификаторы всех методов, на которые ссылается файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован. Определяющий тип (по индексу type_id) – это основной порядок, название метода (по индексу string_id) – промежуточный порядок, а прототип метода (по индексу proto_id) – дополнительный порядок. Список не должен содержать повторяющихся записей.
|
| class_defs | class_def_item[] | список определений классов. Классы должны быть упорядочены таким образом, чтобы надкласс и реализованные интерфейсы данного класса появлялись в списке раньше, чем ссылающийся класс. Кроме того, недопустимо, чтобы определение класса с одним и тем же названием появлялось в списке более одного раза. |
| call_site_ids | call_site_id_item[] | вызовите список идентификаторов сайтов. Это идентификаторы всех сайтов вызовов, на которые ссылается этот файл, независимо от того, определены они в файле или нет. Этот список должен быть отсортирован по возрастанию значения call_site_off.
|
| method_handles | method_handle_item[] | список обработчиков методов. Список всех дескрипторов методов, на которые ссылается этот файл, независимо от того, определены они в файле или нет. Этот список не отсортирован и может содержать дубликаты, которые логически соответствуют разным экземплярам дескриптора метода. |
| данные | ubyte[] | область данных, содержащую все вспомогательные данные для перечисленных выше таблиц. У разных объектов разные требования к выравниванию, и при необходимости перед каждым объектом вставляются байты заполнения, чтобы обеспечить правильное выравнивание. |
| link_data | ubyte[] | данные, используемые в статически связанных файлах. Формат данных в этом разделе не указан в этом документе. В несвязанных файлах этот раздел пуст, и реализации среды выполнения могут использовать его по своему усмотрению. |
Формат контейнера
В версии 41 представлен новый формат контейнера для данных DEX, который позволяет экономить место. Этот формат контейнера позволяет объединить несколько логических файлов DEX в один физический файл. Новый формат – это в основном простое объединение файлов предыдущего формата с некоторыми отличиями:
file_size– это размер логического файла, а не физического. Его можно использовать для итерации по всем логическим файлам в контейнере.- Логические DEX-файлы могут ссылаться на любые более поздние данные в контейнере (но не на более ранние). Это позволяет файлам DEX обмениваться данными, например строками.
- Все смещения указываются относительно физического файла. Смещение относительно заголовка не задано. Это позволяет использовать разделы со смещениями в разных логических файлах.
- В заголовок добавлены два новых поля, описывающих границы контейнера. Это дополнительная проверка на согласованность, которая упрощает перенос кода в новый формат.
data_sizeиdata_offбольше не используются. Данные могут быть распределены по нескольким логическим файлам и не обязательно должны быть непрерывными.
Определения битовых полей, строк и констант
DEX_FILE_MAGIC
Встроено в header_item
Постоянный массив/строка DEX_FILE_MAGIC – это список байтов, которые должны быть в начале файла .dex, чтобы он был распознан как таковой. Значение намеренно содержит символ новой строки ("\n" или 0x0a) и нулевой байт ("\0" или 0x00), чтобы помочь в обнаружении определенных форм повреждения. Значение также содержит номер версии формата в виде трех десятичных цифр, который должен монотонно увеличиваться со временем по мере развития формата.
ubyte[8] DEX_FILE_MAGIC = { 0x64 0x65 0x78 0x0a 0x30 0x33 0x39 0x00 }
= "dex\n039\0"
Примечание. Поддержка версии 041 формата является экспериментальной в Android 16 и предназначена для тестирования формата контейнера.
Однако версию 041 не следует использовать в рабочем коде.
Примечание. Поддержка версии 040 формата была добавлена в Android 10.0. В этой версии был расширен набор допустимых символов в простых именах.
Примечание. Поддержка версии 039 формата была добавлена в Android 9.0. В этой версии появились два новых байт-кода:const-method-handle и const-method-type. (Каждый из них описан в таблице Сводка набора байт-кода.) В Android 10 версия 039 расширяет формат DEX-файлов, добавляя в него скрытую информацию об API, которая применима только к DEX-файлам в пути загрузочного класса.
Примечание. Поддержка версии 038 этого формата была добавлена в Android 8.0. В версии 038 добавлены новые байт-коды (invoke-polymorphic и invoke-custom) и данные для дескрипторов методов.
Примечание. Поддержка формата версии 037 была добавлена в Android 7.0. До версии 037 в большинстве версий Android использовался формат версии 035. Единственное отличие версий 035 и 037 – это добавление методов по умолчанию и изменение invoke.
Примечание. В общедоступных версиях ПО использовались по крайней мере две более ранние версии формата. Например, версия 009 использовалась для выпусков M3 платформы Android (ноябрь–декабрь 2007 г.), а версия 013 – для выпусков M5 платформы Android (февраль–март 2008 г.). В некоторых отношениях эти более ранние версии формата значительно отличаются от версии, описанной в этом документе.
ENDIAN_CONSTANT и REVERSE_ENDIAN_CONSTANT
Встроено в header_item
Константа ENDIAN_CONSTANT используется для указания порядка байтов в файле, в котором она находится. Хотя стандартный формат .dex использует порядок байтов от младшего к старшему, в реализациях может быть выбран другой порядок. Если при реализации встречается заголовок, в котором endian_tag имеет значение REVERSE_ENDIAN_CONSTANT, а не ENDIAN_CONSTANT, то становится понятно, что файл был преобразован из ожидаемого формата.
uint ENDIAN_CONSTANT = 0x12345678; uint REVERSE_ENDIAN_CONSTANT = 0x78563412;
NO_INDEX
Встроен в class_def_item и debug_info_item
Константа NO_INDEX используется, чтобы указать, что значение индекса отсутствует.
Примечание. Это значение не может быть равно 0, поскольку это обычно допустимый индекс.
Значение параметра NO_INDEX можно представить в виде одного байта в кодировке uleb128p1.
uint NO_INDEX = 0xffffffff; // == -1 if treated as a signed int
Определения access_flags
Встроено в class_def_item, encoded_field, encoded_method и InnerClass.
Битовые поля этих флагов используются для указания доступности и общих свойств классов и членов классов.
| Название | Значение | Для классов (и аннотаций InnerClass) |
Для полей | Для методов |
|---|---|---|---|---|
| ACC_PUBLIC | 0x1 | public: видно всем |
public: виден везде. |
public: видно всем |
| ACC_PRIVATE | 0x2 | private: видно только определяющему классу.
|
private: виден только в определяющем классе. |
private: видно только определяющему классу |
| ACC_PROTECTED | 0x4 | protected: видно пакету и подклассам.
|
protected: видно пакету и подклассам |
protected: доступно для пакета и подклассов. |
| ACC_STATIC | 0x8 | static: не содержит внешнюю ссылку this |
static: глобальный в определяющий класс |
static: не принимает аргумент this |
| ACC_FINAL | 0x10 | final: нельзя создать подкласс |
final: нельзя изменить после создания |
final: нельзя переопределить |
| ACC_SYNCHRONIZED | 0x20 | synchronized: связанная блокировка автоматически получена
во время вызова этого метода. Примечание. Этот параметр можно задать, только если также задан параметр |
||
| ACC_VOLATILE | 0x40 | volatile: специальные правила доступа для обеспечения безопасности потоков; |
||
| ACC_BRIDGE | 0x40 | bridge method, added automatically by compiler as a type-safe bridge | ||
| ACC_TRANSIENT | 0x80 | transient: не сохраняется при сериализации по умолчанию |
||
| ACC_VARARGS | 0x80 | Последний аргумент должен обрабатываться компилятором как аргумент "rest". | ||
| ACC_NATIVE | 0x100 | native: реализовано в нативном коде |
||
| ACC_INTERFACE | 0x200 | interface: абстрактный класс с множественной реализацией |
||
| ACC_ABSTRACT | 0x400 | abstract: нельзя создать экземпляр напрямую |
abstract: не реализовано в этом классе |
|
| ACC_STRICT | 0x800 | strictfp: строгие правила для арифметики с плавающей запятой |
||
| ACC_SYNTHETIC | 0x1000 | не определено непосредственно в исходном коде | не определено непосредственно в исходном коде; | не определено непосредственно в исходном коде; |
| ACC_ANNOTATION | 0x2000 | объявлен как класс аннотаций; | ||
| ACC_ENUM | 0x4000 | объявлено как перечисляемый тип | объявлено как перечисляемое значение | |
| (не используется) | 0x8000 | |||
| ACC_CONSTRUCTOR | 0x10000 | метод конструктора (инициализатор класса или экземпляра) | ||
| ACC_DECLARED_ SYNCHRONIZED |
0x20000 | объявлено synchronized. Примечание. Это не влияет на выполнение (кроме отражения этого флага как такового). |
InnerClass и недопустимо для аннотаций class_def_item.
Модифицированная кодировка UTF-8
Чтобы упростить поддержку устаревших систем, формат .dex кодирует строковые данные в модифицированной форме UTF-8, которая является стандартом де-факто и далее будет называться MUTF-8. Эта форма идентична стандартной UTF-8, за исключением следующего:
- Используются только одно-, двух- и трехбайтные кодировки.
- Кодовые точки в диапазоне
U+10000…U+10ffffкодируются как суррогатная пара, каждый элемент которой представлен в виде трехбайтового закодированного значения. - Кодовая точка
U+0000кодируется в двухбайтовом формате. - Простой нулевой байт (значение
0) указывает на конец строки, как это принято в языке C.
Первые два пункта можно обобщить следующим образом: MUTF-8 – это формат кодирования для UTF-16, а не более прямой формат кодирования для символов Unicode.
Два последних пункта позволяют одновременно включать кодовую точку U+0000 в строку и по-прежнему обрабатывать ее как строку с нулевым символом в конце в стиле C.
Однако специальная кодировка U+0000 означает, что, в отличие от обычного UTF-8, результат вызова стандартной функции C strcmp() для пары строк MUTF-8 не всегда указывает на правильный результат сравнения неравных строк.
Если при сравнении строк MUTF-8 важен порядок символов (а не только их равенство), проще всего декодировать строки посимвольно и сравнивать декодированные значения. (Однако возможны и более сложные реализации.)
Дополнительную информацию о кодировке символов можно найти в стандарте Юникод. MUTF-8 ближе к менее известной кодировке CESU-8, чем к UTF-8.
encoded_value encoding
Вложен в annotation_element и encoded_array_item
encoded_value – это закодированный фрагмент (почти) произвольных иерархически структурированных данных. Кодировка должна быть компактной и простой для анализа.
| Название | Формат | Описание |
|---|---|---|
| (value_arg << 5) | value_type | ubyte | байт, указывающий тип следующего за ним элемента value, а также необязательный уточняющий аргумент в трех старших битах.
Ниже приведены определения различных типов value.
В большинстве случаев value_arg кодирует длину следующего за ним параметра value в байтах как (size - 1), например 0 означает, что значение требует одного байта, а 7 – восьми. Однако есть исключения, указанные ниже.
|
| значение | ubyte[] | байты, представляющие значение, переменной длины и интерпретируемые по-разному для разных байтов value_type, хотя всегда с прямым порядком байтов. Подробную информацию о различных значениях можно найти ниже.
|
Форматы значений
| Название типа | value_type |
Формат value_arg |
Формат value |
Описание |
|---|---|---|---|---|
| VALUE_BYTE | 0x00 | (нет; должно быть 0) |
ubyte[1] | значение однобайтового целого числа со знаком |
| VALUE_SHORT | 0x02 | size - 1 (0…1) | ubyte[size] | знаковое двухбайтовое целое число, расширенное знаком |
| VALUE_CHAR | 0x03 | size - 1 (0…1) | ubyte[size] | беззнаковое двухбайтовое целое число, дополненное нулями |
| VALUE_INT | 0x04 | size – 1 (0…3); | ubyte[size] | четырехбайтовое целое число со знаком, расширенное знаком |
| VALUE_LONG | 0x06 | size – 1 (0…7); | ubyte[size] | восьмибайтное целое число со знаком, расширенное до знака; |
| VALUE_FLOAT | 0x10 | size – 1 (0…3); | ubyte[size] | четырехбайтовый битовый шаблон, дополненный нулями справа и интерпретируемый как 32-битное значение с плавающей запятой IEEE754; |
| VALUE_DOUBLE | 0x11 | size – 1 (0…7); | ubyte[size] | восьмибайтовый битовый шаблон, дополненный нулями справа и интерпретируемый как 64-битовое значение с плавающей запятой в формате IEEE754; |
| VALUE_METHOD_TYPE | 0x15 | size - 1 (0…3) | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе proto_ids и представляет собой значение типа метода;
|
| VALUE_METHOD_HANDLE | 0x16 | size - 1 (0…3) | ubyte[size] | Беззнаковое (с расширением нулями) четырехбайтовое целое число, которое интерпретируется как индекс в разделе method_handles и представляет значение дескриптора метода.
|
| VALUE_STRING | 0x17 | size – 1 (0…3); | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе string_ids и представляет строковое значение;
|
| VALUE_TYPE | 0x18 | size - 1 (0…3) | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе type_ids и представляет рефлексивное значение типа/класса;
|
| VALUE_FIELD | 0x19 | size – 1 (0…3); | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе field_ids и представляет значение рефлексивного поля;
|
| VALUE_METHOD | 0x1a | size – 1 (0…3); | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе method_ids и представляет значение рефлексивного метода;
|
| VALUE_ENUM | 0x1b | size – 1 (0…3); | ubyte[size] | четырехбайтовое целое число без знака (дополненное нулями), которое интерпретируется как индекс в разделе field_ids и представляет значение константы перечисляемого типа;
|
| VALUE_ARRAY | 0x1c | (нет; должно быть 0) |
encoded_array | массив значений в формате, указанном в разделе "encoded_array format" ниже. Размер value неявно задан в кодировке.
|
| VALUE_ANNOTATION | 0x1d | (нет; должно быть 0) |
encoded_annotation | дополнительную аннотацию в формате, указанном в разделе "encoded_annotation format" ниже. Размер value определяется кодировкой.
|
| VALUE_NULL | 0x1e | (нет; должно быть 0) |
(нет) | null – справочное значение. |
| VALUE_BOOLEAN | 0x1f | Логическое значение (0…1) | (none) | Однобитное значение: 0 для false и 1 для true. Бит представлен в value_arg.
|
Формат encoded_array
| Название | Формат | Описание |
|---|---|---|
| размер | uleb128 | количество элементов в массиве. |
| values | encoded_value[size] | последовательность байтов size encoded_value в формате, указанном в этом разделе, объединенных последовательно.
|
Формат encoded_annotation
| Название | Формат | Описание |
|---|---|---|
| type_idx | uleb128 | тип аннотации. Это должен быть тип класса (не массив или примитив). |
| размер | uleb128 | количество сопоставлений пар "имя-значение" в этой аннотации; |
| элементы | annotation_element[size] | элементы аннотации, представленные непосредственно в строке (не в виде смещений). Элементы должны быть отсортированы по возрастанию индекса string_id.
|
Формат элемента аннотации
| Название | Формат | Описание |
|---|---|---|
| name_idx | uleb128 | название элемента, представленное в виде индекса в разделе string_ids. Строка должна соответствовать синтаксису MemberName, описанному выше.
|
| значение | encoded_value | значение элемента |
Синтаксис строк
В файле .dex есть несколько типов элементов, которые в конечном итоге ссылаются на строку. Ниже приведены определения в стиле БНФ, которые указывают на допустимый синтаксис для этих строк.
SimpleName
Простое имя – это основа для синтаксиса имен других объектов. Формат .dex допускает значительную свободу действий (гораздо большую, чем большинство распространенных исходных языков). Простое имя состоит из любых букв или цифр из набора ASCII, нескольких определенных символов из этого набора и большинства кодовых точек, не входящих в него, за исключением управляющих, специальных символов и пробелов. Начиная с версии 040
формат также поддерживает пробелы (категория Unicode Zs
). Обратите внимание, что суррогатные кодовые точки (в диапазоне U+d800…U+dfff) не считаются допустимыми символами имени, но дополнительные символы Unicode являются допустимыми (они представлены в последней альтернативе правила для SimpleNameChar) и должны быть представлены в файле как пары суррогатных кодовых точек в кодировке MUTF-8.
| SimpleName → | ||
| SimpleNameChar (SimpleNameChar)* | ||
| SimpleNameChar → | ||
'A' … 'Z' |
||
| | | 'a' … 'z' |
|
| | | '0' … '9' |
|
| | | ' ' |
начиная с версии DEX 040 |
| | | '$' |
|
| | | '-' |
|
| | | '_' |
|
| | | U+00a0 |
начиная с версии DEX 040 |
| | | U+00a1 … U+1fff |
|
| | | U+2000 … U+200a |
начиная с версии DEX 040; |
| | | U+2010 … U+2027 |
|
| | | U+202f |
начиная с версии DEX 040 |
| | | U+2030 … U+d7ff |
|
| | | U+e000 … U+ffef |
|
| | | U+10000 … U+10ffff |
|
MemberName
используется field_id_item и method_id_item
MemberName – это имя члена класса, которым может быть поле, метод или внутренний класс.
| MemberName → | |
| SimpleName | |
| | | '<' SimpleName '>' |
FullClassName
Полное название класса – это полное название класса, включающее необязательный спецификатор пакета, за которым следует обязательное название.
| FullClassName → | |
| OptionalPackagePrefix SimpleName | |
| OptionalPackagePrefix → | |
(SimpleName '/')* |
|
TypeDescriptor
Используется type_id_item
TypeDescriptor – это представление любого типа, включая примитивы, классы, массивы и void. Ниже приведено описание разных версий.
| TypeDescriptor → | |
'V' |
|
| | | FieldTypeDescriptor |
| FieldTypeDescriptor → | |
| NonArrayFieldTypeDescriptor | |
| | | ('[' * 1…255)
NonArrayFieldTypeDescriptor |
| NonArrayFieldTypeDescriptor→ | |
'Z' |
|
| | | 'B' |
| | | 'S' |
| | | 'C' |
| | | 'I' |
| | | 'J' |
| | | 'F' |
| | | 'D' |
| | | 'L' FullClassName ';' |
ShortyDescriptor
Используется в proto_id_item
ShortyDescriptor – это краткое представление прототипа метода, включающее типы возвращаемых значений и параметров, за исключением того, что в нем не различаются разные типы ссылок (классов или массивов). Вместо этого все типы ссылок представлены одним символом 'L'.
| ShortyDescriptor → | |
| ShortyReturnType (ShortyFieldType)* | |
| ShortyReturnType → | |
'V' |
|
| | | ShortyFieldType |
| ShortyFieldType → | |
'Z' |
|
| | | 'B' |
| | | 'S' |
| | | 'C' |
| | | 'I' |
| | | 'J' |
| | | 'F' |
| | | 'D' |
| | | 'L' |
Семантика TypeDescriptor
Ниже приведено значение каждого варианта TypeDescriptor.
| Синтаксис | Значение |
|---|---|
| V | void – только для типов возвращаемого значения. |
| Z | boolean |
| B | byte |
| С | short |
| C | char |
| I | int |
| J | long |
| F | float |
| Д | double |
| Lfully/qualified/Name; | курс fully.qualified.Name; |
| [дескриптор | массив descriptor, который можно использовать рекурсивно для массивов массивов, хотя недопустимо иметь более 255 измерений.
|
Объекты и связанные структуры
В этом разделе приведены определения всех элементов верхнего уровня, которые могут быть в файле .dex.
header_item
Отображается в разделе заголовка
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| волшебный | ubyte[8] = DEX_FILE_MAGIC | волшебное значение. Подробную информацию можно найти в разделе DEX_FILE_MAGIC выше.
|
| контрольная сумма | uint | Контрольная сумма adler32 для остальной части файла (всего, кроме magic и этого поля). Используется для обнаружения повреждений файла.
|
| подпись | ubyte[20] | Подпись (хеш) SHA-1 остальной части файла (всего, кроме magic, checksum и этого поля). Используется для уникальной идентификации файлов.
|
| file_size | uint |
размер всего файла (включая заголовок) в байтах. (версия 40 или более ранняя) расстояние в байтах от начала этого заголовка до следующего заголовка или до конца всего файла (контейнера). (v41 или более поздняя версия) |
| header_size | uint |
Размер заголовка (всего этого раздела) в байтах. Это позволяет обеспечить хотя бы ограниченную обратную и прямую совместимость без нарушения формата. должен составлять 0x70 (112) байт. (версия 40 или более ранняя) должен составлять 120 байт (0x78). (версия 41 или более поздняя) |
| endian_tag | uint = ENDIAN_CONSTANT | тег endianness; Подробнее об этом рассказывается в разделе "ENDIAN_CONSTANT
и REVERSE_ENDIAN_CONSTANT".
|
| link_size | uint | размер раздела ссылок или 0, если файл не связан статически. |
| link_off | uint | смещение от начала файла до раздела ссылки или
0, если link_size == 0. Смещение, если оно не равно нулю, должно быть смещением в разделе link_data. Формат данных, на которые указывает этот заголовок, не определен в этом документе. Это поле заголовка (как и предыдущее) оставлено в качестве точки подключения для использования в реализациях во время выполнения.
|
| map_off | uint | смещение от начала файла до объекта карты. Смещение должно быть ненулевым и указывать на раздел data. Данные должны быть в формате, указанном ниже в разделе map_list.
|
| string_ids_size | uint | количество строк в списке идентификаторов строк; |
| string_ids_off | uint | смещение от начала файла до списка идентификаторов строк или
0, если string_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно указывать на начало раздела string_ids.
|
| type_ids_size | uint | количество элементов в списке идентификаторов типов, не более 65 535; |
| type_ids_off | uint | смещение от начала файла до списка идентификаторов типов или
0, если type_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно быть относительно начала раздела type_ids.
|
| proto_ids_size | uint | количество элементов в списке идентификаторов прототипов (не более 65 535); |
| proto_ids_off | uint | смещение от начала файла до списка идентификаторов прототипов или 0, если proto_ids_size == 0 (довольно странный пограничный случай). Если смещение не равно нулю, оно должно быть относительно начала раздела proto_ids.
|
| field_ids_size | uint | количество элементов в списке идентификаторов полей; |
| field_ids_off | uint | Смещение от начала файла до списка идентификаторов полей или 0, если field_ids_size == 0. Если смещение не равно нулю, оно должно быть относительно начала раздела field_ids. |
| method_ids_size | uint | количество элементов в списке идентификаторов методов; |
| method_ids_off | uint | смещение от начала файла до списка идентификаторов методов или
0, если method_ids_size == 0. Если смещение не равно нулю, оно должно быть относительно начала раздела method_ids. |
| class_defs_size | uint | количество элементов в списке определений классов; |
| class_defs_off | uint | смещение от начала файла до списка определений классов или 0, если class_defs_size == 0 (довольно странный крайний случай). Если смещение не равно нулю, оно должно быть относительно начала раздела class_defs.
|
| data_size | uint |
Размер раздела Не используется (v41 или более поздняя версия) |
| data_off | uint |
смещение от начала файла до начала раздела Не используется (версия 41 или более поздняя) |
| container_size | uint |
этого поля не существует. Можно предположить, что оно равно размер всего файла (включая другие заголовки DEX и их данные). (версия 41 или более поздняя) |
| header_offset | uint |
этого поля не существует. Можно предположить, что оно равно смещение от начала файла до начала этого заголовка. (версия 41 или более поздняя) |
map_list
Показывается в разделе данных
Указано в заголовке header_item
Выравнивание: 4 байта.
Это список всего содержимого файла в том порядке, в котором оно представлено в файле. Он частично дублирует header_item, но предназначен для удобного перебора всего файла. Один тип может встречаться в карте не более одного раза.Порядок типов не ограничен, за исключением ограничений, подразумеваемых остальными элементами формата (например, раздел header должен идти первым, за ним – раздел string_ids и т. д.). Кроме того, записи в карте должны быть упорядочены по начальному смещению и не должны перекрываться.
| Название | Формат | Описание |
|---|---|---|
| размер | uint | размер списка в записях; |
| list | map_item[size] | элементы списка; |
Формат map_item
| Название | Формат | Описание |
|---|---|---|
| тип | ushort | Тип объектов (см. таблицу ниже). |
| unused | ushort | (не используется) |
| размер | uint | количество объектов, которые нужно найти по указанному смещению; |
| вычесть | uint | смещение от начала файла до нужных объектов; |
Введите коды
| Тип продукта | Константа | Значение | Размер объекта в байтах |
|---|---|---|---|
| header_item | TYPE_HEADER_ITEM | 0x0000 | 0x70 |
| string_id_item | TYPE_STRING_ID_ITEM | 0x0001 | 0x04 |
| type_id_item | TYPE_TYPE_ID_ITEM | 0x0002 | 0x04 |
| proto_id_item | TYPE_PROTO_ID_ITEM | 0x0003 | 0x0c |
| field_id_item | TYPE_FIELD_ID_ITEM | 0x0004 | 0x08 |
| method_id_item | TYPE_METHOD_ID_ITEM | 0x0005 | 0x08 |
| class_def_item | TYPE_CLASS_DEF_ITEM | 0x0006 | 0x20 |
| call_site_id_item | TYPE_CALL_SITE_ID_ITEM | 0x0007 | 0x04 |
| method_handle_item | TYPE_METHOD_HANDLE_ITEM | 0x0008 | 0x08 |
| map_list | TYPE_MAP_LIST | 0x1000 | 4 + (item.size * 12) |
| type_list | TYPE_TYPE_LIST | 0x1001 | 4 + (item.size * 2) |
| annotation_set_ref_list | TYPE_ANNOTATION_SET_REF_LIST | 0x1002 | 4 + (item.size * 4) |
| annotation_set_item | TYPE_ANNOTATION_SET_ITEM | 0x1003 | 4 + (item.size * 4) |
| class_data_item | TYPE_CLASS_DATA_ITEM | 0x2000 | неявный; необходимо проанализировать |
| code_item | TYPE_CODE_ITEM | 0x2001 | неявный; необходимо проанализировать |
| string_data_item | TYPE_STRING_DATA_ITEM | 0x2002 | неявное; необходимо выполнить синтаксический анализ |
| debug_info_item | TYPE_DEBUG_INFO_ITEM | 0x2003 | неявное; необходимо выполнить синтаксический анализ |
| annotation_item | TYPE_ANNOTATION_ITEM | 0x2004 | неявный; необходимо проанализировать |
| encoded_array_item | TYPE_ENCODED_ARRAY_ITEM | 0x2005 | неявное; необходимо выполнить синтаксический анализ |
| annotations_directory_item | TYPE_ANNOTATIONS_DIRECTORY_ITEM | 0x2006 | неявный; необходимо проанализировать |
| hiddenapi_class_data_item | TYPE_HIDDENAPI_CLASS_DATA_ITEM | 0xF000 | неявный; необходимо проанализировать |
string_id_item
Появляется в разделе string_ids
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| string_data_off | uint | смещение от начала файла до строковых данных для этого элемента. Смещение должно указывать на место в разделе data, а данные должны быть в формате, указанном в разделе string_data_item ниже.
Смещение не должно быть выровнено.
|
string_data_item
Появляется в разделе данных
Выравнивание: нет (побайтовое)
| Название | Формат | Описание |
|---|---|---|
| utf16_size | uleb128 | размер этой строки в единицах кода UTF-16 (во многих системах это "длина строки"). То есть это декодированная длина строки. (Длина в кодированном виде определяется положением байта 0.) |
| данные | ubyte[] | последовательность кодовых единиц MUTF-8 (также известных как октеты или байты), за которой следует байт со значением 0. Подробную информацию о формате данных можно найти в разделе "Кодировка MUTF-8 (модифицированная UTF-8)" выше.
Примечание. Допускается использование строки, которая включает (в закодированном виде) суррогатные кодовые единицы UTF-16 (то есть |
type_id_item
Появляется в разделе type_ids
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| descriptor_idx | uint | индекс в списке string_ids для строки дескриптора этого типа. Строка должна соответствовать синтаксису TypeDescriptor, описанному выше.
|
proto_id_item
Указывается в разделе proto_ids.
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| shorty_idx | uint | индекс в списке string_ids для строки краткого описания этого прототипа. Строка должна соответствовать синтаксису ShortyDescriptor, определенному выше, а также типу возвращаемого значения и параметрам этого элемента.
|
| return_type_idx | uint | индекс в списке type_ids для типа возвращаемого значения этого прототипа
|
| parameters_off | uint | смещение от начала файла до списка типов параметров для этого прототипа или 0, если у этого прототипа нет параметров. Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром "type_list". Кроме того, в списке не должно быть ссылок на тип void.
|
field_id_item
Появляется в разделе field_ids
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| class_idx | ushort | индекс в списке type_ids для определителя этого поля. Это должен быть тип класса, а не массив или примитивный тип.
|
| type_idx | ushort | индекс в списке type_ids для типа этого поля
|
| name_idx | uint | индекс в списке string_ids для названия этого поля. Строка должна соответствовать синтаксису MemberName, определенному выше.
|
method_id_item
Появляется в разделе method_ids.
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| class_idx | ushort | индекс в списке type_ids для определителя этого метода. Это должен быть класс или массив, а не примитивный тип.
|
| proto_idx | ushort | индекс в списке proto_ids для прототипа этого метода
|
| name_idx | uint | индекс в списке string_ids для названия этого метода. Строка должна соответствовать синтаксису MemberName, описанному выше.
|
class_def_item
Появляется в разделе class_defs
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| class_idx | uint | индекс в списке type_ids для этого класса.
Это должен быть тип класса, а не массив или примитивный тип.
|
| access_flags | uint | флаги доступа для класса (public, final и т. д.). Подробную информацию можно найти в разделе access_flags.
|
| superclass_idx | uint | Индекс в списке type_ids для надкласса или постоянное значение NO_INDEX, если у этого класса нет надкласса (то есть это корневой класс, например Object). Если этот элемент присутствует, он должен быть типом класса, а не массивом или примитивным типом.
|
| interfaces_off | uint | смещение от начала файла до списка интерфейсов или 0, если интерфейсов нет. Это смещение должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром type_list ниже. Каждый элемент списка должен быть типом класса (не массивом или примитивным типом), и не должно быть дубликатов.
|
| source_file_idx | uint | индекс в списке string_ids для названия файла, содержащего исходный код (по крайней мере, большей части) этого класса, или специальное значение NO_INDEX, если такой информации нет. debug_info_item любого метода может переопределять этот исходный файл, но ожидается, что большинство классов будет поступать только из одного исходного файла.
|
| annotations_off | uint | Смещение от начала файла до структуры аннотаций для этого класса или 0, если в этом классе нет аннотаций. Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть представлены в формате, заданном параметром annotations_directory_item, описанным ниже. При этом все элементы должны ссылаться на этот класс как на определяющий.
|
| class_data_off | uint | смещение от начала файла до связанных данных о курсе для этого объекта или 0, если для этого курса нет данных о курсе. (например, если этот класс является интерфейсом-маркером). Если смещение не равно нулю, оно должно быть указано в разделе data, а данные в нем должны быть в формате, заданном в разделе class_data_item ниже. Все элементы должны ссылаться на этот класс как на определяющий.
|
| static_values_off | uint | Смещение от начала файла до списка начальных значений для полей static или 0, если таких полей нет (и все поля static должны быть инициализированы с помощью 0 или null). Это смещение должно быть указано в разделе data, а данные в нем должны быть в формате, заданном параметром encoded_array_item ниже. Размер массива не должен превышать количество полей static, объявленных этим классом, а элементы соответствуют полям static в том же порядке, в котором они объявлены в соответствующем field_list. Тип каждого элемента массива должен соответствовать объявленному типу соответствующего поля.
Если в массиве меньше элементов, чем полей static, то оставшиеся поля инициализируются с соответствующим типу значением 0 или null.
|
call_site_id_item
Появляется в разделе call_site_ids
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| call_site_off | uint | смещение от начала файла до определения сайта; Смещение должно находиться в разделе данных, а данные в нем должны быть в формате, указанном ниже в call_site_item. |
call_site_item
Показывается в разделе данных
Выравнивание: нет (по байтам)
call_site_item – это encoded_array_item, элементы которого соответствуют аргументам, предоставленным методу загрузчика. Первые три аргумента:
- Дескриптор метода, представляющий метод начальной загрузки (VALUE_METHOD_HANDLE).
- Название метода, который должен разрешить загрузчик (VALUE_STRING).
- Тип метода, соответствующий типу имени метода, которое нужно разрешить (VALUE_METHOD_TYPE).
Дополнительные аргументы – это постоянные значения, передаваемые методу связывания начальной загрузки. Эти аргументы передаются в порядке их указания и без преобразования типов.
Дескриптор метода, представляющий метод начальной загрузки компоновщика, должен иметь тип возвращаемого значения java.lang.invoke.CallSite. Первые три типа параметров:
java.lang.invoke.Lookupjava.lang.Stringjava.lang.invoke.MethodType
Типы параметров дополнительных аргументов определяются по их постоянным значениям.
method_handle_item
Появляется в разделе method_handles
Выравнивание: 4 байта.
| Название | Формат | Описание |
|---|---|---|
| method_handle_type | ushort | тип дескриптора метода (см. таблицу ниже); |
| unused | ushort | (unused) |
| field_or_method_id | ushort | Идентификатор поля или метода в зависимости от того, является ли тип дескриптора метода методом доступа или вызывающим методом. |
| unused | ushort | (не используется) |
Коды типов обработчиков методов
| Константа | Значение | Описание |
|---|---|---|
| METHOD_HANDLE_TYPE_STATIC_PUT | 0x00 | Дескриптор метода является статическим сеттером поля (аксессором) |
| METHOD_HANDLE_TYPE_STATIC_GET | 0x01 | Дескриптор метода является статическим геттером поля (аксессором) |
| METHOD_HANDLE_TYPE_INSTANCE_PUT | 0x02 | Дескриптор метода является сеттером поля экземпляра (аксессором) |
| METHOD_HANDLE_TYPE_INSTANCE_GET | 0x03 | Дескриптор метода является геттером поля экземпляра (аксессором) |
| METHOD_HANDLE_TYPE_INVOKE_STATIC | 0x04 | Дескриптор метода – это статический вызывающий метод |
| METHOD_HANDLE_TYPE_INVOKE_INSTANCE | 0x05 | Дескриптор метода является вызывающим методом экземпляра |
| METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR | 0x06 | Дескриптор метода является вызывающим методом конструктора |
| METHOD_HANDLE_TYPE_INVOKE_DIRECT | 0x07 | Дескриптор метода – это прямой вызов метода. |
| METHOD_HANDLE_TYPE_INVOKE_INTERFACE | 0x08 | Дескриптор метода – это вызывающий метод интерфейса |
class_data_item
Ссылка из class_def_item
Появляется в разделе данных
Выравнивание: нет (побайтовое)
| Название | Формат | Описание |
|---|---|---|
| static_fields_size | uleb128 | количество статических полей, определенных в этом объекте; |
| instance_fields_size | uleb128 | количество полей экземпляра, определенных в этом элементе |
| direct_methods_size | uleb128 | количество прямых методов, определенных в этом элементе |
| virtual_methods_size | uleb128 | количество виртуальных методов, определенных в этом элементе; |
| static_fields | encoded_field[static_fields_size] | определенные статические поля, представленные в виде последовательности закодированных элементов. Поля должны быть отсортированы по столбцу field_idx в порядке возрастания.
|
| instance_fields | encoded_field[instance_fields_size] | определенные поля экземпляра, представленные в виде последовательности закодированных элементов. Поля должны быть отсортированы по возрастанию значений field_idx.
|
| direct_methods | encoded_method[direct_methods_size] | определенные прямые методы (static, private или конструктор), представленные в виде последовательности закодированных элементов. Способы оплаты должны быть отсортированы по возрастанию значения method_idx.
|
| virtual_methods | encoded_method[virtual_methods_size] | определенные виртуальные методы (не static, private или конструктор), представленные в виде последовательности закодированных элементов. Этот список не должен включать унаследованные методы, если они не переопределены классом, который представляет этот элемент. Методы должны быть отсортированы по возрастанию значения переменной method_idx.
method_idx виртуального метода не должно совпадать с
прямого метода.
|
Примечание. Все элементы field_id и method_id должны ссылаться на один и тот же определяющий класс.
Формат encoded_field
| Название | Формат | Описание |
|---|---|---|
| field_idx_diff | uleb128 | Индекс в списке field_ids для идентификатора этого поля (включает название и дескриптор), представленный как разница с индексом предыдущего элемента в списке. Индекс первого элемента в списке указывается напрямую.
|
| access_flags | uleb128 | флаги доступа к полю (public, final и т. д.); Подробную информацию можно найти в разделе access_flags.
|
Формат encoded_method
| Название | Формат | Описание |
|---|---|---|
| method_idx_diff | uleb128 | индекс в списке method_ids для идентификатора этого метода (включает название и дескриптор), представленный как разница с индексом предыдущего элемента в списке. Индекс первого элемента в списке указывается напрямую.
|
| access_flags | uleb128 | флаги доступа для метода (public, final и т. д.). Подробную информацию можно найти в разделе access_flags.
|
| код_выключения | uleb128 | смещение от начала файла до структуры кода для этого метода или 0, если этот метод является abstract или native. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "code_item".
|
type_list
Упоминается в class_def_item и proto_id_item
Появляется в разделе данных
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| размер | uint | размер списка в записях; |
| list | type_item[size] | элементы списка; |
type_item format
| Название | Формат | Описание |
|---|---|---|
| type_idx | ushort | индекс в списке type_ids; |
code_item
Ссылка из encoded_method
Показывается в разделе данных
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| registers_size | ushort | количество регистров, используемых этим кодом; |
| ins_size | ushort | количество слов во входящих аргументах метода, для которого предназначен этот код; |
| outs_size | ushort | количество слов в пространстве исходящих аргументов, необходимых этому коду для вызова метода; |
| tries_size | ushort | количество try_item для этого экземпляра. Если значение не равно нулю, то эти значения будут представлены в виде массива tries сразу после insns.
|
| debug_info_off | uint | Смещение от начала файла до последовательности сведений для отладки (номера строк + информация о локальных переменных) для этого кода или 0, если такой информации нет. Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных задается параметром "debug_info_item" ниже.
|
| insns_size | uint | размер списка инструкций в 16-битных единицах кода; |
| insns | ushort[insns_size] | фактический массив байт-кода. Формат кода в массиве insns указан в сопутствующем документе Байт-код Dalvik. Обратите внимание, что, хотя это определено как массив ushort, некоторые внутренние структуры предпочитают выравнивание по четырем байтам. Кроме того, если это происходит в файле с перепутанным порядком байтов, то перестановка выполняется только для отдельных экземпляров ushort, а не для более крупных внутренних структур.
|
| padding | ushort (необязательно) = 0 | два байта заполнения, чтобы выровнять tries по четырем байтам.
Этот элемент присутствует, только если tries_size не равно нулю, а insns_size – нечетное число.
|
| попытки | "попробовать товар" [try_item] (необязательный) | Массив, указывающий, где в коде перехватываются исключения и как их обрабатывать. Диапазоны элементов массива не должны пересекаться и должны быть упорядочены по возрастанию адресов. Этот элемент присутствует, только если значение tries_size не равно нулю.
|
| Обработчики | encoded_catch_handler_list (необязательный) | байты, представляющие список списков типов перехвата и связанных адресов обработчиков. Каждый try_item имеет побайтовое смещение в этой структуре. Этот элемент присутствует, только если значение tries_size не равно нулю.
|
Формат try_item
| Название | Формат | Описание |
|---|---|---|
| start_addr | uint | Начальный адрес блока кода, охваченного этой записью. Адрес – это количество 16-битных единиц кода до начала первой инструкции, которая должна быть покрыта. |
| insn_count | ushort | количество 16-битных единиц кода, охватываемых этой записью. Последняя единица кода – start_addr + insn_count - 1.
|
| handler_off | ushort | смещение в байтах от начала связанного
encoded_catch_hander_list до
encoded_catch_handler для этой записи. Это должно быть смещение относительно начала encoded_catch_handler.
|
Формат encoded_catch_handler_list
| Название | Формат | Описание |
|---|---|---|
| размер | uleb128 | размер списка в записях; |
| list | encoded_catch_handler[handlers_size] | фактический список списков обработчиков, представленный напрямую (не в виде смещений) и последовательно объединенный |
Формат encoded_catch_handler
| Название | Формат | Описание |
|---|---|---|
| размер | sleb128 | количество типов улова в этом списке. Если значение не положительное, то это отрицательное число типов catch, а за catch следует обработчик catch-all. Например, если size равен 0, это означает, что есть универсальный блок catch, но нет блоков catch с явным указанием типа.
Значение size, равное 2, означает, что есть два явно типизированных блока catch и нет блока catch-all. А size со значением -1 означает, что есть один типизированный перехват и один перехват всех исключений.
|
| Обработчики | encoded_type_addr_pair[abs(size)] | Поток закодированных элементов abs(size), по одному для каждого перехваченного типа, в порядке, в котором типы должны быть протестированы.
|
| catch_all_addr | uleb128 (необязательно) | адрес обработчика для всех исключений в байт-коде. Этот элемент присутствует только в том случае, если значение size не положительное.
|
Формат encoded_type_addr_pair
| Название | Формат | Описание |
|---|---|---|
| type_idx | uleb128 | индекс в списке type_ids для типа исключения, которое нужно перехватить.
|
| addr | uleb128 | адрес обработчика исключений в байт-коде; |
debug_info_item
Упоминается в code_item
Показывается в разделе данных
Выравнивание: нет (побайтовое)
Каждый элемент debug_info_item определяет конечный автомат с байт-кодом, вдохновленный форматом DWARF3. При интерпретации этого автомата создается таблица позиций и (потенциально) информация о локальных переменных для элемента code_item. Последовательность начинается с заголовка переменной длины (которая зависит от количества параметров метода), за которым следуют байт-коды конечного автомата, и заканчивается байтом DBG_END_SEQUENCE.
Конечный автомат состоит из пяти регистров. Регистр address представляет собой смещение инструкции в связанном insns_item в 16-битных единицах кода. Регистр address начинается с 0 в начале каждой последовательности debug_info и должен только монотонно возрастать.
Регистр line представляет номер строки источника, который должен быть связан со следующей записью таблицы позиций, созданной конечным автоматом. Он инициализируется в заголовке последовательности и может меняться в положительном или отрицательном направлении, но никогда не должен быть меньше 1. Регистр source_file представляет исходный файл, на который ссылаются записи с номерами строк. Изначально ему присваивается значение source_file_idx из class_def_item.
Две другие переменные, prologue_end и epilogue_begin, представляют собой логические флаги (инициализируются значением false), которые указывают, следует ли считать следующую позицию, полученную от устройства, прологом или эпилогом метода. Кроме того, конечный автомат должен отслеживать имя и тип последней локальной переменной, хранящейся в каждом регистре для кода DBG_RESTART_LOCAL.
Заголовок выглядит следующим образом:
| Название | Формат | Описание |
|---|---|---|
| line_start | uleb128 | начальное значение регистра line конечного автомата;
Не представляет собой фактическую запись о позиции.
|
| parameters_size | uleb128 | количество закодированных названий параметров. Для каждого параметра метода, кроме параметра this метода экземпляра (если он есть), должно быть одно описание.
|
| parameter_names | uleb128p1[parameters_size] | Индекс строки названия параметра метода. Закодированное значение NO_INDEX означает, что для связанного параметра нет названия. Дескриптор и сигнатура типа подразумеваются из дескриптора и сигнатуры метода.
|
Значения байт-кода:
| Название | Значение | Формат | Аргументы | Описание |
|---|---|---|---|---|
| DBG_END_SEQUENCE | 0x00 | (нет) | завершает последовательность сведений для отладки для code_item |
|
| DBG_ADVANCE_PC | 0x01 | uleb128 addr_diff | addr_diff – сумма, которую нужно добавить в реестр адресов. |
перемещает указатель адреса без создания записи о позиции; |
| DBG_ADVANCE_LINE | 0x02 | sleb128 line_diff | line_diff – значение, на которое нужно изменить регистр строки. |
перемещает указатель строки без создания записи о позиции; |
| DBG_START_LOCAL | 0x03 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx |
register_num – регистр, который будет содержать локальныеname_idx – строковый индекс имениtype_idx – индекс типа
|
вводит локальную переменную по текущему адресу. Если значение name_idx или type_idx неизвестно, то вместо него может быть указано NO_INDEX.
|
| DBG_START_LOCAL_EXTENDED | 0x04 | uleb128 register_num uleb128p1 name_idx uleb128p1 type_idx uleb128p1 sig_idx |
register_num: регистр, который будет содержать localname_idx: индекс строки имениtype_idx: индекс типаsig_idx: индекс строки сигнатуры типа
|
представляет локальную переменную с сигнатурой типа по текущему адресу.
Любой из параметров name_idx, type_idx или sig_idx может иметь значение NO_INDEX, если оно неизвестно. (Если sig_idx – это -1, то те же данные можно представить более эффективно, используя код операции DBG_START_LOCAL.)
Примечание. Ознакомьтесь с разделом |
| DBG_END_LOCAL | 0x05 | uleb128 register_num | register_num: зарегистрировать, что контент содержит местный контент |
Помечает текущую локальную переменную как находящуюся вне области видимости по текущему адресу. |
| DBG_RESTART_LOCAL | 0x06 | uleb128 register_num | register_num: зарегистрируйтесь, чтобы перезапустить |
повторно вводит локальную переменную по текущему адресу. Название и тип совпадают с последними локальными данными, которые были активны в указанном реестре. |
| DBG_SET_PROLOGUE_END | 0x07 | (нет) | Устанавливает регистр конечного автомата prologue_end, указывая, что следующая добавленная запись позиции должна считаться концом пролога метода (подходящее место для точки останова метода). Регистр prologue_end очищается любым специальным кодом операции (>= 0x0a).
|
|
| DBG_SET_EPILOGUE_BEGIN | 0x08 | (none) | Устанавливает регистр конечного автомата epilogue_begin, указывая, что следующая добавленная запись позиции должна считаться началом эпилога метода (подходящее место для приостановки выполнения перед выходом из метода).
Регистр epilogue_begin очищается любым специальным операционным кодом (>= 0x0a).
|
|
| DBG_SET_FILE | 0x09 | uleb128p1 name_idx | name_idx – строковый индекс названия исходного файла;
NO_INDEX, если неизвестно.
|
указывает, что все последующие записи номеров строк относятся к этому названию исходного файла, а не к названию по умолчанию, указанному в code_item.
|
| Специальные коды операций | 0x0a…0xff | (нет) | увеличивает значения регистров line и address,
создает запись о местоположении и очищает регистры prologue_end и
epilogue_begin. Описание приведено ниже.
|
Специальные коды операций
Опкоды со значениями от 0x0a до 0xff (включительно) немного смещают регистры line и address, а затем создают новую запись в таблице позиций.
Формулы для расчета прироста приведены ниже.
DBG_FIRST_SPECIAL = 0x0a // the smallest special opcode DBG_LINE_BASE = -4 // the smallest line number increment DBG_LINE_RANGE = 15 // the number of line increments represented adjusted_opcode = opcode - DBG_FIRST_SPECIAL line += DBG_LINE_BASE + (adjusted_opcode % DBG_LINE_RANGE) address += (adjusted_opcode / DBG_LINE_RANGE)
annotations_directory_item
Упоминается в class_def_item
Показывается в разделе данных
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| class_annotations_off | uint | Смещение от начала файла до аннотаций, сделанных непосредственно в классе, или 0, если в классе нет прямых аннотаций.
Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных задается параметром "annotation_set_item" ниже.
|
| fields_size | uint | количество полей, аннотированных этим объектом; |
| annotated_methods_size | uint | количество методов, аннотированных этим элементом |
| annotated_parameters_size | uint | количество списков параметров метода, аннотированных этим элементом; |
| field_annotations | field_annotation[fields_size] (необязательный) | список связанных аннотаций полей. Элементы списка должны быть отсортированы по возрастанию по полю field_idx.
|
| method_annotations | method_annotation[methods_size] (необязательный) | список аннотаций связанных методов. Элементы списка должны быть отсортированы по возрастанию по полю method_idx.
|
| parameter_annotations | parameter_annotation[parameters_size] (необязательно) | список аннотаций параметров метода. Элементы списка должны быть отсортированы по возрастанию по полю method_idx.
|
Примечание. Все экземпляры field_id и method_id элементов должны ссылаться на один и тот же определяющий класс.
Формат аннотации поля
| Название | Формат | Описание |
|---|---|---|
| field_idx | uint | индекс в списке field_ids для идентификации поля, к которому относится аннотация.
|
| annotations_off | uint | смещение от начала файла до списка аннотаций для поля. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "annotation_set_item".
|
Формат аннотации метода
| Название | Формат | Описание |
|---|---|---|
| method_idx | uint | индекс в списке method_ids для идентификации аннотируемого метода.
|
| annotations_off | uint | Смещение от начала файла до списка аннотаций для метода. Смещение должно указывать на место в разделе data. Формат данных определяется значением annotation_set_item.
|
Формат аннотации параметра
| Название | Формат | Описание |
|---|---|---|
| method_idx | uint | индекс в списке method_ids для идентификации метода, параметры которого аннотируются.
|
| annotations_off | uint | смещение от начала файла до списка аннотаций для параметров метода. Смещение должно быть указано относительно местоположения в разделе data. Формат данных указан ниже в разделе "annotation_set_ref_list".
|
annotation_set_ref_list
Ссылка из parameter_annotations_item
Появляется в разделе данных
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| размер | uint | размер списка в записях; |
| list | annotation_set_ref_item[size] | элементы списка |
Формат annotation_set_ref_item
| Название | Формат | Описание |
|---|---|---|
| annotations_off | uint | Смещение от начала файла до набора аннотаций, на который указывает ссылка, или 0, если у этого элемента нет аннотаций.
Если смещение не равно нулю, оно должно указывать на местоположение в разделе data. Формат данных указан ниже в разделе "annotation_set_item".
|
annotation_set_item
Ссылка из annotations_directory_item, field_annotations_item, method_annotations_item и annotation_set_ref_item.
Показывается в разделе данных
Выравнивание: 4 байта
| Название | Формат | Описание |
|---|---|---|
| размер | uint | размер набора в записях; |
| записи; | annotation_off_item[size] | элементы набора. Элементы должны быть отсортированы по возрастанию по значению type_idx.
|
Формат элемента annotation_off_item
| Название | Формат | Описание |
|---|---|---|
| annotation_off | uint | смещение от начала файла до аннотации.
Смещение должно указывать на место в разделе data, а формат данных в этом месте определяется значением annotation_item ниже.
|
annotation_item
Упоминается в annotation_set_item
Появляется в разделе данных
Выравнивание: нет (побайтовое)
| Название | Формат | Описание |
|---|---|---|
| доступ | ubyte | видимость аннотации (см. ниже); |
| аннотация | encoded_annotation | закодированное содержимое аннотации в формате, описанном в разделе "encoded_annotation format" под заголовком "encoded_value encoding" выше.
|
Значения видимости
Ниже перечислены варианты для поля visibility в файле annotation_item:
| Название | Значение | Описание |
|---|---|---|
| VISIBILITY_BUILD | 0x00 | предназначен для использования только во время сборки (например, при компиляции другого кода); |
| VISIBILITY_RUNTIME | 0x01 | предназначен для отображения во время выполнения. |
| VISIBILITY_SYSTEM | 0x02 | предназначен для того, чтобы быть видимым во время выполнения, но только для базовой системы (а не для обычного пользовательского кода); |
encoded_array_item
Упоминается в class_def_item
Появляется в разделе данных
Выравнивание: нет (побайтовое)
| Название | Формат | Описание |
|---|---|---|
| значение | encoded_array | байты, представляющие закодированное значение массива, в формате, указанном в разделе "encoded_array Format" под заголовком "encoded_value Encoding" выше.
|
hiddenapi_class_data_item
В этом разделе содержатся данные об ограниченных интерфейсах, используемых каждым классом.
Примечание. Функция скрытого API была добавлена в Android 10.0 и применяется только к DEX-файлам классов в пути загрузки. Список флагов, описанных ниже, может быть расширен в будущих версиях Android. Подробнее об ограничениях на использование интерфейсов, не относящихся к SDK…
| Название | Формат | Описание |
|---|---|---|
| размер | uint | общий размер раздела |
| компенсации | uint[] | Массив смещений, индексированных по class_idx.
Нулевая запись массива с индексом class_idx означает, что либо для этого class_idx нет данных, либо все флаги скрытого API равны нулю.
В противном случае запись массива не равна нулю и содержит смещение от начала раздела до массива скрытых флагов API для этого class_idx.
|
| флаги | uleb128[] | объединенные массивы скрытых флагов API для каждого класса. Возможные значения флагов описаны в таблице ниже. Флаги кодируются в том же порядке, что и поля и методы в данных класса. |
Типы пометок об ограничениях:
| Название | Значение | Описание |
|---|---|---|
| белый список | 0 | Интерфейсы, которые можно свободно использовать и которые поддерживаются в рамках официально задокументированного индекса пакетов фреймворка Android. |
| серый список | 1 | Интерфейсы, не относящиеся к SDK, которые можно использовать независимо от целевого уровня API приложения. |
| черный список | 2 | Интерфейсы, не относящиеся к SDK, которые нельзя использовать независимо от целевого уровня API приложения. Попытка получить доступ к одному из этих интерфейсов приведет к ошибке выполнения. |
| greylist‑max‑o | 3 | Интерфейсы не из SDK, которые можно использовать в Android 8.x и более ранних версий, если они не ограничены. |
| greylist‑max‑p | 4 | Интерфейсы не из SDK, которые можно использовать в Android 9.x, если они не ограничены. |
| greylist‑max‑q | 5 | Интерфейсы, не относящиеся к SDK, которые можно использовать для Android 10.x, если они не ограничены. |
| greylist‑max‑r | 6 | Интерфейсы, не относящиеся к SDK, которые можно использовать в Android 11.x, если они не ограничены. |
Системные аннотации
Системные аннотации используются для представления различных фрагментов информации о классах (а также методах и полях). Обычно доступ к этой информации осуществляется только косвенно через код клиента (несистемный).
Системные аннотации представлены в файлах .dex как аннотации с параметром видимости VISIBILITY_SYSTEM.
dalvik.annotation.AnnotationDefault
Появляется в интерфейсах аннотаций.
Аннотация AnnotationDefault прикрепляется к каждому интерфейсу аннотаций, в котором нужно указать привязки по умолчанию.
| Название | Формат | Описание |
|---|---|---|
| значение | Аннотация | связи по умолчанию для этой аннотации, представленные в виде аннотации этого типа. Аннотация не обязательно должна включать все имена, определенные аннотацией; для отсутствующих имен просто не будет значений по умолчанию. |
dalvik.annotation.EnclosingClass
Показывается в курсах
Аннотация EnclosingClass прикрепляется к каждому классу, который либо определен как член другого класса, либо является анонимным, но не определен в теле метода (например, синтетический внутренний класс). У каждого класса с этой аннотацией должна быть аннотация InnerClass. Кроме того, в классе не должно быть одновременно аннотаций EnclosingClass и EnclosingMethod.
| Название | Формат | Описание |
|---|---|---|
| значение | Класс | класс, который наиболее точно определяет лексическую область видимости этого класса |
dalvik.annotation.EnclosingMethod
Показывается в курсах
Аннотация EnclosingMethod прикрепляется к каждому классу, определенному в теле метода. Каждый класс с этой аннотацией также должен иметь аннотацию InnerClass.
Кроме того, у класса не может быть одновременно аннотаций EnclosingClass и EnclosingMethod.
| Название | Формат | Описание |
|---|---|---|
| значение | Метод | метод, который наиболее точно определяет лексическую область действия этого класса; |
dalvik.annotation.InnerClass
Показывается в курсах
Аннотация InnerClass прикрепляется к каждому классу, который определен в лексической области видимости определения другого класса.
Если в классе есть эта аннотация, то в нем также должна быть аннотация EnclosingClass или EnclosingMethod.
| Название | Формат | Описание |
|---|---|---|
| название | Строка | Простое имя этого класса, объявленное изначально (без префикса пакета). Если класс анонимный, то название – null.
|
| accessFlags | ПРХВ | первоначально объявленные флаги доступа класса (которые могут отличаться от действующих флагов из-за несоответствия между моделями выполнения исходного языка и целевой виртуальной машины); |
dalvik.annotation.MemberClasses
Показывается в курсах
К каждому классу, объявляющему классы-участники, прикреплена аннотация MemberClasses. (Внутренний класс является прямым, если у него есть имя.)
| Название | Формат | Описание |
|---|---|---|
| значение | Class[] | массив классов участников; |
dalvik.annotation.MethodParameters
Появляется в методах
Примечание. Эта аннотация была добавлена после Android 7.1. На устройствах с более ранними версиями Android он будет игнорироваться.
Аннотация MethodParameters необязательна и может использоваться для предоставления метаданных параметров, таких как имена параметров и модификаторы.
Аннотацию можно опустить в методе или конструкторе, если метаданные параметра не требуются во время выполнения.
java.lang.reflect.Parameter.isNamePresent() можно использовать, чтобы проверить, есть ли метаданные для параметра, а связанные методы отражения, такие как java.lang.reflect.Parameter.getName(), будут возвращаться к режиму работы по умолчанию во время выполнения, если информация отсутствует.
При добавлении метаданных параметров компиляторы должны включать информацию для сгенерированных классов, например перечислений, поскольку метаданные параметров содержат сведения о том, является ли параметр синтетическим или обязательным.
Аннотация MethodParameters описывает только отдельные параметры метода. Поэтому компиляторы могут полностью опускать аннотацию для конструкторов и методов, у которых нет параметров, чтобы уменьшить размер кода и повысить эффективность во время выполнения.
Размеры массивов, описанных ниже, должны совпадать с размерами структуры method_id_item dex, связанной с методом. В противном случае во время выполнения будет выброшено исключение java.lang.reflect.MalformedParametersException.
То есть method_id_item.proto_idx ->
proto_id_item.parameters_off ->
type_list.size должны быть такими же, как names().length и accessFlags().length.
Поскольку MethodParameters описывает все формальные параметры метода, даже те, которые не объявлены явно или неявно в исходном коде, размер массивов может отличаться от сигнатуры или другой информации метаданных, основанной только на явных параметрах, объявленных в исходном коде. MethodParameters также не будет содержать информацию о параметрах получателя аннотации типа, которые отсутствуют в фактической сигнатуре метода.
| Название | Формат | Описание |
|---|---|---|
| имена | String[] | Названия формальных параметров для связанного метода. Массив не должен быть пустым, если формальные параметры отсутствуют. Если у формального параметра с определенным индексом нет имени, значение в массиве должно быть нулевым. Если строки с названиями параметров пустые или содержат символы ".", ";", "[" или "/", во время выполнения будет сгенерирована ошибка java.lang.reflect.MalformedParametersException.
|
| accessFlags | int[] | Флаги доступа формальных параметров для связанного метода. Массив не должен быть пустым, если формальные параметры отсутствуют. Значение представляет собой битовую маску со следующими значениями:
java.lang.reflect.MalformedParametersException.
|
dalvik.annotation.Signature
Появляется в классах, полях и методах
Аннотация Signature прикрепляется к каждому классу, полю или методу, которые определяются с помощью более сложного типа, чем тот, который можно представить с помощью type_id_item. Формат .dex не определяет формат подписей. Он лишь позволяет представлять подписи, необходимые для успешной реализации семантики исходного языка. Поэтому реализации виртуальных машин обычно не анализируют и не проверяют подписи. Подписи просто передаются API и инструментам более высокого уровня (например, отладчикам). Поэтому при использовании подписи следует учитывать, что она может быть недействительной, и предусмотреть возможность обработки синтаксически неверной подписи.
Поскольку строки подписи обычно содержат много повторяющегося контента, аннотация Signature определяется как массив строк, где повторяющиеся элементы относятся к одним и тем же базовым данным, а подпись представляет собой конкатенацию всех строк в массиве. Правила разделения подписи на отдельные строки отсутствуют. Это зависит от инструментов, которые создают файлы .dex.
| Название | Формат | Описание |
|---|---|---|
| значение | String[] | Сигнатура этого класса или элемента в виде массива строк, которые нужно объединить. |
dalvik.annotation.Throws
Появляется в методах
Аннотация Throws прикрепляется к каждому методу, который объявлен как выбрасывающий один или несколько типов исключений.
| Название | Формат | Описание |
|---|---|---|
| значение | Class[] | массив типов исключений, которые были вызваны; |