使用 lld 和 s2wasm 找到堆的开始

Find the Start of Heap using lld and s2wasm

我正在使用 clang -> llc -> s2wasmclang -> lld 从 C 编译到 WebAssembly。因为没有提供 c 库,所以我编写了自己的分配器。但是我不确定找到空闲内存开头的最佳方法是什么。

lld 和 s2wasm 似乎都具有内存布局:| globals | stack | free memory |。使用 s2wasm 的堆栈指针位于内存地址,使用 lld 它位于全局地址(无法从 C 访问?)。

我发现的一种方法是使用这个 hack 在 wasm 执行开始时读取堆栈指针:

int stacktop()
{
  int a;
  return (int)(&a+1);
}

这将创建一个局部变量,它不驻留在线性内存中并获取它的地址。为了生成地址,编译器将其放在内存堆栈中。

我正在使用返回值作为我的堆的开始。是否有更优雅和面向未来的方法来查找可用内存?

lld 创建一个名为 __heap_base 的 C 符号,它指向堆的底部。它还将其导出为全局 wasm,以便嵌入器可以知道堆从哪里开始。

您需要获取由 lld 创建的 __heap_base 符号的地址:

$ cat wasm-heap.c
extern unsigned char __heap_base;

__attribute__ ((visibility("default"))) 
void * get_heap_base(void) {
  return &__heap_base;
}

这将 return 与导出到 JavaScript 的 __heap_base WASM 变量的值相同:

$ cat wasm-heap.js
var imports = {memory: new WebAssembly.Memory({initial:2})};
const module = new WebAssembly.Module(read('wasm-heap.wasm', 'binary'));
const instance = new WebAssembly.Instance(module, { "env" : imports }).exports;
var u8_data = new Uint8Array(imports["memory"]["buffer"]);

print("Heap base in WASM: " + instance.get_heap_base());
print("Heap base exported to JS: " + instance.__heap_base);

$ js52 wasm-heap.js
Heap base in WASM: 66560
Heap base exported to JS: 66560