Что представляет собой адрес функционального элемента в Rust-lldb?

Я использую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.

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В конечном итоге ответ заключается в том, что значение не имеет значения, поскольку функциональные элементы имеют нулевой размер. Им не нужно никуда указывать, поскольку сама информация о типе сообщает компилятору, какую функцию вызывать.

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.

Другие вопросы по теме