WebAssembly 堆栈/堆栈指针初始化和内存布局

WebAssembly stack / stack pointer initialization and memory layout

我目前正在研究通过 LLVM 编译的 WebAssembly,但我还没有设法理解堆栈/堆栈指针以及它与整体内存布局的关系。

我了解到我必须使用 s2wasm--allocate-stack N 来制作我的程序 运行 我认为这基本上是添加 (data (i32.const 4) "8[=12=][=12=][=12=]") (N=8 ) 到我生成的 wast,二进制部分显然是指向内存偏移量的指针,i32 常量是它在线性内存中的偏移量。

不过,我不太明白的是为什么指针的值是 56(同样 N=8)以及这个值如何与内存中堆栈的确切区域相关,其中,我的情况,目前看起来像:

0-3: zero 4-7: 56 7-35: other data sections 36-55: zeroes 56-59: zero

我知道我可能更适合 "just use emscripten",但我也想了解这一点。

我在 中谈到了这一点。从 C++ 的堆栈中,实际上有 3 个值可以结束的地方:

  1. 在执行堆栈上(每个操作码压入和弹出值,所以 add 弹出 2,然后压入 1)。
  2. 作为本地人。
  3. Memory.

请注意,您不能获取 1. 和 2. 的地址。只有在这些情况下,我才希望代码生成器与 3.您选择的 ABI。 Emscripten 和其他工具所做的是将堆栈指针存储在地址 4 处,然后在程序的早期他们选择堆栈应该去的位置。 不必 始终为 4,但始终坚持该 ABI 更简单,尤其是在涉及动态链接时。

关于初始值:该位置必须足够大以容纳整个堆栈,并且 malloc 的实现必须了解它,因为它无法在其上分配堆 space .这就是为什么某些工具允许您指定最大尺寸的原因。

任何东西都可以在之前/之后存储(尽管之后你可能有先前的堆栈值)。 WebAssembly 目前没有保护页,因此耗尽内存堆栈将破坏堆值(除非代码生成器也发出堆栈检查)。 "memory safe" 就是这样,它仍然无法逃脱 WebAssembly.Memory,因此浏览器无法拥有,但开发者自己的代码可以完全拥有。构建在 WebAssembly 之上的内存安全语言必须在 WebAssembly.Memory.

中强制执行内存安全

请注意,我没有解释 1. 和 2. 它们的存在意味着大多数 C++ 程序在 WebAssembly 中使用的内存堆栈比原生 C++ 程序使用的堆栈少。