This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

How to read the Stack Pointer from C

Hi everyone,

I am currently debugging a very nasty problem on the C6474. The symptom seen most often is that I get an exception when core zero (the only core running) tries to execute code from the heap.

I suspect that the stack pointer has been corrupted and that when a function has returned, it has loaded B3 from the wrong address on the stack, and then jumped to B3.

(I suspect this because the SP is pointing to a stack location that contains the address seen in B3 and the Exception Return Pointer. Whilst two words away, there is a perfectly good return address.)

I would like to use Trace to help understand where the code was running prior to the exception, but currently can't figure out how to configure it. I have a parallel post on the CCS forum asking for help setting up trace on the C6474 with CCSv4 and a Spectrum Digital USB XDS510. Due to the time difference between the UK and the US, this is taking a long time to sort out.  If anyone else has any input to that post I would be very grateful.

In the mean time I have decided to try and catch the SP being corrupted. What I would like to do is add a C statement at the top of a number of functions to save the stack pointer value to a variable, and add a test at the end of the same functions that checks it is still the same just before exit.

I am not yet confident to do this in assembler; I am worried that I would corrupt registers if I added my own assembler to do this.

Hence I would like to know if anyone can tell me how to read the stack pointer in C such that I can write it to a variable, and later use it in an if statement to test itagainst that variable. Perhaps you know of a function call, a macro, or some in-line assembler.

Any ideas?

Paul

  • Not familiar with the C6474. Back in the day ... I'd get an idea of where the stack pointer was by declaring a variable on the stack and getting the address of the variable. Something like this:

    void some_func(void)
    {
      volatile register int *pSPsaved;
      {
        automatic int iTemp;
        pSPsaved = &iTemp;
      }
      ...
      {
        automatic int iTemp;
        if(pSPsaved != &iTemp)
          printf("Oops?\n");
      }
    }

    It's very hacky and assumes the compiler will respect the automatic keyword. The compiler might also complain about taking the address of a variable that will go out of scope. Ideally, an asm() directive that copies SP to a variable would be much better.

  • Thanks - Norman

    I had been thinking about the problem too long and the obvious answer did not come to me!

    For my problem your suggestion is good as it will detect a change in the stack pointer. When I examined the assembler, I found that it does not give the actual SP address because the compiler chose to combine the new variable with those on the existing stack.

    e.g. it did not adjust the SP at the point the variable is declared within the { .. } section. In the function I was interested in, the pointer value recorded was actually SP + 12words. This could change if the C code was edited.

    So I decided to create a function that stores the pointer in a static variable. (This does require a new stack check function for each function that is being tested, and the function is not re-entrant.) The benefit of doing this is that because the new variable is in a function, the compiler adjusts the SP by 8 bytes on entry, and so I know the variable address will be very close to the SP of the calling function.

    void <FUNCTION_NAME>_stack_check(Bool bStart)
    {
        static int * pTemp = 0;    /* Pointer to hold address of variable on entry. */
        static int * pTemp2 = 0;   /* Pointer to hold address of variable on error - this ensures the initial point is preserved. */
        
        int iTemp;                 /* DO NOT INITIALISE - this may hamper investigation of stack. */
        
        if (bStart)
        {
            pTemp = &iTemp;        /* Store address for inspection later at end of function (or before the end) */
        }
        else if (pTemp != &iTemp)
        {
            pTemp2 = &iTemp;       /* Put break point here to catch stack pointer corruption before it causes an exception. */
        }
    }

    Examining the assembler, I found that on entry the SP is adjusted by 8 bytes to make room for my temporary integer iTemp. In my case the compiler placed the 4 bytes of  iTemp at the caller's SP and hence pTemp equals the caller's SP. But, I think it could have placed iTemp at SP-4bytes.

    If you wanted to use this function to return the actual SP, you would need mask the LSbits of the address to align to the correct 8 byte boundary. (The SP is always 8 byte aligned.)


    To cut a long story short, the function works - I have detected a stack pointer corruption followed by an exception when the caller copied a data variable address into B3!

    Once again, Thank you very much Norman.

    Sometimes the perfectly simple ideas are simply perfect!

    Regards - Paul