[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Upgrade to libnewt-dev 0.50-6 fixes library reduction problem (glibc bug?)



Hi,

It turns out the undefined fstat symbol problem can be traced to
something going wrong with earlier build of newt.  As you can see,
libnewt.so was providing the fstat symbol:

dhd@doppelbock:/home/scsi/dhd/src/debian/boot-floppies/utilities/dbootstrap$ objdump --dynamic-syms /usr/lib/libnewt.so | grep fstat
0000000000018860  w   DF .text  0000000000000000  Base        0x88 fstat
0000000000018860 g    DF .text  0000000000000038  Base        0x88 __fstat

dhd@elgin:~$ objdump --dynamic-syms /usr/lib/libnewt.so | grep fstat
0000f14c  w   DF .text  00000028  Base        fstat
0000f14c g    DF .text  00000028  Base        __fstat

That version of libnewt0 will break library reduction if you compile
dbootstrap against it, because:

1) libloadtrm.a is compiled without -O and thus depends on fstat
   (fstat is inlined).
2) dbootstrap inherits an undefined fstat symbol from libloadtrm.a
   (which is also not compiled with -O)
3) The reduced version of libnewt.so that ends up on the root.bin disk
   doesn't provide the symbol (as well it shouldn't :P).
4) libc.so.6.1 doesn't provide fstat either.

This may be indicative of a bug in glibc or gcc (take your pick,
they're all broken at one point or another it seems...) - the
changelog indicates that libnewt0 was never compiled with optimization
before 0.50-6.

Specifically it seems that if you have a program that uses fstat() and
is compiled without optimization, that links with a library that uses
fstat() and was compiled without optimization, and then the library is
recompiled with optimization, the aforementioned program will no
longer work.

Here's a demonstration:

/* begin fstattest.c */
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
	int fd;
	struct stat buf;

	fd = open("foobar", O_RDWR | O_CREAT, 0644);
	if (fd < 0) {
		perror("foobar");
		return 1;
	}
	mystat(fd, &buf);
	fstat(fd, &buf);
	return 0;
}
/* end fstattest.c */

/* begin libfstattest.c */
#include <sys/stat.h>

int mystat(int fd, struct stat * buf)
{
	return fstat(fd, buf);
}
/* end libfstattest.c

Now, observe:

$ gcc -shared -o libfstattest.so libfstattest.c 
$ objdump --dynamic-syms libfstattest.so | grep fstat 
libfstattest.so:     file format elf32-i386
000007b4  w   DF .text  00000028  Base        fstat
000007b4 g    DF .text  00000028  Base        __fstat
$ gcc -o fstattest fstattest.c -L. -Wl,-rpath -Wl,`pwd` -lfstattest 
$ nm fstattest | grep fstat 
         U fstat
$ ./fstattest 
$ gcc -shared -o libfstattest.so -O libfstattest.c 
$ objdump --dynamic-syms libfstattest.so | grep fstat 
libfstattest.so:     file format elf32-i386
$ ./fstattest 
./fstattest: error in loading shared libraries: ./fstattest: undefined symbol: fstat

-- 
David Huggins-Daines, Senior Linux Consultant, Linuxcare, Inc.
613.562.1239 desk, 613.223.0225 mobile dhd@linuxcare.com,
http://www.linuxcare.com/
Linuxcare. Support for the revolution.


Reply to: