Stack issues

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
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Stack issues

Post by pcmattman »

I have a working stack setup in my kernel thread generation code, that pushes a return address onto the stack that points to a 'die()' function to delete the process when it returns. The problem is, I can't have anything on the stack between the process entry point and the 'die()' entry point. I wrote this to push the arguments onto the stack:

Code: Select all

	// start the va_list
	va_list pushargs;
	va_start( pushargs, arglist );
	
	// parse it
	i = 0;
	while( arglist[i] != 0 )
	{
		if( arglist[i] == '%' )
		{
			// get each part of it
			if( arglist[i+1] == 'd' )
			{
				// decimal (int)
				i += 2;
				int val = va_arg( pushargs, int );
				*esp-- = val;
			}
			else if( arglist[i+1] == 'u' )
			{
				// unsigned (look at next char)
				if( arglist[i+2] == 'd' )
				{
					// unsigned int
					i += 3;
					unsigned int val = va_arg( pushargs, unsigned int );
					*esp-- = val;
				}
				else
				{
					i++;
				}
			}
			else if( arglist[i+1] == 's' )
			{
				// string pointer (always char*)
				i += 2;
				char* val = va_arg( pushargs, char* );
				*esp-- = (unsigned int) val;
			}
			else
			{
				// unknown format specifier
				i++;
			}
		}
	}
	
	// all done
	va_end( pushargs );
It works, processes spawned can read the arguments and use them etc...

But they can't return without crashing, because, I think, they are trying to return to an address that is pushed by the above code. The main reason, I think, is that C doesn't pop arguments off the stack when it handles them, that's the job of the caller. In that case, how do I pop the arguments off the stack?

I tried this, to sum up the size of all the arguments and add that value to ESP:

Code: Select all

unsigned int stacksize = sizeof( arg1 ) + sizeof( arg2 ) + sizeof( unsigned int );
__asm__ __volatile__ ( "addl %0,%%esp" : : "r" (stacksize) );
It didn't work.
senaus
Member
Member
Posts: 66
Joined: Sun Oct 22, 2006 5:31 am
Location: Oxford, UK
Contact:

Post by senaus »

Do you push the entry point into die() after the arguments or before? By C calling convention, it should be pushed afterwards - this is the return address.

That way, your process's 'main()' or equivalent will pop the entry point to 'die()' and return to that.

Also, is the die() routine in kernel mode or user mode?

Cheers,
Senaus

Code: Select all

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M/MU d- s:- a--- C++++ UL P L++ E--- W+++ N+ w++ M- V+ PS+ Y+ PE- PGP t-- 5- X R- tv b DI-- D+ G e h! r++ y+
------END GEEK CODE BLOCK------
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

I honestly completely forgot that the return address goes first on the stack...
senaus
Member
Member
Posts: 66
Joined: Sun Oct 22, 2006 5:31 am
Location: Oxford, UK
Contact:

Post by senaus »

Aaaah, so is it working now?

Code: Select all

-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/M/MU d- s:- a--- C++++ UL P L++ E--- W+++ N+ w++ M- V+ PS+ Y+ PE- PGP t-- 5- X R- tv b DI-- D+ G e h! r++ y+
------END GEEK CODE BLOCK------
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Post by pcmattman »

Yes.

I also forgot a(nother) very important thing: arguments must be pushed in reverse...
Post Reply