<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - section with start address causes lld to expand the previous region incorrectly"
   href="https://bugs.llvm.org/show_bug.cgi?id=38624">38624</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>section with start address causes lld to expand the previous region incorrectly
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>lld
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>All Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>djc@djc.id.au
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Say you are linking for an embedded target, with two disjoint memory regions
FLASH and RAM. If you declare a section with a specific start address in a new
memory region, lld incorrectly tries to expand the *previous* section's memory
region to reach the specified address.

Here is a reproducer, using lld 7.0.0rc1:

$ cat test.c 
void _start(void) {
}
$ gcc -nostdlib -nostartfiles -c test.c
$ cat link.x 
MEMORY
{
  FLASH : ORIGIN = 0x20400000, LENGTH = 512M
  RAM : ORIGIN = 0x80000000, LENGTH = 16K
}
SECTIONS
{
  .text :
  {
    *(.text);
  } > FLASH

  .rodata :
  {
    *(.rodata);
  } > FLASH

  PROVIDE(_sbss = ORIGIN(RAM));
  .bss _sbss :
  {
    *(.bss);
  } > RAM

  .data : AT(LOADADDR(.rodata) + SIZEOF(.rodata))
  {
    *(.data);
  } > RAM

  /DISCARD/ :
  {
    *(.eh_frame);
  }
}
$ lld -flavor gnu -Tlink.x -o test test.o
lld: error: section '.text' will not fit in region 'FLASH': overflowed by
1069547520 bytes

The problematic part is here:

  PROVIDE(_sbss = ORIGIN(RAM));
  .bss _sbss :
  {

where it specifies the _sbss symbol as the start address for .bss. Lld is
trying to expand the FLASH region up to reach this address, but it's wrong
because .bss is going into the RAM region not FLASH. It fails because FLASH is
not large enough.

If you remove the start address for .bss, namely:

  .bss :
  {

then it links successfully and you get the expected result (.bss is placed at
the beginning of the RAM region, and everything fits normally).</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>