From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 263D63861C56; Mon, 16 Mar 2020 19:06:01 +0000 (GMT) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 34EF1B1CF; Mon, 16 Mar 2020 19:06:00 +0000 (UTC) Date: Mon, 16 Mar 2020 19:05:59 +0000 (UTC) From: Michael Matz To: Fangrui Song cc: "H.J. Lu" , Florian Weimer , GNU C Library , Binutils Subject: Re: Suppress the fetch of an archive member via --defsym (glibc/elf/librtld.map.o) In-Reply-To: <20200316154706.fblgnhpezjggiugx@google.com> Message-ID: References: <20200316045859.hq76yfsdqiupjgiy@google.com> <20200316050202.pql3syb2imduinf7@google.com> <20200316154706.fblgnhpezjggiugx@google.com> User-Agent: Alpine 2.21 (LSU 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-0.0 required=5.0 tests=KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Mar 2020 19:06:02 -0000 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 > > 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.