Reputation: 63
For my own dynamic memory allocation implementation of malloc, I want to access the heap base address and heap limit address during run time. I know they are exported as globals in my startup.s file. How can I access these addresses? Target platform is ARM Cortex-M4 with GCC.
Symbols declared with .globl are known to the linker and should be accessable using the extern symbol within c code. But using this method, I get values that differ from the values within the generated .map file.
Here are the heap symbols defined in the startup.s file:
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x00000C00
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .vectors
.align 2
.globl __Vectors
Here is my access within my c function:
extern volatile __HeapBase;
extern volatile __HeapLimit;
static void heaptest(void) {
uint32_t limit;
uint32_t base;
base = __HeapBase;
limit = __HeapLimit;
}
Debugging this code, I get other addresses than specified in the generated .map file:
.heap 0x200317a0 0x40000
0x200317a0 __HeapBase = .
...
0x200717a0 __HeapLimit = .
...
So I expect the output to be 0x200317a0 for __HeapBase and 0x200717a0 for __HeapLimit, but the actual outputs I get are 0xf377aaa2 and 0xac69254.
Upvotes: 5
Views: 4457
Reputation: 364220
Declare them as extern char __HeapBase[];
because in C the name of an array object converts to a pointer, while names of other objects are implicitly dereferenced.
Maybe also use #define HEAPBASE ((void*)__HeapBase)
to make it convenient to use the name. Or cast it to (uintptr_t)
or whatever.
Having a separate global void *base = &__HeapBase;
would be less good: base
is not a compile-time-constant value because it's not even declared as const
. Code that uses it will have to load a pointer from static storage, instead of having a link-time constant address they can use directly.
Upvotes: 5
Reputation: 58762
The exported symbols are addresses, but the C compiler dereferences them for you. To get the address back, you need to apply the address-of operator &
, that is void* base = &__HeapBase;
should work. As written, you are actually fetching the first item from the heap.
Upvotes: 4