This is the mail archive of the libc-alpha@cygnus.com 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]

Bug in dlsym() (scope problem(?) & RTLD_NEXT problem)


>Submitter-Id:	net
>Originator:	Kars de Jong
>Organization:  none
>Confidential:	no
>Synopsis:	A bug in dlsym() causes it to lookup the wrong symbol.
>Severity:	serious
>Priority:      high
>Category:	libc
>Class:		sw-bug
>Release:	libc-2.0.96
>Environment:

Host type: m68k-unknown-linux-gnu
System: Linux rincewind 2.1.120 #9 Wed Sep 30 23:48:01 CEST 1998 m68k unknown
Architecture: m68k

Addons: crypt linuxthreads
Build CFLAGS: -pipe -O2 -m68060
Build CC: egcs
Compiler version: egcs-2.91.57 19980901 (egcs-1.1 release)
Kernel headers: 2.1.120
Symbol versioning: yes
Build static: yes
Build shared: yes
Build pic-default: no
Build profile: no
Build omitfp: no
Build bounded: no
Build static-nss: no
Stdio: libio

>Description:
	When using dlsym() to lookup a symbol in a shared object from (at
	least) another shared object it fails to give the correct symbol when
	the symbol is defined in the calling shared object as well. Example:
	The JDK 1.1.5 opens libc.so.6 from a shared object (libjava.so). Then
	it wants to store the symbols of a number of functions to make them
	thread-safe with their green_threads package. To this end it opens
	libc.so.6, then does a dlsym(libc6handle, "write"). This however
	returns a pointer to the write function as defined in libjava.so!
	With previous releases, using dlsym(RTLD_NEXT, "write") doesn't work
	either. It also returns the symbol from the calling shared object
	instead of the C-library (as is what happens under Solaris).
>How-To-Repeat:
	file bing.c:
	#include <dlfcn.h>
	#include <stdio.h>

	#define HOW_DLOPEN 0
	#define HOW_RTLD_NEXT 1

	int write(int fd, const void *buf, size_t size) {
		return 0;
	}

	void setup_table(int how) {
		void *sym = NULL;

		if (how == HOW_DLOPEN) {
			void *handle = NULL;

			handle = dlopen("libc.so.6", RTLD_LAZY);
			if (!handle)
				return;
			sym = dlsym(handle, "write");
			fprintf(stderr, "DLOPEN: %p should not equal %p...\n",
				write, sym);
			dlcose(handle);
 		} else /* how == HOW_RTLD_NEXT */ {
			sym = dlsym(RTLD_NEXT, "write");
			fprintf(stderr, "RTLD_NEXT: %p should not equal "
				"%p...\n", write, sym);
		}
	}
	file dltest.c:
	extern void setup_table(int how);

	#define HOW_DLOPEN 0
	#define HOW_RTLD_NEXT 1

	int main() {
		setup_table(HOW_DLOPEN);
		setup_table(HOW_RTLD_NEXT);
		return 0;
	}
	Compile & run:
	gcc -fPIC -O -g -shared -o bing.so bing.c
	gcc -O -g -o dltest dltest.c bing.so -ldl -Wl,-rpath -Wl,.
	./dltest
	The 2 printed pointers should not be the same. They are, however, for
	both methods. I tested this on a i586-pc-linux-gnu platform too.
Fix:
	Nope, sorry. It might be due to the fact that write is a weak symbol
	in the C library. It would be best to use RTLD_NEXT anyway, to
	avoid version problems. But since that's broken as well...
--
------------------------------------------------------------------------------
Kars de Jong             Signaalkamp rules the waves!       Turrican@Discworld
--------======]**-----|      jongk@cs.utwente.nl      |-----**[======---------


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