On 05/18/2014 01:11 PM, Cedric Roux wrote:
On 05/18/2014 12:57 PM, Cedric Roux wrote:
but this is really strange that the tap .so
files
are not linked against the libm.
okay, I downloaded KXStudio_14.04b_64bit.iso and indeed
all the /usr/lib/ladspa/tap_*.so in it are *not* linked against
the libm.
The official tap plugins Makefile for 0.7.2 has the -lm thing.
You should send a bug report to the kxstudio team. It looks like
a bug to me.
and to continue a bit on the subject, there is a very funny and weird
behavior with dlopen(plugpath, RTLD_LAZY);
I tried with tap_rotspeak.so.
Let me extract the funky behavior for the completeness of this email.
Let's write tap.c, which does something similar to tap_rotspeak in its
_init and _fini functions.
<< EOF
#include <stdlib.h>
#include <math.h>
/* in the plugin, a is a struct and b in inside a
* and may have whatever value after the malloc of a
* to simulate this, we set b to 1 (we want a crash!)
*/
float *a;
float *b = (float *)1;
/* dlopen will call _init before it returns to the caller */
void _init()
{
int i;
float table[10];
a = malloc(10*sizeof(float)); if (!a) abort();
/* we never link with -lm, so cos fails and dlopen somehow
* "aborts" _init at this point and right after calls _fini
* (I didn't check the details in dlopen)
*/
for (i = 0; i < 10; i++) table[i] = cos(i);
a[0] = table[0]; /* gcc shut up */
/* this is never reached */
b = malloc(10*sizeof(float*)); if (!b) abort();
}
/* so this function is also called by dlopen because _init
* called "cos" and we didn't link against libm
*/
void _fini()
{
if (!a) return;
/* we come here because a is not 0, it was malloc'd */
/* but b was not, so guess what happens... */
free(b);
free(a);
}
EOF
And here comes my-bug.c
<< EOF
#include <stdio.h>
#include <dlfcn.h>
int main (int argc, char ** argv)
{
char plugpath [] = "./tap.so";
void * pvPluginHandle = dlopen(plugpath, RTLD_LAZY);
if (pvPluginHandle) dlclose (pvPluginHandle);
else printf ("dlopen failed: %s (dlerror: %s)\n",
plugpath, dlerror());
printf("dlerror? %s\n", dlerror());
return 0;
}
EOF
compile with:
gcc -nostartfiles -shared -fPIC tap.c -o tap.so -Wall -g
gcc -Wall -o my-bug my-bug.c -ldl -g
and have fun.
Here is a backtrace in gdb:
Program received signal SIGSEGV, Segmentation fault.
__GI___libc_free (mem=0x1) at malloc.c:2891
2891 malloc.c: No such file or directory.
(gdb) bt
#0 __GI___libc_free (mem=0x1) at malloc.c:2891
#1 0x00007ffff762e566 in _fini () at tap.c:23
#2 0x00007ffff7df0739 in _dl_close_worker (map=<optimized out>)
at dl-close.c:277
#3 0x00007ffff7def42e in _dl_open (file=0x7fffffffe450 "./tap.so",
mode=<optimized out>, caller_dlopen=<optimized out>,
nsid=<optimized out>,
argc=1, argv=0x7fffffffe558, env=0x7fffffffe568) at dl-open.c:686
#4 0x00007ffff7bda02b in dlopen_doit (a=a@entry=0x7fffffffe410) at
dlopen.c:66
#5 0x00007ffff7deb7c4 in _dl_catch_error (
objname=0x7ffff7ddc0f0 <last_result+16>,
errstring=0x7ffff7ddc0f8 <last_result+24>,
mallocedp=0x7ffff7ddc0e8 <last_result+8>,
operate=0x7ffff7bd9fd0 <dlopen_doit>, args=0x7fffffffe410) at
dl-error.c:177
#6 0x00007ffff7bda5dd in _dlerror_run (
operate=operate@entry=0x7ffff7bd9fd0 <dlopen_doit>,
args=args@entry=0x7fffffffe410) at dlerror.c:163
#7 0x00007ffff7bda0c1 in __dlopen (file=<optimized out>,
mode=<optimized out>)
at dlopen.c:87
#8 0x00000000004006cf in main (argc=1, argv=0x7fffffffe558) at my-bug.c:6
It looks very similar to the one of Nikita:
(gdb) backtrace
#0 0x00007ffff762f425 in __GI_raise (sig=<optimized out>) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1 0x00007ffff7632b8b in __GI_abort () at abort.c:91
#2 0x00007ffff766d39e in __libc_message (do_abort=2, fmt=0x7ffff7777748
"*** glibc detected *** %s: %s: 0x%s ***\n") at
../sysdeps/unix/sysv/linux/libc_fatal.c:201
#3 0x00007ffff7677b96 in malloc_printerr (action=3, str=0x7ffff77778a8
"double free or corruption (out)", ptr=<optimized out>) at malloc.c:5039
#4 0x00007ffff61b3957 in delete_descriptor () from
/usr/lib/ladspa/tap_reflector.so
#5 0x00007ffff7dee70e in _dl_close_worker (map=<optimized out>) at
dl-close.c:273
#6 0x00007ffff7ded3b4 in _dl_open (file=0x6217e0
"/usr/lib/ladspa/tap_reflector.so", mode=<optimized out>,
caller_dlopen=0x400c3e, nsid=<optimized out>, argc=1, argv=<optimized
out>, env=0x7fffffffd998) at dl-open.c:664
#7 0x00007ffff7bd6f26 in dlopen_doit (a=0x7fffffffd7b0) at dlopen.c:67
#8 0x00007ffff7de9176 in _dl_catch_error (objname=0x60b0b0,
errstring=0x60b0b8, mallocedp=0x60b0a8, operate=0x7ffff7bd6ec0
<dlopen_doit>, args=0x7fffffffd7b0) at dl-error.c:178
#9 0x00007ffff7bd752f in _dlerror_run (operate=0x7ffff7bd6ec0
<dlopen_doit>, args=0x7fffffffd7b0) at dlerror.c:164
#10 0x00007ffff7bd6fc1 in __dlopen (file=<optimized out>,
mode=<optimized out>) at dlopen.c:88
#11 0x0000000000400c3e in LADSPADirectoryPluginSearch
(pcDirectory=0x603040 "/usr/lib/ladspa", fCallbackFunction=0x400a5c
<describePluginLibrary>) at ladspa/search.c:64
#12 0x0000000000400db9 in LADSPAPluginSearch (fCallbackFunction=0x400a5c
<describePluginLibrary>) at ladspa/search.c:118
#13 0x0000000000400afd in main (argc=1, argv=0x7fffffffd988) at main.c:32
It would be possible to modify the tap plugins to avoid such behaviors.
Simply be sure in the _init to set every pointer to 0 at beginning or
just after a malloc of a struct. And test against 0 in the _fini before
any call to free.
But the libm should have been linked against the plugin in the first
place, so...
Another solution is to use RTLD_NOW, which might be problematic.
Anyway, so be it. Sorry for the noise and have a nice sunday!
And plugin writers, be very careful with your _init/_fini stuff...