0

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

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

但是,我不太明白的是为什么指针的值是56(再次使用 N=8)以及该值与内存中堆栈的确切区域的关系,在我的情况下,当前看起来像:

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

我知道我可能更适合“只使用 emscripten”,但我也想了解这一点。

  • 堆栈指针是否总是存储在线性内存中的偏移量 4 处?
  • 它的初始值是如何计算的?(与数据后的下一个偏移量%16==0 + N 对齐?)
  • 之前存储了什么,它指向的偏移量之后是什么?
4

1 回答 1

4

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

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

请注意,您不能使用 1 和 2 的地址。只有在这些情况下,我才希望代码生成器与 3 一起使用。WebAssembly 并不规定如何完成,这取决于您选择的任何 ABI。Emscripten 和其他工具所做的是将堆栈指针存储在 address 处4,然后在程序的早期选择堆栈应该去的位置。它不一定总是4,但始终坚持使用该 ABI 更简单,尤其是在涉及动态链接的情况下。

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

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

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

于 2017-04-26T20:58:11.877 回答