Bug 6833

Summary: Linker sometimes produces 2MB section gap
Product: binutils Reporter: Jan Kratochvil <jan>
Component: ldAssignee: Jan Kratochvil <jan>
Status: RESOLVED FIXED    
Severity: minor CC: bug-binutils
Priority: P3    
Version: 2.19   
Target Milestone: ---   
Host: x86_64-unknown-linux-gnu Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu Last reconfirmed:
Attachments: Fix

Description Jan Kratochvil 2008-08-11 12:30:17 UTC
The produced file sometimes have a 2MB zeroed gap between sections.

Actual results:
-rwxr-xr-x 1 root root 2475480 Aug  7 17:12 cups-1.3.7-2.x86_64/usr/sbin/cupsd*

Expected results:
-rwxr-xr-x 1 root root 355264 May 13 13:14 /usr/sbin/cupsd*

Additional info:
Section Headers:
[Nr] Name                 Type         Addr             Off      Size     ES
Flags Lk Inf Al
...
[15] .eh_frame_hdr        PROGBITS     0000000000056830 00056830 00000944  0 A 
    0   0  4
[16] .eh_frame            PROGBITS     0000000000057178 00057178 00002a5c  0 A 
    0   0  8
[17] .ctors               PROGBITS     0000000000259bd0 00259bd0 00000010  0 WA
    0   0  8
[18] .dtors               PROGBITS     0000000000259be0 00259be0 00000010  0 WA
    0   0  8

On Thu, 07 Aug 2008 16:55:23 +0200, Ulrich Drepper wrote:
------------------------------------------------------------------------
This looks like a linker bug.  The .ctors section has to be on a 
separate page (given the page size assumed for the binary, which is 2M)
because it is the first writable section.  But this doesn't mean that
the same offset has to be used in the binary itself.  In fact, what
should happen is exactly what you see in the other file, namely, the the
address and file offset differ in the resulting file.
------------------------------------------------------------------------

.eh_frame ends at 0x59bd4 but .ctors starts at 0x259bd0.  This makes the runtime
mapping overlap and a whole MAXPAGE (2MB) range gets inserted into the file.

It is because lang_size_sections() condition
              if (expld.dataseg.base - (1 << max_alignment_power)
                  < old_min_base)
                expld.dataseg.base += expld.dataseg.pagesize;
does not work as OLD_MIN_BASE is there 0x200000 and for example (0x259bec - 32)
can never get under it.  Fixed OLD_MIN_BASE in the attached patch to ensure a
positive gap size for the runtime.
Comment 1 Jan Kratochvil 2008-08-11 12:31:47 UTC
Created attachment 2902 [details]
Fix
Comment 2 Jan Kratochvil 2008-08-11 12:43:01 UTC
After the fix:
[16] .eh_frame            PROGBITS     0000000000057178 00057178 00002a5c  0 A 
    0   0  8
[17] .ctors               PROGBITS     000000000025abd0 0005abd0 00000010  0 WA
    0   0  8

With the RELRO end alignment:
   08      [RELRO: .ctors .dtors .jcr .data.rel.ro .dynamic .got]
[22] .got                 PROGBITS     000000000025ba70 0005ba70 00000560  8 WA
    0   0  8
[23] .got.plt             PROGBITS     000000000025bfe8 0005bfe8 00000bc0  8 WA
    0   0  8

24 bytes before the page boundary to comply with the RELRO largest alignment 32:
[20] .data.rel.ro         PROGBITS     000000000025ac00 0005ac00 00000bc0  0 WA
    0   0 32
Comment 3 Jan Kratochvil 2008-08-21 13:14:11 UTC
http://sourceware.org/ml/binutils/2008-08/msg00182.html
http://sourceware.org/ml/binutils-cvs/2008-08/msg00117.html
	PR ld/6833
	* ldexp.c (fold_binary <DATA_SEGMENT_ALIGN>): Do not align
	EXPLD.DATASEG.MIN_BASE.
	* ldlang.c (lang_size_sections): New variable OLD_BASE.  Rename
	OLD_MIN_BASE to MIN_BASE with the former alignment from `ldexp.c'.
	Use OLD_BASE now for the minimal base check after the base decrease by
	the maximum alignment found.