For gcc+newlib: Adapt the implementation of void *_sbrk(ptrdiff_t incr) in sysmem.c. _sbrk is called twice for the first malloc. The first call with param incr==0 returns the heap bottom address. The second call tells _sbrk the additional space needed for the new allocation and _sbrk return the (current) top of the heap (or -1 on error).
_sbrk returns increasing pointers at each call, and, in contrast to the malloc/free pair never gives back memory or shrinks the heap space.
It should be not too difficult to insert your own bottom and top limits here instead of using the linker script variables.
hth
KnarfB