This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Determining stack overflow by writing to a stack in a startup file

I'm trying to detect stack overflow. One approach that I found online was to prefill the memory with a constant value before the program runs, and see how much of the stack has been overwritten.

So now that I've been looking into it:

  • is ses_startup_common.s the startup file that initializes the RAM and calls main? (seems to be but making sure)
  • STACK_INIT_VAL contains the address of the stack pointer when the program starts, yes? What's
    __RAM1_segment_end__ equal to?
  • how do we go about filling the stack memory with some value? is it mainly loading the value into a general purpose register i.e R2?

Thanks

Parents
  • Hi,

    You can see how to find the start and end of the stack for different toolchains by searching for STACK_BASE and STACK_TOP in <nRF5 SDK>\components\libraries\util\app_util.h. Note that if you just want a stack guard (and not a way to measure stack usage) and use the nRF5 SDK, then you can use the Stack guard library. 

  • Thanks for the response.

    - In <nRF5 SDK>\components\libraries\util\app_util.h, I see there's a bunch of definitions for STACK_TOP and STACK_BASE. Which one is possibly used?

    - I reckon STACK_TOP refers to the starting address of the stack i.e what MSP points to when the program starts in main? 

    - none of this is used inside ses_startup_common.s. In fact, the following seems to be stored in a stack pointer, hence my question about what does STACK_INIT_VAL store?

    ldr r0, =STACK_INIT_VAL
    ldr r1, =0x7
    bics r0, r1
    mov sp, r0

    - how would you fill in the stack memory though? does what I mentioned in my previous comment make sense?

    Is it perhaps using str asm command in a startup file to write at address 0x2000 0000 where the DATA RAM starts in nRF52?

    infocenter.nordicsemi.com/index.jsp

  • Hi,

    morpho said:
    - In <nRF5 SDK>\components\libraries\util\app_util.h, I see there's a bunch of definitions for STACK_TOP and STACK_BASE. Which one is possibly used?

    These are for different toolchains. When you use SES the GNUC part is relevant, so it would be this:

    extern uint32_t __StackTop;
    extern uint32_t __StackLimit;
    #define STACK_BASE    &__StackLimit
    #define STACK_TOP     &__StackTop

    morpho said:
    - I reckon STACK_TOP refers to the starting address of the stack i.e what MSP points to when the program starts in main? 

    Yes, that is entirely correct. STACK_TOP is the end of the stack (i.e. the next address after the highest address of the stack), which is typically what you initialize the stack pointer with (unless you want to waste some stack that will never be used). STACK_BASE is the end/lowest address of the stack.

    morpho said:
    what does STACK_INIT_VAL store?

    This is the address of the end of the RAM. You can see that from how it is defined in modules\nrfx\mdk\ses_startup_nrf_common.s:

    #ifndef STACK_INIT_VAL
    #define STACK_INIT_VAL __RAM1_segment_end__
    #endif

    So for instance if you are using the nRF52840 which has 256 kB RAM and as will all nRF52 devices the RAM is mapped to start at 0x20000000, the STACK_INIT_VAL will be 0x20040000.

    morpho said:
    Is it perhaps using str asm command in a startup file to write at address 0x2000 0000 where the DATA RAM starts in nRF52?

    You can make an assembly loop and write to any part of the RAM in the startup file yes, including the stack and memory immediately after the stack. Typically for a stack guard you would write a known pattern immediately below the stack and check that regularly. (If you want to measure the stack usage you write the pattern within the stack, though.)

    Note that if all you want is a stack guard to detect a stack overflow, as the topic of your original post suggests, then you can simply use what we provide for you in with the stack guard library.

  • Thanks.

    Yes, that is entirely correct. STACK_TOP is the end of the stack (i.e. the next address after the highest address of the stack), which is typically what you initialize the stack pointer with (unless you want to waste some stack that will never be used). STACK_BASE is the end/lowest address of the stack

    Where are __StackLimit and __StackTop defined? Segger isn't helping me navigate and it gets annoying at times.

    So for instance if you are using the nRF52840 which has 256 kB RAM and as will all nRF52 devices the RAM is mapped to start at 0x20000000, the STACK_INIT_VAL will be 0x20040000.

    I see. Can you confirm if `STACK_INIT_VAL` equals `0x20040000` which marks the end of the RAM i.e what MSP points to at the start of main? I found its value in the `.map` file. 

    So if the RAM is between `0x2000 0000 - 0x2004 0000`, how much of that is taken up by the stack?

    You can make an assembly loop and write to any part of the RAM in the startup file yes, including the stack and memory immediately after the stack.

    Sorry, I'm not great at ASM. 

    For instance, if I want to write `5`, I'd perhaps do something like the following?

      ldr r2, = STACK_INIT_VAL
    
      movs  r1, #5
    
      str  r1, [r2]

    Regarding stack guard, sure sounds like something I could use but I also want to write something from scratch to understand how one could detect a stack overflow by writing a simple program. Though, is it just the nrf_stack_guard_init function that's used?

Reply
  • Thanks.

    Yes, that is entirely correct. STACK_TOP is the end of the stack (i.e. the next address after the highest address of the stack), which is typically what you initialize the stack pointer with (unless you want to waste some stack that will never be used). STACK_BASE is the end/lowest address of the stack

    Where are __StackLimit and __StackTop defined? Segger isn't helping me navigate and it gets annoying at times.

    So for instance if you are using the nRF52840 which has 256 kB RAM and as will all nRF52 devices the RAM is mapped to start at 0x20000000, the STACK_INIT_VAL will be 0x20040000.

    I see. Can you confirm if `STACK_INIT_VAL` equals `0x20040000` which marks the end of the RAM i.e what MSP points to at the start of main? I found its value in the `.map` file. 

    So if the RAM is between `0x2000 0000 - 0x2004 0000`, how much of that is taken up by the stack?

    You can make an assembly loop and write to any part of the RAM in the startup file yes, including the stack and memory immediately after the stack.

    Sorry, I'm not great at ASM. 

    For instance, if I want to write `5`, I'd perhaps do something like the following?

      ldr r2, = STACK_INIT_VAL
    
      movs  r1, #5
    
      str  r1, [r2]

    Regarding stack guard, sure sounds like something I could use but I also want to write something from scratch to understand how one could detect a stack overflow by writing a simple program. Though, is it just the nrf_stack_guard_init function that's used?

Children
  • Hi,

    morpho said:
    Where are __StackLimit and __StackTop defined? Segger isn't helping me navigate and it gets annoying at times.

    I recommend just searching through all code in a normal editor then, or grepping or what you prefer. That way you can typically find these things as there are not that many references. Specifically, __StackTop and __StackLimit comes from <SDK>\modules\nrfx\mdk\nrf52_common.ld and you can see how it is done there.

    morpho said:
    I see. Can you confirm if `STACK_INIT_VAL` equals `0x20040000` which marks the end of the RAM i.e what MSP points to at the start of main? I found its value in the `.map` file. 

     Yes.

    morpho said:
    So if the RAM is between `0x2000 0000 - 0x2004 0000`, how much of that is taken up by the stack?

    That is entirely up to you. Most example projects use 8192 byte stacks, but you can change that. For SES, you can do it from here:

    morpho said:
    Sorry, I'm not great at ASM. 

    Neither am I, sorry  Slight smile But why do you need to do this in assembly, then? And why in the startup file if all you want is a stack guard? You are free to play with this as you like to experiment but I do not have much to add.

  • Assembly and the startup file because you would want to write to the stack before the main is called, and track how much is being used by looking at the bits in memory

Related