|
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 |
|
|
| Back to top |
|
| ... |
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 |
|
|
| Back to top |
|
| 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. |
|
|
| Back to top |
|
| 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();
} |
|
|
| Back to top |
|
| 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 |
|
|
| Back to top |
|
| 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... |
|
|
| Back to top |
|
| 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.
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. |
|
|
| Back to top |
|
| 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. |
|
|
| Back to top |
|
| |