Struggling to distinguish difference in C++/Rust link vs. Rust/Rust link

Hi folks,

I'm experimenting with having Rust catch LLVM sanitizer coverage information and have had some success linking with a C++ program but less so linking with a Rust program. I've pushed all my code into a gist but will include everything inline below. First, tracer.rs that exports __sanitizer_cov_trace_pc_guard_init and __sanitizer_cov_trace_pc_guard:

// tracer.rs
#[no_mangle]
pub extern "C" fn __sanitizer_cov_trace_pc_guard_init(start: *mut u32, stop: *mut u32) -> () {
    println!("START: {:?}", start);
    println!("STOP: {:?}", stop);
}

#[no_mangle]
pub extern "C" fn __sanitizer_cov_trace_pc_guard(guard: *const u32) -> () {
    println!("GUARD: {:?}", guard);
}

Here's the C++ program from LLVM's documentation, renamed example.cc:

// example.cc
void foo() { }

int main(int argc, char **argv) {
  if (argc > 1) foo();
}

Compilation and execution works like so:

> rustc --crate-type staticlib tracer.rs
> clang++ -g -fsanitize-coverage=trace-pc-guard example.cc -c -o example_cc.o
> clang++ libtracer.a example_cc.o -fsanitize=address -o example_cc
> ./example_cc
START: 0x104793010
STOP: 0x104793020
GUARD: 0x104793014
GUARD: 0x104793018

My Rust + Rust example is less successful. Here's the Rust program, called example.rs:

// example.rs

#![allow(unused)]

use std::env;

fn foo() -> () {}

fn main() {
    let mut args = env::args_os();
    if let Some(_) = args.next() {
	foo()
    }
}

Now, compilation and running:

> rustc --crate-type staticlib tracer.rs
> RUSTFLAGS="-Cllvm-args=-sanitizer-coverage-trace-pc-guard" rustc --emit obj example.rs -o example_rs.o
> clang++ libtracer.a example_rs.o -fsanitize=address -o example_rs
> ./example_rs

Radio silence. The key difference is the Rust+Rust version is missing the sanitizer callbacks. Take a look:

> nm example_cc | grep sanitizer
00000001000016a0 T ___sanitizer_cov_trace_pc_guard
0000000100001550 T ___sanitizer_cov_trace_pc_guard_init
> nm example_rs | grep sanitizer

I'm not sure where the goof is. Can someone point me in the right direction? Also, having to get clang++ involved for the Rust+Rust version is maybe silly. I'd take suggestions there, too. :slight_smile:

1 Like