thi-ng/tinyalloc

Preventing interference WASM stack (Clang/LLVM)

Closed this issue · 2 comments

I'm compiling to WASM with Clang/LLVM, not Emscripten, and was hoping to use tinyalloc. Going off of the information in this article, specifically the image indicating the data, stack, and heap layouts, it is stated that the .data section comes first, followed by the stack, and then the heap. Notice that the stack grows downwards toward __data_end.

memory layout

(I couldn't find documentation describing Emscripten's memory layout, so I'm not sure if this is the same or different than Emscripten).

That leaves me with a few questions:

  1. __data_end is typically 0x400, which is used for TA_BASE. If I place TA_BASE at 0x400, aren't I at risk of having the tinyalloc blocks clobbered by a stack that grows all the way to __data_end?
  2. For my specific application, I have a lot of static strings compiled into my program, and therefore my .data section is much larger than 0x400, but I don't necessarily know the exact size at compile time (obviously using 0x400 for TA_BASE was overwriting some of my static data). Is it feasible to define a TA_BASE at runtime as part of ta_init(), or are there some reasons that it must be defined at compile time that I just don't understand?
  3. If it's feasible to set TA_BASE and TA_HEAP_START at runtime, I was thinking that it might be a good idea to set TA_BASE to __heap_base and TA_HEAP_START to __heap_base + sizeof(Heap) so that it can grow without interference to the stack and data sections.

If these seem like valuable additions to the project, I'd be happy to take a stab at implementing them in such a way that these things can be configured when calling ta_init() and submitting a PR.

Hi @winduptoy - the only reason for TA_BASE currently being a #define is because of the way I used this project on embedded devices, where I'd simply supply the start address via command line flags (gcc -DTA_BASE=0x1000 ...)

I'd welcome a PR where you can configure heap start/end, splitting threshold and maybe even the number of max blocks used via args passed to ta_init().

Btw. TA_HEAP_START already is currently set to TA_BASE + sizeof(Heap), so your logic with __heap_base + sizeof(Heap) is sound.

Though, if we want to make the number of max blocks runtime configurable, we will need to replace the blocks array (in the Heap struct) with a pointer (or get rid of it totally and update the few use sites in the code) and then update the math to: __heap_base + sizeof(Heap) + maxBlocks * sizeof(Block) and set blocks to __heap_base + sizeof(Heap)

I think we can close this now, right?!