public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
@ 2020-03-16  4:58 Fangrui Song
  2020-03-16  5:02 ` Fangrui Song
  0 siblings, 1 reply; 10+ messages in thread
From: Fangrui Song @ 2020-03-16  4:58 UTC (permalink / raw)
  To: binutils; +Cc: Florian Weimer, libc-alpha

cd /tmp/p
git clone git://sourceware.org/git/glibc.git; cd glibc
mkdir Release; ../configure --prefix=/tmp/opt
make -j

When linking elf/librtld.map.o

% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o -Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0 -Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0 -Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-(' /tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT

Without -Wl,defsym:

dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
__libc_scratch_buffer_set_array_size fetches libc_pic.a(scratch_buffer_set_array_size.os)
libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
free fetches libc_pic.a(malloc.os)
libc_pic.a(malloc.os) has an undefined __libc_message
__libc_message fetches libc_pic.a(libc_fatal.os)

libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
>>> defined at dl-fxstatat64.c
>>>            /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
>>> defined at libc_fatal.c
>>>            libc_fatal.os:(.text+0x240) in archive /tmp/p/glibc/Release/libc_pic.a

glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress libc_pic.a(malloc.os):

% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
    712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail_local
    826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
    876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail
    905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
    975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
   1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free

My question is: does the suppression via --defsym work reliably?

# a.o
call foo

# b.a(b.o)
.globl foo, free
foo:
free:


# GNU ld --defsym is order dependent.
ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent

# gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to match GNU ld.
gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent

# lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
# https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is required to bypass a configure check
ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16  4:58 Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o) Fangrui Song
@ 2020-03-16  5:02 ` Fangrui Song
  2020-03-16 11:27   ` H.J. Lu
  0 siblings, 1 reply; 10+ messages in thread
From: Fangrui Song @ 2020-03-16  5:02 UTC (permalink / raw)
  To: binutils; +Cc: Florian Weimer, libc-alpha

On 2020-03-15, Fangrui Song wrote:
>cd /tmp/p
>git clone git://sourceware.org/git/glibc.git; cd glibc
>mkdir Release; ../configure --prefix=/tmp/opt
>make -j
>
>When linking elf/librtld.map.o
>
>% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o -Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0 -Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0 -Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-(' /tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
>
>Without -Wl,defsym:
>
>dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
>__libc_scratch_buffer_set_array_size fetches libc_pic.a(scratch_buffer_set_array_size.os)
>libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
>free fetches libc_pic.a(malloc.os)
>libc_pic.a(malloc.os) has an undefined __libc_message
>__libc_message fetches libc_pic.a(libc_fatal.os)
>
>libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
>>>>defined at dl-fxstatat64.c
>>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
>>>>defined at libc_fatal.c
>>>>           libc_fatal.os:(.text+0x240) in archive /tmp/p/glibc/Release/libc_pic.a
>
>glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress libc_pic.a(malloc.os):
>
>% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
>   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail_local
>   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
>   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail
>   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
>   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
>  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
>
>My question is: does the suppression via --defsym work reliably?
>
># a.o
>call foo
>
># b.a(b.o)
>.globl foo, free
>foo:
>free:
>
>
># GNU ld --defsym is order dependent.
>ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>
># gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to match GNU ld.
>gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
>gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
>
># lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
># https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is required to bypass a configure check
>ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
>ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent

Sorry, clarify the behavior of lld.

# lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16  5:02 ` Fangrui Song
@ 2020-03-16 11:27   ` H.J. Lu
  2020-03-16 15:47     ` Fangrui Song
  0 siblings, 1 reply; 10+ messages in thread
From: H.J. Lu @ 2020-03-16 11:27 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library

