How to debug my Cross compiled Linux Kernel? - linux

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.

Related

How can I install GCC and other developer tools inside QEMU virtual machine that only has BusyBox?

I download Linux kernel source code, successfully compiled it and run it with BusyBox in QEMU.
Because of BusyBox, I can use some frequently-used tools, such as vi,ls,cp,cat, etc.
But when I try to compile a simple "hello world" C/C++ program, I get gcc: not found.
In addition, I can't make a new Linux module by make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules inside QEMU.
I googled a lot, still can't figure it out.
So my question is: how can I install common developer tools like gcc, make, etc. inside my bare-bones QEMU VM that is running my custom Linux kernel (and not a standard distribution)?
I see that you are trying to compile some program (or module) to use it inside your QEMU machine, but you do not have a compiler toolchain installed in the machine itself. You have a couple of options:
Probably the easiest: since you already compiled the kernel that you are using for QEMU externally (in your host machine), you can easily also compile anything else this way. For modules, just pointing make to the same kernel source directory where you built the VM kernel should suffice. Once compiled you can then copy them inside the VM disk/image like you did for busybox.
You can download and compile your own GCC from source (always on the host), and then install it inside the QEMU virtual machine. This is usually done by mounting the VM disk (QEMU image or whatever you are using) somewhere (e.g. /mnt/my-qemu-disk) and then configuring GCC with --prefix=/mnt/my-qemu-disk/usr/local, building and installing it with make install. This and other stuff is explained in this documentation page.
Once you have GCC installed inside the machine, you should be able to use it as you normally do. You can now use it to compile GNU Make inside the VM, or you can just compile outside in the same way.
For complex stuff like building kernel modules you will probably also need to build and install GNU binutils in the machine, again either from the inside with the GCC you just installed or from the outside.

How to debug Linux kernel modules with QEMU?

I am working on academic project that modifies some Kernel Networking code as well as include a new Kernel module.
I am using QEMU to load modified kernel and test.
However, i find that a complete OS is required in some .img to debug.
Is it possible without it ?
Or, which is the distro that can be used with Kernel 2.6 for system. The distro need not have any features, except ability to run programs, including networking support.
The easiest way in my opinion is to use buildroot
http://buildroot.uclibc.org/
clone it, configure it to use your custom kernel (default userspace is fine for a start, you might want to change it later).
it will build your kernel and root filesystem. the entire process takes about half an hour, twenty minutes of which is compiling the monster
my run line looks something:
qemu-system-i386
-hda rootfs.ext2
-kernel bzImage
-m 512M
-append "root=/dev/sda console=ttyS0"
-localtime
-serial stdio
and some more options regarding a tap device
Minimal fully automated QEMU + GDB + Buildroot example
QEMU + GDB on non-module Linux kernel is covered in detail at: How to debug the Linux kernel with GDB and QEMU? and building the kernel modules inside QEMU at: How to add Linux driver as a Buildroot package Get those working first.
Next, I have also fully automated GDB module debugging at: https://github.com/cirosantilli/linux-kernel-module-cheat/tree/1c29163c3919d4168d5d34852d804fd3eeb3ba67#kernel-module-debugging
These are the main steps you have to take:
Compile the kernel module with debug symbols:
ccflags-y += -g -DDEBUG
as mentioned at: kernel module no debugging symbols found
Stop GDB with Ctrl + C and run:
lx-symbols path/to/parent/of/modules/
This amazing command, which is defined in a GDB Python script inside the Linux kernel source tree, automatically loads symbols for loaded modules present under the given directory recursively whenever GDB stops.
The best way to make that command available is to use:
gdb -ex add-auto-load-safe-path /full/path/to/linux/kernel
as explained at: GDB: lx-symbols undefined command
insmod the kernel module.
This must be done before setting breakpoints, because we don't know where the kernel will insert the module in memory beforehand.
lx-symbols automatically takes care of finding the module location (in host filesystem and guest memory!) for us.
Break GDB again with Ctrl + C, set breakpoints, and enjoy.
If were feeling hardcore, you could also drop lx-symbols entirely, and find the module location after insmod with:
cat /proc/modules
and then add the .ko manually with:
add-symbol-file path/to/mymodule.ko 0xfffffffa00000000

"--target list" meaning in qemu installation

I am new to qemu. I have the following question. I needed to emulate some new instructions using qemu. Basically I modify the target-i386 to something like target-i386-extended. Add tcg/i386-extended.Since qemu supports many architectures, normally i configure using the following command
./configure --target-list=i386-softmmu --enable-debug
make
make install
Are there any changes that needs to be done if we want to emulate new target? If so, what needs to be the command in the above case?
Looking forward to your reply.
./configure --help
shows option for customized building and compiling.
Standard options:
--help print this message
--prefix=PREFIX install in PREFIX [/usr/local]
--interp-prefix=PREFIX where to find shared libraries,
etc.use %M for cpu name [/usr/gnemul/qemu-%M]
--target-list=LIST set target list (default: build everything)
by default it will build for all your targets like x86,x86_64,arm.powerpc etc
./configure --target-list=i386-softmmu
this will build only for x86 target i.e you ll get qemu-i386 binary only.
if you want for arm target only then use
./configure --target-list=arm-softmmu which will build and compile only for arm.
qemu-system-arm binaries you ll get which you can use for emulating ARM board

