Skip to content

__llvm_profile_raw_version doesn't prevent version mismatches hard enough #52683

Open
@glandium

Description

@glandium

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    PGOProfile Guided Optimizations

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions