Description
The profile runtime checks __llvm_profile_raw_version
at runtime so that if you compile something with a version of LLVM that doesn't match that of the profile runtime, the runtime aborts. This is fine if all your compiled code comes from the same compiler, but falls apart when combining them.
For example, as of writing, rustc stable through nightly use LLVM 13. We used in combination of clang trunk (currently 14), things can go pretty badly without noticing until it's too late:
$ cat >lib.rs <<EOF
#[no_mangle]
unsafe extern "C" fn foo() {
println!("Foo");
}
EOF
$ rustc --crate-type=staticlib lib.rs -C panic=abort -C profile-generate -O
$ cat >foo.c <<EOF
extern void foo();
int main() {
foo();
return 1;
}
EOF
$ clang -o foo.o -c foo.c -fprofile-generate -O2
$ clang -o foo foo.o liblib.a -lpthread -ldl -lm -fprofile-generate
$ ./foo
Foo
Here, the profile runtime found __llvm_profile_raw_version
from the C object file rather than the one from the rust library. (Ideally, the linker would complain that all the linked in __llvm_profile_raw_version
symbols don't have the same content... but it probably isn't allowed to).
The result seemingly worked... until you try to actually use the resulting profile:
$ llvm-profdata show default_15853215676058847363_0.profraw
error: default_15853215676058847363_0.profraw: malformed instrumentation profile data: counter offset 666194 is greater than the maximum number of counters 2