On Sun, Mar 15, 2020 at 10:02 PM Fangrui Song via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> On 2020-03-15, Fangrui Song wrote:
> >cd /tmp/p
> >git clone git://sourceware.org/git/glibc.git; cd glibc
> >mkdir Release; ../configure --prefix=/tmp/opt
> >make -j
> >
> >When linking elf/librtld.map.o
> >
> >% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o -Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0 -Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0 -Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-(' /tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
> >
> >Without -Wl,defsym:
> >
> >dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
> >__libc_scratch_buffer_set_array_size fetches libc_pic.a(scratch_buffer_set_array_size.os)
> >libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
> >free fetches libc_pic.a(malloc.os)
> >libc_pic.a(malloc.os) has an undefined __libc_message
> >__libc_message fetches libc_pic.a(libc_fatal.os)
> >
> >libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
> >>>>defined at dl-fxstatat64.c
> >>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
> >>>>defined at libc_fatal.c
> >>>>           libc_fatal.os:(.text+0x240) in archive /tmp/p/glibc/Release/libc_pic.a
> >
> >glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress libc_pic.a(malloc.os):
> >
> >% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
> >   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail_local
> >   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
> >   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail
> >   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
> >   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
> >  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
> >
> >My question is: does the suppression via --defsym work reliably?
> >
> ># a.o
> >call foo
> >
> ># b.a(b.o)
> >.globl foo, free
> >foo:
> >free:
> >
> >
> ># GNU ld --defsym is order dependent.
> >ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> >ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
> >
> ># gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to match GNU ld.
> >gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
> >gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
> >
> ># lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
> ># https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is required to bypass a configure check
> >ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
> >ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent
>
> Sorry, clarify the behavior of lld.
>
> # lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
> ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present

Glibc build requires a linker compatible with ld.  Can you provide an lld
option to make lld compatible with ld for cases like this?

-- 
H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 11:27   ` H.J. Lu
@ 2020-03-16 15:47     ` Fangrui Song
  2020-03-16 16:01       ` H.J. Lu
                         ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Fangrui Song @ 2020-03-16 15:47 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Binutils, GNU C Library, Florian Weimer

On 2020-03-16, H.J. Lu wrote:
>On Sun, Mar 15, 2020 at 10:02 PM Fangrui Song via Libc-alpha
><libc-alpha@sourceware.org> wrote:
>>
>> On 2020-03-15, Fangrui Song wrote:
>> >cd /tmp/p
>> >git clone git://sourceware.org/git/glibc.git; cd glibc
>> >mkdir Release; ../configure --prefix=/tmp/opt
>> >make -j
>> >
>> >When linking elf/librtld.map.o
>> >
>> >% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o -Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0 -Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0 -Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-(' /tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
>> >
>> >Without -Wl,defsym:
>> >
>> >dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
>> >__libc_scratch_buffer_set_array_size fetches libc_pic.a(scratch_buffer_set_array_size.os)
>> >libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
>> >free fetches libc_pic.a(malloc.os)
>> >libc_pic.a(malloc.os) has an undefined __libc_message
>> >__libc_message fetches libc_pic.a(libc_fatal.os)
>> >
>> >libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
>> >>>>defined at dl-fxstatat64.c
>> >>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
>> >>>>defined at libc_fatal.c
>> >>>>           libc_fatal.os:(.text+0x240) in archive /tmp/p/glibc/Release/libc_pic.a
>> >
>> >glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress libc_pic.a(malloc.os):
>> >
>> >% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
>> >   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail_local
>> >   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
>> >   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail
>> >   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
>> >   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
>> >  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
>> >
>> >My question is: does the suppression via --defsym work reliably?
>> >
>> ># a.o
>> >call foo
>> >
>> ># b.a(b.o)
>> >.globl foo, free
>> >foo:
>> >free:
>> >
>> >
>> ># GNU ld --defsym is order dependent.
>> >ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> >ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>> >
>> ># gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to match GNU ld.
>> >gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
>> >gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
>> >
>> ># lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
>> ># https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is required to bypass a configure check
>> >ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
>> >ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent
>>
>> Sorry, clarify the behavior of lld.
>>
>> # lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
>> ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present
>
>Glibc build requires a linker compatible with ld.  Can you provide an lld
>option to make lld compatible with ld for cases like this?

As a contributor of lld, I would be cooperative and be happy to adapt lld if the proposed semantic is reasonable.

I am concerned that the --defsym's order dependence with archive files is not so obvious, given -u's behavior:

# -u inserts an undefined which fetches b.a(b.o)
ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
# This can't be order dependent because b.a (not in a group) should have been dropped when we saw -u
ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present


Some observations:


# GNU ld --defsym interacts with an archive
ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent

# a.x contains one line `foo = 0;`
# -T a.x is similar to --defsym
ld.bfd a.o b.a -T a.x -o a  # b.a(b.o) is fetched. free is present
ld.bfd -T a.x a.o b.a -o a  # b.a(b.o) is not fetched. free is absent

# -u is usually order independent
# The second can't be order dependent because b.a should have been dropped when we see -u
ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present


# gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to make it work
gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent

# gold --export-dynamic-symbol (not in GNU ld) implies -u
gold --export-dynamic-symbol foo b.a    # b.a(b.o) is fetched. free is present
gold b.a --export-dynamic-symbol foo    # b.a(b.o) is fetched. free is present


# lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present


If we aim for robustness and make the librtld.map.o trick supported (I will add a note that gold happens to work),
I will hope both the following can suppress b.a(b.o):

   ld.bfd a.o b.a --defsym foo=0
   ld.bfd --defsym foo=0 a.o b.a

(a) Given --defsym's similarity to a symbol assignment specified by a -T, we will hope -T does not behave too differently.
(b) Note that in a linker script, at least input files should be order dependent w.r.t. input files on the command line.

(a)+(b) => symbol assignments specified by -T need to be declared early but input files specified -T are ordered w.r.t. input files on the command line.


For linker portability, projects using this trick (currently glibc is the only one) should place --defsym first to work with
existing releases of GNU ld.

The added librtld.map.o code is related to https://sourceware.org/bugzilla/show_bug.cgi?id=25486

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 15:47     ` Fangrui Song
@ 2020-03-16 16:01       ` H.J. Lu
  2020-03-16 18:31       ` Fangrui Song
  2020-03-16 19:05       ` Michael Matz
  2 siblings, 0 replies; 10+ messages in thread
From: H.J. Lu @ 2020-03-16 16:01 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Binutils, GNU C Library, Florian Weimer

On Mon, Mar 16, 2020 at 8:47 AM Fangrui Song <maskray@google.com> wrote:
>
> On 2020-03-16, H.J. Lu wrote:
> >On Sun, Mar 15, 2020 at 10:02 PM Fangrui Song via Libc-alpha
> ><libc-alpha@sourceware.org> wrote:
> >>
> >> On 2020-03-15, Fangrui Song wrote:
> >> >cd /tmp/p
> >> >git clone git://sourceware.org/git/glibc.git; cd glibc
> >> >mkdir Release; ../configure --prefix=/tmp/opt
> >> >make -j
> >> >
> >> >When linking elf/librtld.map.o
> >> >
> >> >% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o -Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0 -Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0 -Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-(' /tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a -lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
> >> >
> >> >Without -Wl,defsym:
> >> >
> >> >dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
> >> >__libc_scratch_buffer_set_array_size fetches libc_pic.a(scratch_buffer_set_array_size.os)
> >> >libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
> >> >free fetches libc_pic.a(malloc.os)
> >> >libc_pic.a(malloc.os) has an undefined __libc_message
> >> >__libc_message fetches libc_pic.a(libc_fatal.os)
> >> >
> >> >libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
> >> >>>>defined at dl-fxstatat64.c
> >> >>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
> >> >>>>defined at libc_fatal.c
> >> >>>>           libc_fatal.os:(.text+0x240) in archive /tmp/p/glibc/Release/libc_pic.a
> >> >
> >> >glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress libc_pic.a(malloc.os):
> >> >
> >> >% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
> >> >   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail_local
> >> >   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
> >> >   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS __stack_chk_fail
> >> >   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
> >> >   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
> >> >  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
> >> >
> >> >My question is: does the suppression via --defsym work reliably?
> >> >
> >> ># a.o
> >> >call foo
> >> >
> >> ># b.a(b.o)
> >> >.globl foo, free
> >> >foo:
> >> >free:
> >> >
> >> >
> >> ># GNU ld --defsym is order dependent.
> >> >ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> >> >ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
> >> >
> >> ># gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to match GNU ld.
> >> >gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
> >> >gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent

Gold is irrelevant here since it isn't supported to build glibc:

https://sourceware.org/bugzilla/show_bug.cgi?id=24148

There are also other gold bugs which may impact glibc build.   Please remove
gold from this discussion.

-- 
H.J.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 15:47     ` Fangrui Song
  2020-03-16 16:01       ` H.J. Lu
@ 2020-03-16 18:31       ` Fangrui Song
  2020-03-16 19:05       ` Michael Matz
  2 siblings, 0 replies; 10+ messages in thread
From: Fangrui Song @ 2020-03-16 18:31 UTC (permalink / raw)
  To: H.J. Lu, Florian Weimer; +Cc: Binutils, GNU C Library

>>>On 2020-03-16, H.J. Lu wrote:
>>>Glibc build requires a linker compatible with ld.  Can you provide an lld
>>>option to make lld compatible with ld for cases like this?
>>
>>As a contributor of lld, I would be cooperative and be happy to adapt lld if the proposed semantic is reasonable.
>>
>>I am concerned that the --defsym's order dependence with archive files is not so obvious, given -u's behavior:
>>
>># -u inserts an undefined which fetches b.a(b.o)
>>ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
>># This can't be order dependent because b.a (not in a group) should have been dropped when we saw -u
>>ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
>>
>>
>>Some observations:
>>
>>
>># GNU ld --defsym interacts with an archive
>>ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>>ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>>
>># a.x contains one line `foo = 0;`
>># -T a.x is similar to --defsym
>>ld.bfd a.o b.a -T a.x -o a  # b.a(b.o) is fetched. free is present
>>ld.bfd -T a.x a.o b.a -o a  # b.a(b.o) is not fetched. free is absent
>>
>># -u is usually order independent
>># The second can't be order dependent because b.a should have been dropped when we see -u
>>ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
>>ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
>>
>>
>># gold --defsym is order independent. For the more complex glibc elf/librtld.map.o case, it happens to make it work
>>gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
>>gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
>>
>># gold --export-dynamic-symbol (not in GNU ld) implies -u
>>gold --export-dynamic-symbol foo b.a    # b.a(b.o) is fetched. free is present
>>gold b.a --export-dynamic-symbol foo    # b.a(b.o) is fetched. free is present
>>
>>
>># lld --defsym is order independent. --defsym is processed the last. For elf/librtld.map.o it will report a multiple definition error.
>>ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>>ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present
>>
>>
>>If we aim for robustness and make the librtld.map.o trick supported (I will add a note that gold happens to work),
>>I will hope both the following can suppress b.a(b.o):
>>
>>  ld.bfd a.o b.a --defsym foo=0
>>  ld.bfd --defsym foo=0 a.o b.a
>>
>>(a) Given --defsym's similarity to a symbol assignment specified by a -T, we will hope -T does not behave too differently.
>>(b) Note that in a linker script, at least input files should be order dependent w.r.t. input files on the command line.
>>
>>(a)+(b) => symbol assignments specified by -T need to be declared early but input files specified -T are ordered w.r.t. input files on the command line.
>>
>>
>>For linker portability, projects using this trick (currently glibc is the only one) should place --defsym first to work with
>>existing releases of GNU ld.
>>
>>The added librtld.map.o code is related to https://sourceware.org/bugzilla/show_bug.cgi?id=25486
>
>Gold is irrelevant here since it isn't supported to build glibc:
>
>https://sourceware.org/bugzilla/show_bug.cgi?id=24148
>
>There are also other gold bugs which may impact glibc build.   Please remove
>gold from this discussion.

Thanks for the link. I am aways eager to learn more about linkers..

My motivation is indeed for my selfish dream to make glibc compilable with clang and linkable with lld.
As a contributor of lld and various LLVM tools, I think I am best positioned to make the situation better:)
At least for lld, it seems we need very few portability patches to work.
(At least the default configuration. There are numerous other configurations I don't know how to test now. I know really little about glibc.)

To make it very clear, I won't add workarounds for quality of implementation issues of clang+lld.
I mostly consider lld HEAD (lld<8 is not very reliable.)

To make my intention more plausible, this is in the spirit of https://gcc.gnu.org/wiki/cauldron2019 (GCC/LLVM Collaboration BoF).



Given more thoughts, I would hope we don't rely on the --defsym trick for malloc.os symbols
(already in use before commit 3a0ecccb599a6b1ad4b149dc569c0080e92d057b).

lld processes input files and -T/-u/--defsym in the following order:

1. parseFile(files[i])  // shared, relocatable, archive, linker scripts. Most archive members fetch is done in this step
2. handle -u            // This can trigger more fetch of archive members
3. declare symbols specified by -T and --defsym // too late to suppress fetch of archive members

(I have a feeling that gold's overall strategy is similar, though, when handling --start-group, it
sorta gets into an undesired "mixed" status (my simple a.o b.a example and librtld.map.o exhibit
different behaviors))

I could let lld match GNU ld by adding a separate --defsym step, but the logic would not be
consistent with -T processing.

1. declare symbols specified by --defsym
2. parseFile(files[i])
3. handle -u
4. declare symbols specified by -T

Note that --defsym can accept arbitrary expressions. Their st_shndx/st_value isn't finalized.
Postponing their effectness as late as possible can theoretically make implementations (ld/ldlang.c
ld/ldexp.c) simpler.

Without the --defsym trick, the following scheme may work:

(1) remove malloc.os from libc_pic.a
(2) ld -r -( dl-allobjs.os libc_pic.a -) -Map librtld.map
(3) add malloc.os back to libc_pic.a
(4) process librtld.map and get the libc dependencies
...

(1) and (3) could be avoided if GNU ld supported --start-lib --end-lib (gold,lld):
https://sourceware.org/bugzilla/show_bug.cgi?id=24600


As to why we should make ld a.o b.a --defsym foo=0 and ld --defsym foo=0 a.o b.a behave the same,
order dependency is not robust. We should avoid subtle failures if possible.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 15:47     ` Fangrui Song
  2020-03-16 16:01       ` H.J. Lu
  2020-03-16 18:31       ` Fangrui Song
@ 2020-03-16 19:05       ` Michael Matz
  2020-03-21 16:39         ` Fangrui Song
  2020-04-11 17:04         ` Florian Weimer
  2 siblings, 2 replies; 10+ messages in thread
From: Michael Matz @ 2020-03-16 19:05 UTC (permalink / raw)
  To: Fangrui Song; +Cc: H.J. Lu, Florian Weimer, GNU C Library, Binutils

Hallo,

On Mon, 16 Mar 2020, Fangrui Song via Binutils wrote:

> On 2020-03-16, H.J. Lu wrote:
> >On Sun, Mar 15, 2020 at 10:02 PM Fangrui Song via Libc-alpha
> ><libc-alpha@sourceware.org> wrote:
> >>
> >> On 2020-03-15, Fangrui Song wrote:
> >> >cd /tmp/p
> >> >git clone git://sourceware.org/git/glibc.git; cd glibc
> >> >mkdir Release; ../configure --prefix=/tmp/opt
> >> >make -j
> >> >
> >> >When linking elf/librtld.map.o
> >> >
> >> >% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o
> >> >-Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0
> >> >-Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0
> >> >-Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-('
> >> >/tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a
> >> >-lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
> >> >
> >> >Without -Wl,defsym:
> >> >
> >> >dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
> >> >__libc_scratch_buffer_set_array_size fetches
> >> >libc_pic.a(scratch_buffer_set_array_size.os)
> >> >libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
> >> >free fetches libc_pic.a(malloc.os)
> >> >libc_pic.a(malloc.os) has an undefined __libc_message
> >> >__libc_message fetches libc_pic.a(libc_fatal.os)
> >> >
> >> >libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
> >> >>>>defined at dl-fxstatat64.c
> >> >>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
> >> >>>>defined at libc_fatal.c
> >> >>>>           libc_fatal.os:(.text+0x240) in archive
> >> >>>>           /tmp/p/glibc/Release/libc_pic.a
> >> >
> >> >glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress
> >> >libc_pic.a(malloc.os):
> >> >
> >> >% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
> >> >   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS
> >> >   __stack_chk_fail_local
> >> >   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
> >> >   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS
> >> >   __stack_chk_fail
> >> >   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
> >> >   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
> >> >  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
> >> >
> >> >My question is: does the suppression via --defsym work reliably?
> >> >
> >> ># a.o
> >> >call foo
> >> >
> >> ># b.a(b.o)
> >> >.globl foo, free
> >> >foo:
> >> >free:
> >> >
> >> >
> >> ># GNU ld --defsym is order dependent.
> >> >ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> >> >ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
> >> >
> >> ># gold --defsym is order independent. For the more complex glibc
> >> >elf/librtld.map.o case, it happens to match GNU ld.
> >> >gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
> >> >gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
> >> >
> >> ># lld --defsym is order independent. --defsym is processed the last. For
> >> ># elf/librtld.map.o it will report a multiple definition error.
> >> ># https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is
> >> ># required to bypass a configure check
> >> >ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
> >> >ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent
> >>
> >> Sorry, clarify the behavior of lld.
> >>
> >> # lld --defsym is order independent. --defsym is processed the last. For
> >> elf/librtld.map.o it will report a multiple definition error.
> >> ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> >> ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present
> >
> >Glibc build requires a linker compatible with ld.  Can you provide an lld
> >option to make lld compatible with ld for cases like this?
> 
> As a contributor of lld, I would be cooperative and be happy to adapt lld if
> the proposed semantic is reasonable.
> 
> I am concerned that the --defsym's order dependence with archive files is not
> so obvious, given -u's behavior:
> 
> # -u inserts an undefined which fetches b.a(b.o)
> ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
> # This can't be order dependent because b.a (not in a group) should have been
> dropped when we saw -u
> ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
> 
> Some observations:
> 
> 
> # GNU ld --defsym interacts with an archive
> ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
> ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent

I consider this the correct linker behaviour.  In that sense I would 
consider the inconsistency with -u and -T to be the problems of those, not 
a problem of --defsym (but not necessarily problems we can fix anymore, as 
people might rely on that).  (i.e. I think the second -u command above 
should result in an 'undefined foo' output/error, not in b.a(b.o) being 
fetched).

I consider the above to be correct because this is how traditional link 
editors behave with respect to archives: ordering of file arguments does 
matter (obviously between .o and .a, but also between multiple .a and even 
between .o (think static initializers)).  And if you interpret '--defsym 
bla' as "object file defining symbol bla" and '-u foo' as "object file 
containing reference to foo" the behaviour for --defsym naturally follows 
(and makes the behaviour of -u be the inconsistence).

For this reasoning it's immaterial that --defsym accepts expressions: the 
evaluation of them can be delayed until cmdline arguments are processed.  
But the point of definition or reference should be their place in the 
cmdline.

How that interacts with -T: well, in an ideal world I don't see why those 
shouldn't also be processed in order and at their place within the command 
line (i.e. file arguments before it are available and processed, file 
arguments after it aren't yet), again with the caveat that RHS expressions 
might be evaluated late, but name references or definitions happen 
immediately).  But as said, we might not be able to change ld such that 
this is the case for compat reasons.

> If we aim for robustness and make the librtld.map.o trick supported (I will
> add a note that gold happens to work),
> I will hope both the following can suppress b.a(b.o):
> 
>   ld.bfd a.o b.a --defsym foo=0
>   ld.bfd --defsym foo=0 a.o b.a

And I would hope that the above two would _not_ be made to behave the 
same.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 19:05       ` Michael Matz
@ 2020-03-21 16:39         ` Fangrui Song
  2020-04-11 17:04         ` Florian Weimer
  1 sibling, 0 replies; 10+ messages in thread
From: Fangrui Song @ 2020-03-21 16:39 UTC (permalink / raw)
  To: Michael Matz; +Cc: H.J. Lu, Florian Weimer, GNU C Library, Binutils

On 2020-03-16, Michael Matz wrote:
>Hallo,
>
>On Mon, 16 Mar 2020, Fangrui Song via Binutils wrote:
>
>> On 2020-03-16, H.J. Lu wrote:
>> >On Sun, Mar 15, 2020 at 10:02 PM Fangrui Song via Libc-alpha
>> ><libc-alpha@sourceware.org> wrote:
>> >>
>> >> On 2020-03-15, Fangrui Song wrote:
>> >> >cd /tmp/p
>> >> >git clone git://sourceware.org/git/glibc.git; cd glibc
>> >> >mkdir Release; ../configure --prefix=/tmp/opt
>> >> >make -j
>> >> >
>> >> >When linking elf/librtld.map.o
>> >> >
>> >> >% gcc -nostdlib -nostartfiles -r -o /tmp/p/glibc/Release/elf/librtld.map.o
>> >> >-Wl,--defsym=calloc=0 -Wl,--defsym=free=0 -Wl,--defsym=malloc=0
>> >> >-Wl,--defsym=realloc=0 -Wl,--defsym=__stack_chk_fail=0
>> >> >-Wl,--defsym=__stack_chk_fail_local=0 '-Wl,-('
>> >> >/tmp/p/glibc/Release/elf/dl-allobjs.os /tmp/p/glibc/Release/libc_pic.a
>> >> >-lgcc '-Wl,-)' -Wl,-Map,/tmp/p/glibc/Release/elf/librtld.mapT
>> >> >
>> >> >Without -Wl,defsym:
>> >> >
>> >> >dl-allobjs.os has an undefined __libc_scratch_buffer_set_array_size
>> >> >__libc_scratch_buffer_set_array_size fetches
>> >> >libc_pic.a(scratch_buffer_set_array_size.os)
>> >> >libc_pic.a(scratch_buffer_set_array_size.os) has an undefined free
>> >> >free fetches libc_pic.a(malloc.os)
>> >> >libc_pic.a(malloc.os) has an undefined __libc_message
>> >> >__libc_message fetches libc_pic.a(libc_fatal.os)
>> >> >
>> >> >libc_fatal.os will cause a multiple definition error (__GI___libc_fatal)
>> >> >>>>defined at dl-fxstatat64.c
>> >> >>>>           /tmp/p/glibc/Release/elf/dl-allobjs.os:(__GI___libc_fatal)
>> >> >>>>defined at libc_fatal.c
>> >> >>>>           libc_fatal.os:(.text+0x240) in archive
>> >> >>>>           /tmp/p/glibc/Release/libc_pic.a
>> >> >
>> >> >glibc/elf/Makefile uses -Wl,--defsym= (rtld-stubbed-symbols) to suppress
>> >> >libc_pic.a(malloc.os):
>> >> >
>> >> >% readelf -s elf/librtld.map.o | grep ABS | grep -v LOCAL
>> >> >   712: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS
>> >> >   __stack_chk_fail_local
>> >> >   826: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS malloc
>> >> >   876: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS
>> >> >   __stack_chk_fail
>> >> >   905: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS calloc
>> >> >   975: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS realloc
>> >> >  1174: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  ABS free
>> >> >
>> >> >My question is: does the suppression via --defsym work reliably?
>> >> >
>> >> ># a.o
>> >> >call foo
>> >> >
>> >> ># b.a(b.o)
>> >> >.globl foo, free
>> >> >foo:
>> >> >free:
>> >> >
>> >> >
>> >> ># GNU ld --defsym is order dependent.
>> >> >ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> >> >ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>> >> >
>> >> ># gold --defsym is order independent. For the more complex glibc
>> >> >elf/librtld.map.o case, it happens to match GNU ld.
>> >> >gold a.o b.a --defsym foo=0    # b.a(b.o) is not fetched. free is absent
>> >> >gold --defsym foo=0 a.o b.a    # b.a(b.o) is not fetched. free is absent
>> >> >
>> >> ># lld --defsym is order independent. --defsym is processed the last. For
>> >> ># elf/librtld.map.o it will report a multiple definition error.
>> >> ># https://sourceware.org/pipermail/libc-alpha/2020-March/111899.html is
>> >> ># required to bypass a configure check
>> >> >ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is not fetched. free is absent
>> >> >ld.lld --defsym=0 a.o b.a      # b.a(b.o) is not fetched. free is absent
>> >>
>> >> Sorry, clarify the behavior of lld.
>> >>
>> >> # lld --defsym is order independent. --defsym is processed the last. For
>> >> elf/librtld.map.o it will report a multiple definition error.
>> >> ld.lld a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> >> ld.lld --defsym=0 a.o b.a      # b.a(b.o) is fetched. free is present
>> >
>> >Glibc build requires a linker compatible with ld.  Can you provide an lld
>> >option to make lld compatible with ld for cases like this?
>>
>> As a contributor of lld, I would be cooperative and be happy to adapt lld if
>> the proposed semantic is reasonable.
>>
>> I am concerned that the --defsym's order dependence with archive files is not
>> so obvious, given -u's behavior:
>>
>> # -u inserts an undefined which fetches b.a(b.o)
>> ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
>> # This can't be order dependent because b.a (not in a group) should have been
>> dropped when we saw -u
>> ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
>>
>> Some observations:
>>
>>
>> # GNU ld --defsym interacts with an archive
>> ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>
>I consider this the correct linker behaviour.  In that sense I would
>consider the inconsistency with -u and -T to be the problems of those, not
>a problem of --defsym (but not necessarily problems we can fix anymore, as
>people might rely on that).  (i.e. I think the second -u command above
>should result in an 'undefined foo' output/error, not in b.a(b.o) being
>fetched).
>
>I consider the above to be correct because this is how traditional link
>editors behave with respect to archives: ordering of file arguments does
>matter (obviously between .o and .a, but also between multiple .a and even
>between .o (think static initializers)).  And if you interpret '--defsym
>bla' as "object file defining symbol bla" and '-u foo' as "object file
>containing reference to foo" the behaviour for --defsym naturally follows
>(and makes the behaviour of -u be the inconsistence).

Symbol assignments in -T can override symbols in object files.
PROVIDE(...) is still effectful if -T comes before the object file.

The two facts imply that symbol assignments in -T can be considered
sorta order independent with regard to symbols in other files.

The model is that ad-hoc symbol resolution (symbol assignments in -T,
--defsym, -u, --export-dynamic-symbol) happens after archive file resolution.

>For this reasoning it's immaterial that --defsym accepts expressions: the
>evaluation of them can be delayed until cmdline arguments are processed.
>But the point of definition or reference should be their place in the
>cmdline.
>
>How that interacts with -T: well, in an ideal world I don't see why those
>shouldn't also be processed in order and at their place within the command
>line (i.e. file arguments before it are available and processed, file
>arguments after it aren't yet), again with the caveat that RHS expressions
>might be evaluated late, but name references or definitions happen
>immediately).  But as said, we might not be able to change ld such that
>this is the case for compat reasons.

It is actually possible for GNU ld's symbol resolution rules to behave
more like gold and lld. The amount of work can be large, but it can
improve consistency and simplify the internals.

>> If we aim for robustness and make the librtld.map.o trick supported (I will
>> add a note that gold happens to work),
>> I will hope both the following can suppress b.a(b.o):
>>
>>   ld.bfd a.o b.a --defsym foo=0
>>   ld.bfd --defsym foo=0 a.o b.a
>
>And I would hope that the above two would _not_ be made to behave the
>same.
>
>
>Ciao,
>Michael.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-03-16 19:05       ` Michael Matz
  2020-03-21 16:39         ` Fangrui Song
@ 2020-04-11 17:04         ` Florian Weimer
  2020-04-11 18:16           ` Fangrui Song
  1 sibling, 1 reply; 10+ messages in thread
From: Florian Weimer @ 2020-04-11 17:04 UTC (permalink / raw)
  To: Michael Matz; +Cc: Fangrui Song, GNU C Library, Binutils

* Michael Matz:

> On Mon, 16 Mar 2020, Fangrui Song via Binutils wrote:
>> I am concerned that the --defsym's order dependence with archive files is not
>> so obvious, given -u's behavior:
>> 
>> # -u inserts an undefined which fetches b.a(b.o)
>> ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
>> # This can't be order dependent because b.a (not in a group) should have been
>> dropped when we saw -u
>> ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
>> 
>> Some observations:
>> 
>> 
>> # GNU ld --defsym interacts with an archive
>> ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>> ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>
> I consider this the correct linker behaviour.  In that sense I would 
> consider the inconsistency with -u and -T to be the problems of those, not 
> a problem of --defsym (but not necessarily problems we can fix anymore, as 
> people might rely on that).  (i.e. I think the second -u command above 
> should result in an 'undefined foo' output/error, not in b.a(b.o) being 
> fetched).

I agree, the ld.bfd behavior seems the most reasonable one to me.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o)
  2020-04-11 17:04         ` Florian Weimer
@ 2020-04-11 18:16           ` Fangrui Song
  0 siblings, 0 replies; 10+ messages in thread
