Bug 17931 - --gc-sections doesn't work on section in a group
Summary: --gc-sections doesn't work on section in a group
Status: RESOLVED INVALID
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.26
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-05 23:22 UTC by H.J. Lu
Modified: 2015-02-12 15:41 UTC (History)
3 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 H.J. Lu 2015-02-05 23:22:15 UTC
[hjl@gnu-6 gc-3]$ cat x.s
        .global _start
_start:
        call bar

	.section	.text.bar,"axG",@progbits,foo,comdat
	.weak	bar
	.type	bar,@function
bar:                                    # @bar
	retq

	.section	.text.zed,"axG",@progbits,foo,comdat
	.weak	zed
	.type	zed,@function
zed:                                    # @zed
	retq
[hjl@gnu-6 gc-3]$ make
gcc -O2 -c x.s
./ld --gc-sections -o x x.o
ld.gold --gc-sections -o y x.o
readelf -sW x | grep FUNC
     2: 000000000040007e     0 FUNC    WEAK   DEFAULT    1 zed
     7: 000000000040007d     0 FUNC    WEAK   DEFAULT    1 bar
readelf -sW y | grep FUNC
     2: 000000000040007d     0 FUNC    WEAK   DEFAULT    1 bar
[hjl@gnu-6 gc-3]$ 

zed should be removed.
Comment 1 Alan Modra 2015-02-05 23:59:48 UTC
No, it should not be removed.  See the gABI.  "Therefore, such groups must be included or omitted from the linked object as a unit."
Comment 2 Rafael Ávila de Espíndola 2015-02-06 13:09:13 UTC
(In reply to Alan Modra from comment #1)
> No, it should not be removed.  See the gABI.  "Therefore, such groups must
> be included or omitted from the linked object as a unit."

I believe there is a misunderstanding here.

Semantically, during the "regular" part of the link, the linker includes or discards groups as a unit.

During the --gc-sections part, individual sections are considered.

Even without groups, --gc-sections would be "invalid" according to the spec, since it drop sections that should be copied to the output. The point is that --gc-sections is effectively an extension.

This does show up in the real world since the deleting destructor is unfortunately part of D5:

struct foo {
  virtual ~foo(){};
};
foo x;

produces with gcc 4.9:

 .section        .text._ZN3fooD2Ev,"axG",@progbits,_ZN3fooD5Ev,comdat
...
_ZN3fooD2Ev:
        ret
....
.set    _ZN3fooD1Ev,_ZN3fooD2Ev
....

      .section        .text._ZN3fooD0Ev,"axG",@progbits,_ZN3fooD5Ev,comdat
....
_ZN3fooD0Ev:
        jmp     _ZdlPv


Note that D0 is never equal to D1 or D2 since it has to call delete. If it is not used in a DSO, we bloat the binary.
Comment 3 Alan Modra 2015-02-07 01:55:00 UTC
I hear what you're saying, and accept that gc-sections could be made to work for the specific case you present here.  However, I'm unconvinced that we should do this in the linker, to work around what appears to be a gcc bug.

We've kept groups together under gc-sections right from the initial implementation of section group support in 2001.  The major reason for doing this is to keep on-the-side sections, eg. debug info, when any of their grouped code or data sections are kept.  These on-the-side sections don't have relocations from other sections that would cause them to be kept by the usual gc-sections marking process.  For an example of sections that appear in a loaded image, exception handling info, .eh_frame and associated sections, is another set of on-the-side sections that a compiler could place in a group (and should instead of relying on ld's eh_frame editing!).

Are there similar on-the-side code sections that would prevent us making an exception for code sections in a group?  I don't know of any, but people do weird things..
Comment 4 Rafael Ávila de Espíndola 2015-02-12 15:41:09 UTC
(In reply to Alan Modra from comment #3)
> I hear what you're saying, and accept that gc-sections could be made to work
> for the specific case you present here.  However, I'm unconvinced that we
> should do this in the linker, to work around what appears to be a gcc bug.

I agree that this was originally a gcc bug (https://sourceware.org/bugzilla/show_bug.cgi?id=17931 for reference), but it is now an odd abi issue we have to live with.

> We've kept groups together under gc-sections right from the initial
> implementation of section group support in 2001.  The major reason for doing
> this is to keep on-the-side sections, eg. debug info, when any of their
> grouped code or data sections are kept.  These on-the-side sections don't
> have relocations from other sections that would cause them to be kept by the
> usual gc-sections marking process.  For an example of sections that appear
> in a loaded image, exception handling info, .eh_frame and associated
> sections, is another set of on-the-side sections that a compiler could place
> in a group (and should instead of relying on ld's eh_frame editing!).

Yes, I would love to have the compiler output multiple .eh_frame sections in the correct comdat. I have implementing that in llvm in my todo list, but it is low priority since every current linker has to handle the magical .eh_frame.

> Are there similar on-the-side code sections that would prevent us making an
> exception for code sections in a group?  I don't know of any, but people do
> weird things..

In a world where comdats are fully utilized, the only extra logic that is needed for GC is that some sections have relocations in the opposite direction:

A .eh_frame should be kept if the function it points to is kept. The same goes for debug info.

It would be nice to have the "reverse reloc dependency" marked explicitly in the .o file (a new SHF_SIDE_TABLE maybe?), but adding it implicitly to a few well know sections seems a small cost for extra flexibility.