Skip site navigation (1)Skip section navigation (2)
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>