Поддержка системы команд THUMB в двоичной трансляции (1187412), страница 4
Текст из файла (страница 4)
Обработчик смены контекста между монитором итранслированным блоком из кэша.static void *main_vcpu_thread(void *arg){vcpu_t *vcpu = (vcpu_t *)arg;uint32_t break_condition;set_vcpu_id(vcpu->num);while ( !(break_condition = handle_async_events(vcpu))) {if (!native_execute || native_execute(vcpu))cpu_execute_op(vcpu);};sync_lock(&main_lock);vcpu->break_condition = break_condition;sync_wake(&main_sync);sync_unlock(&main_lock);return NULL;}Листинг 8.
Основной цикл виртуальной машиныtrans_status_t trans_thumb_add_imm(trans_insn_t *insn,x86_reg_t reg_map[ARM_REG_COUNT], uint8_t **write_ptr){arm_reg_t rd = REG_NONE, rn = REG_NONE;uint32_t imm;if (GET_BIT(insn->op, 1))THUMB_DECODE_IMM3(insn->op, rd, rn, imm);elseTHUMB_DECODE_IMM8(insn->op, rd, imm);if (REGPC == rn)MOVD_REG_IMM32(write_ptr, reg_map[rd], insn->addr + 8);elseMOV_REG_REG(write_ptr, reg_map[rd], reg_map[rn]);ADD_REG_IMM32(write_ptr, reg_map[rd], imm);if (REGPC == rd)MOVD_MEM_REG_DISP8(write_ptr, REG_EBP, reg_map[rd],ARM_REG_ADDR_DISP8(REGPC));return TRANS_SUCCESS;Листинг 9.
Пример процедуры обратного вызова для трансляции кода/** As per A6.2.5* Miscellaneous 16-bit instructions* Thumb 16-bit*/void reg_usage_thumb_misc(trans_insn_t *insn){const uint32_t opcode = (insn->op >> 8) & 0xf;switch (opcode){case 0b0000: // add/sub sp immREG_TMP_NEEDED(insn);break;case 0b0001: // cbz/cbnzcase 0b0011:case 0b1001:case 0b1011:REG_TMP_NEEDED(insn);UPDATE_REG_USAGE_MASK(insn, (insn->op) & 0 x7);break;case 0b0010: // stx(hb)/utx(hb)case 0b1010: // rev(16/sh)UPDATE_REG_USAGE_MASK(insn, (insn->op) & 0x7);UPDATE_REG_USAGE_MASK(insn, (insn->op >> 3) & 0 x7);break;case 0b1100: // pop multcase 0b1101:case 0b0100: // push multcase 0b0101:REG_TMP_NEEDED(insn);break;}}Листинг 10. Пример процедуры обратного вызова для анализа использованиярегистров.trans_status_t trans_thumb_cmp_imm(trans_insn_t *insn,x86_reg_treg_map[ARM_REG_COUNT],uint8_t **write_ptr){uint32_t _imm;arm_reg_t _rn;trans_insn_t *dummy_insn;INSTRUCTION_COPY(insn, dummy_insn);THUMB_ENCODE_PROLOGUE(write_ptr, insn);thumb_decode_args_to_arm_imm(insn->op, dummy_insn->op);trans_status_t ret = trans_arm_cmp_imm(dummy_insn,reg_map,write_ptr);If (ret == TRANS_SUCCESS){THUMB_ENCODE_EPILOGUE(write_ptr, insn);}return ret;}Листинг 11a.
Вызов для трансляции кода набора команд arm исоответствующий ему обработчик thumb.trans_status_t trans_arm_cmp_imm(trans_insn_t *insn, x86_reg_treg_map[ARM_REG_COUNT], uint8_t **write_ptr){uint32_t imm;arm_reg_t rn;ARM_DECODE_ARGS_IMM_NI(insn->op, rn, imm);if ( rn == REGPC)MOVD_REG_IMM32(write_ptr, REG_TMP, insn->addr + 8);elseMOV_REG_REG(write_ptr, REG_TMP, reg_map[rn]);SUB_REG_IMM32(write_ptr, REG_TMP, imm);UPDATE_COND_FLAGS(write_ptr, REG_TMP, REG_EBP);return TRANS_SUCCESS;}Листинг 11б.Вызов для трансляции кода набора команд arm исоответствующий ему обработчик thumb.Как видно из листинга 5, монитор виртуальной машины предоставляеттекущий контекст процессора в виде структуры, для хранения адреса которойиспользуется регистр EBP.
Это дополнительно ограничивает количестводоступных для транслятора регистров общего назначения.Однако проблема составления карт регистров выходит за область даннойработы.3.3 Особенности реализации поддержки ThumbРазработка поддержки архитектуры семейства команд Thumb былазначительно облегчена наличием уже существующей и рабочей инфраструктурытранслятора системы команд arm.Основная работа заключалась в анализе инструкций системы команд Thumb исоставлении процедур обратного вызова для подсистем анализа потокаисполнения, составления карты регистров и трансляции.Внушительная часть инструкций первой версии Thumb имеет прямые аналогив наборе команд arm и значит, что для их реализации можно воспользоваться ужесуществующими процедурами обратного вызова с правильной пре- и постобработкой карты регистров и входных данных инструкции.Основную сложность вызывали инструкции второй версии системы командThumb, для которых такого отображения подчас не существовало из-заособенностей условного исполнения инструкцией If-Then и кодированиянепосредственных значений для команд Thumb.Анализ использования регистров был облегчен ограничениями, описаннымив главе 2.
Основной прирост производительности транслятора для Thumb системыкоманд ожидается благодаря более эффективному маппингу регистров. [10]В то же время, “специальные” и “сервисные” инструкции Thumb потребовалимодификации представления контекста процессора, в виде добавления в негосоответствующих полей. В том числе флагов условного исполнения дляинструкции IT.Во время работы над процедурами обратного вызова для подсистемы анализапотока исполнения в ней были выявлены ряд существенных недостатков.Все они были связаны с алгоритмической не оптимальностью используемыхструктур данных.Поэтому вторая часть данной работы посвящена короткому описаниюмодификаций данной системы.4.
Анализатор потока исполнения4.1 Описание анализатораДанный модуль занимается представлением исполняемого файла в видеориентированного графа блоков.Вершины этого дерева содержат блоки: последовательности инструкций,которые гарантированно должны быть исполнены от начала до конца блока одна заодной.Ребра, соединяющие вершины, обозначают условный переход, вызовфункции, либо возврат из вызова, плюс вырожденный случай выхода из режиматрансляции.На вход модуль принимает загруженный в память образ исполняемого файлаи адрес точки входа.typedef struct source_block {/* translated blocks are organized in a list */SLIST_ENTRY(source_block) list;SLIST_ENTRY(source_block) block_in_func_list; * the [begin; end) of this block *//addr_t begin, end;struct source_block *next_block;struct source_block *branch_block;void *translated_data;int is_entry_point : 1;int next_insn_is_invalid : 1;int is_referenced : 1;int is_external_reference : 1;int is_final_block : 1;} source_block_t;Листинг 11.
Структура, описывающие представление блокаНе смотря на это, как видно из листинга 6, в коде монитора виртуальноймашины использовалось представление блоков в виде обыкновенных односвязныхсписков.Иллюстрация 6. Схема представления блоков в графе анализатораЭкспериментальным путем, после запуска анализатора на множествеиспользующихся в условиях производства исполняемых файлов, таких какразличные сторонние графические библиотеки и движки, было выяснено, что всреднем, анализатор составляет один блок кода на ~73 инструкций.Это означает, что при запуска 400kB исходника (встраиваемая поисковаябиблиотека Algolia) может быть создано до тысячи блоков. Для графическихприложений, например, движка трехмерной графики Unity, объем библиотек можетсоставлять пару мегабайт.Конечно, данные числа приблизительны, и очевидно, что на практике такиеприкидки сказываются слабо за счет того, что не все из этого места являетсяисполняемым кодом.Однако даже такие грубые прикидки показывают, что использование другихструктур данных позволит выиграть время на этапе работы анализатора.4.2 Выбор структуры данныхНепосредственная работа с данным ориентированным графом, в основномосуществляется ради поиска в нем блоков по заданному логическому адресу/** Find an untranslated block which contains given "addr".* This is used to split blocks during code flow analysis.*/static source_block_t*user_cfa_find_block_for_addr(translated_image_t *image,addr_t addr);Листинг 12.
Дефиниция процедуры, являющейся “бутылочным горлышком”Прямой перебор по односвязному списку очевидно является неэффективнымподходом к решению данной задачи. [7]Как можно увидеть на листинге 11, блок представляет собой сутьпоследовательность прогрессирующих целочисленных адресов. Известно, чтоадреса непрерывны и не пересекаются, каждый блок определяется своимначальным и конечным адресом в последовательности.Задача поиска среди множества блоков такого, в который входит заданныйадрес, сводится к абстрактной задаче поиска интервала.
Для решения этой задачиобычно используется та или иная модификация структуры данных, называемойинтервальным деревом. [4]Выбор интервального дерева, основанного на самобалансирующемсякрасно-черном дереве, позволил улучшить общую производительность анализаторана Thumb-коде и больших исполняемых файлах.5. Измерение производительностиДля сравнения полученного прироста производительности, необходимо былоподобрать качественные сценарии ее оценки, которые всесторонне отразили бырезультаты данной работы.Ожидается, что имплементация двоичной трансляции для одной системынабора команд должна в результате дать значительный приростпроизводительности на исполняемых файлах, закодированных исключительноданным набором команд и не дать регрессий (т.е.