Bug 21562 - Refs to __start_SCN of non-orphan sections affect --gc-sections
Summary: Refs to __start_SCN of non-orphan sections affect --gc-sections
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.29
: P2 normal
Target Milestone: 2.29
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on: 27495 19167 20022
Blocks:
  Show dependency treegraph
 
Reported: 2017-06-09 17:33 UTC by Alexander Monakov
Modified: 2021-03-01 19:19 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2017-06-10 00:00:00


Attachments
Try this (907 bytes, patch)
2017-06-09 21:17 UTC, H.J. Lu
Details | Diff
A better patch (1.05 KB, patch)
2017-06-09 21:27 UTC, H.J. Lu
Details | Diff
A new patch (4.30 KB, patch)
2017-06-10 14:34 UTC, H.J. Lu
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Alexander Monakov 2017-06-09 17:33:02 UTC
(originally mentioned in bug 21557)

Linker manual explicitly states that __start_SCN symbols are automatically provided only for orphan sections. However, the following testcase shows that such symbols appear virtually present when marking reachable sections for --gc-sections:

cat <<EOF >test.s
        .section        scnfoo,"aw",@progbits
        .zero   1

        .globl  bar
        .data
        .align 8
        .type   bar, @object
        .size   bar, 8
bar:
        .quad   __start_scnfoo
EOF

cat <<EOF >lds
SECTIONS {
        scnfoo : { *(scnfoo) }
}
EOF

$ ld.bfd -shared -o test.so test.o --gc-sections --print-gc-sections -T lds
<no output, scnfoo not eliminated, __start_scnfoo is undefined>
Comment 1 H.J. Lu 2017-06-09 19:11:04 UTC
_bfd_elf_gc_mark_rsec has

      if (start_stop != NULL) 
        {
          /* To work around a glibc bug, mark all XXX input sections
             when there is an as yet undefined reference to __start_XXX
             or __stop_XXX symbols.  The linker will later define such
             symbols for orphan input sections that have a name
             representable as a C identifier.  */
          asection *s = _bfd_elf_is_start_stop (info, h);

          if (s != NULL) 
            {
              *start_stop = !s->gc_mark;
              return s;
            }
        }

The question is if ELF linker automatically creates a definition when
there is a reference, regardless if the input section is orphan or not.
Comment 2 H.J. Lu 2017-06-09 21:17:21 UTC
Created attachment 10084 [details]
Try this
Comment 3 H.J. Lu 2017-06-09 21:27:40 UTC
Created attachment 10085 [details]
A better patch
Comment 4 H.J. Lu 2017-06-10 14:34:41 UTC
Created attachment 10088 [details]
A new patch
Comment 5 Alexander Monakov 2017-06-10 14:46:40 UTC
The patch looks wrong, it appears to ensure that __start_scnfoo is defined. The linker manual says it shouldn't get defined (scnfoo is not orphan), and therefore scnfoo should be eliminated due to --gc-sections.

