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>
