Msg/StackDeallocatedParentFrame: Difference between revisions

From CPUlator Wiki

< Msg
No edit summary
Line 35: Line 35:


=== Debugging ===
=== Debugging ===
* Normally, all stack pointer manipulations are matched: Decrease the stack pointer when entering a function, and increasing the stack pointer immediately before returning. Check for stack pointer operations (push and pop) that are mismatched.
* Normally, all stack pointer manipulations are matched: decrease the stack pointer when entering a function, and increase the stack pointer immediately before returning.  
* Carefully trace through any operations that change the stack pointer. Make sure they're all matched (every decrement is matched by an increment of the same amount). Ensure that the function prologue and epilogue only execute once (not accidentally part of a loop).
* The two places where stack pointer manipulations often occur are at the function prologue and epilogue, and allocating and deallocating arguments passed on the stack when calling a function. These operations are all matched. If your function uses the stack pointer for other purposes, this is an easy source of bugs.


=== Implementation ===
=== Implementation ===

Revision as of 07:24, 10 March 2019

A stack frame is a region of memory used by an executing function. When calling a function, the child function's stack frame is at a lower address than the caller's stack frame. New stack space is allocated by decrementing the stack pointer, and stack space is deallocated by incrementing the stack pointer. However, a function should not deallocate the parent function's stack frame. In other words, the stack pointer should never be greater than the value at the beginning of the function. This warning tells you that the stack pointer has increased past the value it had at the beginning of the current function.

This is a more stringent requirement than simply requiring the stack pointer to be restored to its original value at the end of the function. Because an interrupt can occur at any moment, if the stack pointer increases beyond the current stack frame (deallocating the parent's stack frame) even momentarily, the parent function may lose some of its stack values because an interrupt handler may have executed and used the "free" stack space below the stack pointer.

Example

ARMv7

.global _start
_start:
	mov sp, #0x1000			// Initialize SP to something sane    
    bl Func
    
Func:
	add sp, #4				// Deallocated 4 bytes of the caller's stack frame
    sub sp, #4				// Can't do this even if the operation is reverted
    bx lr

Nios II

.global _start
_start:
	movi sp, 0x1000			# Initialize SP to something sane    
    call Func
    
Func:
	addi sp, sp, 4				# Deallocated 4 bytes of the caller's stack frame
    subi sp, sp, 4				# Can't do this even if the operation is reverted
    ret

In the above examples, the stack pointer is initialized to 0x1000. The child function Func can allocate and deallocate stack space below the stack pointer (currently 0x1000). It is not allowed to deallocate the parent's stack frame. The child function here attempts to move the stack pointer to 0x1004. This results in the warning: Stack pointer moved beyond current stack frame. sp at beginning of current function was 00001000

The message also reminds you that the stack pointer was 0x1000 at the beginning of the function, and that the stack pointer has increased beyond this point (to 0x1004).

Debugging

  • Normally, all stack pointer manipulations are matched: decrease the stack pointer when entering a function, and increase the stack pointer immediately before returning.
  • Carefully trace through any operations that change the stack pointer. Make sure they're all matched (every decrement is matched by an increment of the same amount). Ensure that the function prologue and epilogue only execute once (not accidentally part of a loop).
  • The two places where stack pointer manipulations often occur are at the function prologue and epilogue, and allocating and deallocating arguments passed on the stack when calling a function. These operations are all matched. If your function uses the stack pointer for other purposes, this is an easy source of bugs.

Implementation

The simulator identifies idiomatic call and return instructions executed at runtime. It records the values of registers when executing call instructions, and compares the current stack pointer to the stack pointer at the beginning of the function. This warning is generated at the instruction that modifies the stack pointer.

Disabling this message

This debugging check can be disabled in the Debugging Checks section of the Settings box: SP moved beyond current stack frame.