Найти в Дзене
K12 :: О ESP32 и не только

Расшифровка backtrace в коммандной строке windows

Оглавление

Добрый день, уважаемый читатель! В данной статье будет предложен сравнительно простой способ дешифровки адресов backtrace в среде VSCode + PlatformIO без необходимости установки сторонних программ.

Под дешифровкой backtrace в контексте данной статьи понимается преобразование адресов в имена файлов и номера строк исходного кода. В настоящее время я занимаюсь разработкой для ESP32, поэтому в статье рассмотрен пример именно для этой конфигурации. Но, насколько я понимаю, этот способ вполне применим и для других микроконтроллеров, с которыми можно работать в PlatformIO.

При разработке устройств на микроконтроллерах иногда приходится сталкиваться с различными сбоями, вызванными допущенными ошибками при программировании. При возникновении критических ошибок микроконтроллер печатает дамп регистров и backtrace, а затем перезагружается. В разных ситуациях текст сообщения может быть различным, например, это может выглядеть так:

Знакомая ситуация?
Знакомая ситуация?

Для меня содержимое регистров пока не представляет особой ценности, а вот расшифровка backtrace (то есть преобразование адресов вызовов в имена файлов и номера строк) позволяет точно установить место возникновения исключительной ситуации в коде программы. Проанализировав место возникновения ошибки в большинстве случаев сразу же удается понять причину её появления.

Вместо предисловия

Во всех случаях для декодирования backtrace нам потребуется ELF-файл, в котором, собственно, и содержится вся необходимая отладочная информация для сопоставления адресов номерам строк исходного кода. Для PlatformIO и esp32dev этот файл можно найти в каталоге каталог проекта\.pio\build\esp32dev\firmware.elf.

Для начала стоить упомянуть об штатных (уже имеющихся, готовых) средствах для декодирования исключений.

В Arduino IDE для анализа исключений существует достаточно удобный плагин EspExceptionDecoder. Он позволяет легко и просто декодировать backtrace, но, увы, в PlatformIO не работает.

В PlatformIO имеется возможность включить дешифрацию адресов в номера строк в встроенном терминале “на лету”, прямо при выводе сообщений в терминал. Для этого в файле параметров проекта platformio.ini необходимо добавить следующие строки:

monitor_filters = esp32_exception_decoder

Про этот способ я рассказывал в предыдущей статье. Удобно? Казалось бы очень… На деле это приводит к очень сильному замедлению вывода сообщений в терминал, ведь попытка декодирования производится для каждой новой строки в терминале. Пришлось отказаться от этой сомнительной возможности.

Если взять "лопату" побольше и копнуть глубже, то можно увидеть, что на самом деле и EspExceptionDecoder и esp32_exception_decoder сами по себе ничего не декодируют, а просто используют для декодирования адресов внешнюю программу: addr2line. Эта программа поставляется вместе с компилятором и может различаться для разных платформ и микроконтроллеров. На эту же информацию указывает и справка для IDF Monitor:

-2

Для ESP32 и ESP-IDF (toolchain-xtensa-esp32) ее можно найти здесь:

${env:USERPROFILE}\.platformio\packages\toolchain-xtensa-esp32\bin\xtensa-esp32-elf-addr2line.exe

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

Параметры командной стройки для утилиты addr2line

-3

Источники: ENG, RUS

В утилиту можно передавать не один адрес, а сразу несколько, разделенных пробелами. То есть можно передать сразу несколько адресов, и утилита расшифрует каждый из адресов отдельно.

Практическое применение

Для начала необходимо запустить командную строку Windows. Быстрее всего это делать, нажав клавиши “Win” + “R” на клавиатуре, а затем набрать команду “cmd“. Или через меню “Пуск” – “Служебные” – “Командная строка”. Затем в открытом окне вводим примерно следующую команду (правильные пути к файлам подставьте сами):

c:\Users\<ваш_профиль>\.platformio\packages\toolchain-xtensa-esp32\bin\xtensa-esp32-elf-addr2line.exe -pfiaC
-e c:\PlatformIO\dzen\.pio\build\esp32dev\firmware.elf
<backtrace>

где:

  • c:\Users\<ваш_профиль> – путь к текущему профилю пользователя, подставьте свои данные
  • toolchain-xtensa-esp32 – toolchain, который Вы используете, подставьте свои данные, если это необходимо
  • xtensa-esp32-elf- – префикс, который зависит от toolchain, подставьте свои данные, если это необходимо
  • c:\PlatformIO\dzen – путь к проекту, подставьте свои данные
  • esp32dev – MCU или плата, под которую собирается проект, подставьте свои данные
  • <backtrace>вместо <backtrace> подставляем собственно перечисление адресов, без слова “Backtrace:”

… и нажимаем Enter. Например:

c:\Users\kotyara12\.platformio\packages\toolchain-xtensa-esp32\bin\xtensa-esp32-elf-addr2line.exe -pfiaC -e c:\PlatformIO\village_security\.pio\build\esp32dev\firmware.elf 0x4008150a 0x400d5e4f 0x40082121 0x400d5cd3 0x400e7da6

В результате, если все сделано правильно, получим примерно такие результаты:

-4

На примере показан backtrace при получении “внешней” команды restart через mqtt. Команда оповещает системный цикл событий о перезапуске и запускает таймер на некоторое время, чтобы остальные службы смогли завершить свою работу. Что здесь видно: в последней строке таймер отработал положенное время и запустил callback-функцию espRestartTimer(void*), которая, в свою очередь, вызвала команду esp_restart. Во время завершения работы был вызван espDefaultShutdownHandler(), который, в свою очередь, вызвал debugUpdate(), где, собственно и произошло сохранение данного backtrace в области памяти NO_INIT, чтобы быть отправленным пользователю после перезагрузки.

В заключение небольшой совет: можно сохранить команду в cmd / bat файл и пользоваться более короткой записью.

На этом пока всё. Благодарю за внимание.

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

_______________

На этом пока всё, до встречи на сайте и на dzen-канале!

👍 Понравилась статья? Поддержите канал лайком или комментарием! Каналы на Дзене "живут" только за счет ваших лайков.

📌Подпишитесь на канал и вы всегда будете в курсе новых статей.

🔶 Полный архив статей вы найдете здесь

Благодарю за вашу поддержку! 🙏