ld --gc-sections should work for PE-COFF on MinGW.
MSVC has supported this feature (under the name of /OPT:REF) since time began.
As a result, GCC generates significantly larger executables than MSVC.
Created attachment 5301 [details]
implement --gc-sections for coff (first shot)
- Mostly a copy and paste from elflink.c to cofflink.c
- This is only a first try; however, it reduces the size of a statically compiled wxWidgets app from 5.1 MB to 3.8 MB, so it does something useful for me; YMMV
- I’m by far no COFF export; some linker guru will need to review the patch and comment on all the "FIXME" comments
- I have not yet tried to generate a DLL with gc enabled
- Somehow the entry symbol does not get into _bfd_coff_gc_keep so no gc mark root is available; as a workaround, "-Wl,--undefined=_WinMainCRTStartup" should be used
I changed the Host/Target/Build to include x86_64 and removed the Build specification, because it's not relevant.
This is very useful. A static Qt binary gets from 12MB to 8MB with this.
I found problem with the patch: it will remove the .rsrc section too. This section should be kept, as it contains the application icon, version information, etc.
Created attachment 5960 [details]
Add KEEPs to the linker script template
Very nice. The patch saves me from some boring works splitting source files per function.
- entry symbol
I think "-Wl,-e" works and is better than "-Wl,--undefined" in this case.
For PE-COFF targets, the default entry symbol is used according to the subsystem,
unless explicitly specified by a command-line or a linker script.
And the code setting the gc root (search gc_sym_list in ldlang.c) ignores the linker's default.
MinGW-GCC's default specs file gives -e option to the linker only if the
generating file is a DLL, so for now the linker's default is used for EXE
unless you specify the explicit one.
I don't know whether ignoring the default entry symbol makes sense.
Anyway the current manual says --gc-sections requires -Wl,-e or -Wl,-u
or using KEEPs in a linker script to keep sections.
- .rsrc section
Default linker scripts(generated from pe.sc) lack KEEP commands.
The attached patch may fix it.
It seems to dll build can't use the patches, even if using -Wl,--undefined=_DllMainCRTStartup. Though the dll is generated successfully, we can't use other exes to link the dll (running the exe can't show anything).
How do we make the patches generate the dll correctly?
I try to keep eh_frame section, then the dll build can work (I test it in wxWidgets 2.8.12 Release Mono Unicode Dll).
So we should find some methods to keep some sections of eh_frame.
I was dissatisfied with my DLL size being an order of magnitude bigger than it should be and the search lead me to this bug report. I have just tried the provided patch with binutils-2.23.2 and the initial builds of my statically linked DLL failed with a section named "COMMON" missing. I have changed the cofflink.c to exclude this section from removal and it finally built. However, the functions from my DLL crash so probably something got badly removed. After debugging the removal process by -Wl,--print-gc-sections I also prevented .eh_frame from removal but my application still crashed. At this point I feel only despair as COFF is basically black magic to me. Does anybody work on this feature or have more up to date patches? I would happily do some testing and/or help in other ways.
Found several discussions linking to this page, but none mentioning a somewhat newer patch posted at https://sourceware.org/ml/binutils/2012-08/msg00386.html. Adding that link here for any future readers...
*** Bug 260998 has been marked as a duplicate of this bug. ***
Seen from the domain http://volichat.com
Page where seen: http://volichat.com/adult-chat-rooms
Marked for reference. Resolved as fixed @bugzilla.
Please, no news on this subject yet? I'm sure this is a very important feature for us Windows GCC users (MingW / TDM), and I would help if I had the knowledge.
We have tons of people on the internet talking about how GCC ports to Windows generate bloated code in comparison to MSVC, and this single implementation would help a lot, mainly on projects linked against big libs, like wxWidgets, QT and others.
The master branch has been updated by Nick Clifton <email@example.com>:
Author: Kai Tietz <firstname.lastname@example.org>
Date: Fri Jul 3 15:50:29 2015 +0100
Add experimental support for --gc-sections with COFF and PE based targets.
bfd * coffcode.h (coff_bfd_gc_sections): Define default
to bfd_coff_gc_sections function.
* cofflink.c (init_reloc_cookie): Copy and adjust coff
related code about gc-sections from elflink.c to here.
* libcoff.h (coff_reloc_cookie): New struct.
(bfd_coff_gc_sections): New prototype.
(coff_gc_mark_hook_fn): New type.
ld * scripttempl/pep.sc: Mark .idata*, .CRT*, .tls*,
.rsrc*, .init, .ctor*, .dtor*, .fini, .jcr,
.eh_frame, .pdata. .xdata, and .gcc_except_table sections
* scripttempl/pe.sc: Likewise.
(In reply to Eduardo Luis Marcovecchio from comment #12)
> Please, no news on this subject yet?
Sorry for dropping the ball on this one.
Unfortunately I do not have an easy way of testing COFF/PE binaries at the moment, so I am going to ask for your help. I have checked in Kai's patch to the mainline binutils sources on an experimental basis. Please could you try it out and if/when you encounter problems, please could you file them here. A testcase to reproduce the problem would be very helpful, as would the output from the linkers --print-gc-sections option.
Thanks a lot, Nick!
I will do that as soon as possible, probably recompiling wxWidgets with -ffunction-sections and -fdata-sections, then linking a simple app with -Wl and --gc-sections enabled.
If anyone has suggestions on other libs to test, I will be glad to test with them too.
I would say Qt and Boost could also be used as a testbed. Qt doesn't have a test suite though, but I guess compiling the examples might be a first indication. Boost has a test suite.
(Just FYI - I am going to be on vacation next week, so I will not be able to respond to bug reports until the week after ...)
I have given this a spin with building the OVMF firmware (EDK2/Tianocore)
In my case, I need to pass -fno-asynchrounous-unwind-tables to actually get some noticeable improvement, since the unwind info seems to hold some live references to code that is otherwise unused. But with that added, it works beautifully.
(using GCC 4.9.3 + binutils-gdb 7.10 branch)
I tried this now with gcc 5.3.0 and binutils 2.26.
For x64 I needed -fno-asynchrounous-unwind-tables as described in the last comment (but not for x86).
Additionally I had to use --require-defined=XXX for at least one of my exported functions, otherwise the generated dll is almost empty (both x86 and x64).
The core issue here seems to be resolved in 2.26, but --gc-sections still isn't taking symbols exported by --version-script into account.