mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-28 04:24:26 +01:00
ARM
This commit is contained in:
33
README.md
33
README.md
@@ -1,6 +1,6 @@
|
|||||||
# Linux Kernel Module Cheat
|
# 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:
|
Usage:
|
||||||
|
|
||||||
@@ -176,6 +176,37 @@ And then tell GDB where the module was loaded with:
|
|||||||
Ctrl + C
|
Ctrl + C
|
||||||
add-symbol-file ../kernel_module-1.0/fops.ko 0xfffffffa00000000
|
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
|
## Table of contents
|
||||||
|
|
||||||
1. [Introduction](introduction.md)
|
1. [Introduction](introduction.md)
|
||||||
|
|||||||
@@ -9,7 +9,14 @@ KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH)
|
|||||||
KERNEL_MODULE_SITE_METHOD = local
|
KERNEL_MODULE_SITE_METHOD = local
|
||||||
|
|
||||||
define KERNEL_MODULE_BUILD_CMDS
|
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
|
endef
|
||||||
|
|
||||||
define KERNEL_MODULE_INSTALL_TARGET_CMDS
|
define KERNEL_MODULE_INSTALL_TARGET_CMDS
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ int main(int argc, char **argv) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (delete_module(argv[1], O_NONBLOCK) != 0) {
|
if (delete_module(argv[1], O_NONBLOCK) != 0) {
|
||||||
perror("delete_modul");
|
perror("delete_module");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|||||||
20
run
20
run
@@ -1,7 +1,25 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -e
|
set -e
|
||||||
cd buildroot
|
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.
|
# Can't get rid of this for now.
|
||||||
# http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
# http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
||||||
cat ../buildroot_config_fragment >> .config
|
cat ../buildroot_config_fragment >> .config
|
||||||
|
|||||||
57
rungdb
57
rungdb
@@ -1,22 +1,51 @@
|
|||||||
#!/usr/bin/env bash
|
#!/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
|
if [ "$#" -gt 0 ]; then
|
||||||
brk="-ex 'break $1'"
|
brk="-ex 'break $1'"
|
||||||
else
|
else
|
||||||
brk=""
|
brk=""
|
||||||
fi
|
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-*.*.*/
|
cd buildroot/output/build/linux-*.*.*/
|
||||||
cmd="$gdb \
|
case "$arch" in
|
||||||
-q \
|
x86_64)
|
||||||
-ex 'add-auto-load-safe-path $(pwd)' \
|
# http://stackoverflow.com/questions/11408041/how-to-debug-the-linux-kernel-with-gdb-and-qemu/33203642#33203642
|
||||||
-ex 'file vmlinux' \
|
# http://stackoverflow.com/questions/4943857/linux-kernel-live-debugging-how-its-done-and-what-tools-are-used/42316607#42316607
|
||||||
-ex 'set arch i386:x86-64:intel' \
|
# http://stackoverflow.com/questions/28607538/how-to-debug-linux-kernel-modules-with-qemu/44095831#44095831
|
||||||
-ex 'target remote localhost:1234' \
|
cmd="$gdb \
|
||||||
$brk \
|
-q \
|
||||||
-ex 'continue' \
|
-ex 'add-auto-load-safe-path $(pwd)' \
|
||||||
-ex 'disconnect' \
|
-ex 'file vmlinux' \
|
||||||
-ex 'set arch i386:x86-64' \
|
-ex 'set arch i386:x86-64:intel' \
|
||||||
-ex 'target remote localhost:1234' \
|
-ex 'target remote localhost:1234' \
|
||||||
-ex 'lx-symbols ../kernel_module-1.0/'
|
$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"
|
eval "$cmd"
|
||||||
|
|||||||
56
runqemu
56
runqemu
@@ -3,12 +3,16 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
# CLI handling.
|
# CLI handling.
|
||||||
|
arch=x86_64
|
||||||
debug=false
|
debug=false
|
||||||
nographic=false
|
nographic=false
|
||||||
extra_append=''
|
extra_append=''
|
||||||
extra_flags=''
|
extra_flags=''
|
||||||
while getopts dn OPT; do
|
while getopts a:dn OPT; do
|
||||||
case "$OPT" in
|
case "$OPT" in
|
||||||
|
a)
|
||||||
|
arch=$OPTARG
|
||||||
|
;;
|
||||||
d)
|
d)
|
||||||
debug=true
|
debug=true
|
||||||
extra_flags="$extra_flags -S -s"
|
extra_flags="$extra_flags -S -s"
|
||||||
@@ -21,23 +25,41 @@ while getopts dn OPT; do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# If we turn on buildroot host QEMU some day.
|
images_dir='buildroot/output/images'
|
||||||
#cmd="./buildroot/output/host/usr/bin/qemu-system-x86_64 \
|
case "$arch" in
|
||||||
cmd="qemu-system-x86_64 \
|
x86_64)
|
||||||
-M pc \
|
# If we turn on buildroot host QEMU some day.
|
||||||
-append 'root=/dev/vda $extra_append' \
|
#cmd="./buildroot/output/host/usr/bin/qemu-system-x86_64 \
|
||||||
-drive file=buildroot/output/images/rootfs.ext2,if=virtio,format=raw \
|
cmd="qemu-system-x86_64 \
|
||||||
-kernel buildroot/output/images/bzImage \
|
-M pc \
|
||||||
-m 128M \
|
-append 'root=/dev/vda $extra_append' \
|
||||||
-net nic,model=virtio \
|
-drive file=${images_dir}/rootfs.ext2,if=virtio,format=raw \
|
||||||
-net user \
|
-kernel ${images_dir}/bzImage \
|
||||||
-smp 1 \
|
-m 128M \
|
||||||
$extra_flags \
|
-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
|
if "$debug" && ! "$nographic" && [ ! "$arch" = 'arm' ]; then
|
||||||
eval nohup "$cmd" &>/dev/null &
|
eval "$cmd" &>/dev/null &
|
||||||
# TODO: Ctrl +C gets sent to QEMU? Why? Does not happen if I run
|
# TODO: Ctrl +C gets sent to QEMU? Why? Does not happen if I run
|
||||||
# ./rungdb manually from outside this script!!! But why?!?!
|
# ./rungdb manually from outside this script!!! But why?!?!
|
||||||
# eval has nothing to do with it, minimized example with explicit
|
# eval has nothing to do with it, minimized example with explicit
|
||||||
|
|||||||
Reference in New Issue
Block a user