[Stack Cleanup] returning a C struct from assembly

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
User avatar
Neroku
Posts: 24
Joined: Tue Dec 01, 2015 4:53 am

[Stack Cleanup] returning a C struct from assembly

Post by Neroku »

Hello,

I've been having a look at the assembly code GCC generates when it finds a call to function that is supposed to return a C struct:

Code: Select all

struct st_foo function(void);
struct st_foo foo;

foo = function();
Before the function call, the caller pushes on the stack the address of the struct the return value will be assigned to. This pushed address is then used by the callee, so that it writes the return value at this address.

So far, so good. My question comes up when I observe how the stack is cleaned up:
The callee cleans up the stack by providing assembly instruction ret with an immediate operand which specifies the numbers of bytes to be removed from the stack before returning. However, I expected the caller to clean up the stack, not the callee.

Isn't GCC using the cdecl calling convention?
Isn't then the callee the one responsilbe for cleaning up the stack?
What wrong assumption am I making?

Thanks in advance
Last edited by Neroku on Mon May 30, 2016 12:17 am, edited 2 times in total.
currently working on kboot86, the Genesis of my kernel
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: [Stack Cleanup] returning a C struct from assembly

Post by bluemoon »

A quote from wiki: https://en.wikipedia.org/wiki/X86_calling_conventions
There are some variations in the interpretation of cdecl,[2] particularly in how to return values. As a result, x86 programs compiled for different operating system platforms and/or by different compilers can be incompatible, even if they both use the "cdecl" convention and do not call out to the underlying environment. Some compilers return simple data structures with a length of 2 registers or less in the register pair EAX:EDX, and larger structures and class objects requiring special treatment by the exception handler (e.g., a defined constructor, destructor, or assignment) are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning.
User avatar
Neroku
Posts: 24
Joined: Tue Dec 01, 2015 4:53 am

Re: [Stack Cleanup] returning a C struct from assembly

Post by Neroku »

bluemoon wrote:A quote from wiki: https://en.wikipedia.org/wiki/X86_calling_conventions
There are some variations in the interpretation of cdecl,[2] particularly in how to return values. As a result, x86 programs compiled for different operating system platforms and/or by different compilers can be incompatible, even if they both use the "cdecl" convention and do not call out to the underlying environment. Some compilers return simple data structures with a length of 2 registers or less in the register pair EAX:EDX, and larger structures and class objects requiring special treatment by the exception handler (e.g., a defined constructor, destructor, or assignment) are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning.
Is there then any way to ensure that a future GCC version will not break the current behavior?
currently working on kboot86, the Genesis of my kernel
User avatar
bluemoon
Member
Member
Posts: 1761
Joined: Wed Dec 01, 2010 3:41 am
Location: Hong Kong

Re: [Stack Cleanup] returning a C struct from assembly

Post by bluemoon »

I can't speak for the GCC community but in general there is no guarantee in future.

That's why people suggest to build your own toolchain, such that you can fallback to "tested version" if any future changes break your build.
User avatar
Velko
Member
Member
Posts: 153
Joined: Fri Oct 03, 2008 4:13 am
Location: Ogre, Latvia, EU

Re: [Stack Cleanup] returning a C struct from assembly

Post by Velko »

Neroku wrote:Is there then any way to ensure that a future GCC version will not break the current behavior?
By doing it "manually"?

Code: Select all

void function(struct st_foo *foo);
struct st_foo foo;

function(&foo);
If something looks overcomplicated, most likely it is.
User avatar
Neroku
Posts: 24
Joined: Tue Dec 01, 2015 4:53 am

Re: [Stack Cleanup] returning a C struct from assembly

Post by Neroku »

Velko wrote:
Neroku wrote:Is there then any way to ensure that a future GCC version will not break the current behavior?
By doing it "manually"?

Code: Select all

void function(struct st_foo *foo);
struct st_foo foo;

function(&foo);
Yes, this should do the trick. I have to change the function prototype, though.

Thanks.
currently working on kboot86, the Genesis of my kernel
Post Reply