Como depurar o kernel do Linux com o GDB e o QEMU?

Eu sou novo no desenvolvimento do kernel e gostaria de saber como executar / depurar o kernel do linux usando o QEMU e o gdb. Na verdade, estou lendo o livro de Robert Love, mas infelizmente isso não ajuda o leitor sobre como instalar ferramentas adequadas para executar ou depurar o kernel … Então o que eu fiz foi seguir este tutorial http://opensourceforu.efytimes.com / 2011/02 / kernel-development-debugging-using-eclipse / . Eu estou usando o Eclipse como um IDE para desenvolver no kernel, mas eu queria primeiro fazê-lo funcionar em QEMU / gdb. Então o que eu fiz até agora foi:

1) Para compilar o kernel com:

make defconfig (then setting the CONFIG_DEBUG_INFO=y in the .config) make -j4 

2) Uma vez terminada a compilation, eu corro o Qemu usando:

 qemu-system-x86_64 -s -S /dev/zero -kernel /arch/x86/boot/bzImage 

que lançam o kernel no estado “parado”

3) Assim, eu tenho que usar o gdb, eu tente o seguinte comando:

 gdb ./vmlinux 

que rodá-lo corretamente, mas … Agora eu não sei o que fazer … Eu sei que eu tenho que usar a debugging remota na porta 1234 (porta padrão usada pelo Qemu), usando o vmlinux como o arquivo de tabela de símbolos para debugging.

Então, minha pergunta é: O que devo fazer para executar o kernel no Qemu, append meu depurador a ele e, assim, fazer com que trabalhem juntos para tornar minha vida mais fácil com o desenvolvimento do kernel.

Eu tentaria:

 (gdb) target remote localhost:1234 (gdb) continue 

Usando a opção ‘-s’ faz qemu ouvir na porta tcp :: 1234, que você pode conectar como localhost: 1234 se você estiver na mesma máquina. A opção ‘-S’ do Qemu faz com que o Qemu pare a execução até você dar o comando continue.

A melhor coisa seria provavelmente dar uma olhada em um tutorial decente do GDB para se dar bem com o que você está fazendo. Este parece muito bom.

Procedimento passo a passo testado no host do Ubuntu 16.10

Para começar do zero rapidamente, fiz um exemplo mínimo de QEMU + Buildroot totalmente automatizado em: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/c7bbc6029af7f4fab0a23a380d1607df0b2a3701/gdb-step-debugging.md Major etapas são cobertas abaixo.

Primeiro, obtenha um sistema de arquivos raiz rootfs.cpio.gz . Se você precisar de um, considere:

Então no kernel do Linux:

 git checkout v4.15 make mrproper make x86_64_defconfig cat < .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 \ -append nokaslr 

Em outro terminal, de dentro da tree do kernel Linux, suponha que você queira iniciar a debugging a partir do 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' 

e nós terminamos !!

Para módulos do kernel, veja: Como depurar módulos do kernel Linux com o QEMU?

Para o Ubuntu 14.04, o GDB 7.7.1, hbreak era necessário, os breakpoints do software break eram ignorados. Não é mais o caso em 16.10. Veja também: https://bugs.launchpad.net/ubuntu/+source/qemu-kvm/+bug/901944

A disconnect desordenada e o que vem depois são para contornar o erro:

 Remote 'g' packet reply is too long: 

Tópicos Relacionados:

Limitações Conhecidas:

  • o kernel do Linux não suporta (e nem mesmo compila sem patches) com -O0 : Como -O0 o kernel do Linux e compilá-lo com o -O0?
  • O GDB 7.11 vai explodir sua memory em alguns tipos de conclusão de tabulação, mesmo após a correção max-completions : Interrupção de conclusão de tabulação para binários grandes Provavelmente algum caso de canto que não foi coberto naquele patch. Portanto, um ulimit -Sv 500000 é uma ação sensata antes da debugging. Estourou especificamente quando eu sys_execve file para o argumento filename de sys_execve como em: https://stackoverflow.com/a/42290593/895245

Veja também:

A resposta da BjoernID realmente não funcionou para mim. Após a primeira continuação, nenhum ponto de interrupção é atingido e, na interrupção, eu veria linhas como:

 0x0000000000000000 in ?? () (gdb) break rapl_pmu_init Breakpoint 1 at 0xffffffff816631e7 (gdb) c Continuing. ^CRemote 'g' packet reply is too long: 08793000000000002988d582000000002019[..] 

Eu acho que isso tem algo a ver com diferentes modos de CPU (modo real no modo BIOS vs. modo longo quando o Linux foi inicializado). De qualquer forma, a solução é executar o QEMU primeiro sem esperar (ou seja, sem -S ):

 qemu-system-x86_64 -enable-kvm -kernel arch/x86/boot/bzImage -cpu SandyBridge -s 

No meu caso, eu precisava quebrar algo durante a boot, então após alguns segundos, executei o comando gdb. Se você tiver mais tempo (por exemplo, você precisa depurar um módulo que é carregado manualmente), então o tempo não importa realmente.

gdb permite especificar comandos que devem ser executados quando iniciados. Isso torna a automação um pouco mais fácil. Para conectar-se ao QEMU (que já deve estar iniciado), interromper uma function e continuar a execução, use:

 gdb -ex 'target remote localhost:1234' -ex 'break rapl_pmu_init' -ex c ./vmlinux 

Quando você tenta iniciar o vmlinux exe usando o gdb, a primeira coisa no gdb é emitir cmds:

(gdb) destino localhost remoto: 1234

(gdb) quebra start_kernel

(continuar)

Isto irá quebrar o kernel em start_kernel.

Quanto a mim, a melhor solução para depurar o kernel – é usar o gdb do ambiente Eclipse. Você deve apenas configurar a porta apropriada para o gdb (deve ser a mesma com uma especificada na cadeia de ativação do qemu) na seção de debugging remota. Aqui está o manual: http://www.sw-at.com/blog/2011/02/11/linux-kernel-development-and-debugging-using-eclipse-cdt/