Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access heap start address and heap base address within c function

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.

like image 383
D. Smith Avatar asked Aug 29 '19 11:08

D. Smith


2 Answers

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.

like image 129
Peter Cordes Avatar answered Nov 03 '22 09:11

Peter Cordes


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.

like image 4
Jester Avatar answered Nov 03 '22 09:11

Jester