From: Fangrui Song @ 2020-04-11 18:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Michael Matz, GNU C Library, Binutils, Fangrui Song

On 2020-04-11, Florian Weimer wrote:
>* Michael Matz:
>
>> On Mon, 16 Mar 2020, Fangrui Song via Binutils wrote:
>>> I am concerned that the --defsym's order dependence with archive files is not
>>> so obvious, given -u's behavior:
>>>
>>> # -u inserts an undefined which fetches b.a(b.o)
>>> ld.bfd -u foo b.a       # b.a(b.o) is fetched. free is present
>>> # This can't be order dependent because b.a (not in a group) should have been
>>> dropped when we saw -u
>>> ld.bfd b.a -u foo       # b.a(b.o) is fetched. free is present
>>>
>>> Some observations:
>>>
>>>
>>> # GNU ld --defsym interacts with an archive
>>> ld.bfd a.o b.a --defsym foo=0  # b.a(b.o) is fetched. free is present
>>> ld.bfd --defsym foo=0 a.o b.a  # b.a(b.o) is not fetched. free is absent
>>
>> I consider this the correct linker behaviour.  In that sense I would
>> consider the inconsistency with -u and -T to be the problems of those, not
>> a problem of --defsym (but not necessarily problems we can fix anymore, as
>> people might rely on that).  (i.e. I think the second -u command above
>> should result in an 'undefined foo' output/error, not in b.a(b.o) being
>> fetched).
>
>I agree, the ld.bfd behavior seems the most reasonable one to me.

