Description of problem: Fedora 28 GCC's C compiler 8.1.1 generates 41680 Aug 28 14:51 xfstabxref Running strip for xfstabxref 35280 Aug 28 14:52 xfstabxref However Running strip against gcc 8.2.x for Fedora 29 yields same xfstabxref size but strip size is 45k in size. I typically run strip against all executables and with F29's gcc compiler. I am having 10k extra space used by executable. Version-Release number of selected component (if applicable): 8.2.1 gcc and related strip executable. How reproducible: Steps to Reproduce: 1.xfstabxref : xfstabxref.c $(LIB) dictionary.h #Makefile ${CC} ${CFLAGS} $< $(LIB) -o $@ 2. strip: #shows before/after @for var in ${PROGS} ; \ do \ ls -l $${var} ; \ /usr/bin/strip $${var} ; \ ls -l $${var} ; \ /usr/bin/echo " " ; \ done ; 3. Actual results: Expected results: Additional info:
/usr/bin/strip
(In reply to Leslie Satenstein from comment #0) > Version-Release number of selected component (if applicable): > > 8.2.1 gcc and related strip executable. There is no "related strip executable" because it's not part of gcc. Please provide the proper version info, e.g. by running: rpm -qf /usr/bin/strip /usr/bin/gcc
The version info isn't the only thing totally missing from this, there are no details what exactly you are compiling and whether the problem is in code growth from gcc (I find that quite unlikely, as it is only a very minor difference in between, just 20 days of gcc bugfixing), or if the difference is in the linker between f28 and f29. If it was built using rpm, my first guess would be the annobin plugin and sections it creates, otherwise I wonder if the new -z separate-code isn't the default in the linker. Guess best information would be run readelf -Wa on the f28 and f29 unstripped and stripped binaries and attach those here, then it can be easily compared what grew how much.
For some reason, I did not read your response until I started to look at my active bug report list. My code is pure command line C, with malloc/free, directory reads, and link following. Code can be attached if desired.
Recently I am unable to install F29 Gnome beta. It is not F29 Anaconda or DNF code that prevents the installation, it is one or more rpms that anaconda pulls in that crash dnf which in turn crashes anaconda. Follow up to strip when I can do it. Currently /usr/bin/strip is from binutils-2.29.1-23.fc28.x86_64 Will update with more info when I can clean install F29. Please redirect to binutils.
Hi Leslie, Please can you provide the unstripped executable for testing ? I strongly suspect that the reason will turn out to be a new feature of the linker which is putting code and read-only data into different segments in the executable. This makes the program safer - because the code segment can be marked as executable, whereas the read-only data segment can be marked as non-executable - but it does lead to an increase in the size of the program, because the segments need to be page aligned. You could test this for yourself by adding "-wl,-z,-noseparate-code" to your command line and see if this results in a smaller binary. Cheers Nick
Created attachment 1482376 [details] fstabxref A program to format the /etc/fstab The compiled executable created with 8.1 compiler
Created attachment 1482377 [details] xstabxref the stripped version of fstabxref based on the 8.1 compiler the stripped version of fstabxref based on the 8.1 compiler
Created attachment 1482378 [details] with the 8.2 C compiler output
Created attachment 1482379 [details] stripped version using the 8.2 c compiler CC=gcc CFLAGS= -O3 -Wall -Wextra -Fpic
Created attachment 1482381 [details] example of program output of a processed /etc/fstab
Hi Leslie, This is exactly as I predicted. The Fedora 28 binary (fstabxref) only has two loadable segments in it, one of which contains both the code and the read-only data, and one of which contains the writeable data. The segment containing the code/read-only data has the R (read) and E (execute) permission flags, which means that in theory, if there are sequences in the read-only data that looked like instructions, an attacker might be able to make use of them. The Fedora 29 binary (fstabxref1) has four loadable segments, one containing relocations, one containing only code, one containing read-only data, and one containing writeable data. The segment containing the read-only data just has the R (read) permission flag, so it cannot be executed as if it were code. % readelf --wide --segments fstavxref* File: fstabxref [...] Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align [...] LOAD 0x000000 0x0000400000 0x0000400000 0x006b00 0x006b00 R E 0x200000 LOAD 0x006e10 0x0000606e10 0x0000606e10 0x0013b1 0x0045a8 RW 0x200000 [...] Section to Segment mapping: 02 [...] .text .fini .rodata [...] 03 [...] .data [...] [...] File: fstabxref1 [...] Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0x0000400000 0x0000400000 0x000e18 0x000e18 R 0x1000 LOAD 0x001000 0x0000401000 0x0000401000 0x0039f5 0x0039f5 R E 0x1000 LOAD 0x005000 0x0000405000 0x0000405000 0x002290 0x002290 R 0x1000 LOAD 0x007e10 0x0000408e10 0x0000408e10 0x0013b1 0x0045a8 RW 0x1000 [...] Section to Segment mapping: 02 [...] .rela.dyn .rela.plt 03 [...] .text [...] 04 .rodata [...] 05 [...] .data [...] [...] My advice would be to either accept the increase in size - because it increases the security of your programs - or else to link them with the -Wl,-z,noseparate-code command line option. This will give you back the binary sizes you expect, at the cost of some security hardening of your programs. Cheers Nick
Nick, do we really need 4 PT_LOAD segments rather than just 3 for -z separate-code? I mean, can't we simply use a different linker script for -z separate-code, where sections will be reordered such that all the ones that need to be read-only non-executable go first (first PT_LOAD), then the read-only/executable ones (second PT_LOAD) and finally like before the read-write/non-executable ones including relro ones at the start? E.g. looking at bash in f30: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x02bf60 0x02bf60 R 0x1000 LOAD 0x02c000 0x000000000002c000 0x000000000002c000 0x0a74b5 0x0a74b5 R E 0x1000 LOAD 0x0d4000 0x00000000000d4000 0x00000000000d4000 0x033ff0 0x033ff0 R 0x1000 LOAD 0x108d50 0x0000000000109d50 0x0000000000109d50 0x00b814 0x0153d8 RW 0x1000 02 .interp .note.gnu.property .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 03 .init .plt .plt.sec .text .fini 04 .rodata .eh_frame_hdr .eh_frame 05 .init_array .fini_array .data.rel.ro .dynamic .got .data .bss Can't we move .rodata, .eh_frame_hdr and .eh_frame sections after .rela.plt, to make it: 02 .interp .note.gnu.property .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .rodata .eh_frame_hdr .eh_frame 03 .init .plt .plt.sec .text .fini 04 .init_array .fini_array .data.rel.ro .dynamic .got .data .bss elf.sc already has ${SEPARATE_CODE} conditionals. In elf.sc perhaps easier made by moving the .init ... ${RELOCATING+PROVIDE (${ETEXT_NAME} = .);} stuff if SEPARATE_CODE from the current location to after all the read-only sections.
Hi Jakub, > Do we really need 4 PT_LOAD segments Probably not, but I really do not want to rock the boat here. Changing the default linker script is bound to cause problems somewhere, even if I cannot say exactly where. If a package maintainer is really interested in reducing the size of their binaries, as Leslie clearly is, then they are free to copy the default script, modify it as they wish, and then use that for their linking. But I would much rather that this kind of thing was the exception to the rule, rather than the default. Basically I do not want to break Fedora (again!) Cheers Nick
Sure, this is something that shouldn't be done as a Fedora change, but upstream, get tested there and put into F30 or whenever we grab the binutils that has it. I just don't have spare cycles for binutils development myself (though if needed, I could file an upstream PR).
I can wait. I have ample diskspace remaining on my 128k SSD as I made room therein by moving /var to a spinning HD. I strip all the stuff I write and to keep SSD space use to a minimum, I do likewise where I can with Fedora distributed software. I will go with the "flow" in that if the status is quo, then it is what it is, if there is a merge or relocatable RO with static RO, I can wait for that outcome. What is the status of this bug report? Pending, Closed, Won't fix ?
I would like to set CLOSED/WONTFIX, if that is OK with you.
YES, But instead of wont fix, can you check with gcc maintainers to see if they can get the parameters recognized. By the way, The above program is gcc free license. I wrote it, it is very useful if you have multiple /etc/fstab files scattered and the only reference you have is UUID=xxx or other
The recognized parms was to make the linker more efficient. the above programs are free to use and distribute.
1623218 followup Same executable, when compiled with Clang, produces a 4.5k smaller executable.
GCC version 9 and strip coexist nicely, It now works for me.