Main Page | Report this Page
 
   
Linux Forum Index  »  Linux Development - Applications  »  Resuming execution after handling a signal...
Page 1 of 1    
Author Message
Ranjit...
Posted: Sun Aug 31, 2008 10:55 am
Guest
This is the first time and posting a query on Linux programming, so my
apologies in advance if I have posted on the wrong forum.

Question:

I have a function in which I deliberately dereference a NULL pointer
and want my signal handler to fix the error and resume execution. I
have described the problem via the following code snippet.

int goodLocation = 0;
void function()
{
int* b = (int*)0;
*b = 10; <-- Faults the first time, Should run fine the second
time.

}

void error_handler(int sig, siginfo_t* sip, ucontext_t* ucp)
{
if(sig == SIGSEGV)
{
// ucp is the context in which the error occurred.
// Am changing the EAX register of that context so the code does
not dereference a null pointer again.
ucp->uc_mcontext.gregs{REG_EAX] = &goodLocation;

// When execution resumes in "function" the code still
defererences 0 and not the new EAX value that I
// stuffed into it's context.
}

}

What am I doing wrong? Do I need to use setcontext/makecontext to
apply the changes I make to the context? I tried them out to no avail.

Thanks for any advise.
Ranjit
...
Posted: Sun Aug 31, 2008 6:47 pm
Guest
On Aug 31, 4:55 pm, Ranjit <ranjiti... at (no spam) gmail.com> wrote:

Quote:
What am I doing wrong? Do I need to use setcontext/makecontext to
apply the changes I make to the context? I tried them out to no avail.

You initialize 'b' to '(int*)0' every function call, so unless you
change the value in the function definition itself (which should also
give you a segfault) you'll always have a NULL-dereference when you
call 'function'. You need to define it in a way that allows you to
change the value being dereferenced, and changing a register isn't
going to do that.
ta0kira
Paul Pluzhnikov...
Posted: Mon Sep 01, 2008 12:16 am
Guest
Ranjit <ranjitiyer at (no spam) gmail.com> writes:

Quote:
I have a function in which I deliberately dereference a NULL pointer
and want my signal handler to fix the error and resume execution. I
have described the problem via the following code snippet.

int goodLocation = 0;
void function()
{
int* b = (int*)0;
*b = 10; <-- Faults the first time, Should run fine the second

Please wrap your comments, and make them proper comments,
so your code could be cut/pasted and compiled.

Quote:
time.

}

void error_handler(int sig, siginfo_t* sip, ucontext_t* ucp)
{
if(sig == SIGSEGV)
{
// ucp is the context in which the error occurred.
// Am changing the EAX register of that context so the code does
not dereference a null pointer again.
ucp->uc_mcontext.gregs{REG_EAX] = &goodLocation;

Don't retype code when asking questions, *always* copy it verbatim
(above will never compile).

How did you decide that it is the EAX register that must be fixed?
Why not EBX, or ECX?

Quote:

// When execution resumes in "function" the code still
defererences 0 and not the new EAX value that I
// stuffed into it's context.
}

}

What am I doing wrong?

Besides assuming that faulting instruction uses EAX (which may or
may not be the case), you may also have not established error_handler
as SIGSEGV handler properly. Since you didn't supply a complete
example, there is no way to tell.

Quote:
Do I need to use setcontext/makecontext to
apply the changes I make to the context?

Generally no.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Ranjit...
Posted: Mon Sep 01, 2008 7:58 am
Guest
Thanks for the response guys.

Here's the code once in a form that should compile:

#include <signal.h>
#include <ucontext.h>

int goodLocation = 0;
void function()
{
int* b = (int*) 9; // So we can easily look for this value in EAX
*b = 10; // This is where execution resumes again after the signal
handler runs

}

void error_handler(int sig, siginfo_t* sip, ucontext_t* ucp)
{
mcontext_t mctx = ucp->uc_mcontext;
mctx.gregs[EAX] = (greg_t)&goodLocation ;
}

int main(int args, char** argv)
{
struct sigaction new_action;
sigemptyset(&new_action.sa_mask);
new_action.sa_flags = SA_SIGINFO;
new_action.sa_handler = (void(*)(int))error_handler;

sigaction(SIGSEGV, &new_action, NULL);
function();
}
Ranjit...
Posted: Mon Sep 01, 2008 8:00 am
Guest
Sorry it looks like the closing braces of the main got chopped off.
But anyway, it ends right after the call to "function"

int main()
{
...
function();
}

Thanks
Ranjit
Joe Pfeiffer...
Posted: Mon Sep 01, 2008 3:03 pm
Guest
In your signal handler,

void error_handler(int sig, siginfo_t* sip, ucontext_t* ucp)
{
mcontext_t mctx = ucp->uc_mcontext;
mctx.gregs[EAX] = (greg_t)&goodLocation ;
}

the first line is making a copy of the mcontext (mcontext_t is a
struct, not a pointer). So you're changing eax in the copy, not the
actual context. I changed it to

void error_handler(int sig, siginfo_t* sip, ucontext_t* ucp)
{
(ucp->uc_mcontext).gregs[EAX] = (greg_t)&goodLocation ;
}

and it worked fine.

(note: there were some other wrinkles -- in particular, I had use a
#define __USE_GNU
and change EAX to REG_EAX to get it to compile)

So... why are you doing this? Please don't tell us it's so you can
recover from programmer errors...
Paul Pluzhnikov...
Posted: Mon Sep 01, 2008 5:15 pm
Guest
Joe Pfeiffer <pfeiffer at (no spam) cs.nmsu.edu> writes:

Quote:
the first line is making a copy of the mcontext

Right.

Ranjit, please note that you should have cross-posted your question
instead of multi-posting it.

Then you wouldn't have to read essentially the same answer in
multiple groups, and we wouldn't have to supply these answers.

Quote:
#define __USE_GNU

You should *never* use or define any macros that start with double
underscore (these are reserved for implementation), and I am
really surprized this even worked for you (they are all #undef'd
in features.h).

The proper way to get REG_EAX (and __USE_GNU) is to
'#define _GNU_SOURCE'.

Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
Joe Pfeiffer...
Posted: Mon Sep 01, 2008 7:54 pm
Guest
Paul Pluzhnikov <ppluzhnikov-nsp at (no spam) gmail.com> writes:

Quote:
Joe Pfeiffer <pfeiffer at (no spam) cs.nmsu.edu> writes:

the first line is making a copy of the mcontext

Right.

Ranjit, please note that you should have cross-posted your question
instead of multi-posting it.

Then you wouldn't have to read essentially the same answer in
multiple groups, and we wouldn't have to supply these answers.

#define __USE_GNU

You should *never* use or define any macros that start with double
underscore (these are reserved for implementation), and I am
really surprized this even worked for you (they are all #undef'd
in features.h).

The proper way to get REG_EAX (and __USE_GNU) is to
'#define _GNU_SOURCE'.

Thanks (note that Ranjit isn't the guy who did the __USE_GNU, I
was) -- I wasn't aware of that convention.
 
Page 1 of 1       All times are GMT - 5 Hours
The time now is Fri Nov 21, 2008 4:48 pm