rdimon __heap_limit usage in crt0.S breaks sbrk
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
GNU Arm Embedded Toolchain |
New
|
Undecided
|
Unassigned |
Bug Description
in newlib after 2.2.0, exists in 4.9-2015-q2-update and up
in crt0.s
ldr r0, .LC0 /* point at values read */
/* Set __heap_limit. */
ldr r1, [r0, #4]
cmp r1, #0
beq .LC33
ldr r2, =__heap_limit
str r1, [r2]
.LC33:
...
.LC0:
#ifdef ARM_RDI_MONITOR
.word HeapBase
#else
...
/* Data returned by monitor SWI. */
.global __stack_base__
HeapBase: .word 0
and syscall.c
/* Heap limit returned from SYS_HEAPINFO Angel semihost call. */
uint __heap_limit = 0xcafedead;
caddr_t __attribute_
_sbrk (int incr)
{
@@ -599,7 +602,9 @@ _sbrk (int incr)
prev_heap_end = heap_end;
if (heap_end + incr > stack_ptr)
if ((heap_end + incr > stack_ptr)
/* Honour heap limit if it's valid. */
|| (__heap_limit != 0xcafedead && heap_end + incr > __heap_limit))
{
So on startup our ResetHandler __heap_limit has 0xcafedead copied at the end of .data then _start sees it != HeapBase (0) and overwrites it, now any call to _sbrk fails. When doing semihosting none of the _sinit calls to _malloc_r checks errno or for null ptr returns and the code breaks with null derefencing.
Marcel,
Is this issue still blocking you? I suspect that your semihosting host is not returning with the right heaplimit. _start works on the assumption that either semihosting returns 0 as heap_limit, which means please ignore, or a valid heap_limit that is higher than the heap_base.
So I tenders to invalidate this issue report.