Building Android Kernel
Overview
Goal : Build a development setup in which the target machine runs a KGDB-enabled Android kernel with a Buildroot-based root file system under QEMU, while the host machine runs GDB and ADB to debug the kernel and interact with the target system.
1. Environment setup
Create a working directory.
mkdir androidDebugging && cd androidDebugging
2. Kernel building
Download the kernel
Download the kernel from the Android Common Kernel (ACK) repository. ACK kernels are stable and have strong community and upstream support.
Repository: https://android.googlesource.com/kernel/common/
Choose the kernel version according to your Android target.
git clone \
--depth 1 \
--branch android12-5.10.149_r00 \
https://android.googlesource.com/kernel/common
cd common
Install dependencies and cross-compilation tools
Install the required build dependencies. The command below is for Fedora-based systems.
sudo dnf install \
git bc bison flex elfutils-libelf-devel \
ncurses-compat-libs gcc-aarch64-linux-gnu \
qemu-system-aarch64 make \
openssl-devel openssl-devel-engine
Generate the default kernel configuration.
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
Append the following options to the end of the .config file to enable KGDB, debugging symbols, and serial console support.
CONFIG_CMDLINE="console=ttyAMA0"
CONFIG_CMDLINE_FROM_BOOTLOADER=y
# CONFIG_CMDLINE_EXTEND is not set
# CONFIG_CMDLINE_FORCE is not set
CONFIG_KPROBES=y
CONFIG_KRETPROBES=y
CONFIG_CONSOLE_POLL=y
CONFIG_DEBUG_INFO_REDUCED=y
CONFIG_GDB_SCRIPTS=y
CONFIG_KGDB=y
CONFIG_KGDB_HONOUR_BLOCKLIST=y
CONFIG_KGDB_SERIAL_CONSOLE=y
CONFIG_KGDB_KDB=y
CONFIG_KDB_DEFAULT_ENABLE=0x1
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
CONFIG_FUNCTION_ERROR_INJECTION=y
CONFIG_ANDROID=y
Validate and normalize the configuration.
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make olddefconfig
Compile the kernel
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j$(nproc) vmlinux Image
Compilation typically takes 10–20 minutes depending on hardware.
After a successful build, the following files are generated:
vmlinux(uncompressed ELF with debug symbols)arch/arm64/boot/Image(bootable kernel image)
3. Create a root filesystem
Download Buildroot
cd ..
wget https://buildroot.org/downloads/buildroot-2025.05.1.tar.gz
tar xf buildroot-2025.05.1.tar.gz
cd buildroot-2025.05.1
make menuconfig
Configure Buildroot
Apply the following configuration:
- Target Architecture →
AArch64 (little endian) - Target Architecture Variant →
cortex-A53(found under Target options) - Filesystem Images → enable
ext2/3/4 root filesystem - System configuration → set a root password
- Target packages → Networking applications
- enable
dhcpd - enable
iproute2 - enable
dropbear - enable `openssh
- enable
- Target packages -> System Tools
- enable
android-tools
- enable
Build the filesystem. This may take 20–60 minutes.
make
The generated root filesystem image will be located at:
output/images/rootfs.ext2
4. Emulation using QEMU
Install QEMU
sudo dnf install qemu-system-arm
Create the run script
From the androidDebugging directory, create the script.
touch run.sh
#!/bin/bash
set -euo pipefail
QEMU="qemu-system-aarch64"
KERNEL="common"
ROOTFS="buildroot-2025.05.1/output/images/rootfs.ext2"
# sanity checks
if [ ! -f "$KERNEL/arch/arm64/boot/Image" ]; then
echo "ERROR: kernel not found: $KERNEL/arch/arm64/boot/Image" >&2
exit 1
fi
if [ ! -f "$ROOTFS" ]; then
echo "ERROR: rootfs not found: $ROOTFS" >&2
exit 1
fi
ARGS=()
# Core machine setup
ARGS+=("-machine" "virt")
ARGS+=("-cpu" "cortex-a53")
ARGS+=("-m" "2048")
ARGS+=("-nographic")
# Enable GDB server on tcp::1234
ARGS+=("-s")
# Kernel & rootfs
ARGS+=("-kernel" "$KERNEL/arch/arm64/boot/Image")
ARGS+=("-drive" "file=$ROOTFS,format=raw,if=virtio")
# Kernel command line
ARGS+=("-append" "console=ttyAMA0 earlycon root=/dev/vda rw")
# Networking for ADB over TCP (forward host 5555 -> guest 5555)
ARGS+=("-netdev" "user,id=net0,hostfwd=tcp::5555-:5555")
ARGS+=("-device" "virtio-net,netdev=net0")
# Optional freeze flag (halt CPU at reset)
for opt in "$@"; do
case "$opt" in
freeze)
ARGS+=("-S")
;;
*)
echo "Warning: unknown option '$opt' (supported: freeze)" >&2
;;
esac
done
echo "Running: $QEMU ${ARGS[*]}"
exec "$QEMU" "${ARGS[@]}"
Make the script executable.
chmod +x run.sh
5. Running the kernel with GDB
Open two terminal windows.
Terminal 1: Start QEMU (target)
./run.sh freeze
Terminal 2: Start GDB (host)
gdb common/vmlinux
(gdb) set architecture aarch64
(gdb) target remote 127.0.0.1:1234
(gdb) continue
At this point, the kernel boots under QEMU and can be debugged using GDB.
Terminal 1: Login and Run adbd
adbd --tcpip 5555
Terminal 3: ADB
adb connect localhost:5555
adb devices
adb shell