(note that bug 20022 and bug 19167 are both for orphan sections, linker scripts are not involved there)
Comment 6 H.J. Lu 2017-06-10 22:49:23 UTC
(In reply to Alexander Monakov from comment #5)
> The patch looks wrong, it appears to ensure that __start_scnfoo is defined.
> The linker manual says it shouldn't get defined (scnfoo is not orphan), and
> therefore scnfoo should be eliminated due to --gc-sections.
> 

I posted a patch to always define referenced __start_SECNAME/__stop_SECNAME:

https://sourceware.org/ml/binutils/2017-06/msg00105.html
Comment 7 Alexander Monakov 2017-06-11 08:11:15 UTC
(In reply to H.J. Lu from comment #6)
> I posted a patch to always define referenced __start_SECNAME/__stop_SECNAME:

That's quite confusing, because originally bug 21557 (wrongly) complained about those symbols not being defined, and you closed that bug as WONTFIX. If you changed your mind, can you please update that bug?

I don't see the reason to extend __start_SECNAME auto-provisioning, it seems it would be simpler to avoid extraneous gc-marking shown in this bug.
Comment 8 H.J. Lu 2017-06-11 11:45:52 UTC
(In reply to Alexander Monakov from comment #7)
> (In reply to H.J. Lu from comment #6)
> > I posted a patch to always define referenced __start_SECNAME/__stop_SECNAME:
> 
> That's quite confusing, because originally bug 21557 (wrongly) complained
> about those symbols not being defined, and you closed that bug as WONTFIX.
> If you changed your mind, can you please update that bug?

I will update it after my patch has been checked in.

> I don't see the reason to extend __start_SECNAME auto-provisioning, it seems
> it would be simpler to avoid extraneous gc-marking shown in this bug.

The new approach is faster and happens to support non-orphaned sections.
Comment 9 Sourceware Commits 2017-06-13 15:55:14 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=cbd0eecf261c2447781f8c89b0d955ee66fae7e9

commit cbd0eecf261c2447781f8c89b0d955ee66fae7e9
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Tue Jun 13 08:53:22 2017 -0700

    Always define referenced __start_SECNAME/__stop_SECNAME
    
    Currently, linker will define __start_SECNAME and __stop_SECNAME symbols
    only for orphaned sections.
    
    However, during garbage collection, ELF linker marks all sections with
    references to __start_SECNAME and __stop_SECNAME symbols as used even
    when section SECNAME isn't an orphaned section and linker won't define
    __start_SECNAME nor __stop_SECNAME.  And ELF linker stores the first
    input section whose name matches __start_SECNAME or __stop_SECNAME in
    u.undef.section for garbage collection.  If these symbols are provided
    in linker script, u.undef.section is set to the section where they will
    defined by linker script, which leads to the incorrect output.
    
    This patch changes linker to always define referenced __start_SECNAME and
    __stop_SECNAME if the input section name is the same as the output section
    name, which is always true for orphaned sections, and SECNAME is a C
    identifier.  Also __start_SECNAME and __stop_SECNAME symbols are marked
    as hidden by ELF linker so that __start_SECNAME and __stop_SECNAME symbols
    for section SECNAME in different modules are unique.  For garbage
    collection, ELF linker stores the first matched input section in the
    unused vtable field.
    
    bfd/
    
    	PR ld/20022
    	PR ld/21557
    	PR ld/21562
    	PR ld/21571
    	* elf-bfd.h (elf_link_hash_entry): Add start_stop.  Change the
    	vtable field to a union.
    	(_bfd_elf_is_start_stop): Removed.
    	* elf32-i386.c (elf_i386_convert_load_reloc): Also check for
    	__start_SECNAME and __stop_SECNAME symbols.
    	* elf64-x86-64.c (elf_x86_64_convert_load_reloc): Likewise.
    	* elflink.c (_bfd_elf_is_start_stop): Removed.
    	(_bfd_elf_gc_mark_rsec): Check start_stop instead of calling
    	_bfd_elf_is_start_stop.
    	(elf_gc_propagate_vtable_entries_used): Skip __start_SECNAME and
    	__stop_SECNAME symbols.  Updated.
    	(elf_gc_smash_unused_vtentry_relocs): Likewise.
    	(bfd_elf_gc_record_vtinherit): Likewise.
    	(bfd_elf_gc_record_vtentry): Likewise.
    
    ld/
    
    	PR ld/20022
    	PR ld/21557
    	PR ld/21562
    	PR ld/21571
    	* ld.texinfo: Update __start_SECNAME/__stop_SECNAME symbols.
    	* ldlang.c (lang_insert_orphan): Move handling of __start_SECNAME
    	and __stop_SECNAME symbols to ...
    	(lang_set_startof): Here.  Also define __start_SECNAME and
    	__stop_SECNAME for -Ur.
    	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Mark
    	referenced __start_SECNAME and __stop_SECNAME symbols as hidden
    	and set start_stop for garbage collection.
    	* testsuite/ld-elf/pr21562a.d: New file.
    	* testsuite/ld-elf/pr21562a.s: Likewise.
    	* testsuite/ld-elf/pr21562a.t: Likewise.
    	* testsuite/ld-elf/pr21562b.d: Likewise.
    	* testsuite/ld-elf/pr21562b.s: Likewise.
    	* testsuite/ld-elf/pr21562b.t: Likewise.
    	* testsuite/ld-elf/pr21562c.d: Likewise.
    	* testsuite/ld-elf/pr21562c.t: Likewise.
    	* testsuite/ld-elf/pr21562d.d: Likewise.
    	* testsuite/ld-elf/pr21562d.t: Likewise.
    	* testsuite/ld-elf/pr21562e.d: Likewise.
    	* testsuite/ld-elf/pr21562f.d: Likewise.
    	* testsuite/ld-elf/pr21562g.d: Likewise.
    	* testsuite/ld-elf/pr21562h.d: Likewise.
    	* testsuite/ld-elf/pr21562i.d: Likewise.
    	* testsuite/ld-elf/pr21562j.d: Likewise.
    	* testsuite/ld-elf/pr21562k.d: Likewise.
    	* testsuite/ld-elf/pr21562l.d: Likewise.
    	* testsuite/ld-elf/pr21562m.d: Likewise.
    	* testsuite/ld-elf/pr21562n.d: Likewise.
    	* testsuite/ld-gc/pr20022.d: Likewise.
    	* testsuite/ld-gc/pr20022a.s: Likewise.
    	* testsuite/ld-gc/pr20022b.s: Likewise.
    	* testsuite/ld-gc/gc.exp: Run PR ld/20022 tests.
    	* testsuite/ld-gc/pr19161.d: Also accept local __start_SECNAME
    	symbol.
    	* testsuite/ld-gc/start.d: Likewise.
    	* testsuite/ld-x86-64/lea1a.d: Updated.
    	* testsuite/ld-x86-64/lea1b.d: Updated.
    	* testsuite/ld-x86-64/lea1d.d: Updated.
    	* testsuite/ld-x86-64/lea1e.d: Likewise.
Comment 10 H.J. Lu 2017-06-13 15:56:55 UTC
Fixed.
Comment 11 Sourceware Commits 2017-06-14 13:09:36 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8eca1095d96c215409371c5687573aac89a0a980

commit 8eca1095d96c215409371c5687573aac89a0a980
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Jun 14 04:36:17 2017 -0700

    Skip PR ld/21562 tests on targets with leading char or without --gc-sections
    
    Symbol lookup in linker will always fail on targets with leading char
    in symbol name since __start_SECNAME and __stop_SECNAME in C may be
    ___start_SECNAME and ___stop_SECNAME in assembly.  Also tests with
    --gc-sections always fails on targets without --gc-sections support.
    
    	* testsuite/ld-elf/pr21562a.d: Skip on targets with leading char
    	in in symbol name or without --gc-sections.
    	* testsuite/ld-elf/pr21562b.d: Likewise.
    	* testsuite/ld-elf/pr21562c.d: Likewise.
    	* testsuite/ld-elf/pr21562d.d: Likewise.
    	* testsuite/ld-elf/pr21562i.d: Likewise.
    	* testsuite/ld-elf/pr21562j.d: Likewise.
    	* testsuite/ld-elf/pr21562k.d: Likewise.
    	* testsuite/ld-elf/pr21562l.d: Likewise.
    	* testsuite/ld-elf/pr21562m.d: Likewise.
    	* testsuite/ld-elf/pr21562n.d: Likewise.
    	* testsuite/ld-elf/pr21562e.d: Skip on targets with leading char
    	in symbol name.
    	* testsuite/ld-elf/pr21562f.d: Likewise.
    	* testsuite/ld-elf/pr21562g.d: Likewise.
    	* testsuite/ld-elf/pr21562h.d: Likewise.
Comment 12 Sourceware Commits 2017-06-16 14:09:52 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=7dba9362c172f1073487536eb137feb2da30b0ff

commit 7dba9362c172f1073487536eb137feb2da30b0ff
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Jun 16 19:41:41 2017 +0930

    Rewrite __start and __stop symbol handling
    
    This arranges for __start and __stop symbols to be defined before
    garbage collection, for all target formats.  That should allow the
    COFF and PE --gc-sections to keep a singleton orphan input section,
    a feature lost by 2017-06-13 commit cbd0eecf26.  The fancier ELF
    treatment of keeping all input sections associated with a __start or
    __stop symbol, from 2015-10-23 commit 1cce69b9dc, is retained.
    
    .startof. and .sizeof. symbols are deliberately not defined before
    garbage collection, so these won't affect garbage collection of
    sections.
    
    The patch also ensures __start, __stop, .startof. and .sizeof. symbols
    are defined before target size_dynamic_sections is called, albeit
    with a preliminary value, so that target code doesn't need to cope
    with a symbol changing from undefined at size_dynamic_sections to
    defined at relocate_section.
    
    Also, a number of problems with the testcases have been fixed.
    
    	PR ld/20022
    	PR ld/21557
    	PR ld/21562
    	PR ld/21571
    include/
    	* bfdlink.h (struct bfd_link_hash_entry): Delete undef.section.
    bfd/
    	* targets.c (struct bfd_target): Add _bfd_define_start_stop.
    	(BFD_JUMP_TABLE_LINK): Likewise.
    	* elf-bfd.h (bfd_elf_define_start_stop): Declare.
    	* elflink.c (_bfd_elf_gc_mark_rsec): Update comment.
    	(bfd_elf_define_start_stop): New function.
    	* linker.c (bfd_generic_define_start_stop): New function.
    	* coff64-rs6000.c (rs6000_xcoff64_vec, rs6000_xcoff64_aix_vec): Init
    	new field.
    	* aout-adobe.c (aout_32_bfd_define_start_stop): Define.
    	* aout-target.h (MY_bfd_define_start_stop): Define.
    	* aout-tic30.c (MY_bfd_define_start_stop): Define.
    	* binary.c (binary_bfd_define_start_stop): Define.
    	* bout.c (b_out_bfd_define_start_stop): Define.
    	* coff-alpha.c (_bfd_ecoff_bfd_define_start_stop): Define.
    	* coff-mips.c (_bfd_ecoff_bfd_define_start_stop): Define.
    	* coff-rs6000.c (_bfd_xcoff_bfd_define_start_stop): Define.
    	* coffcode.h (coff_bfd_define_start_stop): Define.
    	* elfxx-target.h (bfd_elfNN_bfd_define_start_stop): Define.
    	* i386msdos.c (msdos_bfd_define_start_stop): Define.
    	* i386os9k.c (os9k_bfd_define_start_stop): Define.
    	* ieee.c (ieee_bfd_define_start_stop): Define.
    	* ihex.c (ihex_bfd_define_start_stop): Define.
    	* libbfd-in.h (_bfd_nolink_bfd_define_start_stop): Define.
    	* mach-o-target.c (bfd_mach_o_bfd_define_start_stop): Define.
    	* mmo.c (mmo_bfd_define_start_stop): Define.
    	* nlm-target.h (nlm_bfd_define_start_stop): Define.
    	* oasys.c (oasys_bfd_define_start_stop): Define.
    	* pef.c (bfd_pef_bfd_define_start_stop): Define.
    	* plugin.c (bfd_plugin_bfd_define_start_stop): Define.
    	* ppcboot.c (ppcboot_bfd_define_start_stop): Define.
    	* som.c (som_bfd_define_start_stop): Define.
    	* srec.c (srec_bfd_define_start_stop): Define.
    	* tekhex.c (tekhex_bfd_define_start_stop): Define.
    	* versados.c (versados_bfd_define_start_stop): Define.
    	* vms-alpha.c (vms_bfd_define_start_stop): Define.
    	(alpha_vms_bfd_define_start_stop): Define.
    	* xsym.c (bfd_sym_bfd_define_start_stop): Define.
    	* bfd-in2.h: Regenerate.
    	* libbfd.h: Regenerate.
    ld/
    	* emultempl/elf32.em (gld${EMULATION_NAME}_after_open): Don't set
    	__start/__stop syms here.
    	* ldlang.c (lang_set_startof): Delete.
    	(start_stop_syms, start_stop_count, start_stop_alloc): New vars.
    	(lang_define_start_stop, lang_init_start_stop, foreach_start_stop,
    	undef_start_stop, lang_undef_start_stop, lang_init_startof_sizeof,
    	set_start_stop, lang_finalize_start_stop): New functions.
    	(lang_process): Call _start_stop functions.
    	* testsuite/ld-elf/pr21562a.d: Use xfail rather than notarget.
    	Correct typos and list of xfail targets.
    	* testsuite/ld-elf/pr21562b.d: Likewise.
    	* testsuite/ld-elf/pr21562c.d: Likewise.
    	* testsuite/ld-elf/pr21562d.d: Likewise.
    	* testsuite/ld-elf/pr21562e.d: Likewise.
    	* testsuite/ld-elf/pr21562f.d: Likewise.
    	* testsuite/ld-elf/pr21562g.d: Likewise.
    	* testsuite/ld-elf/pr21562h.d: Likewise.
    	* testsuite/ld-elf/pr21562i.d: Likewise.
    	* testsuite/ld-elf/pr21562j.d: Likewise.
    	* testsuite/ld-elf/pr21562k.d: Likewise.
    	* testsuite/ld-elf/pr21562l.d: Likewise.
    	* testsuite/ld-elf/pr21562m.d: Likewise.
    	* testsuite/ld-elf/pr21562n.d: Likewise.
    	* testsuite/ld-elf/sizeofa.d: Likewise.  Adjust to pass for generic ELF.
    	* testsuite/ld-elf/sizeofb.d: Likewise.
    	* testsuite/ld-elf/startofa.d: Likewise.
    	* testsuite/ld-elf/startofb.d: Likewise.
Comment 13 Sourceware Commits 2017-11-24 17:02:29 UTC
The master branch has been updated by H.J. Lu <hjl@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8b77421a20c22c9a66048e7d1484b149da060b67

commit 8b77421a20c22c9a66048e7d1484b149da060b67
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Nov 24 08:58:43 2017 -0800

    Update PR ld/21562 tests for underscore targets
    
    We also need to provide __start_scnfoo and __stop_scnfoo with the extra
    leading underscore for underscore targets.
    
    This patch fixed:
    
    FAIL: ld-elf/pr21562k
    FAIL: ld-elf/pr21562l
    FAIL: ld-elf/pr21562m
    FAIL: ld-elf/pr21562n
    
    for metag-linux,
    
    	* testsuite/ld-elf/pr21562c.t: Also provide ___start_scnfoo and
    	___stop_scnfoo.
    	* testsuite/ld-elf/pr21562d.t: Likewise.