This one adds a syscall to the Linux kernel and rebuilds it. The important steps:
- add a Makefile rule to build an rlib (an ar archive) using
rustc
, specifying#![crate_type="rlib"]
in the source - extract the
.o
file from the rlib, and rename it to match the expected name - add the
.o
file toobj-y
They also edit the syscall interrupt handler (in asm) to dispatch to their syscalls.
No reference to lang items. It uses stable #[no_std]
without #[no_core]
-
I'd expect the resulting object file just happens not to reference libcore, but
more complicated objects could.
No custom compiler flags etc. other than #[no_std]
.
A custom Makefile drives the build, by copying a Makefile.in that looks
like a normal Linux module Makefile to a build directory, and then
invoking the usual make -C /lib/modules/$(uname -r)/build M=$PWD
(see
Documentation/kbuild/modules.txt
).
The custom Makefile sets RUSTCFLAGS
to
-O -C code-model=kernel -C relocation-model=static
.
There's also a module.c
file containing the usual MODULE_LICENSE
etc. macros, plus prototypes for init_module
and cleanup_module
.
Makefile.in does the following:
- build the module with
cargo rustc
, specifiyngcrate_type = ['staticlib']
in Cargo.toml - set
foo-objs := module.o libfoo.a
(note that order is significant: as with shared libraries, static libraries need to come after things that depend on them) - set
obj-m := foo.o
(The foo-objs
syntax is for "composite objects," which is documented in
Documentation/kbuild/makefiles.txt
section 3.3, except for the bit where -objs
is synonymous to -y
; see
scripts/Makefile.lib
for that. It works by combining the listed objects with ld -r
aka
--relocatable
to generate foo.o
.)
I couldn't get the out-of-tree build to work right with my 3.16 (Debian
oldstable) kernel; it builds fine if you get rid of the extra Makefile
(rename Makefile.in to Makefile) and get rid of the src
variable there,
making it build in-tree.
kmod includes two other source files besides lib.rs
and module.c
,
which aren't very interesting. lang_items.rs
has ~empty
implementations of all three lang-items, and print.rs
has a
straightforward FFI binding to printk
, plus a macro called println!
that doesn't actually implement the format-string logic. These should be
wired up to Linux's unwinding / OOPSing mechanisms and to core::fmt
respectively.
I can replicate the Makefile parts of this by themselves. The following Makefile successfully links a kernel module out of one.rs and two.c:
obj-m := three.o
three-objs := two.o libone.a
lib%.a: %.rs
rustc -o $@ -O $<
(Since the point of this Makefile is just to make linking work, I'm
being lazy and not specifying #![no_std]
in the Rust source; libstd
gets copied into libone.a
but the linker eliminates it as dead code
when building three.c
. That lets me avoid thinking about lang-items.)
This one is much older (2013, last updated 2016) but much more complete. It brings up a couple of important points:
- You need a custom target file to set things like
disable_redzone
and no use of floating point. (Their custom target file also setscode-model
tokernel
andrelocation-model
tostatic
, as with the previous one.)- Apparently you can just use "+soft-float" in target features these days, See this comment on rust-lang/rfcs#1364.
- The kernel internal ABI has no guarantees at all, and you want to write
against the kernel C API, using bindgen.
- One limitation is that bindgen doesn't support C macros.
MacOS. Also uses -C soft-float
and -C no-redzone=y
(and -C no-stack-check
, which is no longer necessary).