Содержание
Отладка программ в решении на базе KasperskyOS
Использование отладчика GDB
Чтобы выполнить отладку программ в решении на базе KasperskyOS, нужно использовать отладчик GDB из состава KasperskyOS Community Edition на компьютере под управлением ОС Ubuntu. Отладку можно выполнить как на QEMU из состава KasperskyOS Community Edition, так и на аппаратной платформе. Для отладки на QEMU нужно использовать GDB-сервер QEMU или GDB-сервер ядра KasperskyOS. Для отладки на аппаратной платформе требуется использовать GDB-сервер ядра KasperskyOS.
Работоспособность отладчика GDB и QEMU не из состава KasperskyOS Community Edition не гарантируется.
Отладчик GDB по умолчанию поддерживает OS ABI (англ. Operating System ABI), специфичный для KasperskyOS. При изменении профиля OS ABI, заданного по умолчанию, возможность полноценной отладки не гарантируется.
Можно выполнять отладку одновременно нескольких программ решения, загрузив отладочные символы для нескольких исполняемых файлов.
Отладочные символы исполняемых файлов могут сохраняться в самих исполняемых файлах либо в отдельных файлах. Во втором случае можно существенно уменьшить размер образа решения. Чтобы сохранить отладочные символы в файлах *.dbg
, нужно использовать следующую CMake
-команду:
Обратная трассировка стека при аварийном завершении процесса
Если процесс завершается аварийно, то ядро KasperskyOS выводит данные обратной трассировки стека (сведения о стеке вызовов) для потока исполнения, в котором возникло необработанное исключение. Эти данные позволяют определить последовательность вызовов функций, которая привела к аварийному завершению процесса.
В некоторых случаях при аварийном завершении процесса ядро KasperskyOS не может подготовить сведения о стеке вызовов. Причиной этому могут быть, например, параметры оптимизации, которые применялись при сборке программы, исполнявшейся в контексте аварийно завершенного процесса.
Поддержка санитайзеров
В KasperskyOS Community Edition поддерживаются санитайзеры ASAN и UBSAN.
Отладка программ с использованием GDB-сервера QEMU
GDB-сервер QEMU имеет следующие особенности:
- Не распознает процессы и потоки исполнения, управляемые KasperskyOS.
Все процессы, управляемые KasperskyOS, рассматриваются GDB-сервером QEMU как один процесс. Этот процесс включает один или несколько потоков исполнения в зависимости от того, сколько потоков может исполняться параллельно на аппаратной платформе, которую эмулирует QEMU. Таким образом, процессы и потоки исполнения, с которыми работает GDB-сервер QEMU, не являются процессами и потоками исполнения, управляемыми KasperskyOS.
- Не гарантирует возможности отладки при эмуляции на QEMU аппаратных платформ с симметричной многопроцессорностью (англ. Symmetric Multiprocessing, SMP).
GDB-сервер QEMU можно использовать при эмуляции на QEMU аппаратных платформ с SMP. Но при этом, например, могут не работать GDB-команды исполнения программы по шагам (например,
next
,step
).
Подготовка к отладке
Чтобы подготовить условия для отладки с использованием GDB-сервера QEMU, нужно выполнить следующие шаги:
- Отключить поддержку ASLR и задать адреса памяти для загрузки секций
.text
исполняемых файлов.Для этого нужно использовать следующую
CMake
-команду:set_target_properties(<имя программы> PROPERTIES LINK_FLAGS "-no-pie -Ttext <адрес>")Отладчику GDB нужен адрес памяти, по которому загружен ELF-образ, чтобы сопоставить отладочные символы с ELF-образом. ASLR, поддерживаемая по умолчанию, приводит к тому, что этот адрес задается случайным значением, которое не известно отладчику GDB. Это затрудняет отладку. Чтобы отключить поддержку ASLR, нужно указать флаг
-no-pie
.GDB-сервер QEMU рассматривает все исполняющиеся процессы, управляемые KasperskyOS, как один процесс. Если ASLR не поддерживается, то по умолчанию компоновщик делает так, что исполняемые файлы загружаются по одному и тому же адресу памяти процессов. В результате этого загружаемые сегменты исполняемых файлов пересекаются в памяти с точки зрения отладчика GDB, и отладка выполняется некорректно (например, отображаются некорректные значения переменных, или срабатывают точки останова, установленные для другой программы). Чтобы избежать пересечения загружаемых сегментов, соответствующих разным программам, нужно использовать параметр
-Ttext
<адрес
>, который задает адрес загрузки секции.text
. В качестве смещения между адресами загрузки секции.text
в разных процессах можно принять значение, превышающее на 1 МБ размер наибольшего исполняемого файла в образе решения. Например, в качестве адреса загрузки секции.text
для программыClient
в примере ping можно указать значение0x06000000
, а для программыServer
в этом примере можно указать значение0x06200000
.Смещение между адресами секций
.text
не может гарантировать отсутствия пересечений загружаемых сегментов, если заранее собранные исполняемые файлы, используемые в решении (например, из состава KasperskyOS Community Edition), скомпонованы для поддержки ASLR. (Отключить ASLR и задать адреса загрузки секций.text
можно только для тех исполняемых файлов, сборка которых выполняется при создании решения. Для заранее собранных исполняемых файлов этого сделать нельзя.) Секции.text
таких исполняемых файлов загружаются по случайным адресам, что может привести к пересечению с загружаемыми сегментами, соответствующими программе, которую нужно отладить. - [Опционально] Задать параметры запуска QEMU.
Чтобы изменить начальные и/или добавить новые параметры запуска QEMU, нужно использовать параметр
QEMU_FLAGS
CMake
-командыbuild_kos_qemu_image()
.Пример:
set(QEMU_FLAGS "-m 2048 -machine vexpress-a15,secure=on \ -cpu cortex-a72 -nographic -monitor none -smp 4") build_kos_qemu_image(kos-qemu-image ... QEMU_FLAGS "${QEMU_FLAGS}")
Начальные шаги отладки
Чтобы начать отладку с использованием GDB-сервера QEMU, нужно выполнить следующие шаги:
- Собрать отладочные версии исполняемых файлов и библиотек, создать образ решения для QEMU и запустить QEMU в режиме ожидания подключения отладчика GDB.
Для этого нужно вызвать shell-команды
cmake
, указав параметры-D CMAKE_BUILD_TYPE:STRING=Debug
и--target gdbsim
.Пример:
"Unix Makefiles" \ -D CMAKE_BUILD_TYPE:STRING=Debug \ -D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \ -B build \ && cmake --build build --target gdbsim... cmake -GВместо цели
gdbsim
можно указать цельgdbsim/fast
, чтобы не выполнять повторную сборку.QEMU запускается, но не исполняет код решения, ожидая вызова GDB-команды
continue
. - Запустить отладчик GDB и подключиться к GDB-серверу QEMU.
Для этого нужно вызвать shell-команду
make gdb
в директорииbuild
. - [Опционально] Задать дополнительные пути для поиска динамических библиотек с отладочными символами.
На шаге 1 в файл
build/einit/.gdbinit
автоматически добавляется путь, по которому отладчик GDB выполняет поиск динамических библиотек с отладочными символами из состава KasperskyOS Community Edition (в качестве параметра GDB-командыset sysroot
). Чтобы задать дополнительные пути для поиска динамических библиотек, нужно вызвать следующую GDB-команду:set solib-search-path <путь к директории>... - [Опционально] Загрузить отладочные символы исполняемых файлов.
Если для исполняемых файлов со статической компоновкой заданы адреса загрузки секции
.text
(CMake
-командойset_target_properties()
), то GDB-команда загрузки отладочных символов для каждого из этих файлов автоматически добавляется в файлbuild/einit/.gdbinit
на шаге 1.Если для одного исполняемого файла с динамической компоновкой задан адрес загрузки секции
.text
, то GDB-команда загрузки отладочных символов для этого файла автоматически добавляется в файлbuild/einit/.gdbinit
на шаге 1. Если для нескольких исполняемых файлов с динамической компоновкой заданы адреса загрузки секции.text
, то GDB-команда загрузки отладочных символов автоматически не добавляется в файлbuild/einit/.gdbinit
на шаге 1 ни для одного из этих исполняемых файлов.Чтобы загрузить отладочные символы вручную, нужно использовать следующие GDB-команды:
add-symbol-file
<путь к файлу
> – для исполняемых файлов со статической или динамической компоновкой;file
<путь к файлу
> – для исполняемых файлов с динамической компоновкой.
GDB-команду
file
нужно использовать, чтобы отладчик GDB загрузил отладочные символы исполняемого файла и динамических библиотек, от которых зависит этот исполняемый файл. Чтобы отладчик GDB загрузил отладочные символы только исполняемого файла с динамической компоновкой, нужно использовать GDB-командуadd-symbol-file
.GDB-команда
file
может быть применена только для одного исполняемого файла. То есть отладчик GDB не может загрузить отладочные символы динамических библиотек для нескольких исполняемых файлов одновременно.После вызова GDB-команды
file
может появиться следующее сообщение:warning: Unable to find dynamic linker breakpoint function. GDB will be unable to debug shared library initializers and track explicitly loaded dynamic code.Это сообщение нужно проигнорировать.
Если отладочные символы сохраняются не в исполняемых файлах, а в отдельных файлах, то в исполняемые файлы добавляются ссылки на файлы с отладочными символами. При вызове GDB-команды
add-symbol-file
илиfile
можно указать как исполняемый файл, так и файл с отладочными символами.
При выполнении повторной сборки (шаг 1) необязательно завершать сессию отладки, то есть выходить из отладчика. (Это позволяет избежать повторного выполнения таких действий, как загрузка отладочных символов и задание дополнительных путей для поиска динамических библиотек.) Чтобы не завершать сессию отладки, нужно перед повторной сборкой выполнить GDB-команду detach
, а после запуска QEMU выполнить GDB-команду target remote localhost:1234
.
GDB-команды (например, для загрузки отладочных символов или задания дополнительных путей для поиска динамических библиотек) можно записать в файл, а затем вызывать их, используя GDB-команду source
<путь к файлу
>.
Особенности отладки при эмуляции аппаратных платформ с SMP
Процессоры (вычислительные ядра) представляются как потоки исполнения.
Чтобы вывести сведения о процессорах, нужно вызвать следующую GDB-команду:
Чтобы переключиться на другой процессор, нужно вызвать следующую GDB-команду:
Отладка программ с использованием GDB-сервера ядра KasperskyOS
GDB-сервер ядра имеет следующие особенности:
- Распознает процессы и потоки исполнения, управляемые KasperskyOS.
- Поддерживает отладку на аппаратных платформах с SMP (в том числе при эмуляции на QEMU).
Подготовка к отладке на QEMU
Чтобы подготовить условия для отладки с использованием GDB-сервера ядра KasperskyOS на QEMU, нужно выполнить следующие шаги:
- Проверить, что в составе KasperskyOS Community Edition есть версия ядра с GDB-сервером.
Для это нужно убедиться в наличии файла
libexec/aarch64-kos/kos-qemu-gdbstub
в составе KasperskyOS Community Edition. - Добавить параметр
GDBSTUB_KERNEL
в список параметровCMake
-командыbuild_kos_qemu_image()
.Этот параметр включает в решение ядро с GDB-сервером.
Пример:
build_kos_qemu_image(kos-qemu-image GDBSTUB_KERNEL ... QEMU_FLAGS "${QEMU_FLAGS}") - Создать файл
.gdbinit
, чтобы не вызывать вручную начальные GDB-команды при каждом запуске отладчика GDB. (Файл.gdbinit
нужно сохранить в директории, где будет запускаться отладчик GDB.)Пример:
# Задать путь для поиска динамических библиотек с отладочными символами из # состава KasperskyOS Community Edition set sysroot /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos # Задать дополнительные пути для поиска динамических библиотек с отладочными # символами set solib-search-path /home/user/example/build/lib1:/home/user/example/build/lib2 # Настроить управление потоками исполнения (опционально) # Отладчик GDB может работать в режиме all-stop или non-stop. В первом режиме # отладчик GDB считает, что при остановке потока исполнения, контекст которого # находится в фокусе отладки, останавливаются все остальные потоки исполнения, # о которых известно отладчику GDB. Во втором режиме отладчик GDB считает, что # все потоки, кроме остановленного, продолжают исполняться. Режим all-stop # применяется отладчиком GDB по умолчанию, и GDB-сервер ядра дает возможность # использовать только этот режим. Чтобы изменить заданные по умолчанию параметры # управления потоками исполнения в режиме all-stop, нужно использовать GDB-команды # set scheduler-locking и set schedule-multiple. # В этом примере первая GDB-команда указывает отладчику GDB, что при возобновлении # исполнения потока, контекст которого находится в фокусе отладки (например, # GDB-командами continue, step, next), нужно возобновить исполнение остальных потоков. # Вторая GDB-команда указывает отладчику GDB, что при возобновлении исполнения потока, # контекст которого находится в фокусе отладки, нужно возобновить исполнение всех # потоков, входящих в процессы всех программ, для которых выполняется отладка. set scheduler-locking off set schedule-multiple on # Подключить отладчик GDB к GDB-серверу ядра # GDB-сервер ядра взаимодействует с отладчиком GDB по расширенному протоколу, # и QEMU предоставляет доступ к GDB-серверу ядра через TCP-сокет. target extended-remote localhost:1234
Начальные шаги отладки на QEMU
Чтобы начать отладку с использованием GDB-сервера ядра KasperskyOS на QEMU, нужно выполнить следующие шаги:
- Собрать отладочные версии исполняемых файлов и библиотек, создать образ решения для QEMU и запустить QEMU.
Для этого нужно вызвать shell-команды
cmake
, указав параметры-D CMAKE_BUILD_TYPE:STRING=Debug
и--target sim
.Пример:
"Unix Makefiles" \ -D CMAKE_BUILD_TYPE:STRING=Debug \ -D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \ -B build \ && cmake --build build --target sim... cmake -GВместо цели
sim
можно указать цельsim/fast
, чтобы не выполнять повторную сборку.QEMU запускается и исполняет код решения. Исполнение кода решения останавливается при подключении отладчика GDB.
- Запустить отладчик GDB и подключиться к GDB-серверу ядра.
Для этого нужно запустить исполняемый файл
toolchain/bin/aarch64-kos-gdb
из состава KasperskyOS Community Edition. Запуск нужно выполнить в директории, где сохранен созданный вручную файл.gdbinit
. - Создать инфериоры, привязать их к процессам и загрузить отладочные символы.
Чтобы загрузить отладочные символы, нужно переключиться на инфериор, ассоциированный с процессом, и использовать следующие GDB-команды:
add-symbol-file
<путь к файлу
> – для исполняемых файлов со статической или динамической компоновкой;file
<путь к файлу
> – для исполняемых файлов с динамической компоновкой.
GDB-команду
file
нужно использовать, чтобы отладчик GDB загрузил отладочные символы исполняемого файла и динамических библиотек, от которых зависит этот исполняемый файл. Чтобы отладчик GDB загрузил отладочные символы только исполняемого файла с динамической компоновкой, нужно использовать GDB-командуadd-symbol-file
.Если отладочные символы сохраняются не в исполняемых файлах, а в отдельных файлах, то в исполняемые файлы добавляются ссылки на файлы с отладочными символами. При вызове GDB-команды
add-symbol-file
илиfile
можно указать как исполняемый файл, так и файл с отладочными символами.
При повторной сборке (шаг 1) нужно завершить сессию отладки (выйти из отладчика GDB) и выполнить повторно шаги 2 и 3.
Подготовка к отладке на аппаратной платформе
Чтобы подготовить условия для отладки с использованием GDB-сервера ядра KasperskyOS на аппаратной платформе, нужно выполнить следующие шаги:
- Проверить, что в составе KasperskyOS Community Edition есть версии ядра с GDB-сервером.
Для это нужно убедиться в наличии файла
libexec/aarch64-kos/kos-gdbstub
в составе KasperskyOS Community Edition. - Скоммутировать компьютер, на котором будет работать отладчик GDB, с аппаратной платформой.
Для подключения компьютера к аппаратной платформе нужно использовать преобразователи USB-UART. Схемы соединения преобразователей USB-UART и аппаратных платформ см. в "Подготовка Raspberry Pi 4 B к запуску примеров" и "Подготовка Radxa ROCK 3A к запуску примеров".
- Добавить параметр
GDBSTUB_KERNEL
в список параметровCMake
-командыbuild_kos_hw_image()
.Этот параметр включает в решение ядро с GDB-сервером.
Пример:
build_kos_hw_image(kos-image GDBSTUB_KERNEL ... IMAGE_FILES ${ENTITIES}) - Создать файл
.gdbinit
, чтобы не вызывать вручную начальные GDB-команды при каждом запуске отладчика GDB. (Файл.gdbinit
нужно сохранить в директории, где будет запускаться отладчик GDB.)Пример:
# Задать путь для поиска динамических библиотек с отладочными символами из # состава KasperskyOS Community Edition set sysroot /opt/KasperskyOS-Community-Edition-<version>/sysroot-aarch64-kos # Задать дополнительные пути для поиска динамических библиотек с отладочными # символами set solib-search-path /home/user/example/build/lib1:/home/user/example/build/lib2 # Настроить управление потоками исполнения (опционально) # Отладчик GDB может работать в режиме all-stop или non-stop. В первом режиме # отладчик GDB считает, что при остановке потока исполнения, контекст которого # находится в фокусе отладки, останавливаются все остальные потоки исполнения, # о которых известно отладчику GDB. Во втором режиме отладчик GDB считает, что # все потоки, кроме остановленного, продолжают исполняться. Режим all-stop # применяется отладчиком GDB по умолчанию, и GDB-сервер ядра дает возможность # использовать только этот режим. Чтобы изменить заданные по умолчанию параметры # управления потоками исполнения в режиме all-stop, нужно использовать GDB-команды # set scheduler-locking и set schedule-multiple. # В этом примере первая GDB-команда указывает отладчику GDB, что при возобновлении # исполнения потока, контекст которого находится в фокусе отладки (например, # GDB-командами continue, step, next), нужно возобновить исполнение остальных потоков. # Вторая GDB-команда указывает отладчику GDB, что при возобновлении исполнения потока, # контекст которого находится в фокусе отладки, нужно возобновить исполнение всех # потоков, входящих в процессы всех программ, для которых выполняется отладка. set scheduler-locking off set schedule-multiple on # Задать символьную скорость для взаимодействия с GDB-сервером ядра # Нужно задать значение 115200 бод. set serial baud 115200 # Подключить отладчик GDB к GDB-серверу ядра # Нужно задать порт USB, через который подключен преобразователь USB-UART, # используемый для отладки. Также необходимо задать, что GDB-сервер ядра # взаимодействует с отладчиком GDB по расширенному протоколу. target extended-remote /dev/ttyUSB1
Начальные шаги отладки на аппаратной платформе
Чтобы начать отладку с использованием GDB-сервера ядра KasperskyOS на аппаратной платформе, нужно выполнить следующие шаги:
- Собрать отладочные версии исполняемых файлов и библиотек и создать образ решения для аппаратной платформы.
Для этого нужно вызвать shell-команды
cmake
, указав параметры-D CMAKE_BUILD_TYPE:STRING=Debug
и--target
<tgt
>, гдеtgt
– значение параметраNAME
вCMake
-командеbuild_kos_hw_image()
.Пример:
"Unix Makefiles" \ -D CMAKE_BUILD_TYPE:STRING=Debug \ -D CMAKE_TOOLCHAIN_FILE=$SDK_PREFIX/toolchain/share/toolchain-$TARGET.cmake \ -B build \ && cmake --build build --target kos-image... cmake -G - Загрузить образ решения на аппаратную платформу и запустить решение.
Исполнение кода решения останавливается при подключении отладчика GDB.
- Запустить отладчик GDB и подключиться к GDB-серверу ядра.
Для этого нужно запустить исполняемый файл
toolchain/bin/aarch64-kos-gdb
из состава KasperskyOS Community Edition. Запуск нужно выполнить в директории, где сохранен созданный вручную файл.gdbinit
. - Создать инфериоры, привязать их к процессами и загрузить отладочные символы.
Чтобы загрузить отладочные символы, нужно переключиться на инфериор, ассоциированный с процессом, и использовать следующие GDB-команды:
add-symbol-file
<путь к файлу
> – для исполняемых файлов со статической или динамической компоновкой;file
<путь к файлу
> – для исполняемых файлов с динамической компоновкой.
GDB-команду
file
нужно использовать, чтобы отладчик GDB загрузил отладочные символы исполняемого файла и динамических библиотек, от которых зависит этот исполняемый файл. Чтобы отладчик GDB загрузил отладочные символы только исполняемого файла с динамической компоновкой, нужно использовать GDB-командуadd-symbol-file
.Если отладочные символы сохраняются не в исполняемых файлах, а в отдельных файлах, то в исполняемые файлы добавляются ссылки на файлы с отладочными символами. При вызове GDB-команды
add-symbol-file
илиfile
можно указывать как исполняемый файл, так и файл с отладочными символами.
При повторной сборке (шаг 1) нужно завершить сессию отладки (выйти из отладчика GDB) и выполнить повторно шаги 2-4.
Работа с процессами и потоками исполнения
В отладчике GDB для работы с процессами используются объекты, которые называются инфериорами (англ. inferiors). Процесс каждой программы, которую нужно отладить, должен быть привязан к отдельному инфериору. Переключение между инфериорами соответствует переключению фокуса отладки в контекст другого процесса. Отладочные символы для программы, которую требуется отладить, нужно загружать после переключения на инфериор, который привязан к процессу этой программы.
При запуске отладчика GDB автоматически создается инфериор. При подключении отладчика GDB к GDB-серверу ядра исполнение кода решения останавливается, и этот инфериор автоматически привязывается к процессу, содержащему поток исполнения, в контексте которого останавливается исполнение кода решения. Остальные требуемые инфериоры могут быть созданы, привязаны к процессам и отвязаны от процессов вручную или автоматически. В первом случае нужно использовать GDB-команды для работы с инфериорами. Во втором случае требуется настроить обработку событий жизненного цикла процессов.
GDB-команды для работы с инфериорами
Для работы с инфериорами нужно использовать следующие GDB-команды:
info inferiors
Выводит список инфериоров. Текущий инфериор отмечается символом
*
. (Контекст процесса, ассоциированного с текущим инфериором, находится в фокусе отладки.)add-inferior
Создает инфериор.
inferior
<номер инфериора
>Переключает на другой инфериор.
attach
<PID
>Привязывает текущий инфериор к процессу с идентификатором PID. Чтобы вывести список процессов, нужно выполнить GDB-команду
info os processes
.detach
Отвязывает текущий инфериор от процесса.
Настройка обработки событий жизненного цикла процессов
GDB-сервер ядра сообщает отладчику GDB о наступлении следующих событий:
- создание дочернего процесса;
- запуск начального потока исполнения дочернего процесса;
- завершение процесса.
Отладчик GDB обрабатывает событие 1 только в том случае, если существует инфериор, привязанный к родительскому процессу. Для обработки события 2 необходимо, чтобы отладчик GDB предварительно обработал событие 1 при создании дочернего процесса. При этом событие 2 обрабатывается, даже если родительский процесс уже отвязан от инфериора, например, по причине завершения.
Чтобы настроить обработку событий 1 и 2, нужно использовать следующие GDB-команды:
set follow-fork-mode
{child
|parent
}Указывает отладчику GDB перейти в контекст дочернего процесса (
child
) или остаться в контексте родительского процесса (parent
) при наступлении события 1. Второй вариант выполняется по умолчанию.set detach-on-fork
{on
|off
}Указывает отладчику GDB оставить родительский или дочерний процесс привязанным к инфериору (
on
) или оставить родительский процесс привязанным к инфериору, а также создать новый инфериор и привязать его к дочернему процессу (off
) при наступлении события 1. Первый вариант выполняется по умолчанию. При этом, какой процесс привязан к инфериору (родительский или дочерний), зависит от параметра GDB-командыset follow-fork-mode
.set follow-exec-mode
{new
|same
}Указывает отладчику GDB создать новый инфериор и привязать его к дочернему процессу (
new
) или не делать этого (same
) при наступлении события 2. Второй вариант выполняется по умолчанию.
Рекомендуется настроить обработку событий 1 и 2 следующим образом:
Такая конфигурация обеспечивает обработку событий 1 и 2 отладчиком GDB следующим образом:
- При наступлении события 1 создается новый инфериор, который привязывается к дочернему процессу.
- При наступлении события 1 родительский процесс остается привязанным к инфериору.
- При наступлении события 2 не создается новый инфериор для дочернего процесса.
Обработку отладчиком GDB события 2 можно использовать для остановки исполнения программы до передачи управления функции main()
, чтобы не применять бесконечный цикл.
Чтобы исполнение программы остановилось при наступлении события 2, нужно использовать следующую GDB-команду:
Эта GDB-команда обеспечивает остановку исполнения каждого дочернего процесса, при создании которого было обработано событие 1. Чтобы выполнить остановку исполнения отдельных процессов, нужно использовать следующую GDB-команду:
Последующий вызов этой GDB-команды отменяет предыдущий, а ее вызов без параметров означает остановку каждого дочернего процесса, при создании которого было обработано событие 1.
Событие 3 обрабатывается отладчиком GDB только в том случае, если созданы инфериоры, привязанные к завершившимся процессам. При обработке этого события отладчик GDB отвязывает инфериор от завершившегося процесса. Обработку события 3 не требуется настраивать.
GDB-команды для работы с потоками исполнения
Чтобы вывести список потоков исполнения, которые содержатся в процессах, привязанных к инфериорам, нужно выполнить следующую GDB-команду:
Текущий поток исполнения отмечается символом *
. (Контекст текущего потока исполнения находится в фокусе отладки.)
Чтобы перейти в контекст другого потока исполнения, нужно выполнить следующую GDB-команду:
Переход в контекст другого потока исполнения приводит к переключению на другой инфериор, если этот поток исполнения содержится процессе, привязанном к инфериору, который не является текущим.
В началоАнализ данных обратной трассировки стека при аварийном завершении процесса
При завершении процесса в результате необработанного исключения ядро KasperskyOS выводит данные обратной трассировки стека в следующем виде:
Здесь очевидна последовательность вызовов функций, которая привела к аварийному завершению процесса. В конце последовательности код функции _vfs_backend_create()
, размещенный в памяти процесса по адресу 0x000000000405f478
, вызвал функцию __assert_func()
, а код функции __assert_func()
, размещенный в памяти процесса по адресу 0x0000000004068498
, вызвал исключение. То есть исключение возникло при проверке корректности условий в функции _vfs_backend_create()
. (Запись вида <имя функции
>+0x
<смещение
> означает адрес внутри кода функции. Например, запись _vfs_backend_create+0xe8
означает адрес внутри кода функции _vfs_backend_create()
, смещенный относительно адреса начала кода этой функции на 0xe8
байт. Запись _vfs_backend_create+0xe8
соответствует адресу 0x000000000405f478
.)
Имена всех или части функций в последовательности вызовов могут быть не указаны, что осложняет определение причины аварийного завершения процесса.
Пример данных обратной трассировки стека, содержащих только адреса памяти:
Причина отсутствия имен функций в данных обратной трассировки стека заключается в следующем. Для вывода данных обратной трассировки стека ядро получает имена функций из таблицы символов .symtab
и таблицы строк .strtab
, загруженных в память аварийно завершившегося процесса из отладочной версии исполняемого файла. Эти таблицы могут быть неполными либо вообще отсутствовать в памяти аварийно завершившегося процесса. Также ядро не может вывести имена функций, импортированных из динамических библиотек.
Таблица символов .symtab
и таблица строк .strtab
отсутствуют в памяти процесса в следующих случаях:
- Процесс создан из выпускной версии исполняемого файла. (Исполняемый файл собран как выпускной, и при сборке в него включены выпускные версии статических библиотек.)
Выпускная версия исполняемого файла, в отличие от отладочной, не содержит таблицу символов
.symtab
и таблицу строк.strtab
. - Процесс создан из отладочной версии исполняемого файла, из которого перед добавлением в образ решения были удалены таблица символов
.symtab
и таблица строк.strtab
, например, утилитойstrip
. - Процесс создан из отладочной версии исполняемого файла, из которого перед добавлением в образ решения не были удалены таблица символов
.symtab
и таблица строк.strtab
, но эти таблицы не были загружены в память процесса.Создать процесс с опциональной загрузкой таблицы символов
.symtab
и таблицы строк.strtab
позволят высокоуровневый API управления процессами и низкоуровневый API управления процессами.
Таблица символов .symtab
и таблица строк .strtab
являются неполными в следующих случаях:
- Если исполняемый файл собран как отладочный, но при сборке в него включены выпускные версии статических библиотек, то в таблице символов
.symtab
и таблице строк.strtab
не будет сведений о функциях, которые реализованы в этих библиотеках. - Если исполняемый файл собран как выпускной, но при сборке в него включены отладочные версии статических библиотек, то в таблице символов
.symtab
и таблице строк.strtab
будут сведения только о тех функциях, которые реализованы в этих библиотеках.
Для некоторых адресов памяти, указанных в данных обратной трассировки стека, сведения о функциях можно получить из исполняемого файла. Если адрес памяти присутствует в таблице символов .symtab
исполняемого файла, то можно получить номер строки кода и имя функции, соответствующие этому адресу памяти. Если адрес памяти отсутствует в таблице символов .symtab
, но присутствует в таблице символов .dynsym
исполняемого файла, то можно получить имя функции, соответствующей этому адресу памяти. (При использовании ASLR адреса памяти, указанные в данных обратной трассировки стека, увеличены на значение смещения загрузки ELF-образа Relocation base
, которое выводится вместе с данными обратной трассировки стека.) В иных случаях получить из исполняемого файла сведения о функциях нельзя. Например, это относится к функциям, импортируемым из динамических библиотек, а также к функциям, реализованным в выпускных версиях статических библиотек.
Исполняемый файл в KasperskyOS содержит набор экспортируемых функций (хотя не является динамической библиотекой). Например, функции библиотеки libc
, которая включается в исполняемые файлы, являются экспортируемыми. Таблица символов .dynsym
содержит сведения об экспортируемых функциях. Эта таблица присутствует в выпускной версии исполняемого файла, а также остается в отладочной версии исполняемого файла после удаления из него отладочных символов. (Таблица символов .symtab
и таблица строк .strtab
являются частью отладочных символов.)
Чтобы получить из исполняемого файла сведения о функциях, соответствующих адресам памяти, указанным в данных обратной трассировки, нужно использовать утилиту addr2line
, поставляемую в составе KasperskyOS Community Edition (исполняемый файл toolchain/bin/aarch64-kos-addr2line
). Формат команды запуска утилиты addr2line
:
В команде нужно указать адреса памяти из данных обратной трассировки стека, уменьшенные на значение Relocation base
. Параметр --functions
требует вывода имен функций в дополнение к номерам строк исходного кода.
Пример: