Stack frame error

Hi.

I ask couple of days ago about unexplained code behavior. It hasn't been solved completely.

I now have some more specific details about that.

Function InitDeviceasBC call function sitalDevice_Initialize.

When sitalDevice_Initialize returns addresses of local variables in InitDeviceasBC suddenly changed.

InitDeviceasBC :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 void InitDeviceAsBC()
{
	unsigned int uiDeviceCount = 1;
    unsigned int uiDeviceID = 0;
 
 
	U16BIT NumberOfDevices = 0;
	S16BIT iResult = sitalDevice_GetCount(&NumberOfDevices);
	printf ("Device Count: %i\n", NumberOfDevices);
	for(int idx = 0 ; idx < 1/*NumberOfDevices*/ ; idx++){
		uiDeviceID = idx;
		printf("\nuiDeviceID before device_initialize: %p\n\r",&uiDeviceID);
		printf("\nNumberOfDevices before device_initialize: %p\n\r",&NumberOfDevices);
 
		iResult = sitalDevice_Initialize(uiDeviceID, sitalAccess_CARD, sitalMode_BC, 0, 0, 0);
		if(iResult != 0)
		{
			printf("sitalDevice_InitializeBC.Error: %i", iResult);
			return;
		}
		printf("\nuiDeviceID after device_initialize: %p\n\r",&uiDeviceID);
		printf("\nNumberOfDevices after device_initialize: %p\n\r",&NumberOfDevices);
 
 
		iResult = sitalDevice_TimeTag_SetResolution(uiDeviceID, sitalTimeTagResolution_64US);
		if(iResult != 0)
		{
			printf("TimeTag_SetResolution Error: %i", iResult);
			return;
		}
		printf ("Time Tag resolution of %i\n", sitalTimeTagResolution_64US);
 
 
		iResult = sitalDevice_Irq_Manipulate(uiDeviceID, 1, sitalInterruptRegister2_BC_IRQ3, &funcExternalISR);
		if(iResult != 0)
		{
			printf("sitalDevice_Irq_Manipulate Error: %i", iResult);
			return;
		}
		printf ("sitalDevice_Irq_Manipulate %i\n", iResult);
	}
}



sitalDevice_Initialize :

S16BIT _DECL sitalDevice_Initialize ( S16BIT swDevice,
U16BIT wAccess,
U16BIT wMode,
U32BIT dwSizeOfAllocatedMemory,
U32BIT dwRegistersAddress,
U32BIT dwMemoryAddress)

Definition is too long..

I check memory address of variables before and after call to sitalDevice_Initialize:


uiDeviceID before device_initialize: 0x191154

NumberOfDevices before device_initialize: 0x191174

uiDeviceID after device_initialize: 0x190028

NumberOfDevices after device_initialize: 0x190048


notice a similar offset between vatiables old and new address.
Is this indicating about wrong stack frame?

Any help will be appreciated.
Last edited on
You are probably overthinking something basic here.
lets get it down to the smallest scenario that explains what is going on.
Are you using a debugger or pointer or something to monitor a specific location in memory?
or are you using a debugger to track a variable by name, and if so, is that name duplicated (eg main has int x, and function foo has int x)?

in scenario 1, if you are looking at a memory location and it changed after a function call, yes, that is normal. The function ends and its local values are released, and can be overwritten -- you are looking at memory that used to be one thing and is now something else.

in scenario 2, these are not the same variable, but for this most debuggers are stupid and will fetch the variable of the name at the current scope, so when the scope changes, the value changes too.
I think it is misunderstood
(i use what you describe in scenario 1)

if uiDeviceID is located in memory address 0x191154 in function InitDeviceasBC,
this need to stay the same after sitalDevice_Initialize ends, but as i
show it is changing.

it is actually happens to all of InitDeviceasBC local variables.
The stack pointer for this function is somehow change after sitalDevice_Initialize
returns.
Last edited on
What's the code for sitalDevice_initialize()? Is it a c/c++ function or an assembler function? what's its calling convention?
It is c function , too big to publish here
see if you can see it here:

https://raw.githubusercontent.com/Yonatan1990/Unified_Version/main/Unified_100822/Unified_Version/src/stld1553.cpp?token=GHSAT0AAAAAABXSVE4TBAE356KDFHCE5V6QY6G2PJA

what's its calling convention?

How can i determine that?

I actually find piece of code in sitalDevice_initialize that seems like the cause of the problem:

1
2
3
4
5
6
7
	swResult = device_Reset (swDevice);
	if (sitalReturnCode_SUCCESS != swResult)
	{
		S16BIT swUnusedResult; // Result of operation or function call.
		swUnusedResult = sitalDevice_Free (swDevice);
		return swResult;
	}


In this line:
S16BIT swUnusedResult; // Result of operation or function call.
I have warning:
variable 'swUnusedResult' set but not used [-Wunused-but-set-variable]

Why is that? And why those lines create the problem (I assume my hw debugger can't understand them)?
Last edited on
swUnusedResult is defined, it's then set but the set value is never used. You could code as:

1
2
3
4
5
6
        swResult = device_Reset (swDevice);
	if (sitalReturnCode_SUCCESS != swResult)
	{
		sitalDevice_Free (swDevice);
		return swResult;
	}


That won't be the cause of the problem.

The github link is invalid.

Last edited on
Try what i uploaded now:

https://github.com/Yonatan1990/BareMetalPseudoCode

code for sitalDevice_initialize is in stld1553.cpp

code for InitDeviceAsBCis in User_1553.cpp

That won't be the cause of the problem.


The fact is that when I comment those lines the code is running properly
or there is something in that code slice that create stack overflow somehow 🤔
Last edited on
What do you get with this change (printing out the values of the variables).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void InitDeviceAsBC()
{
    unsigned int uiDeviceCount = 1;
    unsigned int uiDeviceID = 0;
    U16BIT NumberOfDevices = 0;

    S16BIT iResult = sitalDevice_GetCount(&NumberOfDevices);
    if (iResult != 0) { // I assume this would mean an error
        printf("sitalDevice_GetCount.Error: %i", iResult);
        return;
    }

    printf("uiDeviceID: %u  address %p\n", uiDeviceID, &uiDeviceID);
    printf ("Device Count: %i  address: \n", NumberOfDevices, &NumberOfDevices);

    for (int idx = 0; idx < 1/*NumberOfDevices*/; idx++) {
        uiDeviceID = idx;
        printf("\nuiDeviceID before: value %u  address %p\n", uiDeviceID, &uiDeviceID);
        printf("\nNumberOfDevices before: value %i  address %p\n", NumberOfDevices, &NumberOfDevices);
 
        iResult = sitalDevice_Initialize(uiDeviceID, sitalAccess_CARD, sitalMode_BC, 0, 0, 0);
        if (iResult != 0) {
            printf("sitalDevice_InitializeBC.Error: %i", iResult);
            return;
        }
        printf("\nuiDeviceID after: value %u  address %p\n", uiDeviceID, &uiDeviceID);
        printf("\nNumberOfDevices after: value %i  address %p\n", NumberOfDevices, &NumberOfDevices);

        ...

Post something we can compile and run.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
$ g++ stld1553.cpp User_1553.cpp
stld1553.cpp:13:10: fatal error: OperatingSystemDependencies.h: No such file or directory
   13 | #include "OperatingSystemDependencies.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
User_1553.cpp:8:10: fatal error: stld1553_operatingSystemDependencies.h: No such file or directory
    8 | #include "stld1553_operatingSystemDependencies.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.


$ touch OperatingSystemDependencies.h stld1553_operatingSystemDependencies.h
$ g++ stld1553.cpp User_1553.cpp
stld1553.cpp:14:10: fatal error: InterProcessSemaphore.h: No such file or directory
   14 | #include "InterProcessSemaphore.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
User_1553.cpp:9:10: fatal error: stld1553_returnCodes.h: No such file or directory
    9 | #include "stld1553_returnCodes.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
$ touch InterProcessSemaphore.h stld1553_returnCodes.h
$ g++ stld1553.cpp User_1553.cpp
stld1553.cpp:15:10: fatal error: stld1553.h: No such file or directory
   15 | #include "stld1553.h"
      |          ^~~~~~~~~~~~
compilation terminated.
User_1553.cpp:10:10: fatal error: stld1553.h: No such file or directory
   10 | #include "stld1553.h"
      |          ^~~~~~~~~~~~
compilation terminated.


$ touch stld1553.h
$ g++ stld1553.cpp User_1553.cpp
stld1553.cpp:17:10: fatal error: stld1553_driverInterface.h: No such file or directory
   17 | #include "stld1553_driverInterface.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
User_1553.cpp:11:10: fatal error: stld1553_driverInterface.h: No such file or directory
   11 | #include "stld1553_driverInterface.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.


Nobody wants to play whack-a-mole trying to second guess what you missed out.
Outside home. Tmrw i will post

but i dont think you can compile it as it is based on hardware platform
(.xsa file)

Do you have Vitis?
Does your code compile without warnings? You have fix those first.

For example, sitalDevice_Initialize() takes a device of type S16BIT, but you're passing an unsigned.
The fact is that when I comment those lines the code is running properly
or there is something in that code slice that create stack overflow somehow


Exactly which lines do you comment out that causes the code to run properly?

That if statement deals with an error returned from device_Reset(). If there was no error, then the body of the if statement won't be executed. If that code is commented out, then you're trying to do a device_Reset(), ignore any issues and continue as if device_Reset() had worked OK.

But if you also commented out the call to device_Reset() and the code works then device_Reset() is a good candidate for suspicion for the cause of the issue. Have you got the source code for that function?

Also note that that code-snippet compares the value to sitalReturnCode_SUCCESS for success, but in the calling code the value is compared to 0 for success. sitalReturnCode_SUCCESS may well be set to 0, but the code should be consistent.

Also note that you're mixing U16BIT, int and unsigned int. Whilst this is unlikely to cause the current issue, it could cause run-time issues at some point. The types used should be consistent.

Irrespective of what sitalDevice_Initialize() does, the addresses of uiDeviceID and NumberOfDevices are set by the compiler during compilation and shouldn't change. If these are relative to the current stack pointer (probably), then somehow sitalDevice_Initialize() is corrupting the stack pointer. They are 4396 bytes lower than what would be expected. There is either something happening in sitalDevice_Initialize() which is upsetting the compiler or there is a code generation problem with the compiler. For a Windows system, I'd suspect an issue with function calling convention (__cdecl or __stdcall) which defines whether the caller or callee cleans up the stack for function params. But I don't know how the system for which you're compiling deals with function call params.
I don't know what development tools you have available, but if you can trace the sp through the code.

Last edited on
Thanks for the good insights guys.

My code is compiling fine. Although i am gonna changed the types as you suggested.

Here is chapter that describe stack convention for my hw platform:
https://manualzz.com/doc/o/143r6w/xilinx-microblaze-reference-manual-stack-convention

I'm wondering if there is something unusual there that cause those issues.
In sitalDevice_Initialize() (which we believe has the problem), I'd suggest you create a new temp var at the beginning, display it's address and then after every function call display it's address. All the addresses shown should be the same. When you find one that's different, you're found the problem function. This can then be repeated for that function if it also calls other functions etc until you find the bottom level function. That function can then be looked at more closely and tried in test code etc etc.

For normal c, something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <cstdio>

void funca() {
	puts("In funca");
}

void funcb() {
	puts("In funcb");
}

void func() {
	int temp = 0;

	printf("Before funca %p\n", &temp);
	funca();
	printf("After funca %p\n", &temp);
	funcb();
	printf("After funcb %p\n", &temp);

}

int main() {
	func();
}


which for me displays:


Before funca 000000000021FB50
In funca
After funca 000000000021FB50
In funcb
After funcb 000000000021FB50

Last edited on
Hi.

DizzyDon (91)
What do you get with this change (printing out the values of the variables).


This is what i get [Before the change i made]:

Memory Block Size: 0x4000
Device Count: 1
uiDeviceID: 0  address 0x19129c
Device Count: 1  address:0x1912bc

uiDeviceID before: value 0  address 0x19129c

NumberOfDevices before: value 1  address 0x1912bc

uiDeviceID after: value 167964672  address 0x190028

NumberOfDevices after: value 3977  address 0x190048
TimeTag_SetResolution Error: -50
Hi folks. I have an update about the issue.

in sitalDevice_Initialize function, we see that our problematic code-snippet:

1
2
3
4
5
6
7
	swResult = device_Reset (swDevice);
	if (sitalReturnCode_SUCCESS != swResult)
	{
		S16BIT swUnusedResult; // Result of operation or function call.
		swUnusedResult = sitalDevice_Free (swDevice);
		return swResult;
	}



When i define variable swUnusedResult as static, the error disappears.

1
2
3
4
5
6
7
	swResult = device_Reset (swDevice);
	if (sitalReturnCode_SUCCESS != swResult)
	{
		static S16BIT swUnusedResult; // Result of operation or function call.
		swUnusedResult = sitalDevice_Free (swDevice);
		return swResult;
	}


Here i put the stld1553.cpp where sitalDevice_Initialize function is located:
https://github.com/Yonatan1990/BareMetalPseudoCode

1. What does it actually mean? When i define the variable as static what is changing when it comes to stack and memory concept?
2. I have another definition of the same variable in the function [line 5798 in stld1553.cpp]. How it will behave now that it is static?
1
2
3
4
5
6
	if (sitalReturnCode_SUCCESS != swResult)
	{
		S16BIT swUnusedResult; // Result of operation or function call.
		swUnusedResult = sitalDevice_Free (swDevice);
		return swResult;
	}
Last edited on
Topic archived. No new replies allowed.