For Programmers: Free Programming Magazines  


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.
jasen

2006-08-13, 7:01 pm

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.

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com