Отладка ядра Linux в реальном времени, как это делается и какие инструменты используются? - PullRequest
52 голосов
/ 09 февраля 2011

Каковы наиболее распространенные и почему не редкие методы и инструменты, используемые для живой отладки в ядре Linux? Я знаю, что Линус например. против такого рода отладки для ядра Linux или, по крайней мере, так было, и, таким образом, ничего не было сделано в этом смысле в те годы, но, честно говоря, с 2000 года прошло много времени, и мне интересно, если это изменился менталитет в отношении проекта Linux и какие современные методы используются для отладки в реальном времени в ядре Linux (локальном или удаленном)?

Приветствуются ссылки на руководства и учебные пособия по упомянутым методам и инструментам.

Ответы [ 11 ]

28 голосов
/ 11 февраля 2011

Другой вариант - использовать ICE / JTAG контроллер и GDB.Это «аппаратное» решение особенно используется со встроенными системами,

, но, например, Qemu предлагает аналогичные функции:

  • запуск qemu с удаленной заглушкой gdb, которая прослушивает'localhost: 1234': qemu -s ...,

  • , затем с помощью GDB вы открываете файл ядра vmlinux, скомпилированный с отладочной информацией (вы можете посмотреть this ветка списка рассылки, где обсуждается неоптимизация ядра).

  • соедините GDB и Qemu: target remote localhost:1234

  • см. ваш live kernel:

    (gdb) where
    #0  cpu_v7_do_idle () at arch/arm/mm/proc-v7.S:77
    #1  0xc0029728 in arch_idle () atarm/mach-realview/include/mach/system.h:36
    #2  default_idle () at arm/kernel/process.c:166
    #3  0xc00298a8 in cpu_idle () at arch/arm/kernel/process.c:199
    #4  0xc00089c0 in start_kernel () at init/main.c:713
    

к сожалению, пока отладка пространства пользователя невозможна с GDB (нет информации о списке задач, перепрограммирование MMU для просмотра различных контекстов процесса,...), но если вы остаетесь в пространстве ядра, это довольно удобно.

  • info threads выдаст вам список и состояния различных процессоров

РЕДАКТИРОВАТЬ:

Более подробную информацию о процедуре можно получить в тего PDF:

Отладка систем Linux с использованием GDB и QEMU .

21 голосов
/ 02 марта 2015

При отладке ядра Linux мы можем использовать несколько инструментов, например, отладчики (KDB, KGDB), дамп при сбое (LKCD), инструментарий трассировки (LTT, LTTV, LTTng), пользовательские инструменты ядра (dprobes, kprobes). В следующем разделе я попытался обобщить большинство из них, надеюсь, они помогут.

LKCD (Linux Kernel Crash Dump) позволяет системе Linux записывать содержимое своей памяти при возникновении сбоя. Эти журналы могут быть дополнительно проанализированы на предмет первопричины сбоя. Ресурсы, касающиеся LKCD

Упс когда ядро ​​обнаруживает проблему, оно печатает сообщение Упс. Такое сообщение генерируется операторами printk в обработчике ошибок (arch / * / kernel / traps.c). Выделенный кольцевой буфер в ядре, используемый операторами printk. Oops содержит такую ​​информацию, как процессор, на котором произошли Oops, содержимое регистров CPU, количество Oops, описание, трассировка стека и другие. Ресурсы, касающиеся ядра Упс

Dynamic Probes - это один из популярных инструментов отладки для Linux, разработанный IBM. Этот инструмент позволяет разместить «зонд» практически в любом месте системы, как в пространстве пользователя, так и в пространстве ядра. Зонд состоит из некоторого кода (написанного на специализированном, ориентированном на стек языке), который выполняется, когда управление достигает заданной точки. Ресурсы, касающиеся Dynamic Probe, перечислены ниже