How to use kgdb over ethernet (kgdboe)?

i am using ubuntu 12.04 and kernel version is 3.12.6, i want to learn how to use kgdb to debug kernel. I didn't get much info. regarding kgdboe (kgdb over ethernet). I have compiled kernel and enabled kgdb in menuconfig, i have created kernel image using make bzImage on development machine and copied same on target machine, now problem is how to connect both target and development machine. i m not getting parameter set for kgbdoe. Plz help if anybody know how to use kgdb over ethernet
Have you read this:
https://www.kernel.org/pub/linux/kernel/people/jwessel/kgdb/ch03s04.html
?
You have to run debugged kernel with special options - like for example:
kgdbwait kgdbcon kgdboe=#192.168.248.76/,#192.168.242.24/00:11:22:33:44:55
and on debugging side you run following commands:
gdb
file vmlinux
target remote udp:192.168.248.76:6443
it has worked for me.
You can get the kgdboe source from here, build it and load it into your kernel:
make -C /lib/modules/$(uname -r)/build M=$(pwd)
sudo insmod kgdboe.ko
Then type 'dmesg' to see the load log and get instructions on connecting from gdb.

chroot into other arch's environment

Following the Linux from Scratch book I have managed to build a toolchain for an ARM on
an ARM. This is till chapter 6 of the book, and on the ARM board itself I could go on further with no problems.
My question is if I can use the prepared environment to continue building the soft from chapter 6 on my x86_64 Fedora 16 laptop?
I thought that while I have all the binaries set up I could just copy them to laptop, chroot inside and feel myself as on the ARM board, but using the command from the book gives no result:
`# chroot "$LFS" /tools/bin/env -i HOME=/root TERM="$TERM" PS1='\u:\w\$
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/tools/bin /tools/bin/bash --login +h
chroot: failed to run command `/tools/bin/env': No such file or directory`
The binary is there, but it doesn't belong to this system:
`# ldd /tools/bin/env
not a dynamic executable`
The binary is compiled as per the book:
# readelf -l /tools/bin/env | grep interpreter
[Requesting program interpreter: /tools/lib/ld-linux.so.3]
So I wonder if there is a way, like using proper environment variables for CC LD READELF, to continue building for ARM using these tools on x86_64 host.
Thank you.
Yes, you certainly can chroot into an ARM rootfs on an x86 box.
Basically, like this:
$ sudo chroot /path/to/arm/rootfs /bin/sh
sh-4.3# ls --version 2>&1 | head
/bin/ls: unrecognized option '--version'
BusyBox v1.22.1 (2017-03-02 15:41:43 CST) multi-call binary.
Usage: ls [-1AaCxdLHRFplinsehrSXvctu] [-w WIDTH] [FILE]...
List directory contents
-1 One column output
-a Include entries which start with .
-A Like -a, but exclude . and ..
sh-4.3# ls
bin css dev home media proc sbin usr wav
boot data etc lib mnt qemu-arm sys var
My rootfs is for a small embedded device, so everything is BusyBox-based.
How is this working? Firstly, I have the binfmt-misc support running in the kernel. I didn't have to do anything; it came with Ubuntu 18. When the kernel sees an ARM binary, it hands it off to the registered interpreter /usr/bin/qemu-arm-static.
A static executable by that name is found inside my rootfs:
sh-4.3# ls /usr/bin/q*
/usr/bin/qemu-arm-static
I got it from a Ubuntu package. I installed:
$ apt-get install qemu-user-static
and then copied /usr/bin/qemu-arm-static into the usr/bin subdirectory of the rootfs tree.
That's it; now I can chroot into that rootfs without even mentioning QEMU on the chroot command line.
Nope. You can't run ARM binaries on x86, so you can't enter its chroot. No amount of environment variables will change that.
You might be able to continue the process by creating a filesystem image for the target and running it under an emulator (e.g, qemu-system-arm), but that's quite a different thing.
No you cannot, at least not using chroot. What you have in your hands is a toolchain with an ARM target for an ARM host. Binaries are directly executable only on architectures compatible with their host architecture - and x86_64 is not ARM-compatible.
That said, you might be able to use an emulated environment. qemu, for example, offers two emulation modes for ARM: qemu-system-arm that emulates a whole ARM-based system and qemu-arm that uses ARM-native libraries to provide a thinner emulation layer for running ARM Linux executables on non-ARM hosts.

Resources