I am writing a Rust library containing an implementation of the callbacks for LLVM SanitizerCoverage. These callbacks can be used to trace the execution of an instrumented program.
A common way to produce a trace is to print the address of each executed basic block. However, in order to do that, it is necessary to retrieve the address of the call
instruction that invoked the callback. The C++ examples provided by LLVM rely on the compiler intrinsic __builtin_return_address(0)
in order to obtain this information.
extern "C" void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { if (!*guard) return; void *PC = __builtin_return_address(0); printf("guard: %p %x PC %p\n", guard, *guard, PC); }
I am trying to reproduce the same function in Rust but, apparently, there is no equivalent to __builtin_return_address
. The only reference I found is from an old version of Rust, but the function described is not available anymore. The function is the following:
pub unsafe extern "rust-intrinsic" fn return_address() -> *const u8
My current hacky solution involves having a C file in my crate that contains the following function:
void* get_return_address() { return __builtin_return_address(1); }
If I call it from a Rust function, I am able to obtain the return address of the Rust function itself. This solution, however, requires the compilation of my Rust code with -C force-frame-pointers=yes
for it to work, since the C compiler intrinsic relies on the presence of frame pointers.
Concluding, is there a more straightforward way of getting the return address of the current function in Rust?
edit: The removal of the return_address
intrinsic is discussed in this GitHub issue.
edit 2: Further testing showed that the backtrace
crate is able to correctly extract the return address of the current function, thus avoiding the hack I described before. Credit goes to this tweet.
The problem with this solution is the overhead that is generated creating a full backtrace when only the return address of the current function is needed. In addition, the crate is using C libraries to extract the backtrace; this looks like something that should be done in pure Rust.
edit 3: The compiler intrinsic __builtin_return_address(0)
generates a call to the LLVM intrinsic llvm.returnaddress
. The corresponding documentation can be found here.
We can get the address of a function by just writing the function's name without parentheses. Please refer function pointer in C for details. In C/C++, name of a function can be used to find address of function.
We can pass pointers to the function as well as return pointer from a function. But it is not recommended to return the address of a local variable outside the function as it goes out of scope after function returns.
The return address is pushed on the stack by the caller by means of the callq instruction. At the moment of entering the callee function it is at the top of the stack, i.e.: at that moment, rsp contains the address where the return address is stored.
On some architectures, you can find it on the stack relative to the first parameter. On ia32, for example, the parameters are pushed (in opposite order) and then a call is made that will push the return address. Remember that the stack almost always (and on ia32) grows downward.
The ADDRESS function in Excel is meant to exactly this. It takes the row and the column number and gives you the cell address of that specific cell. Below is the syntax of the ADDRESS function:
We can get the address of a function by just writing the function’s name without parentheses. Please refer function pointer in C for details. In C/C++, name of a function can be used to find address of function. Writing code in comment? Please use ide.geeksforgeeks.org , generate link and share the link here.
Lookup a value and return cell address with formula 1 Type BB into a cell, here I type BB into cell A10. See screenshot: 2 In the cell adjacent to the cell A10 (the cell you typed BB), type this formula =SMALL (IF ($A$10=$A$2:$A$8, ROW ($A$2:$A$8)-ROW ($A$2)+1), ROW (1:1)), and press Shift + Ctrl ... 3 Then you can delete #NUM!. See screenshot:
While the ADDRESS function was made specifically to give you the cell reference of the specified row and column number, there is another function that also does this. It’s called the CELL function (and it can give you a lot more information about the cell than the ADDRESS function).
I could not find any official documentation about this, but found out by asking in the rust-lang
repository: You can link against LLVM intrinsics, like llvm.returnaddress
, with only a few lines of code:
extern { #[link_name = "llvm.returnaddress"] fn return_address() -> *const u8; } fn foo() { println!("I was called by {:X}", return_address()); }
The LLVM intrinsic llvm.addressofreturnaddress
might also be interesting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With