Bug 25081 - Discrepancy between VMA and LMA after ALIGN
Summary: Discrepancy between VMA and LMA after ALIGN
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: ld (show other bugs)
Version: 2.34
: P2 normal
Target Milestone: ---
Assignee: Alan Modra
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-10-08 12:55 UTC by Joey Ye
Modified: 2019-10-10 22:43 UTC (History)
1 user (show)

See Also:
Host:
Target: 2019-10-09 0:00
Build:
Last reconfirmed: 2019-10-09 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joey Ye 2019-10-08 12:55:08 UTC
Following case fails with trunk 2.33 on x86_64 and arm, and seems to be working with 2.27:

$ cat a.c
int g = 4;
int main()
{
    return g;
}
$ cat s.ld
MEMORY
{
  FLASH (rx) : ORIGIN = 0, LENGTH = 0x10000000
  RAM (rwx) : ORIGIN = 0x10000000, LENGTH = 0x10000000
}
ENTRY(main)
SECTIONS
{
    .text :
    {
        *(.text*)
        /* Force text section end unaligned */
	. = ALIGN(16);
        LONG(0)
        LONG(0)
        LONG(0)
    } > FLASH
    .sec1 : ALIGN(16)
    {
	*(.section_noexist)
	/* Aligning LMA in a leading empty section, for some reason
           doesn't align VMA according */
        . = ALIGN(16);
	__some_symbol = .;
    } > FLASH

    .sec2 :
    {
        /* To reproduce following must match one or more empty sections */
        /* Discrepancy between VMA and LMA starts from here */
	*(.bss*)
    } > FLASH

    .sec3 :
    {
        /* Discrepancy between VMA and LMA remains here */
	LONG(0)
	LONG(0)
    } > FLASH

    .data :
    {
        *(.data*)
    } > RAM AT> FLASH
    .bss :
    {
        *(COMMON)
    } > RAM
}
$ ld -v
GNU ld (GNU Binutils) 2.33.50.20191008
$ gcc -c a.c
$ ld -T s.ld -Map=a.map a.o -o a.out
ld: section .data LMA [0000000000000060,0000000000000063] overlaps section .sec3 LMA [0000000000000060,0000000000000067]
Comment 1 Tamar Christina 2019-10-09 11:05:39 UTC
Ah I see Alan has already claimed it,

if it helps I've bisected it to

commit 14ea2c1b230a62f312346fb16716b3dd4850815b
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Tue Jan 17 19:13:29 2017 +0000

    ld: Track changes to default region LMA even for empty sections

    Given a linker script fragment like this:

       SECTIONS {
         . = 0x1000;
         .text   : AT(0x100) { *(.text)   }
         .data   : AT(0x200) { *(.data)   }
         .rodata : AT(0x300) { *(.rodata) }
       }

    and an input file containing sections, '.text', '.data.1', and
    '.rodata', then we'd expect the linker to place '.text' and '.rodata' in
    the obvious way, and the '.data.1' orphan section would be located after
    the '.data' section (assuming similar section properties).

    Further, I believe that the expectation would be that the LMA for the
    orphan '.data.1' section would start from 0x200 (as there is no '.data'
    content).

    However, right now, the LMA for '.data.1' would be 0x101, following on
    from the '.text' section, this is because the change in LMA for the
    '.data' section is not noticed by the linker, if there's no content in
    the '.data' section.

    What can be even more confusing to a user (though the cause is obvious
    once you understand what's going on) is that adding some content to
    '.data' will cause the orphan '.data.1' to switch to an LMA based off of
    0x200.

    This commit changes the behaviour so that an empty section that is in
    the default lma region, and sets its lma, will adjust the lma of the
    default region, this change will then be reflected in following sections
    within the default lma memory region.

    There's a new test to cover this issue that passes on a range of
    targets, however, some targets generate additional sections, or have
    stricter memory region size requirements that make it harder to come
    up with a generic pass pattern, that still tests the required
    features.  For now I've set the test to ignore these targets.

    ld/ChangeLog:

            * ldlang.c (lang_size_sections_1): Shortcut loop only after
            tracking changes to the default regions LMA.
            * testsuite/ld-elf/orphan-9.ld: Extend header comment.
            * testsuite/ld-elf/orphan-10.d: New file.
            * testsuite/ld-elf/orphan-10.s: New file.
            * NEWS: Mention change in behaviour.
Comment 2 Sourceware Commits 2019-10-09 11:30:55 UTC
The master branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8610e0fd93ea253f9beb9ebb6e50e8807ed83327

commit 8610e0fd93ea253f9beb9ebb6e50e8807ed83327
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Oct 9 21:25:25 2019 +1030

    PR25081, Discrepancy between VMA and LMA after ALIGN
    
    The testcase in the PR has two empty output sections, .sec1 with an
    ALIGN and symbol assignment, and .sec2 just with an empty input
    section.  The symbol assignment results in .sec1 being kept, but
    because it is empty this section doesn't take space from the memory
    region as you might expect from the ALIGN.  Instead the next section
    .sec2, has vma/lma as if .sec1 wasn't present.  However, .sec2 is
    discarded and os->ignored set, which unfortunately meant that dot
    wasn't set from .sec2 vma.  That in turn results in .sec2 lma being
    set incorrectly.  That vma/lma difference is then propagated to
    .sec3 where it is seen as an overlap.
    
    	PR 25081
    	* ldlang.c (lang_size_sections_1): Set lma from section vma
    	rather than dot.
Comment 3 Alan Modra 2019-10-09 11:37:13 UTC
Fixed, hopefully.
Comment 4 Joey Ye 2019-10-09 14:48:44 UTC
Confirmed.
Comment 5 Sourceware Commits 2019-10-10 22:43:02 UTC
The binutils-2_33-branch branch has been updated by Alan Modra <amodra@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=4526ef25548f141529c3a31129e7962d69258d45

commit 4526ef25548f141529c3a31129e7962d69258d45
Author: Alan Modra <amodra@gmail.com>
Date:   Wed Oct 9 21:25:25 2019 +1030

    PR25081, Discrepancy between VMA and LMA after ALIGN
    
    The testcase in the PR has two empty output sections, .sec1 with an
    ALIGN and symbol assignment, and .sec2 just with an empty input
    section.  The symbol assignment results in .sec1 being kept, but
    because it is empty this section doesn't take space from the memory
    region as you might expect from the ALIGN.  Instead the next section
    .sec2, has vma/lma as if .sec1 wasn't present.  However, .sec2 is
    discarded and os->ignored set, which unfortunately meant that dot
    wasn't set from .sec2 vma.  That in turn results in .sec2 lma being
    set incorrectly.  That vma/lma difference is then propagated to
    .sec3 where it is seen as an overlap.
    
    	PR 25081
    	* ldlang.c (lang_size_sections_1): Set lma from section vma
    	rather than dot.
    
    (cherry picked from commit 8610e0fd93ea253f9beb9ebb6e50e8807ed83327)