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",但我也想了解这一点。
- 堆栈指针是否总是存储在线性内存中的偏移量 4 处?
- 它的初值是怎么计算出来的? (对齐到下一个offset%16==0 + N之后的数据?)
- 之前存储的是什么,它指向的偏移量之后是什么?
我在 中谈到了这一点。从 C++ 的堆栈中,实际上有 3 个值可以结束的地方:
- 在执行堆栈上(每个操作码压入和弹出值,所以
add
弹出 2,然后压入 1)。
- 作为本地人。
- 在
Memory
.
请注意,您不能获取 1. 和 2. 的地址。只有在这些情况下,我才希望代码生成器与 3.您选择的 ABI。 Emscripten 和其他工具所做的是将堆栈指针存储在地址 4
处,然后在程序的早期他们选择堆栈应该去的位置。 不必 始终为 4,但始终坚持该 ABI 更简单,尤其是在涉及动态链接时。
关于初始值:该位置必须足够大以容纳整个堆栈,并且 malloc
的实现必须了解它,因为它无法在其上分配堆 space .这就是为什么某些工具允许您指定最大尺寸的原因。
任何东西都可以在之前/之后存储(尽管之后你可能有先前的堆栈值)。 WebAssembly 目前没有保护页,因此耗尽内存堆栈将破坏堆值(除非代码生成器也发出堆栈检查)。 "memory safe" 就是这样,它仍然无法逃脱 WebAssembly.Memory
,因此浏览器无法拥有,但开发者自己的代码可以完全拥有。构建在 WebAssembly 之上的内存安全语言必须在 WebAssembly.Memory
.
中强制执行内存安全
请注意,我没有解释 1. 和 2. 它们的存在意味着大多数 C++ 程序在 WebAssembly 中使用的内存堆栈比原生 C++ 程序使用的堆栈少。
我目前正在研究通过 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",但我也想了解这一点。
- 堆栈指针是否总是存储在线性内存中的偏移量 4 处?
- 它的初值是怎么计算出来的? (对齐到下一个offset%16==0 + N之后的数据?)
- 之前存储的是什么,它指向的偏移量之后是什么?
我在
- 在执行堆栈上(每个操作码压入和弹出值,所以
add
弹出 2,然后压入 1)。 - 作为本地人。
- 在
Memory
.
请注意,您不能获取 1. 和 2. 的地址。只有在这些情况下,我才希望代码生成器与 3.您选择的 ABI。 Emscripten 和其他工具所做的是将堆栈指针存储在地址 4
处,然后在程序的早期他们选择堆栈应该去的位置。 不必 始终为 4,但始终坚持该 ABI 更简单,尤其是在涉及动态链接时。
关于初始值:该位置必须足够大以容纳整个堆栈,并且 malloc
的实现必须了解它,因为它无法在其上分配堆 space .这就是为什么某些工具允许您指定最大尺寸的原因。
任何东西都可以在之前/之后存储(尽管之后你可能有先前的堆栈值)。 WebAssembly 目前没有保护页,因此耗尽内存堆栈将破坏堆值(除非代码生成器也发出堆栈检查)。 "memory safe" 就是这样,它仍然无法逃脱 WebAssembly.Memory
,因此浏览器无法拥有,但开发者自己的代码可以完全拥有。构建在 WebAssembly 之上的内存安全语言必须在 WebAssembly.Memory
.
请注意,我没有解释 1. 和 2. 它们的存在意味着大多数 C++ 程序在 WebAssembly 中使用的内存堆栈比原生 C++ 程序使用的堆栈少。