Живая отладка ядра Linux, как это делается и какие инструменты используются?

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

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

Ответ 1

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

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

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

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

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

  • увидеть ваше живое ядро:

    (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
    

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

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

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

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

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

Ответ 2

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

Еще один хороший инструмент для "живой" отладки - это 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.

КГДБ + Малина Пи

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

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

  • добавьте параметры конфигурации и перекомпилируйте ядро, как описано на 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 останова в sys_write, приостановить выполнение программы, sys_write список источников и продолжить.

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

Ignoring packet error, continuing...

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

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

Ответ 6

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

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

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

Ответ 7

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

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

Ответ 8

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

Связанные темы:

См. также:

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

Ответ 9

Режим пользователя 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

Defconfig um устанавливает CONFIG_DEBUG_INFO=y по умолчанию (yup, это вещь для разработки), поэтому мы в порядке.

В гостях:

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

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

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

В GDB:

break sys_write
continue
continue

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

Плюсы:

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

Минусы:

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

    Но API-интерфейсы более высокого уровня вне спецификаций ARCH должны оставаться неизменными.

  • возможно, не очень активен: Прекращен ли проект linux (UML)?

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

Ответ 10

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

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

Новая игра - kgdboe, следом является лог трассировки:

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

[email protected]:~/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

Ответ 11

kgdb и gdb почти бесполезны для отладки ядра, потому что код оптимизирован, он не имеет отношения к исходному источнику, и многие переменные оптимизированы. Это делает steppijng, поэтому переходить через источник невозможно, рассмотрение переменных невозможно и, следовательно, является самым большим количеством точек.

На самом деле это хуже, чем бесполезно, это фактически дает вам ложную инфоструктуру, поэтому отключенный код - это код, который вы просматриваете в текущем рабочем коде.

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

Я должен сказать, что, исходя из среды ядра Windows, отсутствие достойного отладчика является анонимным, учитывая, что для поддержания есть нежелательный код.