This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

dlfcn.h dlopen() problem


Hello,

I might have found a bug in glibc.

On my Ubuntu64 server I have glibc 2.17 (see attached libc.version)
and gcc 4.7.3.

In dlfcn.h I have this definition of dlopen():
/* Open the shared object FILE and map it in; return a handle that can be
   passed to `dlsym' to get symbol values from it.  */
extern void *dlopen (const char *__file, int __mode) __THROW;

I have a small test case with a static variable and a call to dlopen()
or a similar function: see attached main.c.

When I compile with the given Makefile
cc -O2 -Wall -Wextra -save-temps -S -o main.s main.c
the generated assembly code (attached main.s) does not contain the
assignment "var=3;" anymore.  I think it is a bug: the assignment
"var=3" should be done, because in the .so if there are constructors
(functions called at dlopen() time) they might use "var" indirectly
via the function increase_var().  And that's what is currently
happening to me (in a more complex case): I have a constructor that
actually needs some "var" to be set to 3.

Now why is this assignment removed by the compiler?

If in call_external_function() I call my_external_function() instead
of dlopen(), the problem remains, except if I remove the __THROW
attribute in which case "var" is assigned 3, then the funcall is done,
then "var" is assigned to 0.

According to cc -O2 -save-temps file.c (look at the generated .i),
__THROW means:
__attribute__((nothrow, leaf))

Maybe it is the "leaf" attribute that allows gcc to remove the
"var=3;" assignment?  See
http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Maybe dlopen() should not be marked as "leaf".  What do you think?

Thanks!

Best regards
Fabrice

Attachment: libc.version
Description: Binary data

#include <dlfcn.h>              /* dlopen ().  */

extern void *my_external_function (const char *__file, int __mode) __THROW;

static int var = 0;

int
increase_var (void)
{
  return ++var;
}

void
call_external_function (void)
{
  var = 3;
  dlopen ("hello", RTLD_NOW);
  var = 0;
}

Attachment: main.s
Description: Binary data

Attachment: Makefile
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]