This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Question
- To: "'gcc at gcc dot gnu dot org'" <gcc at gcc dot gnu dot org>
- Subject: Question
- From: "Tervel Atanassov (Anaheim)" <TAtanassov at printrak dot com>
- Date: Mon, 9 Jul 2001 17:01:39 -0700
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