Linux Trace Toolkit - это патч для ядра и набор связанных утилит, которые позволяют отслеживать события в ядре. Трассировка включает в себя информацию о времени и может создать достаточно полную картину того, что произошло за определенный период времени. Ресурсы LTT, LTT Viewer и LTT Next Generation

MEMWATCH - это инструмент обнаружения ошибок памяти с открытым исходным кодом. Он работает, определяя MEMWATCH в инструкции gcc и добавляя заголовочный файл в наш код. Благодаря этому мы можем отслеживать утечки памяти и повреждения памяти. Ресурсы, касающиеся MEMWATCH

ftrace - хороший фреймворк трассировки для ядра Linux. ftrace отслеживает внутренние операции ядра. Этот инструмент включен в ядро ​​Linux в 2.6.27. С помощью различных подключаемых модулей трассировки ftrace может быть нацелена на различные статические точки трассировки, такие как события планирования, прерывания, отображаемый в памяти ввод-вывод, переходы состояния питания ЦП и операции, связанные с файловыми системами и виртуализацией. Кроме того, доступно динамическое отслеживание вызовов функций ядра, опционально ограниченное подмножеством функций с помощью глобусов, и с возможностью генерировать графики вызовов и обеспечивать использование стека. Вы можете найти хороший учебник по ftrace на https://events.linuxfoundation.org/slides/2010/linuxcon_japan/linuxcon_jp2010_rostedt.pdf

ltrace - это утилита отладки в Linux, используемая для отображения вызовов, выполняемых приложением пользовательского пространства, к разделяемым библиотекам. Этот инструмент может использоваться для отслеживания любого вызова функции динамической библиотеки. Он перехватывает и записывает динамические библиотечные вызовы, которые вызываются исполняемым процессом, и сигналы, которые получает этот процесс. Он также может перехватывать и распечатывать системные вызовы, выполняемые программой.

KDB - встроенный в ядро ​​отладчик ядра Linux.KDB следует упрощенному интерфейсу в стиле оболочки.Мы можем использовать его для проверки памяти, регистров, списков процессов, dmesg и даже для установки точек останова для остановки в определенном месте.С помощью KDB мы можем устанавливать точки останова и выполнять некоторые основные функции управления ядром ( Хотя KDB не является отладчиком исходного уровня ).Несколько полезных ресурсов, касающихся KDB

KGDB предназначен для использования в качестве отладчика исходного уровня для ядра Linux.Он используется вместе с gdb для отладки ядра Linux.Для использования kgdb требуются две машины.Одна из этих машин является машиной разработки, а другая - целевой машиной.Отлаживаемое ядро ​​работает на целевой машине.Ожидается, что GDB можно будет использовать для «взлома» ядра, чтобы проверить память, переменные и просмотреть информацию стека вызовов, аналогично тому, как разработчик приложения будет использовать GDB для отладки приложения.Можно разместить точки останова в коде ядра и выполнить некоторые ограниченные шаги выполнения.Несколько полезных ресурсов, касающихся KGDB

20 голосов
/ 09 февраля 2011

Согласно вики , kgdb было объединено с ядром в 2.6.26, что происходит в течение последних нескольких лет.kgdb - это удаленный отладчик , поэтому вы активируете его в своем ядре , а затем каким-то образом подключаете к нему gdb.Я говорю как-то, так как кажется, что есть много вариантов - см. Соединение GDB .Учитывая, что kgdb сейчас находится в дереве исходных текстов, я бы сказал, что в дальнейшем вам следует использовать именно это.

Так что, похоже, Линус сдался. Однако я бы подчеркнул его аргумент - выдолжен знать, что вы делаете, и хорошо знать систему.Это земля ядра.Если что-то пойдет не так, вы не получите segfault, позже вы получите что-то от какой-то непонятной проблемы до полного падения системы.Здесь будут драконы.Будьте осторожны, вас предупредили.

14 голосов
/ 09 февраля 2011

Еще один хороший инструмент для «живой» отладки - это kprobes / динамические пробники.

