Date: Tue, 19 May 1998 19:28:50 +1000 From: Stephen McKay <syssgm@dtir.qld.gov.au> To: Terry Lambert <tlambert@primenet.com> Cc: freebsd-current@FreeBSD.ORG, syssgm@dtir.qld.gov.au Subject: Re: Fix for undefined "__error" and discussion of shared object versioning Message-ID: <199805190928.TAA10958@troll.dtir.qld.gov.au> In-Reply-To: <199805181843.LAA09263@usr01.primenet.com> from Terry Lambert at "Mon, 18 May 1998 18:43:57 %2B0000" References: <199805181843.LAA09263@usr01.primenet.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Monday, 18th May 1998, Terry Lambert wrote: >> I tried a number of variants of this approach and could not make any of >> them work. In all cases (well, all that compiled at all), the local >> hack ___error() was used in preference to the system supplied __error(). >> Otherwise, this would be a good hack, costing only 12 bytes per .o file. > >Use this one instead: > >----------------------------------------------------------------------- >#ifndef __GNUC__ >#ifndef _ERRNO_C_ >static int *___error( void) { extern int errno; return &errno; } >#pragma weak __error = ___error >#endif /* _ERRNO_C_*/ >#endif /* __GNUC__*/ >extern int * __error __P((void)); >#define errno (* __error()) >----------------------------------------------------------------------- > >This works *IF* libc and libc_r are compiled with -D_ERRNO_C_. I still don't think this works. I'm not testing this live, I'm faking up test cases. Assume I changed #ifndef __GNUC__ to #ifdef __GNUC__ already. I've renamed stuff to show the principle not working more easily: === main.c === int fake_errno = 100; main() { int x; x = wibble(); printf("%d\n", x); return 0; } int real_errno = 200; int *real_error() { return &real_errno; } === sub.c === #include <sys/cdefs.h> #ifdef __GNUC__ #ifndef _ERRNO_C_ static int *fake_error(void) { extern int fake_errno; return &fake_errno; } #pragma weak real_error = fake_error #endif /* _ERRNO_C_*/ #endif /* __GNUC__*/ extern int * real_error __P((void)); #define errno (* real_error()) wibble() { return errno; } ====== This should print 200 if the fix works, but prints 100. Even when I built a mini shared library with real_error() in it, the output was still 100. real_error() was executed as expected when the #pragma was removed, but that doesn't help much. :-) >An ld.so hack is precisely the wrong thing to do; it results in an >infinite recursion on the first error set which happens (which is >usually when Poul's malloc() code calls readlink() for /etc/malloc.conf >and gets an error when it's not a symlink when you link with libc_r). So, it will have to be a better hack and supply __error() internally. >> In my view, the least pleasant option is to bump all major library >> numbers. > >It is, however, the correct one, I've decided, working on getting >this hack to actually work. It would be a big pain though. Could we wait for ELF instead? >The versioning needs major, minor, and subminor. I don't see how your major/minor/subminor is any better than the current major/minor, or how it would avoid the current problem. The current problem is due to replacing a global integer with a function. Replacing one function with another would have been simple. The lesson here is to have no global variables! >There is also a weakness in ld.so; specifically, ld.so, being a shared >object, should also be versioned (Sun does this). This would have let >use "fix" the problem in ld.so by stepping it with libc.so and libc_r.so. Can't we still fix it in ld.so? A new ld.so with the new libc.so should be able to fiddle anything. Stephen. To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199805190928.TAA10958>