Home > Archive > Unix Programming > August 2006 > Calling dlsym()-ed function causes segfault
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Calling dlsym()-ed function causes segfault
|
|
| nirnimesh@gmail.com 2006-08-12, 7:00 pm |
| I'm intercepting a library function call using LD_PRELOAD and in-turn
calling the orignial library function. Essentially,
intercept.cc:
void (*real_func)(void) = (void (*) (void)) dlsym(RTLD_NEXT,
"_mangled_name_of_func_");
real_func(); //! Calling the original function -- SEGFAULT
This is compiled as:
g++ -shared -fPIC -Wall -o libintercept.so intercept.cc -ldl
When I run it as:
LD_PRELOAD=libintercept.so progname
it leads to a SEGFAULT at the place where real_func() is called. I've
checked to ensure that dlsym() succeeds. In fact, I've also checked
that dladdr() gives the correct function and file name for the resolved
library. The trouble, I guess, is with resolving some things since
things work OK if I replace the call to real_func() with the actual
code implemented in func().
Any leads to what's going wrong?
Machine: FC4-x86_64 with gcc-4.0.0
Regards
Nirnimesh
| |
| Henry Townsend 2006-08-12, 7:00 pm |
| nirnimesh@gmail.com wrote:
> I'm intercepting a library function call using LD_PRELOAD and in-turn
> calling the orignial library function. Essentially,
>
> intercept.cc:
> void (*real_func)(void) = (void (*) (void)) dlsym(RTLD_NEXT,
> "_mangled_name_of_func_");
> real_func(); //! Calling the original function -- SEGFAULT
>
> This is compiled as:
> g++ -shared -fPIC -Wall -o libintercept.so intercept.cc -ldl
>
> When I run it as:
> LD_PRELOAD=libintercept.so progname
> it leads to a SEGFAULT at the place where real_func() is called. I've
> checked to ensure that dlsym() succeeds. In fact, I've also checked
> that dladdr() gives the correct function and file name for the resolved
> library. The trouble, I guess, is with resolving some things since
> things work OK if I replace the call to real_func() with the actual
> code implemented in func().
[Followups trimmed]
Just a couple of thoughts:
1. Have you tested that your code will correctly intercept a non-mangled
symbol? There are plenty of examples on the net for how to intercept
open() or similar. Make sure you have that much working first.
2. You might stick in a couple of printfs using %p to show the address
of the original func, real_func, and what dlsym returns for real_func.
3. Note that if your interposed routine makes use of low-level system
services it's at risk of core dumping anyway. This is because the
LD_PRELOAD-ed library is in front of libc so it runs before libc's
initializers have run. Malloc (or new in C++) is in this category.
Most importantly, boil this down to a simple test case. Odds are this
will help you figure out the problem yourself and if not, posting it
here will dramatically improve your odds.
HT
| |
| nirnimesh@gmail.com 2006-08-12, 7:00 pm |
| > 1. Have you tested that your code will correctly intercept a non-mangled
> symbol? There are plenty of examples on the net for how to intercept
> open() or similar. Make sure you have that much working first.
> 2. You might stick in a couple of printfs using %p to show the address
> of the original func, real_func, and what dlsym returns for real_func.
I'm reproducing my code, with some printf()'s added:
intercept.cc:
void osgUtils::SceneView::setSceneData(osg::N
ode* node)
{
static void (*real_func) (osg::Node*) =
(void (*) (osg::Node*)) dlsym(RTLD_NEXT,
" _ZN7osgUtil9SceneView12setSceneDataEPN3o
sg4NodeE");
printf("real setSceneData: %p\n", real_func);
Dl_info info;
if (dladdr((void*) real_func, &info)==0)
{
perror("dladdr");
exit(1);
}
printf("dli_fname=%s dli_sname=%s\n",
info.dli_fname, info.dli_sname);
(*real_func)(node);
}
Output:
real setSceneData: 0x2aaaab0dd400
dli_fname=/usr/local/lib64/libosgUtil.so
dli_sname=_ZN7osgUtil9SceneView12setScen
eDataEPN3osg4NodeE
Segmentation fault
The orignial shared library's name (/usr/local/lib64/libosgUtil.so) is
correct. Just when I call it however ( real_func(node) ), it segfaults.
> 3. Note that if your interposed routine makes use of low-level system
> services it's at risk of core dumping anyway. This is because the
> LD_PRELOAD-ed library is in front of libc so it runs before libc's
> initializers have run. Malloc (or new in C++) is in this category.
I thought so too, but that's not the case, since when I copy paste the
code from the real setSceneData(), it works.
Any clues?
Regards,
Nirnimesh
| |
| Paul Pluzhnikov 2006-08-13, 4:00 am |
| nirnimesh@gmail.com writes:
> intercept.cc:
> void osgUtils::SceneView::setSceneData(osg::N
ode* node)
Since (AFAICT) setSceneData() is a *non-static* member function,
it is passed *two* parameters (the hidden "this" and the "node").
Here:
> (*real_func)(node);
you invoke the "real" libosgUtil.so`osgUtils::SceneView::setSceneData()
and you pass "node" for "this", and garbage for "node".
Once you fix the casts, the call should be:
(*real_func)(this, node);
> Output:
> real setSceneData: 0x2aaaab0dd400
> dli_fname=/usr/local/lib64/libosgUtil.so
> dli_sname=_ZN7osgUtil9SceneView12setScen
eDataEPN3osg4NodeE
> Segmentation fault
Is entirely expected: garbage in, garbage out.
> Any clues?
Read-up on C++ calling conventions.
Cheers,
--
In order to understand recursion you must first understand recursion.
Remove /-nsp/ for email.
| |
|
| On 2006-08-12, nirnimesh@gmail.com <nirnimesh@gmail.com> wrote:
> Output:
> real setSceneData: 0x2aaaab0dd400
> dli_fname=/usr/local/lib64/libosgUtil.so
> dli_sname=_ZN7osgUtil9SceneView12setScen
eDataEPN3osg4NodeE
> Segmentation fault
>
> The orignial shared library's name (/usr/local/lib64/libosgUtil.so) is
> correct. Just when I call it however ( real_func(node) ), it segfaults.
where does it segfault ?
>
> I thought so too, but that's not the case, since when I copy paste the
> code from the real setSceneData(), it works.
>
> Any clues?
try gdb
after running it to the segfault repeated use of the up command will give you
a stack trace.
Bye.
Jasen
| |
| Nirnimesh 2006-08-13, 7:01 pm |
|
> Since (AFAICT) setSceneData() is a *non-static* member function,
> it is passed *two* parameters (the hidden "this" and the "node").
>
> Here:
>
>
> you invoke the "real" libosgUtil.so`osgUtils::SceneView::setSceneData()
> and you pass "node" for "this", and garbage for "node".
>
> Once you fix the casts, the call should be:
>
> (*real_func)(this, node);
With the cast fix, it works. Thanks Paul.
|
|
|
|
|