Это позволяет динамически создавать маленькие крошечные модули, которые запускаются при выполнении определенных адресов - что-то вроде точки останова.

Большим их преимуществом являются:

  1. Они не влияют на систему, т. Е. Когда происходит попадание в локацию, она просто выполняет код, но не останавливает все ядро.
  2. Вам не нужны две разные системы (целевая и отладочная), как с kgdb

Лучше всего делать такие вещи, как попадание на точку останова и просмотр значений данных, или проверка того, что что-то было изменено / перезаписано и т. Д. Если вы хотите «пройти по коду» - он этого не делает.

Дополнение - 2018:

Другим очень мощным методом является программа, называемая просто «perf», которая сворачивает многие инструменты (например, динамические пробники) и заменяет / удаляет другие (например, oprofile).

В частности, команда perf probe может быть использована для простого создания / добавления динамических пробников в систему, после чего perf record может производить выборку системы и сообщать информацию (и обратные трассировки), когда пробник нажимается для сообщения через perf report (или perf script). Если у вас есть хорошие символы отладки в ядре, вы можете получить отличную информацию из системы, даже не отключая ядро. Сделайте man perf (в Google или в вашей системе) для получения дополнительной информации об этом инструменте или посмотрите на эту замечательную страницу:

http://www.brendangregg.com/perf.html

5 голосов

KGDB + QEMU пошагово

KGDB - это подсистема ядра, которая позволяет пошагово отлаживать само ядро ​​с хоста GDB.

Мой пример QEMU + Buildroot - хороший способ почувствовать его без реального оборудования: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/1969cd6f8d30dace81d9848c6bacbb8bad9dacd8#kgdb

За и против против других методов:

  • преимущество перед QEMU:
    • у вас часто нет программной эмуляции для вашего устройства, поскольку поставщики оборудования не любят выпускать точные программные модели для своих устройств
    • реальное аппаратное обеспечение быстрее, чем QEMU
  • преимущество по сравнению с JTAG: нет необходимости в дополнительном оборудовании JTAG, проще в настройке
  • недостатки по сравнению с QEMU и JTAG: меньше видимости и больше навязчивости. KGDB опирается на определенные части ядра, работающие для связи с хостом. Так, например он ломается в панике, вы не можете просмотреть последовательность загрузки.

Основные шаги:

  1. Скомпилируйте ядро ​​с помощью:

    CONFIG_DEBUG_KERNEL=y
    CONFIG_DEBUG_INFO=y
    
    CONFIG_CONSOLE_POLL=y
    CONFIG_KDB_CONTINUE_CATASTROPHIC=0
    CONFIG_KDB_DEFAULT_ENABLE=0x1
    CONFIG_KDB_KEYBOARD=y
    CONFIG_KGDB=y
    CONFIG_KGDB_KDB=y
    CONFIG_KGDB_LOW_LEVEL_TRAP=y
    CONFIG_KGDB_SERIAL_CONSOLE=y
    CONFIG_KGDB_TESTS=y
    CONFIG_KGDB_TESTS_ON_BOOT=n
    CONFIG_MAGIC_SYSRQ=y
    CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
    CONFIG_SERIAL_KGDB_NMI=n
    

    Большинство из них не являются обязательными, но это то, что я проверял.

  2. Добавьте к вашей команде QEMU:

    -append 'kgdbwait kgdboc=ttyS0,115200' \
    -serial tcp::1234,server,nowait
    
  3. Запустите GDB из корня дерева исходных текстов ядра Linux с помощью:

    gdb -ex 'file vmlinux' -ex 'target remote localhost:1234'
    
  4. В ГБД:

    (gdb) c
    

    и загрузка должна завершиться.

  5. В QEMU:

    echo g > /proc/sysrq-trigger
    

    А ГБД должен сломаться.

  6. Теперь мы закончили, вы можете использовать GDB как обычно:

    b sys_write
    c
    

Протестировано в Ubuntu 14.04.

KGDB + Raspberry Pi

