我们如何告诉 Rust 编译器在输入函数之前和之后内联一个特殊函数?
我正在尝试实现一种跟踪函数调用的方法,并且可能使用这种方法来跟踪借用引用的使用(很像一个简单的影子堆栈)。一种替代方法是使用宏,但我需要在#[xxx]
任何地方添加。
我看到添加了拉取请求 57220-Z instrument-mcount
:
a.rs
#[no_mangle]
fn mcount() {
println!("enter function");
}
#[no_mangle]
fn foo(x: i32) -> i32 {
x + 1
}
fn bar(y: i32) -> i32 {
2 * foo(y)
}
fn main() {
println!("{}",bar(10));
}
编译它 ( rustc a.rs --emit asm -Z instrument-mcount
) 产生:
.globl _foo
.p2align 4, 0x90
_foo:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
callq mcount
^^^^^^^^^^^^^^
movl -4(%rbp), %eax
incl %eax
seto %cl
testb $1, %cl
movl %eax, -8(%rbp)
jne LBB10_2
movl -8(%rbp), %eax
addq $16, %rsp
popq %rbp
retq
LBB10_2:
leaq l___unnamed_2(%rip), %rdi
callq __ZN4core9panicking5panic17had60f09514be3bbcE
.cfi_endproc
.globl _mcount
.p2align 4, 0x90
_mcount:
^^^^^^^^
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $48, %rsp
callq mcount
leaq l___unnamed_3(%rip), %rax
leaq l___unnamed_4(%rip), %rcx
xorl %edx, %edx
movl %edx, %r8d
leaq -48(%rbp), %rdi
movq %rax, %rsi
movl $1, %edx
callq __ZN4core3fmt9Arguments6new_v117hcdff95254bf53f10E
leaq -48(%rbp), %rdi
callq __ZN3std2io5stdio6_print17hec5f1d503bfcb744E
addq $48, %rsp
popq %rbp
retq
.cfi_endproc
.globl _bar
.p2align 4, 0x90
该mcount
函数已翻译为_mcount
,但我如何调用my mcount
而不是一些默认实现?
它似乎设置在这里:
#[inline]
pub fn set_instrument_function(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
if cx.sess().instrument_mcount() {
// Similar to `clang -pg` behavior. Handled by the
// `post-inline-ee-instrument` LLVM pass.
llvm::AddFunctionAttrStringValue(
llfn, llvm::AttributePlace::Function,
const_cstr!("instrument-function-entry-inlined"), const_cstr!("mcount"));
}
}
GCC 中类似的事情是
void __cyg_profile_func_enter (void *, void *) __attribute__((no_instrument_function));