I cannot break with GDB and QEMU - linux

I am debugging the Linux Kernel (latest version) using GDB and QEMU.
I have set DEBUG_INFO to yes in the configuration file.
Here is how I call QEMU:
$> qemu-system-x86_64 -snapshot -m 4G -serial stdio -kernel ~/Documents/kernel/arch/x86_64/boot/bzImage -initrd ~/D\
ocuments/kernel/initrd/initrd_x86_64.gz -append "root=/dev/sda1 ignore_loglevel" -s
And GDB of course:
$> gdb vmlinux
Then inside gdb:
(gdb)> target remote :1234
So nothing amazing.
It stops QEMU. I set my breakpoints, which seems to work as usual, and I type "continue". The QEMU execution resumes.
But then, even if my function is reached (I see the kernel message printk I set inside the function), gdb does not stop.
$> qemu-system-x86_64 --version
QEMU emulator version 2.12.0 (Debian 1:2.12+dfsg-3)
Copyright (c) 2003-2017 Fabrice Bellard and the QEMU Project developers
And
$> gdb --version
GNU gdb (Debian 8.1-4) 8.1
I don't know what to try next.
Any help would be appreciated.
PS: for information, I am writing a keylogger as a Linux driver. So I am registering a new keyboard notifier, and this is the keyboard notifier that is failing.
PS2: I also tried what they recommend here stack overflow question about setting hardware breakpoints instead, but it did not change anything, same problem.
Thank you.
Julien

Related

Debugging linux kernel with gdb via QEMU issue

I am newbie in Linux kernel and I'm trying to debug it with gdb via QEMU. My problem is gdb doesn't stop after break start_kernel. More details is below.
My host system is ArchLinux 5.0.10-arch1-1-ARCH x86_64.
Qemu is QEMU emulator version 4.0.0
gdb is GNU gdb (GDB) 8.2.1.
Debugged kernel is linux-4.20.12
I have done following steps:
Compile kernel with
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_KERNEL=y
CONFIG_GDB_SCRIPTS=y
# CONFIG_DEBUG_INFO_REDUCED is not set
Try to run LFS-8.4 system with it kernel via QEMU
qemu-system-x86_64 lfs-8.4-08052019.raw
System starts good.
Run this system with stop CPU and gdbserver options via QEMU
qemu-system-x86_64 lfs-8.4-08052019.raw -S -s
Start gdb
$ gdb
Load symbols
(gdb) file /mnt/lfs/sources/linux-4.20.12/vmlinux
Reading symbols from /mnt/lfs/sources/linux-4.20.12/vmlinux...done.
Connect to QEMU
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x000000000000fff0 in cpu_hw_events ()
Set break point
(gdb) break start_kernel
Breakpoint 1 at 0xffffffff82761ab5: file init/main.c, line 538.
(I have tried hardware break point hbreak, but result is the same)
Continue
(gdb) c
Continuing.
Further system loads login prompt without any breaks and gdb doesn't show any new messages.
What I do wrong?
UPD: starting QEMU with embed -kernel facility give the same result
qemu-system-x86_64 -kernel /mnt/lfs/sources/linux-4.20.12/arch/x86/boot/bzImage -append 'root=/dev/sda3' -drive file=lfs-8.4-08052019.raw -S -s
UPD2: I have tried to start QEMU without -S key and run target remote localhost:1234 in gdb immediately. QEMU have stopped loading at
Decompressing Linux... Parsing ELF... Performing relocations... done.
Booting kernel.
When I type s in gdb it says
(gdb) s
Cannot find bounds of current function
I suspect that debug symbols in vmlinux isn't related to bzImage. Maybe they was made wrong, but I don't how to make them another way.
UPD3: I have built kernel 2.6 in LFS-8.4 chroot environment. System isn't loaded, but kernel is successfully debugged by method described above! So, I think that it is problem of new kernels. Maybe I should switch off/on something in my 4.20.12 kernel, but I don't know what is exactly. For my purpose (reading Robert Love "Linux Kernel Development") kernel version 2.6 is enough.
You need to pass nokaslr to kernel cmdline.
qemu-system-x86_64 -kernel /mnt/lfs/sources/linux-4.20.12/arch/x86/boot/bzImage -append 'root=/dev/sda3 nokaslr' -drive file=lfs-8.4-08052019.raw -S -s

