mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
ARM
This commit is contained in:
33
README.md
33
README.md
@@ -1,6 +1,6 @@
|
||||
# Linux Kernel Module Cheat
|
||||
|
||||
Run one command, get into QEMU Buildroot BusyBox with several minimal Linux kernel 4.9 module example tutorials with GDB debug support. Tested in Ubuntu 14.04 - 16.10 hosts.
|
||||
Run one command, get into QEMU Buildroot BusyBox with several minimal Linux kernel 4.9 module example tutorials with GDB debug support. x86 and ARM guests supported. Tested in Ubuntu 14.04 - 16.10 hosts.
|
||||
|
||||
Usage:
|
||||
|
||||
@@ -176,6 +176,37 @@ And then tell GDB where the module was loaded with:
|
||||
Ctrl + C
|
||||
add-symbol-file ../kernel_module-1.0/fops.ko 0xfffffffa00000000
|
||||
|
||||
## ARM
|
||||
|
||||
The portability of the kernel and toolchains is amazing.
|
||||
|
||||
If you already have an x86 build present, first:
|
||||
|
||||
cd buildroot
|
||||
mv output output.x86~
|
||||
|
||||
First ARM build:
|
||||
|
||||
./run -a arm
|
||||
|
||||
Run without build:
|
||||
|
||||
./runqemu -a arm
|
||||
|
||||
Debug:
|
||||
|
||||
./runqemu -a arm -d
|
||||
# On another terminal.
|
||||
./rungdb -a arm
|
||||
|
||||
ARM TODOs:
|
||||
|
||||
- only managed to run in the terminal interface (but weirdly an blank QEMU window is still opened)
|
||||
- Ctrl + C kills the emulator, not sent to guest. See:
|
||||
- <https://github.com/cloudius-systems/osv/issues/49>
|
||||
- <https://unix.stackexchange.com/questions/167165/how-to-pass-ctrl-c-in-qemu>
|
||||
- `fops.ko`, `printf a >fops` crashes with `BUG: recent printk recursion!`
|
||||
|
||||
## Table of contents
|
||||
|
||||
1. [Introduction](introduction.md)
|
||||
|
||||
@@ -9,7 +9,14 @@ KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH)
|
||||
KERNEL_MODULE_SITE_METHOD = local
|
||||
|
||||
define KERNEL_MODULE_BUILD_CMDS
|
||||
$(MAKE) -C '$(@D)' LINUX_DIR='$(LINUX_DIR)' PWD='$(@D)' CC='$(TARGET_CC)' LD='$(TARGET_LD)'
|
||||
$(MAKE) \
|
||||
-C '$(@D)' \
|
||||
ARCH='$(KERNEL_ARCH)' \
|
||||
CC='$(TARGET_CC)' \
|
||||
CROSS_COMPILE='$(TARGET_CROSS)' \
|
||||
LD='$(TARGET_LD)' \
|
||||
LINUX_DIR='$(LINUX_DIR)' \
|
||||
PWD='$(@D)'
|
||||
endef
|
||||
|
||||
define KERNEL_MODULE_INSTALL_TARGET_CMDS
|
||||
|
||||
@@ -15,7 +15,7 @@ int main(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (delete_module(argv[1], O_NONBLOCK) != 0) {
|
||||
perror("delete_modul");
|
||||
perror("delete_module");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
20
run
20
run
@@ -1,7 +1,25 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
cd buildroot
|
||||
make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig
|
||||
arch='x86_64'
|
||||
while getopts a: OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
defconfig=qemu_x86_64_defconfig
|
||||
;;
|
||||
arm)
|
||||
# qemu_arm_vexpress_defconfig required a newer QEMU than 2.0.0 on a Ubuntu host.
|
||||
# so let's stick to versatile for now.
|
||||
defconfig=qemu_arm_versatile_defconfig
|
||||
;;
|
||||
esac
|
||||
make BR2_EXTERNAL="$(pwd)/../kernel_module" "$defconfig"
|
||||
# Can't get rid of this for now.
|
||||
# http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
||||
cat ../buildroot_config_fragment >> .config
|
||||
|
||||
57
rungdb
57
rungdb
@@ -1,22 +1,51 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
arch=x86_64
|
||||
while getopts a: OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch=$OPTARG
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
if [ "$#" -gt 0 ]; then
|
||||
brk="-ex 'break $1'"
|
||||
else
|
||||
brk=""
|
||||
fi
|
||||
gdb="$(pwd)/buildroot/output/host/usr/bin/x86_64-linux-gdb"
|
||||
|
||||
gdb="$(pwd)/buildroot/output/host/usr/bin/${arch}-linux-gdb"
|
||||
cd buildroot/output/build/linux-*.*.*/
|
||||
cmd="$gdb \
|
||||
-q \
|
||||
-ex 'add-auto-load-safe-path $(pwd)' \
|
||||
-ex 'file vmlinux' \
|
||||
-ex 'set arch i386:x86-64:intel' \
|
||||
-ex 'target remote localhost:1234' \
|
||||
$brk \
|
||||
-ex 'continue' \
|
||||
-ex 'disconnect' \
|
||||
-ex 'set arch i386:x86-64' \
|
||||
-ex 'target remote localhost:1234' \
|
||||
-ex 'lx-symbols ../kernel_module-1.0/'
|
||||
"
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
# http://stackoverflow.com/questions/11408041/how-to-debug-the-linux-kernel-with-gdb-and-qemu/33203642#33203642
|
||||
# http://stackoverflow.com/questions/4943857/linux-kernel-live-debugging-how-its-done-and-what-tools-are-used/42316607#42316607
|
||||
# http://stackoverflow.com/questions/28607538/how-to-debug-linux-kernel-modules-with-qemu/44095831#44095831
|
||||
cmd="$gdb \
|
||||
-q \
|
||||
-ex 'add-auto-load-safe-path $(pwd)' \
|
||||
-ex 'file vmlinux' \
|
||||
-ex 'set arch i386:x86-64:intel' \
|
||||
-ex 'target remote localhost:1234' \
|
||||
$brk \
|
||||
-ex 'continue' \
|
||||
-ex 'disconnect' \
|
||||
-ex 'set arch i386:x86-64' \
|
||||
-ex 'target remote localhost:1234' \
|
||||
-ex 'lx-symbols ../kernel_module-1.0/'
|
||||
"
|
||||
;;
|
||||
arm)
|
||||
cmd="$gdb \
|
||||
-q \
|
||||
-ex 'add-auto-load-safe-path $(pwd)' \
|
||||
-ex 'file vmlinux' \
|
||||
-ex 'target remote localhost:1234' \
|
||||
-ex 'lx-symbols ../kernel_module-1.0/'
|
||||
"
|
||||
;;
|
||||
esac
|
||||
eval "$cmd"
|
||||
|
||||
56
runqemu
56
runqemu
@@ -3,12 +3,16 @@
|
||||
set -e
|
||||
|
||||
# CLI handling.
|
||||
arch=x86_64
|
||||
debug=false
|
||||
nographic=false
|
||||
extra_append=''
|
||||
extra_flags=''
|
||||
while getopts dn OPT; do
|
||||
while getopts a:dn OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch=$OPTARG
|
||||
;;
|
||||
d)
|
||||
debug=true
|
||||
extra_flags="$extra_flags -S -s"
|
||||
@@ -21,23 +25,41 @@ while getopts dn OPT; do
|
||||
esac
|
||||
done
|
||||
|
||||
# If we turn on buildroot host QEMU some day.
|
||||
#cmd="./buildroot/output/host/usr/bin/qemu-system-x86_64 \
|
||||
cmd="qemu-system-x86_64 \
|
||||
-M pc \
|
||||
-append 'root=/dev/vda $extra_append' \
|
||||
-drive file=buildroot/output/images/rootfs.ext2,if=virtio,format=raw \
|
||||
-kernel buildroot/output/images/bzImage \
|
||||
-m 128M \
|
||||
-net nic,model=virtio \
|
||||
-net user \
|
||||
-smp 1 \
|
||||
$extra_flags \
|
||||
;
|
||||
"
|
||||
images_dir='buildroot/output/images'
|
||||
case "$arch" in
|
||||
x86_64)
|
||||
# If we turn on buildroot host QEMU some day.
|
||||
#cmd="./buildroot/output/host/usr/bin/qemu-system-x86_64 \
|
||||
cmd="qemu-system-x86_64 \
|
||||
-M pc \
|
||||
-append 'root=/dev/vda $extra_append' \
|
||||
-drive file=${images_dir}/rootfs.ext2,if=virtio,format=raw \
|
||||
-kernel ${images_dir}/bzImage \
|
||||
-m 128M \
|
||||
-net nic,model=virtio \
|
||||
-net user \
|
||||
-smp 1 \
|
||||
$extra_flags
|
||||
"
|
||||
;;
|
||||
arm)
|
||||
cmd="qemu-system-arm \
|
||||
-M versatilepb \
|
||||
-append 'root=/dev/sda console=ttyAMA0,115200' \
|
||||
-drive file=${images_dir}/rootfs.ext2,if=scsi,format=raw \
|
||||
-dtb ${images_dir}/versatile-pb.dtb \
|
||||
-kernel ${images_dir}/zImage \
|
||||
-m 128M \
|
||||
-net nic,model=rtl8139 \
|
||||
-net user \
|
||||
-serial stdio \
|
||||
-smp 1 \
|
||||
$extra_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if $debug && ! $nographic; then
|
||||
eval nohup "$cmd" &>/dev/null &
|
||||
if "$debug" && ! "$nographic" && [ ! "$arch" = 'arm' ]; then
|
||||
eval "$cmd" &>/dev/null &
|
||||
# TODO: Ctrl +C gets sent to QEMU? Why? Does not happen if I run
|
||||
# ./rungdb manually from outside this script!!! But why?!?!
|
||||
# eval has nothing to do with it, minimized example with explicit
|
||||
|
||||
Reference in New Issue
Block a user