ld accepts two types of command line arguments: input files / options.

Examples of order dependency between two input files:

* an earlier archive member can override a subsequent archive member
* a shared object can suppress the fetch of a subsequent archive member
* a fetched archive member (turns to an object file) overrides a shared object

Examples of order dependency between an input file and an option:

* --as-needed --no-as-needed
* --whole-archive --no-whole-archive
* --start-lib --end-lib
* -Bdynamic -Bstatic -static (I am saddened by https://sourceware.org/pipermail/binutils/2020-March/000110.html)
* --start-group --end-group

I acknowledge all the above. However, a large set of options have no
order dependency issues.

* --allow-shlib-undefined
* --dynamic-list
* --version-script
* --apply-dynamic-relocs
* --omagic
* ...
* -u
* --export-dynamic-symbol
* --exclude-libs

I am glad the options are designed this way, otherwise in people's build
systems they could notice many more hard-to-diagnose problems.

As my very first message said, if GNU ld had --start-lib for a long time
(feature request: https://sourceware.org/bugzilla/show_bug.cgi?id=24600), this shadowing
malloc.o definition issue can be fixed very elegantly.

Now, we don't have --start-lib for GNU ld, but we can probably use GNU
ar thin archives as an alternative. The Linux kernel makes use of a
similar trick.


------- Random out of topic comments

In FreeBSD ports, 32k pieces of software just work, 130+ packages are
marked as LLD_UNSAFE, but many should be safe (need developers' testing)
as of lld 9. It is very likely none of the packages makes use of the
--defsym feature.

Most configurations of x86/x86-64/aarch64/ppc64le/ppc64le ports of the
Linux kernel link fine with LLD.

Making glibc compilable/linkable with clang/LLD is not at all my work
requirement.  It is simply I want to earn myself some contributions + I
don't want glibc to be tied to very specific toolchain. I started with
LLD because it is the relatively easy task. Clang compilability is more
troublesome. If I feel sufficient enmity, I will surely stop.

I tried stripping down LLD yesterday, just wanted to know how much code
is sufficient as the core https://github.com/MaskRay/picolld WoW, 18000+
LOC is capable to keep x86/ARM/AArch64/PPC ports and most functionality.
The GNU ld core probably really needs a refinement.

I have been thinking how to detect discrepancy between lld's and
traditional linkers' resolution rules. (The FreeBSD ports stats tell us
the "order dependency" issues are very few.) https://reviews.llvm.org/D77512

I am saddened that for some bug reports/enhancement proposals, the
initial reaction of some people in the community is usually "this is not
a bug." "this is an LLD bug" "GCC does this, so clang should do this as well."

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94391 is an awesome recent
showcase. It was then followed by an unfounded "NO LLD is not
implemented the ABI as PIE COPYRELOC is required by ABI these days".
The status was updated back and forth between "invalid", "wontfix" and
"worksforme" until a maintainer realized GNU ld had indeed one bug
(R_X86_64_[REX_]GOTPCRELX cannot be relaxed for SHN_ABS) and one
enhancement (PC relative relocations to a non-preemptible symbol should
be rejected). No one is probably willing to admit that LLD is good, though.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-04-11 18:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-16  4:58 Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o) Fangrui Song
2020-03-16  5:02 ` Fangrui Song
2020-03-16 11:27   ` H.J. Lu
2020-03-16 15:47     ` Fangrui Song
2020-03-16 16:01       ` H.J. Lu
2020-03-16 18:31       ` Fangrui Song
2020-03-16 19:05       ` Michael Matz
2020-03-21 16:39         ` Fangrui Song
2020-04-11 17:04         ` Florian Weimer
2020-04-11 18:16           ` Fangrui Song

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).