Bug 27692 - Configuring with --disable-hidden-plt on x86_64 and arm64 makes built fail
Summary: Configuring with --disable-hidden-plt on x86_64 and arm64 makes built fail
Status: UNCONFIRMED
Alias: None
Product: glibc
Classification: Unclassified
Component: build (show other bugs)
Version: 2.33
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-04-02 17:27 UTC by Robert Henry
Modified: 2022-04-08 21:27 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Henry 2021-04-02 17:27:58 UTC

    
Comment 1 Robert Henry 2021-04-02 17:47:33 UTC
On x86_64, ubuntu 21.04.  Configuring out-of-the-box glibc 2.33 build with --disable-hidden-plt results in a build-time failure (there may be more errors like this)

./sysdeps/x86_64/multiarch/strcat.c:32:1: error: data definition has no type or storage class [-Werror]
   32 | __hidden_ver1 (strcat, __GI_strcat, __redirect_strcat)
      | ^~~~~~~~~~~~~
../sysdeps/x86_64/multiarch/strcat.c:32:1: error: type defaults to ‘int’ in declaration of ‘__hidden_ver1’ [-Werror=implicit-int]
../sysdeps/x86_64/multiarch/strcat.c:33:3: error: parameter names (without types) in function declaration [-Werror]
   33 |   __attribute__ ((visibility ("hidden"))) __attribute_copy__ (strcat);
      |   ^~~~~~~~~~~~~
../sysdeps/x86_64/multiarch/strcat.c:33:3: error: ‘nonnull’ attribute without arguments on a non-prototype
cc1: all warnings being treated as errors


On ARM64, ubuntu 21.04, configuring the same way, results in a similar error at a different location (there may  be more errors; make stopped on first fail)
../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: data definition has no type or storage class [-Werror]
   53 | __hidden_ver1 (__setrlimit64, __GI___setrlimit, __setrlimit64);
      | ^~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: type defaults to ‘int’ in declaration of ‘__hidden_ver1’ [-Werror=implicit-int]
../sysdeps/unix/sysv/linux/setrlimit64.c:53:1: error: parameter names (without types) in function declaration [-Werror]
cc1: all warnings being treated as errors

------------
Is the flag --disable-hidden-plt checked on a regular basis?
Comment 2 H.J. Lu 2021-04-03 13:01:49 UTC
This option was added by

commit 749a9a4fbfd261e2d9811d9bc4507478c2f7cc58
Author: Roland McGrath <roland@gnu.org>
Date:   Tue Oct 1 08:45:44 2002 +0000

    2002-10-01  Roland McGrath  <roland@frob.com>
    
            * config.h.in (NO_HIDDEN): New #undef.
            * include/libc-symbols.h [! NO_HIDDEN]: Add this condition to
            nonempty definitions of hidden_proto et al.
            * configure.in: Grok --disable-hidden-plt to define NO_HIDDEN.
            * configure: Regenerated.
            * sysdeps/mach/hurd/configure.in: Always define NO_HIDDEN.
            * sysdeps/mach/hurd/configure: Regenerated.

I have no idea what it was used for.  I think it should be removed.
Comment 3 Robert Henry 2021-04-03 15:08:05 UTC
I was hoping the flag would make all intra-libc function calls use the same dynamic linkage mechanisms that are used for functions calling into libc.  I would then use LD_PRELOAD mechanisms to wrap (interpose) some functions in libc, and the same mechanisms then intercept both calls into libc as well as calls from within libc.  See https://jayconrod.com/posts/23/tutorial-function-interposition-in-linux

