This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-05-05 00:00:00 +00:00
parent 0ef494b681
commit aea97698c3
48 changed files with 840 additions and 798 deletions

View File

@@ -977,23 +977,38 @@ Build, run and example, and clean it in-tree with:
.... ....
cd userland cd userland
./build ./build c/hello
./c/hello.out ./c/hello.out
./build --clean ./build --clean
.... ....
Source: link:userland/c/hello.c[]. Source: link:userland/c/hello.c[].
Or build just one directory: Build an entire directory:
.... ....
./build c ./build c
.... ....
or just one executable: Build the current directory:
.... ....
./build c/hello ./build
....
Note however that this would try to build the link:userland/libs/[] folder, which depends on certain libraries being installed on the host, e.g. <<blas>>.
You can install those libraries and do the build in one go with:
....
cd linux-kernel-module-cheat
./build --download-dependencies userland-host
....
If you modify a dependency that is not currently considered such as a header file, force the rebuild with:
....
./build --force-rebuild
.... ....
Do a more clean out of tree build and run the program instead: Do a more clean out of tree build and run the program instead:
@@ -1003,11 +1018,7 @@ Do a more clean out of tree build and run the program instead:
"$(./getvar --userland-build-id host userland_build_dir)/hello.out" "$(./getvar --userland-build-id host userland_build_dir)/hello.out"
.... ....
If you modify a dependency that is not currently considered such as a header file, force the rebuild with: Here we put the host executables in a separate <<build-variants,build-variant>> to avoid conflict with Buildroot builds.
....
./build --force-rebuild
....
===== Userland setup getting started full system ===== Userland setup getting started full system
@@ -1699,7 +1710,7 @@ Alternatively, if the module panics before you can read `/proc/modules`, there i
.... ....
echo 8 > /proc/sys/kernel/printk echo 8 > /proc/sys/kernel/printk
echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control
./myinsmod.out hello.ko ./linux/myinsmod.out hello.ko
.... ....
And then search for a line of type: And then search for a line of type:
@@ -1874,12 +1885,12 @@ Non-init process:
* Shell 2: * Shell 2:
+ +
.... ....
./run-gdb-user myinsmod main ./run-gdb-user linux/myinsmod main
.... ....
* Shell 1 after the boot finishes: * Shell 1 after the boot finishes:
+ +
.... ....
./myinsmod.out hello.ko ./linux/myinsmod.out hello.ko
.... ....
This is the least reliable setup as there might be other processes that use the given virtual address. This is the least reliable setup as there might be other processes that use the given virtual address.
@@ -1995,10 +2006,10 @@ For a more minimal baremetal multicore setup, see: <<arm-multicore>>.
We can set and get which cores the Linux kernel allows a program to run on with `sched_getaffinity` and `sched_setaffinity`: We can set and get which cores the Linux kernel allows a program to run on with `sched_getaffinity` and `sched_setaffinity`:
.... ....
./run --cpus 2 --eval-after './sched_getaffinity.out' ./run --cpus 2 --eval-after './linux/sched_getaffinity.out'
.... ....
Source: link:userland/sched_getaffinity.c[] Source: link:userland/linux/sched_getaffinity.c[]
Sample output: Sample output:
@@ -2025,7 +2036,7 @@ The number of cores is modified as explained at: <<number-of-cores>>
--config 'BR2_PACKAGE_UTIL_LINUX=y' \ --config 'BR2_PACKAGE_UTIL_LINUX=y' \
--config 'BR2_PACKAGE_UTIL_LINUX_SCHEDUTILS=y' \ --config 'BR2_PACKAGE_UTIL_LINUX_SCHEDUTILS=y' \
; ;
./run --eval-after 'taskset -c 1,1 ./sched_getaffinity.out' ./run --eval-after 'taskset -c 1,1 ./linux/sched_getaffinity.out'
.... ....
output: output:
@@ -2041,20 +2052,20 @@ so we see that the affinity was restricted to the second core from the start.
Let's do a QEMU observation to justify this example being in the repository with <<gdb-step-debug-userland-non-init,userland breakpoints>>. Let's do a QEMU observation to justify this example being in the repository with <<gdb-step-debug-userland-non-init,userland breakpoints>>.
We will run our `./sched_getaffinity.out` infinitely many time, on core 0 and core 1 alternatively: We will run our `./linux/sched_getaffinity.out` infinitely many time, on core 0 and core 1 alternatively:
.... ....
./run \ ./run \
--cpus 2 \ --cpus 2 \
--wait-gdb \ --wait-gdb \
--eval-after 'i=0; while true; do taskset -c $i,$i ./sched_getaffinity.out; i=$((! $i)); done' \ --eval-after 'i=0; while true; do taskset -c $i,$i ./linux/sched_getaffinity.out; i=$((! $i)); done' \
; ;
.... ....
on another shell: on another shell:
.... ....
./run-gdb-user "$(./getvar userland_build_dir)/sched_getaffinity.out" main ./run-gdb-user "$(./getvar userland_build_dir)/linux/sched_getaffinity.out" main
.... ....
Then, inside GDB: Then, inside GDB:
@@ -2079,13 +2090,13 @@ We should also try it out with kernel modules: https://stackoverflow.com/questio
TODO we then tried: TODO we then tried:
.... ....
./run --cpus 2 --eval-after './sched_getaffinity_threads.out' ./run --cpus 2 --eval-after './linux/sched_getaffinity_threads.out'
.... ....
and: and:
.... ....
./run-gdb-user "$(./getvar userland_build_dir)/sched_getaffinity_threads.out" ./run-gdb-user "$(./getvar userland_build_dir)/linux/sched_getaffinity_threads.out"
.... ....
to switch between two simultaneous live threads with different affinities, it just didn't break on our threads: to switch between two simultaneous live threads with different affinities, it just didn't break on our threads:
@@ -2431,10 +2442,10 @@ First build `gdbserver` into the root filesystem:
./build-buildroot --config 'BR2_PACKAGE_GDB=y' ./build-buildroot --config 'BR2_PACKAGE_GDB=y'
.... ....
Then on guest, to debug link:userland/myinsmod.c[]: Then on guest, to debug link:userland/linux/myinsmod.c[]:
.... ....
./gdbserver.sh ./myinsmod.out hello.ko ./gdbserver.sh ./linux/myinsmod.out hello.ko
.... ....
Source: link:rootfs_overlay/lkmc/gdbserver.sh[]. Source: link:rootfs_overlay/lkmc/gdbserver.sh[].
@@ -2442,13 +2453,13 @@ Source: link:rootfs_overlay/lkmc/gdbserver.sh[].
And on host: And on host:
.... ....
./run-gdbserver myinsmod ./run-gdbserver linux/myinsmod
.... ....
or alternatively with the full path: or alternatively with the full path:
.... ....
./run-gdbserver "$(./getvar userland_build_dir)/myinsmod.out" ./run-gdbserver "$(./getvar userland_build_dir)/linux/myinsmod.out"
.... ....
https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-arm-mips-elf-with-qemu-toolchain/16214#16214 https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-arm-mips-elf-with-qemu-toolchain/16214#16214
@@ -2587,7 +2598,7 @@ traps: ring0.out[55] general protection ip:40054c sp:7fffffffec20 error:0 in rin
Sources: Sources:
* link:kernel_modules/ring0.c[] * link:kernel_modules/ring0.c[]
* link:kernel_modules/ring0.h[] * link:include/ring0.h[]
* link:userland/ring0.c[] * link:userland/ring0.c[]
In both cases, we attempt to run the exact same code which is shared on the `ring0.h` header file. In both cases, we attempt to run the exact same code which is shared on the `ring0.h` header file.
@@ -2832,14 +2843,14 @@ ____
And you can try it out with: And you can try it out with:
.... ....
./run --kernel-cli 'init=/lkmc/init_env_poweroff.out - asdf=qwer zxcv' ./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out - asdf=qwer zxcv'
.... ....
Output: Output:
.... ....
args: args:
/lkmc/init_env_poweroff.out /lkmc/linux/init_env_poweroff.out
- -
zxcv zxcv
@@ -2849,7 +2860,7 @@ TERM=linux
asdf=qwer asdf=qwer
.... ....
Source: link:userland/init_env_poweroff.c[]. Source: link:userland/linux/init_env_poweroff.c[].
==== init arguments ==== init arguments
@@ -2858,14 +2869,14 @@ The annoying dash `-` gets passed as a parameter to `init`, which makes it impos
Arguments with dots that come after `-` are still treated specially (of the form `subsystem.somevalue`) and disappear, from args, e.g.: Arguments with dots that come after `-` are still treated specially (of the form `subsystem.somevalue`) and disappear, from args, e.g.:
.... ....
./run --kernel-cli 'init=/lkmc/init_env_poweroff.out - /lkmc/linux/poweroff.out' ./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out - /lkmc/linux/poweroff.out'
.... ....
outputs: outputs:
.... ....
args args
/lkmc/init_env_poweroff.out /lkmc/linux/init_env_poweroff.out
- -
ab ab
.... ....
@@ -3380,12 +3391,12 @@ See also: <<user-mode-simulation-with-glibc>>
=== QEMU user mode getting started === QEMU user mode getting started
Let's run link:userland/print_argv.c[] built with the Buildroot toolchain on QEMU user mode: Let's run link:userland/c/print_argv.c[] built with the Buildroot toolchain on QEMU user mode:
.... ....
./build user-mode-qemu ./build user-mode-qemu
./run \ ./run \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
; ;
.... ....
@@ -3413,12 +3424,12 @@ The commands are analogous to full system <<gdb>>, e.g. without tmux:
.... ....
./run \ ./run \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
--wait-gdb \ --wait-gdb \
; ;
./run-gdb \ ./run-gdb \
--userland print_argv \ --userland c/print_argv \
main main
; ;
.... ....
@@ -3427,7 +3438,7 @@ or with <<tmux>>:
.... ....
./run \ ./run \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
--tmux-args main \ --tmux-args main \
--wait-gdb \ --wait-gdb \
@@ -3449,7 +3460,7 @@ sudo apt-get install gcc-aarch64-linux-gnu qemu-system-aarch64
--arch aarch64 \ --arch aarch64 \
--qemu-which host --qemu-which host
--userland-build-id host \ --userland-build-id host \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
; ;
.... ....
@@ -3544,7 +3555,7 @@ Example:
./run \ ./run \
--arch aarch64 \ --arch aarch64 \
--static \ --static \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
; ;
.... ....
@@ -3567,7 +3578,7 @@ So programs that rely on those libraries might not compile as GCC can't find the
For example, if we try to build <<blas>> statically: For example, if we try to build <<blas>> statically:
.... ....
./build-userland --has-package openblas --static -- libs/openblas_hello ./build-userland --has-package openblas --static -- libs/openblas/hello
.... ....
it fails with: it fails with:
@@ -3583,7 +3594,7 @@ It's nice when <<gdb,the obvious>> just works, right?
.... ....
./run \ ./run \
--arch aarch64 \ --arch aarch64 \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
--wait-gdb \ --wait-gdb \
; ;
@@ -3594,7 +3605,7 @@ and on another shell:
.... ....
./run-gdb \ ./run-gdb \
--arch aarch64 \ --arch aarch64 \
--userland print_argv \ --userland c/print_argv \
main \ main \
; ;
.... ....
@@ -3605,7 +3616,7 @@ Or alternatively, if you are using <<tmux>>, do everything in one go with:
./run \ ./run \
--arch aarch64 \ --arch aarch64 \
--tmux-args main \ --tmux-args main \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
--wait-gdb \ --wait-gdb \
; ;
@@ -3643,7 +3654,7 @@ So let's just play with some static ones:
./run \ ./run \
--arch aarch64 \ --arch aarch64 \
--emulator gem5 \ --emulator gem5 \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
; ;
.... ....
@@ -3657,7 +3668,7 @@ TODO: how to escape spaces on the command line arguments?
--arch aarch64 \ --arch aarch64 \
--emulator gem5 \ --emulator gem5 \
--static \ --static \
--userland print_argv \ --userland c/print_argv \
--userland-args 'asdf "qw er"' \ --userland-args 'asdf "qw er"' \
--wait-gdb \ --wait-gdb \
; ;
@@ -3665,7 +3676,7 @@ TODO: how to escape spaces on the command line arguments?
--arch aarch64 \ --arch aarch64 \
--emulator gem5 \ --emulator gem5 \
--static \ --static \
--userland print_argv \ --userland c/print_argv \
main \ main \
; ;
.... ....
@@ -3794,18 +3805,18 @@ If you are feeling raw, you can insert and remove modules with our own minimal m
.... ....
# init_module # init_module
./myinsmod.out hello.ko ./linux/myinsmod.out hello.ko
# finit_module # finit_module
./myinsmod.out hello.ko "" 1 ./linux/myinsmod.out hello.ko "" 1
./myrmmod.out hello ./linux/myrmmod.out hello
.... ....
which teaches you how it is done from C code. which teaches you how it is done from C code.
Source: Source:
* link:userland/myinsmod.c[] * link:userland/linux/myinsmod.c[]
* link:userland/myrmmod.c[] * link:userland/linux/myrmmod.c[]
The Linux kernel offers two system calls for module insertion: The Linux kernel offers two system calls for module insertion:
@@ -5252,7 +5263,7 @@ But the awesome `CONFIG_DYNAMIC_DEBUG=y` option which we enable by default allow
.... ....
echo 8 > /proc/sys/kernel/printk echo 8 > /proc/sys/kernel/printk
echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control echo 'file kernel/module.c +p' > /sys/kernel/debug/dynamic_debug/control
./myinsmod.out hello.ko ./linux/myinsmod.out hello.ko
.... ....
and we have a shortcut at: and we have a shortcut at:
@@ -6375,7 +6386,7 @@ Outcome: `jiffies` gets printed to stdout every second from userland.
Sources: Sources:
* link:kernel_modules/poll.c[] * link:kernel_modules/poll.c[]
* link:kernel_modules/poll.c[] * link:include/poll.h[]
* link:rootfs_overlay/lkmc/poll.sh[] * link:rootfs_overlay/lkmc/poll.sh[]
Typically, we are waiting for some hardware to make some piece of data available available to the kernel. Typically, we are waiting for some hardware to make some piece of data available available to the kernel.
@@ -6404,8 +6415,8 @@ Outcome: the test passes:
Sources: Sources:
* link:kernel_modules/ioctl.c[] * link:kernel_modules/ioctl.c[]
* link:kernel_modules/ioctl.h[] * link:include/ioctl.h[]
* link:userland/ioctl.c[] * link:userland/kernel_modules/ioctl.c[]
* link:rootfs_overlay/lkmc/ioctl.sh[] * link:rootfs_overlay/lkmc/ioctl.sh[]
`ioctl` is one of the most important methods of communication with real device drivers, which often take several fields as input. `ioctl` is one of the most important methods of communication with real device drivers, which often take several fields as input.
@@ -6489,8 +6500,8 @@ Outcome: the test passes:
Sources: Sources:
* link:kernel_modules/anonymous_inode.c[] * link:kernel_modules/anonymous_inode.c[]
* link:kernel_modules/anonymous_inode.h[] * link:include/anonymous_inode.h[]
* link:userland/anonymous_inode.c[] * link:userland/kernel_modules/anonymous_inode.c[]
* link:rootfs_overlay/lkmc/anonymous_inode.sh[] * link:rootfs_overlay/lkmc/anonymous_inode.sh[]
This example gets an anonymous inode via <<ioctl>> from a debugfs entry by using `anon_inode_getfd`. This example gets an anonymous inode via <<ioctl>> from a debugfs entry by using `anon_inode_getfd`.
@@ -6517,8 +6528,8 @@ Outcome: the test passes:
Sources: Sources:
* link:kernel_modules/netlink.c[] * link:kernel_modules/netlink.c[]
* link:kernel_modules/netlink.h[] * link:include/netlink.h[]
* link:userland/netlink.c[] * link:userland/kernel_modules/netlink.c[]
* link:rootfs_overlay/lkmc/netlink.sh[] * link:rootfs_overlay/lkmc/netlink.sh[]
Launch multiple user requests in parallel to stress our socket: Launch multiple user requests in parallel to stress our socket:
@@ -6993,10 +7004,10 @@ In this section we will play with them.
First get a virtual address to play with: First get a virtual address to play with:
.... ....
./virt_to_phys_test.out & ./posix/virt_to_phys_test.out &
.... ....
Source: link:userland/virt_to_phys_test.c[] Source: link:userland/posix/virt_to_phys_test.c[]
Sample output: Sample output:
@@ -7091,7 +7102,7 @@ After one second, we see on the screen:
.... ....
i 9abcdef0 i 9abcdef0
[1]+ Done ./virt_to_phys_test.out [1]+ Done ./posix/virt_to_phys_test.out
.... ....
so the value changed, and the `while` loop exited! so the value changed, and the `while` loop exited!
@@ -7116,7 +7127,7 @@ Dump the physical address of all pages mapped to a given process using `/proc/<p
First launch `linux/virt_to_phys_user.out` as described at <<userland-physical-address-experiments>>. Suppose that the output was: First launch `linux/virt_to_phys_user.out` as described at <<userland-physical-address-experiments>>. Suppose that the output was:
.... ....
# ./virt_to_phys_test.out & # ./posix/virt_to_phys_test.out &
vaddr 0x601048 vaddr 0x601048
pid 63 pid 63
# ./linux/virt_to_phys_user.out 63 0x601048 # ./linux/virt_to_phys_user.out 63 0x601048
@@ -7133,9 +7144,9 @@ Sample output excerpt:
.... ....
vaddr pfn soft-dirty file/shared swapped present library vaddr pfn soft-dirty file/shared swapped present library
400000 1ede 0 1 0 1 ./virt_to_phys_test.out 400000 1ede 0 1 0 1 ./posix/virt_to_phys_test.out
600000 1a6f 0 0 0 1 ./virt_to_phys_test.out 600000 1a6f 0 0 0 1 ./posix/virt_to_phys_test.out
601000 1a61 0 0 0 1 ./virt_to_phys_test.out 601000 1a61 0 0 0 1 ./posix/virt_to_phys_test.out
602000 2208 0 0 0 1 [heap] 602000 2208 0 0 0 1 [heap]
603000 220b 0 0 0 1 [heap] 603000 220b 0 0 0 1 [heap]
7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so 7ffff78ec000 1fd4 0 1 0 1 /lib/libuClibc-1.0.30.so
@@ -7150,7 +7161,7 @@ Meaning of the flags:
* `vaddr`: first virtual address of a page the belongs to the process. Notably: * `vaddr`: first virtual address of a page the belongs to the process. Notably:
+ +
.... ....
./run-toolchain readelf -- -l "$(./getvar userland_build_dir)/virt_to_phys_test.out" ./run-toolchain readelf -- -l "$(./getvar userland_build_dir)/posix/virt_to_phys_test.out"
.... ....
+ +
contains: contains:
@@ -7222,7 +7233,7 @@ Logs proc events such as process creation to a link:kernel_modules/netlink.c[net
We then have a userland program that listens to the events and prints them out: We then have a userland program that listens to the events and prints them out:
.... ....
# ./proc_events.out & # ./linux/proc_events.out &
# set mcast listen ok # set mcast listen ok
# sleep 2 & sleep 1 # sleep 2 & sleep 1
fork: parent tid=48 pid=48 -> child tid=79 pid=79 fork: parent tid=48 pid=48 -> child tid=79 pid=79
@@ -7236,7 +7247,7 @@ a
# #
.... ....
Source: link:userland/proc_events.c[] Source: link:userland/linux/proc_events.c[]
TODO: why `exit: tid=79` shows after `exit: tid=80`? TODO: why `exit: tid=79` shows after `exit: tid=80`?
@@ -7245,7 +7256,7 @@ Note how `echo a` is a Bash built-in, and therefore does not spawn a new process
TODO: why does this produce no output? TODO: why does this produce no output?
.... ....
./proc_events.out >f & ./linux/proc_events.out >f &
.... ....
* https://stackoverflow.com/questions/6075013/detect-launching-of-programs-on-linux-platform/8255487#8255487 * https://stackoverflow.com/questions/6075013/detect-launching-of-programs-on-linux-platform/8255487#8255487
@@ -7725,7 +7736,7 @@ UIO interface in a nutshell:
Sources: Sources:
* link:userland/uio_read.c[] * link:userland/kernel_modules/uio_read.c[]
* link:rootfs_overlay/lkmc/uio_read.sh[] * link:rootfs_overlay/lkmc/uio_read.sh[]
Bibliography: Bibliography:
@@ -8169,8 +8180,8 @@ DRM / DRI is the new interface that supersedes `fbdev`:
.... ....
./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y' ./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y'
./build-userland --has-package libdrm -- libs/libdrm_modeset ./build-userland --has-package libdrm -- libs/libdrm/modeset
./run --eval-after './libs/libdrm_modeset.out' --graphic ./run --eval-after './libs/libdrm/modeset.out' --graphic
.... ....
Source: link:userland/libs/libdrm_modeset.c[] Source: link:userland/libs/libdrm_modeset.c[]
@@ -8183,7 +8194,7 @@ TODO not working for `aarch64`, it takes over the screen for a few seconds and t
./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y' ./build-buildroot --config 'BR2_PACKAGE_LIBDRM=y'
./build-userland --has-package libdrm ./build-userland --has-package libdrm
./build-buildroot ./build-buildroot
./run --eval-after './libs/libdrm_modeset.out' --graphic ./run --eval-after './libs/libdrm/modeset.out' --graphic
.... ....
<<kmscube>> however worked, which means that it must be a bug with this demo? <<kmscube>> however worked, which means that it must be a bug with this demo?
@@ -8208,7 +8219,7 @@ Try creating new displays:
to see multiple `/dev/dri/cardN`, and then use a different display with: to see multiple `/dev/dri/cardN`, and then use a different display with:
.... ....
./run --eval-after './libs/libdrm_modeset.out' --graphic ./run --eval-after './libs/libdrm/modeset.out' --graphic
.... ....
Bibliography: Bibliography:
@@ -9909,8 +9920,8 @@ Buildroot supports it, which makes everything just trivial:
.... ....
./build-buildroot --config 'BR2_PACKAGE_OPENBLAS=y' ./build-buildroot --config 'BR2_PACKAGE_OPENBLAS=y'
./build-userland --has-package openblas -- libs/openblas_hello ./build-userland --has-package openblas -- libs/openblas/hello
./run --eval-after './libs/openblas_hello.out; echo $?' ./run --eval-after './libs/openblas/hello.out; echo $?'
.... ....
Outcome: the test passes: Outcome: the test passes:
@@ -9919,7 +9930,7 @@ Outcome: the test passes:
0 0
.... ....
Source: link:userland/libs/openblas.c[] Source: link:userland/libs/openblas/hello.c[]
The test performs a general matrix multiplication: The test performs a general matrix multiplication:
@@ -9949,13 +9960,13 @@ Header only linear algebra library with a mainline Buildroot package:
.... ....
./build-buildroot --config 'BR2_PACKAGE_EIGEN=y' ./build-buildroot --config 'BR2_PACKAGE_EIGEN=y'
./build-userland --has-package eigen -- libs/eigen_hello ./build-userland --has-package eigen -- libs/eigen/hello
.... ....
Just create an array and print it: Just create an array and print it:
.... ....
./run --eval-after './libs/eigen_hello.out' ./run --eval-after './libs/eigen/hello.out'
.... ....
Output: Output:
@@ -9965,7 +9976,7 @@ Output:
2.5 1.5 2.5 1.5
.... ....
Source: link:userland/libs/eigen_hello.cpp[] Source: link:userland/libs/eigen/hello.cpp[]
This example just creates a matrix and prints it out. This example just creates a matrix and prints it out.
@@ -10192,7 +10203,7 @@ The alternative is to do as in <<gdb-step-debug-userland-processes>>.
Next, follow the exact same steps explained at <<gdb-step-debug-userland-non-init-without--d>>, but passing `-g` to every command as usual. Next, follow the exact same steps explained at <<gdb-step-debug-userland-non-init-without--d>>, but passing `-g` to every command as usual.
But then TODO (I'll still go crazy one of those days): for `arm`, while debugging `./myinsmod.out hello.ko`, after then line: But then TODO (I'll still go crazy one of those days): for `arm`, while debugging `./linux/myinsmod.out hello.ko`, after then line:
.... ....
23 if (argc < 3) { 23 if (argc < 3) {

8
build
View File

@@ -339,6 +339,14 @@ so looping over all of them would waste time.
self._build_file('build-userland'), self._build_file('build-userland'),
dependencies=['buildroot'], dependencies=['buildroot'],
), ),
'userland-host': _Component(
self._build_file('build-userland'),
apt_get_pkgs={
'libdrm-dev',
'libeigen3-dev',
'libopenblas-dev',
},
),
'userland-gem5': _Component( 'userland-gem5': _Component(
self._build_file('build-userland', static=True, userland_build_id='static'), self._build_file('build-userland', static=True, userland_build_id='static'),
dependencies=['buildroot'], dependencies=['buildroot'],

View File

@@ -25,6 +25,13 @@ Build our compiled userland examples.
help='''\ help='''\
Indicate that a given package is present in the root filesystem, which Indicate that a given package is present in the root filesystem, which
allows us to build examples that rely on it. allows us to build examples that rely on it.
''',
)
self.add_argument(
'--has-all-packages',
action='store_true',
help='''\
Indicate that all packages from --has-package are available.
''', ''',
) )
self.add_argument( self.add_argument(
@@ -138,6 +145,7 @@ Default: build all examples that have their package dependencies met, e.g.:
def build(self): def build(self):
build_dir = self.get_build_dir() build_dir = self.get_build_dir()
has_packages = set(self.env['has_package']) has_packages = set(self.env['has_package'])
has_all_packages = self.env['has_all_packages']
ccflags = [ ccflags = [
'-I', self.env['root_dir'], LF, '-I', self.env['root_dir'], LF,
'-O0', LF, '-O0', LF,
@@ -179,6 +187,10 @@ Default: build all examples that have their package dependencies met, e.g.:
extra_deps=[self.env['common_h']], extra_deps=[self.env['common_h']],
link=False, link=False,
) )
if self.env['gcc_which'] == 'host':
eigen_root = '/'
else:
eigen_root = self.env['buildroot_staging_dir']
pkgs = { pkgs = {
'eigen': { 'eigen': {
# TODO: was failing with: # TODO: was failing with:
@@ -188,7 +200,7 @@ Default: build all examples that have their package dependencies met, e.g.:
'ccflags': [ 'ccflags': [
'-I', '-I',
os.path.join( os.path.join(
self.env['buildroot_staging_dir'], eigen_root,
'usr', 'usr',
'include', 'include',
'eigen3' 'eigen3'
@@ -217,26 +229,19 @@ Default: build all examples that have their package dependencies met, e.g.:
dirpath_relative_root = path_abs[rootdir_abs_len + 1:] dirpath_relative_root = path_abs[rootdir_abs_len + 1:]
dirpath_relative_root_components = dirpath_relative_root.split(os.sep) dirpath_relative_root_components = dirpath_relative_root.split(os.sep)
dirpath_relative_root_components_len = len(dirpath_relative_root_components) dirpath_relative_root_components_len = len(dirpath_relative_root_components)
do_build_dir = True
in_arch = False
if dirpath_relative_root_components_len > 0:
if dirpath_relative_root_components[0] == 'arch':
if dirpath_relative_root_components_len > 1:
if dirpath_relative_root_components[1] == self.env['arch']:
in_arch = True
else:
do_build_dir = False
else:
do_build_dir = False
in_libs = dirpath_relative_root_components[0] == 'libs'
if do_build_dir:
out_dir = os.path.join( out_dir = os.path.join(
build_dir, build_dir,
dirpath_relative_root dirpath_relative_root
) )
common_objs_dir = [common_obj] common_objs_dir = [common_obj]
ccflags_after = []
ccflags_dir = ccflags.copy() ccflags_dir = ccflags.copy()
if dirpath_relative_root_components in ('gcc', 'kernel_modules', 'linux'): if dirpath_relative_root_components_len > 0:
if dirpath_relative_root_components[0] in (
'gcc',
'kernel_modules',
'linux',
):
cstd = 'gnu11' cstd = 'gnu11'
cxxstd = 'gnu++17' cxxstd = 'gnu++17'
else: else:
@@ -244,7 +249,9 @@ Default: build all examples that have their package dependencies met, e.g.:
cxxstd = self.default_cxxstd cxxstd = self.default_cxxstd
# -pedantic complains even if we use -std=gnu11. # -pedantic complains even if we use -std=gnu11.
ccflags_dir.extend(['-pedantic', LF]) ccflags_dir.extend(['-pedantic', LF])
if in_arch: if dirpath_relative_root_components[0] == 'arch':
if dirpath_relative_root_components_len > 1:
if dirpath_relative_root_components[1] == self.env['arch']:
ccflags_dir.extend([ ccflags_dir.extend([
'-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF, '-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF,
'-I', os.path.join(self.env['userland_source_arch_dir']), LF, '-I', os.path.join(self.env['userland_source_arch_dir']), LF,
@@ -281,6 +288,34 @@ Default: build all examples that have their package dependencies met, e.g.:
# So we just write divided inline assembly for now. # So we just write divided inline assembly for now.
'-masm-syntax-unified', LF, '-masm-syntax-unified', LF,
]) ])
else:
continue
else:
continue
elif dirpath_relative_root_components[0] == 'libs':
if dirpath_relative_root_components_len > 1:
pkg_key = dirpath_relative_root_components[1]
if not (has_all_packages or pkg_key in has_packages):
continue
pkg = pkgs[pkg_key]
if 'ccflags' in pkg:
ccflags_dir.extend(pkg['ccflags'])
else:
pkg_config_output = subprocess.check_output([
self.env['pkg_config'],
'--cflags',
pkg_key
]).decode()
ccflags_dir.extend(self.sh.shlex_split(pkg_config_output))
if 'ccflags_after' in pkg:
ccflags_dir.extend(pkg['ccflags_after'])
else:
pkg_config_output = subprocess.check_output([
self.env['pkg_config'],
'--libs',
pkg_key
]).decode()
ccflags_after.extend(self.sh.shlex_split(pkg_config_output))
for in_filename in in_filenames: for in_filename in in_filenames:
path_relative_root = os.path.join(dirpath_relative_root, in_filename) path_relative_root = os.path.join(dirpath_relative_root, in_filename)
if path_relative_root == common_obj_asm_relpath: if path_relative_root == common_obj_asm_relpath:
@@ -291,36 +326,10 @@ Default: build all examples that have their package dependencies met, e.g.:
out_dir, out_dir,
in_name + self.env['userland_build_ext'] in_name + self.env['userland_build_ext']
) )
ccflags_file = ccflags_dir.copy()
ccflags_after = []
if in_libs:
pkg_key = in_name.split('_')[0]
if pkg_key in pkgs:
if pkg_key not in has_packages:
continue
pkg = pkgs[pkg_key]
if 'ccflags' in pkg:
ccflags_file.extend(pkg['ccflags'])
else:
pkg_config_output = subprocess.check_output([
self.env['buildroot_pkg_config'],
'--cflags',
pkg_key
]).decode()
ccflags_file.extend(self.sh.shlex_split(pkg_config_output))
if 'ccflags_after' in pkg:
ccflags_file.extend(pkg['ccflags_after'])
else:
pkg_config_output = subprocess.check_output([
self.env['buildroot_pkg_config'],
'--libs',
pkg_key
]).decode()
ccflags_after.extend(self.sh.shlex_split(pkg_config_output))
error = thread_pool.submit({ error = thread_pool.submit({
'in_path': in_path, 'in_path': in_path,
'out_path': out_path, 'out_path': out_path,
'ccflags': ccflags_file, 'ccflags': ccflags_dir,
'cstd': cstd, 'cstd': cstd,
'cxxstd': cxxstd, 'cxxstd': cxxstd,
'extra_objs': common_objs_dir, 'extra_objs': common_objs_dir,

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
"$(git rev-parse --show-toplevel)/build-userland" \ "$(git rev-parse --show-toplevel)/build-userland" \
--gcc-which host \ --gcc-which host \
--has-all-packages \
--in-tree \ --in-tree \
--target-cwd \ --target-cwd \
"$@" \ "$@" \

View File

@@ -10,7 +10,6 @@ import imp
import inspect import inspect
import json import json
import math import math
import multiprocessing
import os import os
import platform import platform
import re import re
@@ -824,6 +823,7 @@ lunch aosp_{}-eng
env['buildroot_toolchain_prefix'] env['buildroot_toolchain_prefix']
) )
env['userland_library_dir'] = env['buildroot_target_dir'] env['userland_library_dir'] = env['buildroot_target_dir']
env['pkg_config'] = env['buildroot_pkg_config']
elif env['gcc_which'] == 'crosstool-ng': elif env['gcc_which'] == 'crosstool-ng':
env['toolchain_prefix'] = os.path.join( env['toolchain_prefix'] = os.path.join(
env['crosstool_ng_bin_dir'], env['crosstool_ng_bin_dir'],
@@ -837,6 +837,7 @@ lunch aosp_{}-eng
env['userland_library_dir'] = '/usr/arm-linux-gnueabihf' env['userland_library_dir'] = '/usr/arm-linux-gnueabihf'
elif env['arch'] == 'aarch64': elif env['arch'] == 'aarch64':
env['userland_library_dir'] = '/usr/aarch64-linux-gnu/' env['userland_library_dir'] = '/usr/aarch64-linux-gnu/'
env['pkg_config'] = 'pkg-config'
elif env['gcc_which'] == 'host-baremetal': elif env['gcc_which'] == 'host-baremetal':
if env['arch'] == 'arm': if env['arch'] == 'arm':
env['toolchain_prefix'] = 'arm-none-eabi' env['toolchain_prefix'] = 'arm-none-eabi'
@@ -1249,7 +1250,7 @@ TODO: not yet implemented on all scripts.
self.add_argument( self.add_argument(
'-j', '-j',
'--nproc', '--nproc',
default=multiprocessing.cpu_count(), default=len(os.sched_getaffinity(0)),
type=int, type=int,
help='Number of processors to use for the build.', help='Number of processors to use for the build.',
) )

View File

@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
# https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode
set -e set -e
insmod anonymous_inode.ko insmod anonymous_inode.ko
[ "$(/anonymous_inode.out /sys/kernel/debug/lkmc_anonymous_inode 3)" = "$(printf '1\n10\n100')" ] [ "$(./kernel_modules/anonymous_inode.out /sys/kernel/debug/lkmc_anonymous_inode 3)" = "$(printf '1\n10\n100')" ]
rmmod anonymous_inode rmmod anonymous_inode

View File

@@ -1,7 +1,8 @@
#!/bin/sh #!/bin/sh
# https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl
set -e set -e
f=/sys/kernel/debug/lkmc_ioctl f=/sys/kernel/debug/lkmc_ioctl
insmod ioctl.ko insmod ioctl.ko
[ "$(/ioctl.out "$f" 0 1)" = 2 ] [ "$(./kernel_modules/ioctl.out "$f" 0 1)" = 2 ]
[ "$(/ioctl.out "$f" 1 1 1)" = '2 0' ] [ "$(./kernel_modules/ioctl.out "$f" 1 1 1)" = '2 0' ]
rmmod ioctl rmmod ioctl

View File

@@ -1,7 +1,8 @@
#!/bin/sh #!/bin/sh
# https://github.com/cirosantilli/linux-kernel-module-cheat#netlink-sockets
set -e set -e
insmod netlink.ko insmod netlink.ko
[ "$(/netlink.out)" = 0 ] [ "$(./linux/netlink.out)" = 0 ]
[ "$(/netlink.out)" = 1 ] [ "$(./linux/netlink.out)" = 1 ]
[ "$(/netlink.out)" = 2 ] [ "$(./linux/netlink.out)" = 2 ]
rmmod netlink rmmod netlink

View File

@@ -1,5 +1,6 @@
#!/bin/sh #!/bin/sh
# https://github.com/cirosantilli/linux-kernel-module-cheat#poll
set -e set -e
insmod poll.ko insmod poll.ko
./poll.out /sys/kernel/debug/lkmc_poll ./kernel_modules/poll.out /sys/kernel/debug/lkmc_poll
#rmmod poll #rmmod poll

View File

@@ -4,7 +4,7 @@ set -e
modprobe uio_pci_generic modprobe uio_pci_generic
# pci_min device # pci_min device
echo '1234 11e9' > /sys/bus/pci/drivers/uio_pci_generic/new_id echo '1234 11e9' > /sys/bus/pci/drivers/uio_pci_generic/new_id
./uio_read.out & ./kernel_modules/uio_read.out &
# Helper to observe interrupts. # Helper to observe interrupts.
insmod irq.ko insmod irq.ko
base="$(setpci -d 1234:11e9 BASE_ADDRESS_0)" base="$(setpci -d 1234:11e9 BASE_ADDRESS_0)"

View File

@@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from typing import Any, Callable, Dict, Iterable, Union from typing import Any, Callable, Dict, Iterable, Union
import multiprocessing
import queue import queue
import sys import sys
import threading import threading
@@ -66,7 +65,7 @@ class ThreadPool:
handle_output = lambda input, output, exception: exception handle_output = lambda input, output, exception: exception
self.handle_output = handle_output self.handle_output = handle_output
if nthreads is None: if nthreads is None:
nthreads = multiprocessing.cpu_count() nthreads = len(os.sched_getaffinity(0))
self.nthreads = nthreads self.nthreads = nthreads
self.error_output = None self.error_output = None
self.error_output_lock = threading.Lock() self.error_output_lock = threading.Lock()

View File

@@ -1,46 +0,0 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /* sleep */
#include "../include/anonymous_inode.h"
int main(int argc, char **argv)
{
char buf[1024];
int fd_ioctl, fd_ioctl_anon, ret;
size_t i, nreads;
if (argc < 2) {
puts("Usage: ./prog <ioctl-file> [<nreads>]");
return EXIT_FAILURE;
} else if (argc > 2) {
nreads = strtol(argv[2], NULL, 10);
} else {
nreads = 3;
}
fd_ioctl = open(argv[1], O_RDONLY);
if (fd_ioctl == -1) {
perror("open");
return EXIT_FAILURE;
}
ret = ioctl(fd_ioctl, LKMC_ANONYMOUS_INODE_GET_FD, &fd_ioctl_anon);
if (ret == -1) {
perror("ioctl");
return EXIT_FAILURE;
}
for (i = 0; i < nreads; ++i) {
ret = read(fd_ioctl_anon, buf, sizeof(buf));
printf("%.*s\n", ret, buf);
}
close(fd_ioctl_anon);
close(fd_ioctl);
return EXIT_SUCCESS;
}

14
userland/c/print_argv.c Normal file
View File

@@ -0,0 +1,14 @@
/* Print each command line argument received, one per line.
*
* Good sanity check for user mode:
* https://github.com/cirosantilli/linux-kernel-module-cheat#qemu-user-mode-getting-started
*/
#include <stdio.h>
int main(int argc, char **argv) {
size_t i;
for (i = 0; i < (size_t)argc; ++i)
printf("%s\n", argv[i]);
return 0;
}

View File

@@ -26,8 +26,7 @@ typedef struct {
* @param[in] vaddr virtual address to get entry for * @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure * @return 0 for success, 1 for failure
*/ */
int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr) {
{
size_t nread; size_t nread;
ssize_t ret; ssize_t ret;
uint64_t data; uint64_t data;
@@ -62,8 +61,7 @@ int pagemap_get_entry(PagemapEntry *entry, int pagemap_fd, uintptr_t vaddr)
* @param[in] vaddr virtual address to get entry for * @param[in] vaddr virtual address to get entry for
* @return 0 for success, 1 for failure * @return 0 for success, 1 for failure
*/ */
int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr) int virt_to_phys_user(uintptr_t *paddr, pid_t pid, uintptr_t vaddr) {
{
char pagemap_file[BUFSIZ]; char pagemap_file[BUFSIZ];
int pagemap_fd; int pagemap_fd;

View File

@@ -1,26 +0,0 @@
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <sys/reboot.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int i;
puts("args:");
for (i = 0; i < argc; ++i)
puts(argv[i]);
puts("");
puts("env:");
extern char **environ;
char **env = environ;
while (*env) {
printf("%s\n", *env);
env++;
}
puts("");
/* Poweroff. */
reboot(RB_POWER_OFF);
}

View File

@@ -1,67 +0,0 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "../include/ioctl.h"
int main(int argc, char **argv)
{
char *ioctl_path;
int fd, request, arg0, arg1, arg_int, ret;
lkmc_ioctl_struct arg_struct;
if (argc < 2) {
puts("Usage: ./prog <ioctl-file> <request> [<arg>...]");
return EXIT_FAILURE;
}
ioctl_path = argv[1];
request = strtol(argv[2], NULL, 10);
if (argc > 3) {
arg0 = strtol(argv[3], NULL, 10);
}
if (argc > 4) {
arg1 = strtol(argv[4], NULL, 10);
}
fd = open(ioctl_path, O_RDONLY);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
switch (request)
{
case 0:
arg_int = arg0;
ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int);
if (ret != -1) {
printf("%d\n", arg_int);
}
break;
case 1:
arg_struct.i = arg0;
arg_struct.j = arg1;
ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct);
if (ret != -1) {
printf("%d %d\n", arg_struct.i, arg_struct.j);
}
break;
default:
puts("error: unknown request");
return EXIT_FAILURE;
}
if (ret == -1) {
perror("ioctl");
printf("errno = %d\n", errno);
return EXIT_FAILURE;
}
close(fd);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,45 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#anonymous-inode */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h> /* sleep */
#include <include/anonymous_inode.h>
int main(int argc, char **argv) {
char buf[1024];
int fd_ioctl, fd_ioctl_anon, ret;
size_t i, nreads;
if (argc < 2) {
puts("Usage: ./prog <ioctl-file> [<nreads>]");
return EXIT_FAILURE;
} else if (argc > 2) {
nreads = strtol(argv[2], NULL, 10);
} else {
nreads = 3;
}
fd_ioctl = open(argv[1], O_RDONLY);
if (fd_ioctl == -1) {
perror("open");
return EXIT_FAILURE;
}
ret = ioctl(fd_ioctl, LKMC_ANONYMOUS_INODE_GET_FD, &fd_ioctl_anon);
if (ret == -1) {
perror("ioctl");
return EXIT_FAILURE;
}
for (i = 0; i < nreads; ++i) {
ret = read(fd_ioctl_anon, buf, sizeof(buf));
printf("%.*s\n", ret, buf);
}
close(fd_ioctl_anon);
close(fd_ioctl);
return EXIT_SUCCESS;
}

View File

@@ -0,0 +1,66 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#ioctl */
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <include/ioctl.h>
int main(int argc, char **argv) {
char *ioctl_path;
int fd, request, arg0, arg1, arg_int, ret;
lkmc_ioctl_struct arg_struct;
if (argc < 2) {
puts("Usage: ./prog <ioctl-file> <request> [<arg>...]");
return EXIT_FAILURE;
}
ioctl_path = argv[1];
request = strtol(argv[2], NULL, 10);
if (argc > 3) {
arg0 = strtol(argv[3], NULL, 10);
}
if (argc > 4) {
arg1 = strtol(argv[4], NULL, 10);
}
fd = open(ioctl_path, O_RDONLY);
if (fd == -1) {
perror("open");
return EXIT_FAILURE;
}
switch (request)
{
case 0:
arg_int = arg0;
ret = ioctl(fd, LKMC_IOCTL_INC, &arg_int);
if (ret != -1) {
printf("%d\n", arg_int);
}
break;
case 1:
arg_struct.i = arg0;
arg_struct.j = arg1;
ret = ioctl(fd, LKMC_IOCTL_INC_DEC, &arg_struct);
if (ret != -1) {
printf("%d %d\n", arg_struct.i, arg_struct.j);
}
break;
default:
puts("error: unknown request");
return EXIT_FAILURE;
}
if (ret == -1) {
perror("ioctl");
printf("errno = %d\n", errno);
return EXIT_FAILURE;
}
close(fd);
return EXIT_SUCCESS;
}

View File

@@ -7,7 +7,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h> #include <unistd.h>
#include "../include/netlink.h" #include <include/netlink.h>
#define MAX_PAYLOAD 1024 #define MAX_PAYLOAD 1024

View File

@@ -0,0 +1,41 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#poll */
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(int argc, char **argv) {
char buf[1024];
int fd, i, n;
short revents;
struct pollfd pfd;
if (argc < 2) {
fprintf(stderr, "usage: %s <poll-device>\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
i = poll(&pfd, 1, -1);
if (i == -1) {
perror("poll");
assert(0);
}
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
}
}

View File

@@ -16,8 +16,7 @@
#include <assert.h> #include <assert.h>
#include <sys/mman.h> #include <sys/mman.h>
int main(int argc, char **argv) int main(int argc, char **argv) {
{
char *dev = "/dev/uio0"; char *dev = "/dev/uio0";
if (argc > 1) { if (argc > 1) {
dev = argv[1]; dev = argv[1];
@@ -30,12 +29,14 @@ int main(int argc, char **argv)
} }
/* TODO not supported by this kernel module? */ /* TODO not supported by this kernel module? */
/*int *addr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);*/ #if 0
/*if (addr == MAP_FAILED) {*/ int *addr = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
/*perror("mmap");*/ if (addr == MAP_FAILED) {
/*assert(0);*/ perror("mmap");
/*}*/ assert(0);
/**addr = 0x12345678;*/ }
*addr = 0x12345678;
#endif
while (1) { while (1) {
uint32_t info = 1; uint32_t info = 1;
@@ -66,8 +67,7 @@ int main(int argc, char **argv)
#include <unistd.h> #include <unistd.h>
#include <unistd.h> #include <unistd.h>
int main(void) int main(void) {
{
int uiofd; int uiofd;
int configfd; int configfd;
int err; int err;

1
userland/libs/eigen/build Symbolic link
View File

@@ -0,0 +1 @@
../build

View File

@@ -1,8 +1,11 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#eigen /* https://github.com/cirosantilli/linux-kernel-module-cheat#eigen
* Adapted from: https://eigen.tuxfamily.org/dox/GettingStarted.html * Adapted from: https://eigen.tuxfamily.org/dox/GettingStarted.html
*/ */
#include <iostream> #include <iostream>
#include <Eigen/Dense> #include <Eigen/Dense>
int main() { int main() {
Eigen::MatrixXd m(2,2); Eigen::MatrixXd m(2,2);
m(0,0) = 3; m(0,0) = 3;

1
userland/libs/libdrm/build Symbolic link
View File

@@ -0,0 +1 @@
../build

View File

@@ -87,7 +87,7 @@ static int modeset_open(int *out, const char *node)
fd = open(node, O_RDWR | O_CLOEXEC); fd = open(node, O_RDWR | O_CLOEXEC);
if (fd < 0) { if (fd < 0) {
ret = -errno; ret = -errno;
fprintf(stderr, "cannot open '%s': %m\n", node); fprintf(stderr, "cannot open '%s': %s\n", node, strerror(errno));
return ret; return ret;
} }
@@ -197,8 +197,8 @@ static int modeset_prepare(int fd)
/* retrieve resources */ /* retrieve resources */
res = drmModeGetResources(fd); res = drmModeGetResources(fd);
if (!res) { if (!res) {
fprintf(stderr, "cannot retrieve DRM resources (%d): %m\n", fprintf(stderr, "cannot retrieve DRM resources (%d): %s\n",
errno); errno, strerror(errno));
return -errno; return -errno;
} }
@@ -207,8 +207,8 @@ static int modeset_prepare(int fd)
/* get information for each connector */ /* get information for each connector */
conn = drmModeGetConnector(fd, res->connectors[i]); conn = drmModeGetConnector(fd, res->connectors[i]);
if (!conn) { if (!conn) {
fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %m\n", fprintf(stderr, "cannot retrieve DRM connector %u:%u (%d): %s\n",
i, res->connectors[i], errno); i, res->connectors[i], errno, strerror(errno));
continue; continue;
} }
@@ -222,8 +222,8 @@ static int modeset_prepare(int fd)
if (ret) { if (ret) {
if (ret != -ENOENT) { if (ret != -ENOENT) {
errno = -ret; errno = -ret;
fprintf(stderr, "cannot setup device for connector %u:%u (%d): %m\n", fprintf(stderr, "cannot setup device for connector %u:%u (%d): %s\n",
i, res->connectors[i], errno); i, res->connectors[i], errno, strerror(errno));
} }
free(dev); free(dev);
drmModeFreeConnector(conn); drmModeFreeConnector(conn);
@@ -378,8 +378,8 @@ static int modeset_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn,
for (i = 0; i < (unsigned int)conn->count_encoders; ++i) { for (i = 0; i < (unsigned int)conn->count_encoders; ++i) {
enc = drmModeGetEncoder(fd, conn->encoders[i]); enc = drmModeGetEncoder(fd, conn->encoders[i]);
if (!enc) { if (!enc) {
fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %m\n", fprintf(stderr, "cannot retrieve encoder %u:%u (%d): %s\n",
i, conn->encoders[i], errno); i, conn->encoders[i], errno, strerror(errno));
continue; continue;
} }
@@ -453,8 +453,8 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
creq.bpp = 32; creq.bpp = 32;
ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq); ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "cannot create dumb buffer (%d): %m\n", fprintf(stderr, "cannot create dumb buffer (%d): %s\n",
errno); errno, strerror(errno));
return -errno; return -errno;
} }
dev->stride = creq.pitch; dev->stride = creq.pitch;
@@ -465,8 +465,8 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride, ret = drmModeAddFB(fd, dev->width, dev->height, 24, 32, dev->stride,
dev->handle, &dev->fb); dev->handle, &dev->fb);
if (ret) { if (ret) {
fprintf(stderr, "cannot create framebuffer (%d): %m\n", fprintf(stderr, "cannot create framebuffer (%d): %s\n",
errno); errno, strerror(errno));
ret = -errno; ret = -errno;
goto err_destroy; goto err_destroy;
} }
@@ -476,8 +476,8 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
mreq.handle = dev->handle; mreq.handle = dev->handle;
ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq); ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
if (ret) { if (ret) {
fprintf(stderr, "cannot map dumb buffer (%d): %m\n", fprintf(stderr, "cannot map dumb buffer (%d): %s\n",
errno); errno, strerror(errno));
ret = -errno; ret = -errno;
goto err_fb; goto err_fb;
} }
@@ -486,8 +486,8 @@ static int modeset_create_fb(int fd, struct modeset_dev *dev)
dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED, dev->map = mmap(0, dev->size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, mreq.offset); fd, mreq.offset);
if (dev->map == MAP_FAILED) { if (dev->map == MAP_FAILED) {
fprintf(stderr, "cannot mmap dumb buffer (%d): %m\n", fprintf(stderr, "cannot mmap dumb buffer (%d): %s\n",
errno); errno, strerror(errno));
ret = -errno; ret = -errno;
goto err_fb; goto err_fb;
} }
@@ -571,8 +571,8 @@ int main(int argc, char **argv)
ret = drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0, ret = drmModeSetCrtc(fd, iter->crtc, iter->fb, 0, 0,
&iter->conn, 1, &iter->mode); &iter->conn, 1, &iter->mode);
if (ret) if (ret)
fprintf(stderr, "cannot set CRTC for connector %u (%d): %m\n", fprintf(stderr, "cannot set CRTC for connector %u (%d): %s\n",
iter->conn, errno); iter->conn, errno, strerror(errno));
} }
/* draw some colors for 5seconds */ /* draw some colors for 5seconds */
@@ -588,7 +588,7 @@ out_close:
out_return: out_return:
if (ret) { if (ret) {
errno = -ret; errno = -ret;
fprintf(stderr, "modeset failed with error %d: %m\n", errno); fprintf(stderr, "modeset failed with error %d: %s\n", errno, strerror(errno));
} else { } else {
fprintf(stderr, "exiting\n"); fprintf(stderr, "exiting\n");
} }
@@ -683,14 +683,16 @@ static void modeset_cleanup(int fd)
modeset_list = iter->next; modeset_list = iter->next;
/* restore saved CRTC configuration */ /* restore saved CRTC configuration */
drmModeSetCrtc(fd, drmModeSetCrtc(
fd,
iter->saved_crtc->crtc_id, iter->saved_crtc->crtc_id,
iter->saved_crtc->buffer_id, iter->saved_crtc->buffer_id,
iter->saved_crtc->x, iter->saved_crtc->x,
iter->saved_crtc->y, iter->saved_crtc->y,
&iter->conn, &iter->conn,
1, 1,
&iter->saved_crtc->mode); &iter->saved_crtc->mode
);
drmModeFreeCrtc(iter->saved_crtc); drmModeFreeCrtc(iter->saved_crtc);
/* unmap buffer */ /* unmap buffer */

View File

@@ -0,0 +1 @@
../build

View File

@@ -1,3 +1,5 @@
Programs in this directory rely on Linux kernel specific functionality such as `/proc`. Programs in this directory rely on Linux kernel specific functionality such as `/proc` or raw system calls.
These programs may also conform to ANSI C or POSIX, but we put them here because you can only observe them at work under Linux. These programs may also conform to ANSI C or POSIX, but we put them here because you can only observe them at work under Linux.
Many of these programs use glibc or GCC extensions.

View File

@@ -0,0 +1,25 @@
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <sys/reboot.h>
#include <unistd.h>
int main(int argc, char **argv) {
int i;
puts("args:");
for (i = 0; i < argc; ++i)
puts(argv[i]);
puts("");
puts("env:");
extern char **environ;
char **env = environ;
while (*env) {
printf("%s\n", *env);
env++;
}
puts("");
/* Poweroff. */
reboot(RB_POWER_OFF);
}

View File

@@ -1,41 +0,0 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#poll */
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(int argc, char **argv) {
char buf[1024];
int fd, i, n;
short revents;
struct pollfd pfd;
if (argc < 2) {
fprintf(stderr, "usage: %s <poll-device>\n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
pfd.fd = fd;
pfd.events = POLLIN;
while (1) {
puts("loop");
i = poll(&pfd, 1, -1);
if (i == -1) {
perror("poll");
assert(0);
}
revents = pfd.revents;
if (revents & POLLIN) {
n = read(pfd.fd, buf, sizeof(buf));
printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
}
}
}

View File

@@ -1,10 +0,0 @@
/* Print each command line argument received, one per line. */
#include <stdio.h>
int main(int argc, char **argv) {
size_t i;
for (i = 0; i < (size_t)argc; ++i)
printf("%s\n", argv[i]);
return 0;
}