Точно такая же настройка, как и выше, почти сработала на Raspberry Pi 2, Raspbian Jessie 2016-05-27.

Вам просто нужно научиться выполнять шаги QEMU на Пи, которые легко Googlable:

  • добавить параметры конфигурации и перекомпилировать ядро, как описано в https://www.raspberrypi.org/documentation/linux/kernel/building.md К сожалению, в сборке ядра по умолчанию отсутствовали параметры, в частности, отсутствуют символы отладки, поэтому необходима перекомпиляция.

  • отредактируйте cmdline.txt загрузочного раздела и добавьте:

    kgdbwait kgdboc=ttyAMA0,115200
    
  • подключить gdb к серийному номеру с помощью:

    arm-linux-gnueabihf-gdb -ex 'file vmlinux' -ex 'target remote /dev/ttyUSB0'
    

    Если вы не знакомы с серийным номером, проверьте это: https://www.youtube.com/watch?v=da5Q7xL_OTo Все, что вам нужно, это дешевый адаптер , как этот . Удостоверьтесь, что вы можете получить оболочку через последовательный порт, чтобы убедиться, что она работает, прежде чем испытывать KGDB.

  • сделать:

    echo g | sudo tee /proc/sysrq-trigger
    

    изнутри сеанса SSH, поскольку последовательный порт уже занят GDB.

С помощью этой настройки я смог установить точку останова в sys_write, приостановить выполнение программы, указать источник и продолжить.

Однако иногда, когда я делал next в sys_write, GDB просто зависал и печатал это сообщение об ошибке несколько раз:

Ignoring packet error, continuing...

поэтому я не уверен, что с моей настройкой что-то не так, или это ожидается из-за того, что делает какой-то фоновый процесс на более сложном изображении Распбиана.

Мне также сказали попробовать отключить многопроцессорную обработку с помощью параметров загрузки Linux, но я еще не пробовал.

4 голосов
/ 10 февраля 2011

На самом деле шутка в том, что Linux имеет встроенный в ядро ​​отладчик начиная с 2.2.12, xmon, но только для архитектуры powerpc (на самом деле это был ppc тогда).

Это не отладчик исходного уровня, и он почти полностью недокументирован, но все же.

http://lxr.linux.no/linux-old+v2.2.12/arch/ppc/xmon/xmon.c#L119

3 голосов

Пошаговая процедура QEMU + GDB протестирована на хосте Ubuntu 16.10

Чтобы быстро начать с нуля, я сделал минимальный полностью автоматизированный пример QEMU + Buildroot по адресу: https://github.com/cirosantilli/linux-kernel-module-cheat Основные шаги описаны ниже.

Сначала получите корневую файловую систему rootfs.cpio.gz. Если вам это нужно, подумайте:

Затем в ядре Linux:

git checkout v4.9
make mrproper
make x86_64_defconfig
cat <<EOF >.config-fragment
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
EOF
./scripts/kconfig/merge_config.sh .config .config-fragment
make -j"$(nproc)"
qemu-system-x86_64 -kernel arch/x86/boot/bzImage \
                   -initrd rootfs.cpio.gz -S -s

На другом терминале, предположим, что вы хотите начать отладку с start_kernel:

gdb \
    -ex "add-auto-load-safe-path $(pwd)" \
    -ex "file vmlinux" \
    -ex 'set arch i386:x86-64:intel' \
    -ex 'target remote localhost:1234' \
    -ex 'break start_kernel' \
    -ex 'continue' \
    -ex 'disconnect' \
    -ex 'set arch i386:x86-64' \
    -ex 'target remote localhost:1234'

и мы закончили !!

Для модулей ядра см .: Как отлаживать модули ядра Linux с QEMU?

Для Ubuntu 14.04, GDB 7.7.1, hbreak требовалось, break программные точки останова игнорировались. Не так больше в 16.10. Смотрите также: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

Грязный disconnect и что после него, чтобы обойти ошибку:

