This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Question


Hello,

I am trying to port some more code from windows 2000 to linux.  The specific
functionality I would like to port is called "Structured Exception Handling"
and it works like so:

1.	Define a function which based upons a signal throws an exceptoion.
For example:
	void translateException(unsigned int u, EXCEPTION_POINTERS* pExp)
	{
		switch (u)
		{
		case (unsigned int)0xc0000005:
			throw AccessViolationException(
"SE_Exception::translateException() - u == 0xc0000005",
	
pExp,
	
u );
		break;
		default:
			throw SE_Exception(
"SE_Exception::translateException() - default:",
								pExp,
								u );
		}
	}
	The idea here is that the function translates the windows "signal"
to a user defined exception object.

2.	call the Windows API function
_set_se_translator(translateException).
3.	when a OS trap -- like an access violation -- occurs the specified
function will be called.
4.	From within the body of that function a user defined exception
object (MyAccessViolationException) can be thrown  which can be caught
anywhere in the offending stack frame. e.g.
	try
	{
		int* pNull = 0;
		*pNull = 12;
	}
	catch (MyAccessViolationException& e)
	{
		printf ("success.\n");
	}

I found a related article at http://gcc.gnu.org/java/port-signals.html which
explains how to raise Java exceptions in response to SIGSEGV and such.
Using that I came up with the following example:

void on_accvio(int signo/*, siginfo_t *info, void *ignored*/)
{
	void **_p = (void **)&signo;
	struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p;
	register unsigned long _ebp = _regs->ebp;
	register unsigned long _eip = _regs->eip;
	asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp)" : : "r"(_ebp),
"r"(_eip));
//	register unsigned long _esp = _regs->esp;
//	asm volatile ("mov %0, (%%ebp); mov %1, 4(%%ebp); mov %1, 4(%%esp)"
: : "r"(_ebp), "r"(_eip), "r"(_esp));
	//I am only throwing the true for now
	throw true;
}

struct sigaction sa;
void init()
{
	sigemptyset(&sa.sa_mask);
	sa.sa_handler = on_accvio;
	sa.sa_flags = 0;
	if (sigaction(SIGSEGV, &sa, NULL))
	{
		printf("initlog() : sigaction() failed.\n");
		exit(1);
	}
	return;
}


int main(int argc, char ** argv)
{
	init();
	//start a bunch of threads.  which contain the follwoing code.
	try 
	{
		printf ("[%d]\tEventWaiterThread(%lu)::Run() : Generating an
exception.\n",GetCurrentThreadId(), this);
		int* pNull = 0;
		*pNull = 9;
	}
	catch (bool b)
	{
		printf ("[%d]\tEventWaiterThread(%lu)::Run() : Caught an
exception.\n",GetCurrentThreadId(), this);
	}

...
}

The code works -- sorta.  The exception gets handled fine, however as soon
as the catch occurs, the argument list of the offending method is seriously
messed up.  As you can see from the commented out code, i tried overwritting
the stack register (I guessed it's called %%esp) in the hope of fixing this.
It didn't work.  What should i do?

Any help would be greatly appreciated, as assembly and I are on VERY formal
terms.

Thanks,

Tervel Atanassov


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]