Есть ли способ внедрить вызов пользовательской функции до и после каждого вызова функции в Rust?
Как мы можем сказать компилятору 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
, но как я могу назвать свой 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));