使用 Rust 构建“.wasm”二进制文件时访问“__heap_base”

问题描述 投票:0回答:2

想要遵循本文中的操作:https://surma.dev/things/c-to-webassemble/但是使用 Rust 并编写一个自定义分配器。

为此,我需要访问 llvm 添加的

__heap_base
变量作为线性内存中堆开始位置的指针。 Rust 有没有办法实现这一点?

我尝试了

的变体
extern "C" {
    static __heap_base: i32;
}

#[no_mangle]
pub unsafe extern "C" fn main() -> i32 {
    __heap_base
}

但它们返回 0 而不是二进制中分配的实际值。

rust llvm webassembly lld
2个回答
1
投票

经过一番研究后。答案的一个想法是,您的程序的值与编译器/链接器然后在 wasm 文件中定义的值之间似乎存在差异。原则上不存在一对一的关系。

当你在 C/Rust 中定义变量时,你得到的是变量,而不是变量本身的地址。即:如果定义一个指针,您将获得指针指向的数据的地址,而不是存储该指针的值的地址。

因此,通过指定

static __heap_base: i32
,您要求编译器将 __heap_base 值设置为 i32,而不是堆基指针(这就是 llvm 然后将其写入 wasm i32,无论您为
__heap_base
设置什么类型)。该值的地址是指向
__heap_base

的实际指针

为什么你可以导入

__heap_base
因为堆基指向的值对我来说仍然不太清楚。也许符号总是意味着值,像
*__heap_base
这样的东西只是一个指针,当取消引用时它会给你
__heap_base
(值),并且它在内部被这样对待


0
投票

链接器符号始终是指针,因此在 Rust 中,

extern static
声明定义了它指向的事物的类型。
i32
很好,但
i8
可能更好,因为这清楚地表明 __heap_base
dereferenced
值太小而不会被混淆为指针。你想要的是一个指向(Rust 的概念)__heap_base
指针。

这是一些适用于我的项目的示例代码:

extern "C" {
    /// &__heap_base: the start of the heap
    static __heap_base: u8;
}

fn heap_start() -> usize {
    // SAFETY: __heap_base is actually const (read-only) from our POV.
    // it's initialized by the runtime, and provides the address where
    // our "heap" should start.
    unsafe { &__heap_base as *const u8 as usize }
}

如果您想要原始指针,可以删除

as usize

© www.soinside.com 2019 - 2024. All rights reserved.