Инструменты отладки нужны каждому разработчику. Однако, не существует универсальных решений, подходящих и тем, кто создаёт приложения пользовательского уровня, и тем, кто пишет низкоуровневые программы, вроде драйверов оборудования. Чем ближе к «железу» — тем больше хардкора в отладке и тестировании.
Из этого материала вы узнаете о том, как отлаживать код и анализировать исключения на уровне ядра Linux ОС Android в системах, основанных на архитектуре Intel. А именно, мы рассмотрим отладочный инструмент JTAG Debugger, который является частью пакета Intel System Studio Ultimate Edition. Мы расскажем о стандарте JTAG, о вышеупомянутом JTAG-отладчике Intel, об обработке исключений. В качестве примера мы будем использовать мини-компьютер MinnowBoard MAX с Intel Atom на борту.
Обзор JTAG
JTAG (произносится как «джей-таг», «jay-tag») – это сокращение от Joint Test Action Group. Обычно, когда говорят «JTAG», подразумевают стандарт IEEE 1149.1-1990 (IEEE Standard Test Access Port and Boundary-Scan Architecture). Этот стандарт устанавливает правила отладки и тестирования однокристальных систем (SoC, System on Chip) и программного обеспечения микропроцессоров (Microprocessor Software).
При JTAG-отладке используется набор инструментов, состоящий из трёх частей: программный JTAG-отладчик, установленный на главном компьютере, аппаратный JTAG-адаптер (датчик) и внутрисхемный отладчик (OCD, On Chip Debug), которым оснащена тестируемая микросхема.
Программный JTAG-отладчик
JTAG-отладчик – это программный инструмент, установленный на главном компьютере. Он получает данные и сведения об адресах от JTAG-адаптера и отображает их в пользовательском интерфейсе. Разработчик, в свою очередь, может отправлять команды JTAG-адаптеру, который подключен к основному компьютеру по USB или с помощью другого интерфейса.
Пользуясь этим инструментом, можно контролировать выполнение программы и отлаживать её на уровне исходного кода. Подобное реализуется благодаря файлам символов, которые соответствуют двоичным образам, загружаемым на целевые системы. Эти средства дают разработчику следующие возможности: запуск (run) и остановка (stop) исполнения кода, выполнение в ходе отладки шага с обходом (step over) и шага с заходом (step into), указание точек останова (breakpoints), доступ к памяти.
Пользуясь вышеописанными средствами, программист может выполнять отладку программной части целевой системы, исследовать системную память и регистры.
Intel JTAG Debugger (известный как XDB), входит в состав Intel System Studio Ultimate Edition. XDB – это тот самый программный инструмент JTAG-отладки, который должен быть установлен на главном компьютере.
Аппаратный JTAG-адаптер
JTAG-адаптер – это устройство, которое преобразует JTAG-сигналы в формат, подходящий для передачи компьютеру. Для сопряжения адаптеров и ПК используются такие интерфейсы, как USB, параллельный порт, RS-232, Ethernet. USB – самый популярный среди них. Именно он применяется для связи многих JTAG-адаптеров с компьютерами. Стандартом предусмотрено минимальное число JTAG-контактов для подключения целевых устройств к JTAG-адаптерам, однако, на практике применяются самые разные интерфейсы. Например, это 10- и 20-контактные разъемы для ARM, 14-контактный для ST, 16-контактный для OCDS.
В связке из отладчика Intel JTAG и MinnowBoard MAX, о которой идёт речь в этом материале, используется 60-контактный разъем для подключения целевого устройства. В качестве JTAG-адаптера для MinnowBoard MAX применяется Intel ITP-XDP3. Отладчик Intel JTAG совместим и с JTAG-адаптерами других производителей. Например – с Macraigor Systems usb2Demon и OpenOCD.
Внутрисхемный отладчик (целевой микрочип)
Главные компоненты внутрисхемного отладчика – это TAP (Test Access Point, тестовый порт) и TDI (Test Data In, вход тестовых данных)/TDP (Test Data Out, выход тестовых данных). Используя TAP можно сбрасывать, читать и записывать состояние регистров, пользоваться инструкцией BYPASS. Основная технология, которая применяется в JTAG – это так называемое граничное сканирование (Boundary Scan) с использованием сигнальных линий TDI/TDO.
Конфигурация из JTAG-адаптера и целевой системы. Здесь же показана плата расширения, которая используется для соединения Intel ITP-XDP3 и MinnowBoard MAX
Обзор исключений в архитектуре Intel
Исключение (exception) – это синхронное событие, которое генерируется, когда процессор, при выполнении инструкций, обнаруживает одно или несколько предопределенных условий. Архитектура IA-32 предусматривает три класса исключений: отказ (fault), ловушка (trap) и авария (abort). Обычно при возникновении отказов и ловушек возможно продолжение прерванной работы, в то время как при авариях – нет. Когда возникает исключение, оно обрабатывается так же, как обрабатываются прерывания. Это означает, что после остановки и сохранения текущего процесса, система переключается на обработчик исключения, а после того, как обработчик завершил работу, возвращается к исполняемой ранее задаче.
Исключения и прерывания защищенного режима
Вектор | Сокращённое наименование | Описание | Тип | Код ошибки | Источник |
0 | #DE | Ошибка деления | Отказ | Нет | Инструкции DIV и IDIV |
1 | #DB | Зарезервировано | Отказ / ловушка | Нет | Только для использования Intel |
2 | — | Прерывание NMI | Прерывание | Нет | Внешнее немаскируемое прерывание |
3 | #BP | Точка останова | Ловушка | Нет | Инструкция INT 3 |
4 | #OF | Переполнение | Ловушка | Нет | Инструкция INT0 |
5 | #BR | Выход за границы диапазона | Отказ | Нет | Инструкция BOUND |
6 | #UD | Неправильный (неопределенный) код операции | Отказ | Нет | Инструкция UD2 или зарезервированный код операции |
7 | #NM | Устройство недоступно (Нет математического сопроцессора) | Отказ | Нет | Инструкции вычислений с плавающей точкой или инструкции WAIT/FWAIT |
8 | #DF | Двойной отказ | Авария | Да (ноль) | Любая инструкция, которая может сгенерировать исключение, NMI или INTR |
9 | Выход за пределы сегмента сопроцессора (зарезервировано) | Отказ | Нет | Инструкция, выполняющая вычисления с плавающей точкой | |
10 | #TS | Неверный TSS | Отказ | Да | Переключение задач или доступ к TSS |
11 | #NP | Сегмент отсутствует | Отказ | Да | Загрузка сегментных регистров или доступ к системным сегментам |
12 | #SS | Отказ сегмента стека | Отказ | Да | Операции со стеком и загрузка регистра SS |
13 | #GP | Общая ошибка защиты | Отказ | Да | Ошибки, связанные с памятью, проверками защиты |
14 | #PF | Отказ страницы | Отказ | Да | Работа с памятью |
15 | — | Зарезервировано Intel, не предназначено для использования | Нет | ||
16 | #MF | Ошибка вычислений с плавающей точкой x87 FPU (Ошибка вычислений) | Отказ | Нет | Вычисления с плавающей точкой на x87 FPU или инструкции WAIT/FWAIT |
17 | #AC | Ошибка проверки выравнивания | Отказ | Да (ноль) | Работа с данными в памяти |
18 | #MC | Аппаратная ошибка | Авария | Нет | Коды ошибок (если они есть) и их источник зависят от аппаратного обеспечения |
19 | #XM | Исключения вычислений с плавающей точкой SIMD | Отказ | Нет | Инструкции вычислений с плавающей точкой SSE, SSE2, SSE3 |
20 | #VE | Исключение виртуализации | Отказ | Нет | EPT-нарушения |
21 – 31 | — | Зарезервировано Intel, не предназначено для использования | |||
32 – 255 | — | Прерывания, заданные разработчиком (не зарезервированы) | Прерывание | Внешние прерывания или инструкции INT n. |
Подготовка MinnowBoard MAX и Intel ITP-XDP3 к подключению к главному компьютеру по USB
Для начала надо установить на MinnowBoard MAX ОС Android. Для того чтобы это сделать, обратитесь к материалу «Статья разработчика Intel System Studio: настройка, сборка и профилировка Linux-ядра Android с помощью VTune». Он содержит инструкцию по сборке, установке и настройке Android на MinnowBoard MAX.
После установки ОС подключим MinnowBoard MAX к JTAG-адаптеру Intel ITP-XDP3 с помощью платы расширения. JTAG-адаптер присоединим к ПК по USB. На главном компьютере должна быть установлена Intel System Studio Ultimate Edition, в состав которой входит USB-драйвер для Intel ITP-XDP3.
MinnowBoard MAX подключён к JTAG-адаптеру Intel ITP-XDP3, который, в свою очередь, подключён к хост-компьютеру с установленным на нём JTAG-отладчиком от Intel (XDB)
Использование JTAG-отладчика Intel (XDB) для отладки ядра Android на MinnowBoard MAX
Рассмотрим пошаговую процедуру использования XDB в деле отладки Linux-ядра ОС Android.
1. Запустим JTAG-отладчик Intel. Для этого нужно перейти в папку, где он установлен, и запустить пакетный файл (например – start_xdb_legacy_products.bat).
2. Подключимся к целевому устройству. Для этого нужно, в интерфейсе JTAG-отладчика, выполнить команду File > Connect и выбрать, во-первых, аппаратный JTAG- адаптер. В нашем случае это Intel ITP-XPD3. Во-вторых – надо указать целевую платформу. Нас интересует Intel Atom Processor E38xx, Z3680, X37xx – 2 cores (ValleyView).
Выбор аппаратного JTAG-адаптера и целевой платформы в XDB
3. Загрузим файлы символов и укажем директорию файлов исходного кода. Для этого нужно выполнить в JTAG-отладчике Intel команду File > Load / Unload Symbol и указать файлы символов. Для файлов исходного кода нужно выполнить команду Options > Source Directories и указать правила сопоставления файлов исходного кода и файлов символов, а так же соответствующие директории. Правила позволяют настроить соответствие путей в файле символов, которые записываются во время компиляции, и текущих мест расположения файлов исходного кода.
4. Найдём entry-файл, в котором имеется обработчик исключений. Воспользуемся командой меню JTAG-отладчика Intel View > Source files и откроем файл entry_64.S.
Поиск файла entry_64.S
5. Установим точку останова на точке входа исключения. Для этого найдём строку ENTRY(error_entry), которая является точкой входа исключения с кодом ошибки в регистре RAX. Каждый обработчик исключения определён как макрос zeroentry или errorentry. Таким образом, можно установить точку останова в error_entry или в каком-то конкретном обработчике. В данном материале мы используем для тестирования «zeroentry invalid_op do_invalid_op».
ENTRY(error_entry) XCPT_FRAME CFI_ADJUST_CFA_OFFSET 15*8 /* oldrax contains error code */ cld movq_cfi rdi, RDI+8 movq_cfi rsi, RSI+8 movq_cfi rdx, RDX+8 movq_cfi rcx, RCX+8 movq_cfi rax, RAX+8 movq_cfi r8, R8+8 movq_cfi r9, R9+8 movq_cfi r10, R10+8 movq_cfi r11, R11+8 movq_cfi rbx, RBX+8 movq_cfi rbp, RBP+8 movq_cfi r12, R12+8 movq_cfi r13, R13+8 movq_cfi r14, R14+8 movq_cfi r15, R15+8 xorl %ebx,%ebx testl $3,CS+8(%rsp) je error_kernelspace error_swapgs: SWAPGS error_sti: TRACE_IRQS_OFF ret <....> zeroentry divide_error do_divide_error zeroentry overflow do_overflow zeroentry bounds do_bounds zeroentry invalid_op do_invalid_op zeroentry device_not_available do_device_not_available paranoiderrorentry double_fault do_double_fault zeroentry coprocessor_segment_overrun do_coprocessor_segment_overrun errorentry invalid_TSS do_invalid_TSS errorentry segment_not_present do_segment_not_present zeroentry spurious_interrupt_bug do_spurious_interrupt_bug zeroentry coprocessor_error do_coprocessor_error errorentry alignment_check do_alignment_check zeroentry simd_coprocessor_error do_simd_coprocessor_error
Теперь, в качестве примера, вызовем исключение, и проверим, сработал ли обработчик, на котором мы установили точку останова. Установим точку останова на «zeroentry invalid_op do_invalid_op» и вызовем блок кода BUG(), который выполняет инструкцию ud2, вызывающую отказ (fault) «Неправильный код операции».
#define BUG() \ do { \ asm volatile("ud2"); \ unreachable(); \ } while (0)
Вызов BUG()
Макрос BUG() надо добавить в собственный тестовый код уровня ядра для того, чтобы было вызвано исключение. В данном примере мы добавили его в keyboard.c для того, чтобы исключение вызывалось при появлении особых последовательностей символов, вводимых с клавиатуры.
Результат вызова макроса BUG()
Результат вызова макроса BUG(), увеличенный фрагмент копии экрана
Остановка на точке останова Invalid_op
Если установить точку останова в обработчике исключения «Неправильный код операции» или на входе в обработчик исключения, можно увидеть сообщение об исключении, и, в ходе отладки, добраться до места возникновения ошибки.
Точка останова в обработчике исключения «Неправильный код операции»
Точка останова в обработчике исключения «Неправильный код операции», увеличенный фрагмент копии экрана
Заключение
Некоторые исключения – это критические ошибки аппаратного и программного обеспечения системы. Поэтому очень важно знать – как, почему и где они происходят. Используя JTAG-отладчик Intel, такие ошибки легко обнаружить и добраться до причины их возникновения. Всё это возможно потому, что данный отладчик предоставляет разработчику мощные возможности. Среди них – лёгкий доступ к скомпилированному и исходному коду, просмотр стека вызовов и регистров.
Полезные ссылки
Intel 64 and IA-32 Architectures Software Developer’s Manual
JTAG Tutorial: IEE 1149.x and Software Debug
ссылка на оригинал статьи http://habrahabr.ru/post/266701/
Добавить комментарий