1
votes

I'm trying to generate a code coverage report for a kernel written in rust. I'm trying to do something similar as in this example for C code. Basically I want to run the instrumented kernel with qemu and get the code coverage via gdb. Now the first step here is getting an instrumented kernel, which lead me to the (unstable) Rustflag -Zprofile. Now when trying to build the kernel with RUSTFLAGS=-Zprofile cargo build -Z build-std=core,alloc --target x86_64-unknown-hermit-kernel -vv

I get the following error:

error[E0463]: can't find crate for `profiler_builtins`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0463`.
error: could not compile `core`. 

When adding std to build-std I then get the following error from the build script of profiler_builtins:

[profiler_builtins 0.0.0] 
[profiler_builtins 0.0.0] exit code: 1
The following warnings were emitted during compilation:

warning: cc: error: ../llvm-project/compiler-rt/lib/profile/GCDAProfiling.c: No such file or directory
warning: cc: fatal error: no input files
warning: compilation terminated.

error: failed to run custom build command for `profiler_builtins v0.0.0 (/home/jonathan/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libprofiler_builtins)`

Caused by:
  process didn't exit successfully: `/home/jonathan/Dev/rusty-hermit/libhermit-rs/target/debug/build/profiler_builtins-f84959e01c52c161/build-script-build` (exit code: 1)
--- stdout
TARGET = Some("x86_64-unknown-hermit-kernel")
OPT_LEVEL = Some("1")
HOST = Some("x86_64-unknown-linux-gnu")
CC_x86_64-unknown-hermit-kernel = None
CC_x86_64_unknown_hermit_kernel = None
TARGET_CC = None
CC = None
CROSS_COMPILE = None
CFLAGS_x86_64-unknown-hermit-kernel = None
CFLAGS_x86_64_unknown_hermit_kernel = None
TARGET_CFLAGS = None
CFLAGS = None
CRATE_CC_NO_DEFAULTS = None
DEBUG = Some("true")
CARGO_CFG_TARGET_FEATURE = Some("fxsr")
running: "cc" "-O1" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-m64" "-I" "../llvm-project/compiler-rt/include" "-fno-builtin" "-fvisibility=hidden" "-fomit-frame-pointer" "-DVISIBILITY_HIDDEN" "-DCOMPILER_RT_HAS_UNAME=1" "-o" "/home/jonathan/Dev/rusty-hermit/libhermit-rs/target/x86_64-unknown-hermit-kernel/debug/build/profiler_builtins-92f0d39567de220a/out/../llvm-project/compiler-rt/lib/profile/GCDAProfiling.o" "-c" "../llvm-project/compiler-rt/lib/profile/GCDAProfiling.c"
cargo:warning=cc: error: ../llvm-project/compiler-rt/lib/profile/GCDAProfiling.c: No such file or directory
cargo:warning=cc: fatal error: no input files
cargo:warning=compilation terminated.
exit code: 1

--- stderr


error occurred: Command "cc" "-O1" "-ffunction-sections" "-fdata-sections" "-fPIC" "-g" "-fno-omit-frame-pointer" "-m64" "-I" "../llvm-project/compiler-rt/include" "-fno-builtin" "-fvisibility=hidden" "-fomit-frame-pointer" "-DVISIBILITY_HIDDEN" "-DCOMPILER_RT_HAS_UNAME=1" "-o" "/home/jonathan/Dev/rusty-hermit/libhermit-rs/target/x86_64-unknown-hermit-kernel/debug/build/profiler_builtins-92f0d39567de220a/out/../llvm-project/compiler-rt/lib/profile/GCDAProfiling.o" "-c" "../llvm-project/compiler-rt/lib/profile/GCDAProfiling.c" with args "cc" did not execute successfully (status code exit code: 1).



warning: build failed, waiting for other jobs to finish...
error[E0463]: can't find crate for `profiler_builtins`

error: aborting due to previous error

Investigating the rustlib folder showed that llvm-project is indeed not there.

$ ls  ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src
build_helper  libpanic_abort   libprofiler_builtins  libtest    tools
liballoc      libpanic_unwind  libstd                libunwind
libcore       libproc_macro    libterm               stdarch

I tried copying the llvm-project/compiler-rt folder from the master branch of rust:

$ mkdir ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/llvm-project
$ cp -r ~/Dev/rust/src/llvm-project/compiler-rt/ ~/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/llvm-project/compiler-rt/

Running RUSTFLAGS=-Zprofile cargo build -Z build-std=std,core,alloc,profiler_builtins --target x86_64-unknown-hermit-kernel -vv again just gave me E0463 error for profiler_builtins, but without any of the output of buildscript being printed.

I'm still very new to rust, so I'd appreciate any help regarding instrumenting no_std code to generate code coverage. I'm using rust nightly from 2020-05-14 (newer versions are apparently missing rls-preview):

rustc 1.45.0-nightly (a74d1862d 2020-05-14)
binary: rustc
commit-hash: a74d1862d4d87a56244958416fd05976c58ca1a8
commit-date: 2020-05-14
host: x86_64-unknown-linux-gnu
release: 1.45.0-nightly
LLVM version: 9.0
1

1 Answers

0
votes

I managed to identify and solve my original Problem. RUSTFLAGS get passed to everything built by cargo, which in this case included profiler_builtins. Building profiler_builtins with -Zprofile will of course fail, since the latter depends on the former.

The solution was to use a RUSTC_WRAPPER that I adapted from here. I changed the case statement to

case $(get_crate_name "$@") in
  crate1|crate2|crate3)
    EXTRA="-Zprofile -Zno-profiler-runtime -Copt-level=0 -Clink-dead-code -Coverflow-checks=off"
    ;;
  *)
    ;;
esac

This results in the flags only being appended to the whitelisted crates. Additionally I had to disable incremental compilation, since this is apparently not compatible with code coverage. My final build command was then: CARGO_INCREMENTAL=0 RUSTC_WRAPPER="/home/xxx/Dev/rustc_wrapper" cargo build -Z build-std=core,alloc,profiler_builtins --target x86_64-unknown-hermit-kernel This instrumented my kernel and generated a .gcno file, which solved my original question.

I've still not managed to get a Code coverage report, since my kernel seems to get stuck when entering the _start function. This probably means that instrumenting the entire kernel might be a bad idea, but I guess this is outside of the scope of the original question.