QEMU Showing Black Screen Only

I compiled my custom kernel with different configs and images like u,zImages. But when I try to run qemu with my image, qemu showing only black screen.
Also I looked at this post but it didn't help me.
EDIT
I just tried to compile kernel with these commands.
make ARCH=arm distclean
make ARCH=arm integrator_defconfig
make ARCH=arm menuconfig
NOTE: I used default menuconfig.
make ARCH=arm CROSS_COMPILE=arm-none-eabi- zImage
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage
And last i tried this command;
qemu-system-arm -M integratorcp -kernel arch/arm/boot/zImage -append 'console=ttyAMA0 earlyprintk=ttyAMA0' -serial stdio
NOTE: when i try to use -dtb, qemu giving to me "Unable to copy device tree in memory." error.
"QEMU does nothing with a black screen" almost always means "QEMU is running fine, but the guest code crashed or stopped early in the boot process without sending any output". Almost certainly either your kernel is misconfigured, or your QEMU command line is wrong. You don't give enough information to say which. You need to tell us at least:
what the kernel is you're running and what machine you've configured it for
what the QEMU command line you're using is
Given your updated question with a command line, some suggestions:
tell your guest to use the serial port (use the QEMU option -append 'console=ttyAMA0' to set the guest kernel command line)
either check the serial output view in the GUI, or send it to stdout with -nographic or -serial stdio
enable any earlyprintk or earlycon options in the guest config that you can and on the guest command line, so if the guest fails early you have more chance to catch it
pass the device tree for the kernel with -dtb integratorcp.dtb (use the one from your kernel tree; you'll probably have to tell the kernel makefiles to build it for you)
PS: integratorcp is an absolutely ancient development board -- why do you want to use it?

How to show more information in QEMU

I am trying to launch a Linux kernel by QEMU on Ubuntu by:
qemu-system-i386 -kernel: arch/i386/boot/bzImage -initrd ../busybox-1.19.4/rootfs.img -append "root=/dev/ram rdinit=/sbin/init"
These are the kernel logs.
I cannot see the cause of failure. But when I adjust the window, the font size gets bigger. How can I debug this issue?
First I see that you don't pass the architecture name with the option -M and -m to - specify the amount of memory.
You can debug your problem with GNU debugger (gdb).
But first you should enable the debug option when configuring QEMU so you should activate this option by:
./configure --enable-debug
Because by default builds with this flags "CFLAGS = -O2 -g" that block debugging.
After that, run:
gdb --args ./path/to your/executable_file_of_qemu -your_options
And you can run by the command run and step with s.

Guest OS in Qemu generates too much interrupts on irq4

I am facing problem with interrupt in guest OS runing in qemu-2.3.0.
I am loading windriver (Linux kernel-2.6.34.12-grsec) in -nographic mode in Qemu emulator on Ubuntu 14.04 host.
Host details:
>$ uname -a
>$ Linux my-qemu-host 3.13.0-52-generic #86-Ubuntu SMP Mon May 4 04:32:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
my command line is:
>$ qemu-system-x86_64 -enable-kvm -nographic -k en-us -kernel ${KERNEL} -cpu kvm64 -smp 4 -m 1G ${NETCFG} -gdb tcp::1234 -append "console=ttyS0,115200 ip=dhcp root=/dev/nfs nfsroot=${NFSROOT}" -hda /home/hda
I am getting following logs in /var/log/kern.log
kernel: serial8250: too much work for irq4
I searched to get rid of this but so many people are suggesting to increase PASS_LIMIT in /serial/8250.c file. this workaround is just avoiding error messages in kern.log file.
Any one having idea how to stop or slow down interrupt frequency?
What exactly are you running i.e. what sort of build? It appears that some hefty serial work is going on (which is expected with embedded).
I just googled how to disable the kernel module for the serial8250 to see if that would help and happened upon this:
http://www.spinics.net/lists/linux-serial/msg12360.html
Another thought, seeing as windriver (if it's this: http://www.windriver.com/products/linux/) then I wouldn't be shocked if a "serial console" is automatically enabled. This too could drive s/w interrupt watchdogs to blacklist them as the can spam quite a bit of info depending on what they're set to output.
Sorry, it's just totally a random guess, but I'm going by pure experience with embedded serial device fun (MIPS) and (ARM) past experiences with generic distros

How to debug my Cross compiled Linux Kernel?

I 've cross compiled a Linux Kernel (for ARM on i686 - using Cross-LFS).
Now I'm trying to boot this Kernel using QEMU.
$ qemu-system-arm -m 128 -kernel /mnt/clfs-dec4/boot/clfskernel-2.6.38.2 --nographic -M versatilepb
Then, it shows this line and waits for infinite time !!
Uncompressing Linux... done, booting the kernel.
So, I want to debug the kernel, so that I can study what exactly is happening.
I'm new to these kernel builds, Can someone please help me to debug my custom built kernel as it is not even showing anything after that statement. Is there any possibility of the kernel being broken? ( I dont think so, b'se it didnot give any error while compiling )
And my aim is to generate a custom build very minimal Linux OS. Any suggestions regarding any tool-chains etc which would be easy & flexible depending on my requirements like drivers etc.,
ThankYou
You can use GDB to debug your kernel with QEMU you can use -s -S options. If you want a simple and reliable toolchain, you can use ELDK from DENX (http://www.denx.de/wiki/DULG/ELDK).
You can install it like this (It's not the last version, but you got the idea):
wget http://ftp.denx.de/pub/eldk/4.2/arm-linux-x86/iso/arm-2008-11-24.iso
sudo mkdir -p /mnt/cdrom (if necessary)
sudo mount -o loop arm-2008-11-24.iso /mnt/cdrom
/mnt/cdrom/install -d $HOME/EMBEDDED_TOOLS/ELDK/
The command above should install the toolchain under $HOLE/EMBEDDED_TOOLS/ELDK (modify it if you need)
echo "export PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin" >> $HOME/.bashrc
You can then see the version of your ARM toolchain like this:
arm-linux-gcc -v
You can test a hello_world.c program like this:
arm-linux-gcc hello_world.c -o hello_world
And you type: file hello_wrold to see the target architecture of the binary, it should be something like this:
hello_wrold: ELF 32-bit LSB executable, ARM, version 1 (SYSV)
Now if you want to compile a production kernel, you need to optimize it (i suggest using busybox) and if you want just one for testing now, try this steps:
Create a script to set your chain tool set_toolchain.sh:
#! /usr/bin/sh
PATH=$PATH:$HOME/EMBEDDED_TOOLS/ELDK/ELDK42/usr/bin
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabi-
export PATH ARCH CROSS_COMPILE
And run your script (source ./set_toolchain.sh)
Download a linux kernel and unzip it (Let's assume 2.6.x, it's an old kernel, but there are a lot of chances that it work without compilation errors).
Inside your unzipped kernel:
cd ~/linux-2.6.29/arch/arm/configs
make versatile_defconfig
Here we use versatile chip, you may need to use make menuconfig to modify the option OABI and set it to ARM EABI, this option is under Kernel features menu
After all this steps, you can compile you kernel:
make
if you want verbose compilation make v=1
After this you got your kernel under arch/arm/boot/zImage.
Hope this help.
Regards.
I would suggest to build your kernel by activating the option in the section Kernel hacking of your configuration file.
Then you may use kdb or kgdb which is easier to use but requires another machine running gdb.
`
You can also connect Qemu and GDB. Qemu has the -s and -S options that run a GDB server and allow you to connect to it via TCP to localhost:1234. Then you can load your kernel image (the unzipped one) in GDB and see how far your kernel boots.

Resources