Я используюrust-lldb для изучения элемента функции и указателя функции в Rust. Код очень прост:
// src/main.rs
#[inline(never)]
fn add(a: i32, b: i32) -> i32 {
a + b
}
#[inline(never)]
fn sub(a: i32, b: i32) -> i32 {
a - b
}
fn main() {
let item = add; // function item
let item1 = sub; // function item
let ptr: fn(i32, i32) -> i32 = add; // function pointer
let x = item(1, 2);
let y = item1(3, 2);
let z = ptr(1, 2);
assert_eq!(3, x);
assert_eq!(1, y);
assert_eq!(3, z);
}
Когда я установил точку останова и начал отладку, я обнаружил, что оба item и item1 указывают на неверный адрес.
➜ function git:(master) ✗ rust-lldb --version
lldb-1500.0.404.7
Apple Swift version 5.10 (swiftlang-5.10.0.13 clang-1500.3.9.4)
➜ function git:(master) ✗ rustc -g -C opt-level=0 src/main.rs -o main
➜ function git:(master) ✗ rust-lldb main
(lldb) command script import "/Users/caelansar/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/etc/lldb_lookup.py"
(lldb) command source -s 0 '/Users/caelansar/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/etc/lldb_commands'
Executing commands in '/Users/caelansar/.rustup/toolchains/nightly-aarch64-apple-darwin/lib/rustlib/etc/lldb_commands'.
(lldb) type synthetic add -l lldb_lookup.synthetic_lookup -x ".*" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)String$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?str$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?\\[.+\\]$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::ffi::([a-z_]+::)+)OsString$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Vec<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)VecDeque<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)BTreeMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashMap<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::collections::([a-z_]+::)+)HashSet<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Rc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(alloc::([a-z_]+::)+)Arc<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Cell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)Ref<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefMut<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)RefCell<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(core::([a-z_]+::)+)NonZero<.+>$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^core::num::([a-z_]+::)*NonZero.+$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^(std::([a-z_]+::)+)PathBuf$" --category Rust
(lldb) type summary add -F lldb_lookup.summary_lookup -e -x -h "^&(mut )?(std::([a-z_]+::)+)Path$" --category Rust
(lldb) type category enable Rust
(lldb) target create "main"
Current executable set to '/Users/caelansar/RustroverProjects/function/main' (arm64).
(lldb) b 18
Breakpoint 1: where = main`main::main::h8d79616f9b6b86ce + 96 at main.rs:18:13, address = 0x000000010000169c
(lldb) r
Process 96136 launched: '/Users/caelansar/RustroverProjects/function/main' (arm64)
Process 96136 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010000169c main`main::main::h8d79616f9b6b86ce at main.rs:18:13
15 let ptr: fn(i32, i32) -> i32 = add; // function pointer
16 let x = item(1, 2);
17 let y = item1(3, 2);
-> 18 let z = ptr(1, 2);
19 assert_eq!(3, x);
20 assert_eq!(1, y);
21 assert_eq!(3, z);
Target 0: (main) stopped.
(lldb) v
(int (*)(int, int)) item = 0x0001000000030000
(int (*)(int, int)) item1 = 0x0000010000000300
(int (*)(int, int)) ptr = 0x00000001000015b4 (main`main::add::h243b87047811e43e at main.rs:2)
(int) x = 3
(int) y = 1
(lldb) n
Process 96136 stopped
* thread #1, name = 'main', queue = 'com.apple.main-thread', stop reason = step over
frame #0: 0x00000001000016b8 main`main::main::h8d79616f9b6b86ce at main.rs:19:5
16 let x = item(1, 2);
17 let y = item1(3, 2);
18 let z = ptr(1, 2);
-> 19 assert_eq!(3, x);
20 assert_eq!(1, y);
21 assert_eq!(3, z);
22 }
Target 0: (main) stopped.
(lldb) v
(int (*)(int, int)) item = 0x0001000000030000
(int (*)(int, int)) item1 = 0x0000010000000300
(int (*)(int, int)) ptr = 0x00000001000015b4 (main`main::add::h243b87047811e43e at main.rs:2)
(int) x = 3
(int) y = 1
(int) z = 3
(lldb)
Что представляет собой адрес 0x0001000000030000/0x0000010000000300? Похоже, они не являются адресами функциональных инструкций.
Не уверен, связано ли это с ОС, я использую Apple Silicon MBP.

В конечном итоге ответ заключается в том, что значение не имеет значения, поскольку функциональные элементы имеют нулевой размер. Им не нужно никуда указывать, поскольку сама информация о типе сообщает компилятору, какую функцию вызывать.
fn add(a: i32, b: i32) -> i32 {
a + b
}
// Wrapper to allow us to "name" T using a value of T.
fn size_of<T>(_: T) -> usize {
std::mem::size_of::<T>()
}
fn main() {
assert_eq!(0, size_of(add));
}
Значение, отображаемое в отладчике, может быть произвольным или неопределенным, но это не имеет значения, поскольку на самом деле это значение никогда не используется. С тем же успехом вы могли бы спросить, каково значение () — на самом деле, если вы это сделаете let item2 = ();, а затем проверите это значение в отладчике, я подозреваю, что вы увидите какое-то другое бессмысленное значение.
Обратите внимание, что когда у меня Rusc излучает LLVM IR, даже на нулевом уровне оптимизации ничего не излучается ни для item, ни для item1. То, что вы видите, скорее всего, просто причуда lldb.