bug-gnulib
[Top][All Lists]
Advanced

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

Re: overriding glibc stub functions


From: Bruno Haible
Subject: Re: overriding glibc stub functions
Date: Mon, 24 Feb 2020 03:27:43 +0100
User-agent: KMail/5.1.3 (Linux/4.4.0-171-generic; KDE/5.18.0; x86_64; ; )

Paul Eggert wrote:
> On 2/23/20 2:58 AM, Bruno Haible wrote:
> > the file doc/glibc-functions/lchmod.texi still says
> > 
> >    ...
> >    This function always fails with @code{errno} set to @code{ENOSYS},
> >    even when the file is not a symbolic link:
> >    GNU/Linux with glibc 2.31.
> > 
> > Overriding the system's lchmod function requires the case REPLACE_LCHMOD=1.
> 
> Hmm, why? 'configure' says that GNU/Linux functions that always fail with 
> errno==ENOSYS do not exist, i.e., 'configure' sets HAVE_LCHMOD=0 on 
> GNU/Linux. 
> This convention is used often by Autoconf and Gnulib. And if HAVE_LCHMOD=0 
> why 
> would we want REPLACE_LCHMOD=1?

Ouch. I had completely forgotten about this.

Yes, lchmod is defined as a stub in glibc/Linux:

$ nm --dynamic /lib/x86_64-linux-gnu/libc.so.6 | grep lchmod
00000000000f6f40 T lchmod
$ grep lchmod /usr/include/x86_64-linux-gnu/gnu/stubs-64.h
#define __stub_lchmod

And, as you say, this leads to HAVE_LCHMOD=0.

But why do we to distinguish 'lchmod' and 'rpl_lchmod' when we are overriding
lchmod? For three reasons:

  1) So that there is no conflict when linking statically.

  2) So that the behaviour is reliable, and does not break when '-lc' occurs
     in the link command line (or as dependency of other shared libraries on
     the link command line).

  3) So that when debugging with gdb, you know where you are.

Test case for 1):

$ gcc -Wall -O2 -c main.c
$ gcc -Wall -O2 -c lib.c
$ gcc -static main.c lib.c -o main1
$ gcc -static main.c lib.c -lc -o main2
$ gcc -static main.c -lc lib.c -o main3
/tmp/ccPmrK5B.o: In function `main':
main.c:(.text+0x1a): warning: lchmod is not implemented and will always fail
/tmp/ccJXO5KR.o: In function `lchmod':
lib.c:(.text+0x0): multiple definition of `lchmod'
/usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/libc.a(lchmod.o):(.text+0x0):
 first defined here
collect2: error: ld returned 1 exit status

Test case for 2):

$ gcc -Wall -O2 -c main.c
$ gcc -Wall -O2 -fPIC -c lib.c
$ gcc -shared -o libfoo.so lib.o
$ gcc main.c -o main1
$ gcc main.c -L. -lfoo -o main2
$ gcc main.c -L. -lc -lfoo -o main3
$ touch foo
$ ./main1  =>  lchmod -> -1
$ LD_LIBRARY_PATH=. ./main2  =>  lchmod -> 0
$ LD_LIBRARY_PATH=. ./main3  =>  lchmod -> -1

(main.c and lib.c are attached below.)

3) is relatively unimportant, but
* 1) is important if we don't want to receive bug reports from people who
     do embedded systems (OpenWRT and such), and
* 2) is important for projects that use gnulib in shared libraries
     (from gettext to guile) and don't use the [expensive] renaming of
     symbols in the shared library. (For example, in libunistring,
     lchmod would be renamed to libunistring_lchmod, thus eliminating
     the conflict. But not all libraries do this.)

Therefore I think we need to do two things:

  * For those functions that may be stubs in glibc, define HAVE_FUNC to 1
    instead of 0 if glibc implements it as a stub.
  * Reinstall (at least partially) the code for REPLACE_LCHMOD=1.

Bruno

=================================== main.c ===================================
#include <stdio.h>
#include <sys/stat.h>

int
main (int argc, char *argv[])
{
  int ret = lchmod ("foo", 0444);
  printf ("lchmod -> %d\n", ret);
}

=================================== lib.c ===================================
#include <sys/stat.h>

/* This function is intended to override the libc function.  */
int
lchmod (const char *file, mode_t mode)
{
  return chmod (file, mode);
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]