Remote 'g' packet reply is too long: 000000000000000017d11000008ef4810120008000000000fdfb8b07000000000d352828000000004040010000000000903fe081ffffffff883fe081ffffffff00000000000e0000ffffffffffe0ffffffffffff07ffffffffffffffff9fffff17d11000008ef4810000000000800000fffffffff8ffffffffff0000ffffffff2ddbf481ffffffff4600000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007f0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000801f0000

Похожие темы:

Смотри также:

Известные ограничения:

3 голосов
/ 10 февраля 2011

Как тот, кто много пишет код ядра, я должен сказать, что я никогда не использовал kgdb, и только редко использую kprobes и т. Д.

Это все еще часто лучший способ добавить некоторые стратегические printks.В более новых ядрах trace_printk - это хороший способ сделать это без спама dmesg.

1 голос

Пользовательский режим Linux (UML)

https://en.wikipedia.org/wiki/User-mode_Linux

Еще одна виртуализация, еще один метод, позволяющий выполнять пошаговую отладку кода ядра.

UML очень изобретателен: он реализован как ARCH, точно так же как x86, но вместо использования инструкций низкого уровня он реализует функции ARCH с системными вызовами пользователя.

В результате вы можете запускать код ядра Linux как пользовательский процесс на хосте Linux!

Сначала создайте rootfs и запустите его, как показано на: https://unix.stackexchange.com/questions/73203/how-to-create-rootfs-for-user-mode-linux-on-fedora-18/372207#372207

um defconfig устанавливает CONFIG_DEBUG_INFO=y по умолчанию (да, это разработка), так что у нас все хорошо.

На гостя:

i=0
while true; do echo $i; i=$(($i+1)); done

На хосте в другой оболочке:

ps aux | grep ./linux
gdb -pid "$pid"

В ГБД:

break sys_write
continue
continue

И теперь вы управляете счетчиком из GDB и можете видеть источник, как и ожидалось.

Плюсы:

  • полностью содержится в основном дереве ядра Linux
  • более легкий, чем полная системная эмуляция QEMU

Минусы:

Смотри также: https://unix.stackexchange.com/questions/127829/why-would-someone-want-to-run-usermode-linux-uml

0 голосов
/ 22 июня 2019

Вы, ребята, не правы, kgdb по-прежнему хорошо работает для последнего ядра, вам нужно позаботиться о конфигурации ядра разделенного образа, оптимизации рандомизации.

kgdb через последовательный порт бесполезен, потому что сегодня ни один компьютер не поддерживает DB9 для последовательного порта материнской платы, а последовательный порт USB не поддерживает режим опроса.

Новая игра - kgdboe, а след в журнале:

ниже - хост-машина, vmlinux с целевой машины

root@Thinkpad-T510:~/KGDBOE# gdb vmlinux
Reading symbols from vmlinux...done.
(gdb) target remote udp:192.168.1.22:31337
1077    kernel/debug/debug_core.c: No such file or directory.
(gdb) l oom_kill_process 
828 mm/oom_kill.c: No such file or directory.
(gdb) l oom_kill_process 
828 in mm/oom_kill.c
(gdb) break oom_kill_process
Breakpoint 1 at 0xffffffff8119e0c0: file mm/oom_kill.c, line 833.
(gdb) c
Continuing.
[New Thread 1779]
[New Thread 1782]
[New Thread 1777]
[New Thread 1778]
[New Thread 1780]
[New Thread 1781]
[Switching to Thread 1779]

Thread 388 hit Breakpoint 1, oom_kill_process (oc=0xffffc90000d93ce8, message=0xffffffff82098fbc "Out of memory")
at mm/oom_kill.c:833
833 in mm/oom_kill.c
(gdb) s
834 in mm/oom_kill.c
(gdb) 

На одноранговом целевом компьютере ниже описано, как вызвать его аварийное завершение и захват на хост-компьютере

#swapoff -a
#stress -m 4 --vm-bytes=500m
...