82197

WebAssembly stack / stack pointer initialization and memory layout

Question:

I am currently toying around with WebAssembly compiled through LLVM but I haven't yet managed to understand the stack / stack pointer and how it relates to the overall memory layout.

I learned that I have to use s2wasm with --allocate-stack N to make my program run and I figured that this is basically adding (data (i32.const 4) "8\00\00\00") (with N=8) to my generated wast, with the binary part obviously being a pointer to a memory offset and the i32 constant being its offset in linear memory.

What I do not quite understand, though, is why the pointer's value is 56 (again with N=8) and how this value relates to the exact region of the stack in memory, which, in my case, currently looks like:

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

I know that I am probably more a candidate for "just use emscripten", but I'd also like to understand this.

<ul><li>Is the stack pointer always stored at offset 4 in linear memory?</li> <li>How is its initial value calculated? (aligned to next offset%16==0 + N after data?)</li> <li>What's stored before, and what's after the offset it points at?</li> </ul>

Answer1:

I touched on this in <a href="https://stackoverflow.com/questions/43571620/understanding-class-structures-and-constructor-calls" rel="nofollow">another question</a>. From C++'s stack there are actually 3 places where the values can end up:

<ol><li>On the execution stack (each opcode pushes and pops values, so add pops 2 and then pushes 1).</li> <li>As a local.</li> <li>In the Memory.</li> </ol>

Notice that you can't take the address of 1. and 2. Only in these cases would I expect a code generator to go with 3. How this is done isn't dictated by WebAssembly, it's up to whatever ABI you chose. What Emscripten and other tools do is they store the stack pointer at address 4, and then very early in the program they choose a spot where the stack should go. It doesn't <em>have</em> to always be 4, but it's simpler to always stick to that ABI especially if dynamic linking is involved.

On initial value: that location has to be big enough to hold the whole stack, and the implementation of malloc has to know about it because it can't allocate heap space over it. That's why some tooling allows you to specify max size.

Anything can be stored before / after (though after you'd likely have prior stack values). WebAssembly doesn't currently have guard pages, so exhausting the in-memory stack will clobber heap values (unless the code generator also emits stack checks). That's all "memory safe" in that it still can't escape the WebAssembly.Memory, so the browser can't get owned but the developer's own code can totally be owned. A memory-safe language built on top of WebAssembly would have to enforce memory safety within the WebAssembly.Memory.

Note that I haven't explained 1. and 2. Their existence means that most C++ programs will use less in-memory stack in WebAssembly than a native C++ program uses stack.

Recommend

  • sorting element from linked list
  • How to pass strings between C++ and javascript via emscripten
  • bison only reads one line [closed]
  • How to find the deviation using Java
  • If “NULL” then use 0 in shell scripting
  • Selecting the nth-element of class X
  • BulletPhysics (ammo.js) - How would you go about applying force to an object?
  • Emscripten Bindings: How to create an accessible C/C++ array from Javascript?
  • jquery mobile and flot library
  • Is there a way to visually see what has been render by PhantomJS on a Browser
  • VBA: How can I keep only the date values from a string?
  • Using a support vector classifier with polynomial kernel in scikit-learn
  • fonts in tables rendering inconsistently on mobile browsers
  • Matlab imwrite() quality
  • is there anyway to pass back additional data in jqgrid treeGrid url request?
  • Extract text from “” HTML tag
  • npm thinks node is out of date, but it isn't
  • Deploy same Javascript webapp build to different environments
  • Solving multiple interface implementation
  • javascript add operation returns bad result
  • ASM ClassReader failed to parse class file - probably due to a new Java class file version that isn&
  • Why is it ambiguous to call overloaded ambig(long) and ambig(unsigned long) with an integer literal?
  • WebApp in AppServices vs CloudService
  • Swipe Gesture Recognizer not working for me
  • How to merge two Request in Laravel
  • Picasso Taking time to load images
  • Android application not restoring state when installed from .apk, works fine from eclipse
  • It is possible use the same sql azure instance from two different cloud service of two different sub
  • SqlCommand back up Database
  • Python cosine function precision [duplicate]
  • HttpClient: disabling chunked encoding
  • blade.php method outputting it's result to the form
  • Trying to get the char code of ENTER key
  • xcode don't localize specific strings
  • how does System.Web.HttpRequest::PathInfo work?
  • Converting a WriteableBitmap image ToArray in UWP
  • Is there any way to access browser form field suggestions from JavaScript?
  • NetLogo BehaviorSpace - Measure runs using reporters
  • Hazelcast - OperationTimeoutException
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET