Bug 879 – support for --gc-sections

Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
Linux
Creation time
2007-01-23T17:28:15Z
Last change time
2019-07-13T12:10:01Z
Assigned to
Martin Nowak
Creator
Thomas Kühne

Attachments

IDFilenameSummaryContent-TypeSize
106binutils-2.17-dmd-exception.tbzBinutils workaroundapplication/x-bzip297680

Comments

Comment #0 by thomas-dloop — 2007-01-23T17:28:15Z
--gc-sections is ld's flag to "Enable garbage collection of unused input sections." As known(#100 and #101) it currently breaks DMD's exception handling on Linux. I think I've found the cause and know a simple fix. # # void main(){ # throw new Exception("message"); # } # dmd a.d -ofa; nm --numeric-sort a [...] > 000000000805c4b0 R _D3std6thread6Thread6__vtblZ > 000000000805c508 R _deh_beg > 000000000805c508 r _TMP3 > 000000000805c514 r _TMP1 [...] > 000000000805c604 r _TMP14 > 000000000805c610 r _TMP27 > 000000000805c61c R _deh_end > 000000000805c61c r __FRAME_END__ [...] dmd a.d -ofa -L--gc-sections; nm --numeric-sort a > [...] > 0000000008053270 R _D3std6thread6Thread6__vtblZ > 00000000080532c8 R _deh_beg > 00000000080532c8 R _deh_end > 00000000080532c8 r __FRAME_END__ > [...] The missing _TMP... symbols are of type internal.deh2.FuncTable and describe where to find the exception handlers of a given function. BUG 1: ld rightfully removed those as they are never directly referenced. However they are accessed indirectly via _deh_beg and _deh_end (-> internal/deh2.d:98-100). FIX 1: Define an elf symbol with the following characteristics: address: _deh_beg size: _deh_end - _deh_beg + sizeof(_deh_end) and ensure that this symbol is guaranteed to be referenced somewhere regardless of compiler flags like -O, -release and -inline. BUG 2: from above: > 00000000080532c8 R _deh_beg > 00000000080532c8 R _deh_end > 00000000080532c8 r __FRAME_END__ _deh_beg, _deh_end and __FRAME_END__ have the same addresses because _deh_beg and _deh_end claim to be of size zero. FIX 2: The same as #472, please emit correct size information for all elf symbols.
Comment #1 by thomas-dloop — 2007-03-31T15:08:41Z
Created attachment 106 Binutils workaround
Comment #2 by thomas-dloop — 2007-04-04T15:39:31Z
Daniel Jacobowitz suggested a much more straight forward solution on the binutils mailing list(http://sourceware.org/ml/binutils/): > Another way to fix this would be to emit R_arch_NONE relocations from > the code sections to the EH tables they require.
Comment #3 by fvbommel — 2007-04-04T18:10:32Z
[email protected] wrote: > ------- Comment #2 from [email protected] 2007-04-04 15:39 ------- > Daniel Jacobowitz suggested a much more straight forward solution on the > binutils mailing list(http://sourceware.org/ml/binutils/): > >> Another way to fix this would be to emit R_arch_NONE relocations from >> the code sections to the EH tables they require. Interesting. And should be easy enough to implement. An added advantage to this approach would be that no relatively new version of binutils will be required to use --gc-sections[1], which might require working around (Linux) package managers. It'd just a recent version of DMD (after this is implemented) which is more likely to be manually installed (and frequently updated) anyway. [1]: (Assuming R_arch_NONE isn't a recent feature)
Comment #4 by thomas-dloop — 2007-04-25T12:56:31Z
Walter, are you going to implement the R_arch_NONE solution or should we patch binutils?
Comment #5 by braddr — 2010-08-29T12:35:37Z
*** Issue 4758 has been marked as a duplicate of this issue. ***
Comment #6 by hoganmeier — 2013-07-23T02:26:15Z
--gc-sections breaks everything, even hello world. import std.stdio; void main() { writefln("FIXME!"); } $ dmd -L--gc-sections -L--print-gc-sections test.d ld: Removing unused section '.deh_eh' in file 'test.o' ld: Removing unused section '.minfo' in file 'test.o' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__34_85a.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__54_915.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__5a_ff3.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__5e_8d3.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__60_fb1.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__62_882.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__63_f60.o)' ld: Removing unused section '.data' in file 'libphobos2.a(dmain2_44e_47b.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(dmain2_44e_47b.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_455_482.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_462_7db.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_467_46f.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_475_60d.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_478_6c8.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_47b_4cd.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_47c_53b.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_480_2a1.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(sections_linux.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__4db_e8d.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(console.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(container.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__551_86e.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(array.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(conv.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(exception.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(exception_599_8af.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(format.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(functional.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(math.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(range.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(stdio.o)' ld: Removing unused section '.data' in file 'libphobos2.a(stdio_c2b_180.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(stdio_c2b_180.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(stdiobase.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(string.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(traits.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(typecons.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(typetuple.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(utf.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(object__6_32e.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(object__1b_3a8.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__57_ef0.o)' ld: Removing unused section '.data' in file 'libphobos2.a(runtime_e3_76e.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(runtime_e3_76e.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_12d_5a0.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(gc.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(gcx_2f3_8a.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(deh2.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__434_e4b.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(dmain2.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(lifetime.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_459_856.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(lifetime_459_856.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_45e_4a3.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_461_4e2.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_463_4df.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_464_548.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_471_4c9.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(lifetime_471_4c9.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(monitor_.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(tlsgc.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(algorithm.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(ascii.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(bitmanip.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(container.o)' ld: Removing unused section '.data' in file 'libphobos2.a(exception_5c8_d27.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(exception_5c8_d27.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(random.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(regex.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(uni.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(uni_tab.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object_.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(exception.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__d9_929.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(runtime.o)' ld: Removing unused section '.data' in file 'libphobos2.a(runtime_e2_2e4.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(thread.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_109_236.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_10b_1b0.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_10e_330.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_10e_330.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_110_3bd.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_117_2e5.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_117_2e5.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_118_1b8.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_120_21c.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_124_28e.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_124_28e.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_126_48b.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_128_6e4.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_128_6e4.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_130_6f2.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_131_291.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_132_681.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_132_681.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_136_595.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_13a_85e.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_13e_762.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_13f_465.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_144_236.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_14e_1b8.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(time.o)' ld: Removing unused section '.data' in file 'libphobos2.a(time_177_5cc.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(mutex_225_213.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(gcx.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__343_b3c.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(critical_.o)' ld: Removing unused section '.data' in file 'libphobos2.a(dmain2_448_2f9.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(dmain2_448_2f9.o)' ld: Removing unused section '.data' in file 'libphobos2.a(dmain2_44a_2fd.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(dmain2_44a_2fd.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_46f_815.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_470_809.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(numeric.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object_891_87d.o)' ld: Removing unused section '.data' in file 'libphobos2.a(demangle_b8_ab6.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(demangle_b8_ab6.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_105_897.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_106_826.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_107_1b8.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_108_1b8.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_10a_22e.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_10a_22e.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_113_219.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_115_2d8.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_121_129.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_121_129.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_123_129.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_123_129.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_12e_726.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_12f_302.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_134_737.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_135_5f2.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_135_5f2.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_13b_469.o)' ld: Removing unused section '.data' in file 'libphobos2.a(time_16b_346.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(time_16b_346.o)' ld: Removing unused section '.data' in file 'libphobos2.a(time_178_297.o)' ld: Removing unused section '.data' in file 'libphobos2.a(time_17e_48a.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(time_17e_48a.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(aaA.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__340_aeb.o)' ld: Removing unused section '.data' in file 'libphobos2.a(lifetime_474_7cc.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(complex.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(demangle_b4_31d.o)' ld: Removing unused section '.data' in file 'libphobos2.a(demangle_b9_81f.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(demangle_b9_81f.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_104_713.o)' ld: Removing unused section '.deh_eh' in file 'libphobos2.a(thread_104_713.o)' ld: Removing unused section '.data' in file 'libphobos2.a(thread_119_155.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__341_c78.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__344_c36.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__345_be5.o)' ld: Removing unused section '.minfo' in file 'libphobos2.a(object__33f_b6c.o)'
Comment #7 by hoganmeier — 2013-07-23T02:28:14Z
As far as I remember the flag works fine with gdc.
Comment #8 by code — 2014-05-23T00:54:23Z
There is a potential to reduce the binary size and gain speedups from this.
Comment #9 by code — 2014-05-25T01:00:26Z
It should be possible to put the EH tables and ModuleInfos into section groups, so the linker wouldn't dismiss them even though they aren't referenced explicitly. http://docs.oracle.com/cd/E19683-01/816-1386/chapter7-26/index.html
Comment #10 by code — 2014-05-27T22:09:51Z
OK, group sections didn't work out too well, so I just added fake references to the .deh_eh and .minfo sections in the dso startup code. https://github.com/D-Programming-Language/dmd/pull/3597
Comment #11 by blah38621 — 2014-05-27T22:21:10Z
It would also be nice if a dmd equivalent of -fdata-sections and -ffunction-sections was supported by dmd, but the issue with that is quite simple; optlink.
Comment #12 by code — 2014-05-27T23:44:58Z
(In reply to Orvid King from comment #11) > It would also be nice if a dmd equivalent of -fdata-sections and > -ffunction-sections was supported by dmd, but the issue with that is quite > simple; optlink. If you build a -lib, then the compiler will put every symbol into it's own object. This is a linux bug, so it's the wrong place for an optlink rant ;).
Comment #13 by code — 2014-07-04T19:16:54Z
The R_arch_NONE solution of pinning the .deh_eh and .minfo sections in the d_dso_init function doesn't work with ld.gold because the gold linker removes sections before dragging in object files from an archive whereas the bfd linker removes sections after copying all input sections to the output sections. For ld.gold one would need to pin the .deh_beg/.deh_eh/.deh_end and the .minfo_beg/.minfo/.minfo_end sections in every object file of an archive. At best the pinning would be done from the associated symbol (e.g. function for .deh and ModuleInfo for .minfo).
Comment #14 by code — 2014-07-04T19:28:57Z
I don't see how pinning the ModuleInfo reference from the ModuleInfo itself would work, as there might not be any direct references to the ModuleInfo. In fact, unless your module makes calls to _d_array_bounds or so, it's even rather unlikely that such a reference that would keep the ModuleInfo alive exists. Thus, the global ctor needs to keep the ModuleInfo alive (via the .minfo ref), not the other way round.
Comment #15 by code — 2014-07-04T19:37:00Z
(In reply to David Nadlinger from comment #14) > I don't see how pinning the ModuleInfo reference from the ModuleInfo itself > would work, as there might not be any direct references to the ModuleInfo. > In fact, unless your module makes calls to _d_array_bounds or so, it's even > rather unlikely that such a reference that would keep the ModuleInfo alive > exists. Thus, the global ctor needs to keep the ModuleInfo alive (via the > .minfo ref), not the other way round. ModuleInfos are exported global symbols, so the linker should not remove them.
Comment #16 by code — 2014-07-04T19:49:25Z
Another problem that I have is that ld.gold with --gc-sections doesn't copy the .minfo_beg/.minfo_end sections from an archive object, so it breaks the section brackets even when all .minfo* sections are pinned.
Comment #17 by code — 2014-07-04T22:25:15Z
(In reply to Martin Nowak from comment #15) > ModuleInfos are exported global symbols, so the linker should not remove > them. I was under the impression that --gc-sections indeed does this when linking an executable. Default visibility on its own is not enough to keep a symbol (and thus its section) alive, unless it is required to resolve an undefined symbol from a linked shared object. Maybe we have a different understanding of what an "exported symbol" is, though. (In reply to Martin Nowak from comment #16) > Another problem that I have is that ld.gold with --gc-sections doesn't copy the .minfo_beg/.minfo_end sections from an archive object, so it breaks the section brackets even when all .minfo* sections are pinned. What precisely do you refer to as "archive object"? An object file pulled in from a static library? As we discussed a while ago, for LDC I currently emit one unique global ctor per object file (as we emit one section per text/data symbol like -ffunction-sections, this is not quite as bad as it maybe would be for dmd -lib, even though still a bit wasteful). As .ctors are roots for the linker's live section graph, I can conveniently pin the bracketing symbols as well as the ModuleInfo reference itself that way. The whole "design" was purely a workaround for LLVM bugs/limitations, but it lead to LDC passing the test suite [*] using both ld.bfd and ld.gold without too much effort. As mentioned above, LDC currently generates quite a bit of cruft in the executable due to unneeded symbols in .minfo_beg/.minfo_end and all the duplicate global ctors, but it's still better than not being able to use --gc-sections at all. On Linux x86_64, our static release-mode binaries are on average 1/4 the size of DMD's for small programs now (Git master vs. Git master, which isn't entirely fair because we are still on 2.065, of course). [*] Except for the module conflict check in druntime being broken due to copy relocations.
Comment #18 by code — 2014-07-05T16:01:49Z
(In reply to David Nadlinger from comment #17) > I was under the impression that --gc-sections indeed does this when linking > an executable. Default visibility on its own is not enough to keep a symbol > (and thus its section) alive, unless it is required to resolve an undefined > symbol from a linked shared object. Maybe we have a different understanding > of what an "exported symbol" is, though. Right, gc-sections doesn't care about visibility, but the ModuleInfos are not emitted to individual sections (.rodata or .text) so they won't get removed unless they are the only symbols in .rodata/.text. > (In reply to Martin Nowak from comment #16) > > Another problem that I have is that ld.gold with --gc-sections doesn't copy the .minfo_beg/.minfo_end sections from an archive object, so it breaks the section brackets even when all .minfo* sections are pinned. > > What precisely do you refer to as "archive object"? An object file pulled in > from a static library? Yes, object files from an archive. It's probably the same for normal objects. With --gc-sections the ld.gold linker seems to only copy sections that contain referenced symbols. I can also reference .minfo_beg/.minfo/.minfo_end in each ctor, but for some reason the order for the output sections isn't preserved. > On Linux x86_64, our static release-mode binaries > are on average 1/4 the size of DMD's for small programs now Interesting, dmd uses a section per function by default, but for unknown reasons --gc-sections doesn't have a huge effect. https://github.com/D-Programming-Language/dmd/pull/3597#issuecomment-44671223 I'd like to give the linker as good information as possible. For example when a functions isn't used the linker should strip the associated EH data. Likewise ModuleInfo is needed only when any data or function of a module end up in a DSO.
Comment #19 by code — 2014-07-05T16:32:01Z
(In reply to Martin Nowak from comment #18) > I can also reference .minfo_beg/.minfo/.minfo_end in each ctor. Actually this doesn't work with ld.gold because dmd only uses a single ctor per DSO (COMDAT) and ld.gold will merge the ctors before checking their references. So I only end up with the .minfo* sections of the first object file.
Comment #20 by code — 2014-07-05T23:36:40Z
(In reply to Martin Nowak from comment #19) > Actually this doesn't work with ld.gold because dmd only uses a single ctor > per DSO (COMDAT) and ld.gold will merge the ctors before checking their > references. > So I only end up with the .minfo* sections of the first object file. This was the reason for me to switch to emitting one ctor per module (due to an LLVM implementation quirk, the situation was a bit different and I already ran into this problem with ld.bfd, but it was more or less the same). Of course, it's an ugly and hacky approach, but it seems to work for now. The more beautiful option (doesn't apply to the pin-required-EH-tables-from-function, of course) seems to be to use a custom linker script for generating the bracketing symbols as well as KEEP()ing the .minfo section. Because of INSERT and implicit linker scripts, this probably could be made to work, but ensuring that this also works with ld.gold and doesn't break any user expectations was a can of worms I decided not to open just yet.
Comment #21 by code — 2014-07-09T17:55:57Z
There is an additional complication: ld.bfd turns __bss_start/_end into local symbols when passing --gc-sections. This breaks the module collision check in druntime, as discussed here: http://forum.dlang.org/post/[email protected]. The linked discussion is about LDC in particular, but from a few preliminary tests, DMD also seems to be affected. The root cause for this behavior seems to be this change in binutils 2.19: https://sourceware.org/bugzilla/show_bug.cgi?id=13683. It's hard to tell whether this is a bug in ld or not, but either way we'll have to live with it. ld.gold is not affected.
Comment #22 by code — 2014-07-09T23:39:18Z
(In reply to David Nadlinger from comment #21) > There is an additional complication: ld.bfd turns __bss_start/_end into > local symbols when passing --gc-sections. […] LDC now uses special weak symbols, strongly defined in the D entry point module, to avoid this problem altogether: https://github.com/ldc-developers/druntime/commit/f57df3f586ba445b94b167106f82a807c0f1738e https://github.com/ldc-developers/ldc/commit/4abdec752eed1d8eeff116251fdf8c3733927704
Comment #23 by Marco.Leise — 2016-02-01T16:18:26Z
Issue persists with dmd-2.070 on amd64. For example compiling dub fails.
Comment #24 by bugzilla — 2016-05-09T20:11:13Z
DMD on Linux/Elf/OSX now uses Dwarf exception handling info, so the deh sections are no longer an issue.
Comment #25 by Marco.Leise — 2017-04-02T23:07:02Z
I haven't thoroughly tested it, but at least dub works with --gc-sections since - I believe - dmd-2.072. So from my side this issue can be closed.
Comment #26 by code — 2017-04-02T23:13:27Z
(In reply to Marco Leise from comment #25) > I haven't thoroughly tested it, but at least dub works with --gc-sections > since - I believe - dmd-2.072. So from my side this issue can be closed. Are you sure it works with both ld.bfd and ld.gold and against a static as well as shared runtime? This should be the minimum set of tests before considering this closed, although the set of linker bugs also differs between the various distros (i.e. linker versions) out there.
Comment #27 by Marco.Leise — 2017-04-03T00:11:57Z
Shame on me, I only tested with ld.gold and shared Phobos library. I extended the 1x1 test matrix by a static Phobos library on one axis and ld.bfd on the other and found that in all 4 cases dub greets me with the expected "Neither a package ..." message. (I used dmd and Phobos in version 2.073.2 and binutils-2.26.1 on Gentoo.)
Comment #28 by code — 2017-04-03T00:26:11Z
(In reply to Marco Leise from comment #27) > I extended the 1x1 test matrix by a static Phobos library on one axis and > ld.bfd on the other and found that in all 4 cases dub greets me with the > expected "Neither a package ..." message. > (I used dmd and Phobos in version 2.073.2 and binutils-2.26.1 on Gentoo.) That's quite promising already. From what it took to get --gc-sections working on LDC it would be a minor miracle if it suddenly started working on DMD as well (unless we have been slowly porting over the required changes by accident). This is also the reason why I asked about different configurations; this is not just a "normal" backend issue, but the druntime module registration code is heavily affected by a few --gc-sections linker bugs/peculiarities. When implementing this on LDC, I only found out about the bigger part of the issues when pushing the changes to CI resp. from user reports in the subsequent beta. If the flag really works on DMD now, it would be nice to enable it by default to drastically reduce binary sizes (LDC has been shipping with --gc-sections on for a couple of releases now). Building the test suite on the different CI systems and having people test it during pre-release would be a good stress test as well.
Comment #29 by razvan.nitu1305 — 2019-07-13T12:10:01Z
I haven't been able to reproduce any of the issues posted. It seems that this issue has been fixed. Closing as WORKSFORME. Please reopen if you find any other issues.