Yes, there's potential for cycles and catastrophe.  I'm interested in mem* and str* functions, which I think would be low risk.
Comment 4 H.J. Lu 2021-04-03 17:40:03 UTC
(In reply to Robert Henry from comment #3)
> I was hoping the flag would make all intra-libc function calls use the same
> dynamic linkage mechanisms that are used for functions calling into libc.  I
> would then use LD_PRELOAD mechanisms to wrap (interpose) some functions in
> libc, and the same mechanisms then intercept both calls into libc as well as
> calls from within libc.  See
> https://jayconrod.com/posts/23/tutorial-function-interposition-in-linux
> 
> Yes, there's potential for cycles and catastrophe.  I'm interested in mem*
> and str* functions, which I think would be low risk.

You can add --disable-multi-arch with --disable-hidden-plt.  But it may not
work.
Comment 5 Robert Henry 2021-04-03 18:45:59 UTC
Adding --disable-multi-arch to the configure invocation, when run on an x86_64, does not show the problem with strcat I initially reported. This is progress, I suppose.

It does then trip up on the same setrlimit issue I saw on arm64.
Comment 6 Robert Henry 2021-04-04 01:45:43 UTC
On x86_64, commenting out line 53 of the commonly-offending file /sysdeps/unix/sysv/linux/setrlimit64.c, and configuring --disable-hidden-plt --disable-multi-arch compiles OK, but when linking build/libc.so fails with many unresolved references to __GI_memset, __GI_memcpy and perhaps more.

On ARM64, commenting out line 53 of setrlimit64.c and configuring --disable-hidden-plt, and both with and without --disable-multi-arch, the link of build/elf/ld.so.new fails:

/usr/bin/ld: /mnt/robhenry/glibc/2.33/build/elf/librtld.os: in function `_dl_start_user':
(.text+0x68): undefined reference to `__GI__dl_argv'
/usr/bin/ld: /mnt/robhenry/glibc/2.33/build/elf/librtld.os: relocation R_AARCH64_ADR_PREL_PG_HI21 against symbol `__GI__dl_argv' which may bind externally can not be used when making a shared object; recompile with -fPIC
(.text+0x68): dangerous relocation: unsupported relocation
/usr/bin/ld: (.text+0x6c): undefined reference to `__GI__dl_argv'
collect2: error: ld returned 1 exit status

Again, my goal is to send all libc-internal (intra-libc) function calls through a PLT.  There's some  troubling commentary about this goal in sysdeps/aarch64/multiarch/memcpy_generic.S which enigmatically says that "It doesn't make sense to send libc-internal memcpy calls through a PLT"
Comment 7 Szabolcs Nagy 2021-04-06 11:15:38 UTC
(In reply to Robert Henry from comment #6)
> Again, my goal is to send all libc-internal (intra-libc) function calls
> through a PLT.  There's some  troubling commentary about this goal in
> sysdeps/aarch64/multiarch/memcpy_generic.S which enigmatically says that "It
> doesn't make sense to send libc-internal memcpy calls through a PLT"

that comment is mainly for performance reasons.

note that calls in the dynamic linker (ld.so) would
still not be interposable (that would create cycles
e.g. during module loading or lazy symbol resolution.
it has its own copy of str*/mem* functions.)

and libc internal calls may assume different (stricter)
interface contract than the public api (which your
interposer does not know about), e.g. memmove may call
memcpy if that handles the overlap case so if you only
interpose memcpy with the usual api contract that can
be an issue (this is not a realistic example since in
such case memmove would just be an alias, not doing plt
calls). there are also problems about what libc calls
are valid to do from a memcpy implementation (even some
as-safe apis may not work if they create a cycle).
Comment 8 Rich Newman 2022-04-08 21:27:13 UTC
This behavior started at version 2.18, 2.17 can be compiled w/ --disable-hidden-plt, but 2.18 and beyond cannot, (at least not without some significant patching.)

See also: 

commit 5e5b3b886635b52d9baa87414b97965190035e46
Author: Stefan Liebler <stli@linux.vnet.ibm.com>
Date:   Mon Jun 19 11:06:49 2017 +0200

and


commit 9ac3b5047e6bbea03437d020fab9a728e123445b
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
Date:   Thu Apr 4 19:43:56 2013 +0530

The problem revolves around use of the __hidden_ver1 macro, which doesn't protect against --disable-hidden-plt, whereas libc_hidden_def does.