ld: Allow symbols from PROVIDE to be use in MEMORY regions
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 7 Oct 2020 13:27:56 +0000 (14:27 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 16 Oct 2020 12:43:49 +0000 (13:43 +0100)
commit874ef0386fe438d654f0c3c230d4a9d0c4db9213
treed60d334d383bd1a1476da0341ce543583417fb74
parent54874444da47cab42de1d0b22e7009e7ca3eb6f2
ld: Allow symbols from PROVIDE to be use in MEMORY regions

I wanted to write a linker script like this:

  PROVIDE(mem_origin = 0x1000);
  PROVIDE(mem_length = 0x1000);

  MEMORY
  {
    REGION : ORIGIN = mem_origin, LENGTH = mem_length
  }

  ....

Then when I link using this script I can optionally supply:

  --defsym=mem_origin=..... --defsym=mem_length=....

to override the defaults.

And though passing `--defsym' does work, if I remove the use of
`--defsym' and just rely on the defaults I get an error:

  ld-new: invalid origin for memory region REGION

Interestingly, if I make the above error non-fatal and dump a linker
map file I see that (a) REGION has origin 0x0, and length 0xffff...,
and (b) the symbol from the PROVIDE is provided.

An examination of ldlang.c:lang_process shows us what the issue is,
the origin and length of all memory regions are set as a result of a
single call to lang_do_memory_regions, this call is done after calling
open_input_bfds.

During the open_input_bfds call provide statements can be converted to
provided statements if we know that the assigned symbol is needed, but
for symbols that are only used in the memory regions we are unaware
that we need these symbols.

What I propose in this patch is to make two calls to
lang_do_memory_regions, in the first call we process the expressions
for the origin and length fields of each region, however, errors,
especially undefined symbols, will be ignored.  The origin and length
values are not updated.  However, by evaluating the expressions any
symbols we need will be added to the symbol table.

Now when we call open_input_bfds, when we process the provide
statements, we will see that the assigned symbol is needed add its new
value to the symbol table.

Finally we reach the original call to lang_do_memory_regions, in
this (now second) call we again process the expressions, and this time
update the origin and length values.  Any errors encountered now are
reported to the user.

ld/ChangeLog:

* ldlang.c (lang_process): Add extra call to
lang_do_memory_regions, and pass parameter.
(lang_do_memory_regions): Add parameter, only define origin and
length when requested.  Reindent.
* testsuite/ld-scripts/provide-10.d: New file.
* testsuite/ld-scripts/provide-10.map: New file.
* testsuite/ld-scripts/provide-11.d: New file.
* testsuite/ld-scripts/provide-11.map: New file.
* testsuite/ld-scripts/provide-12.d: New file.
* testsuite/ld-scripts/provide-12.map: New file.
* testsuite/ld-scripts/provide-9.d: New file.
* testsuite/ld-scripts/provide-9.map: New file.
* testsuite/ld-scripts/provide-9.t: New file.
ld/ChangeLog
ld/ldlang.c
ld/testsuite/ld-scripts/provide-10.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-10.map [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-11.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-11.map [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-12.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-12.map [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-9.d [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-9.map [new file with mode: 0644]
ld/testsuite/ld-scripts/provide-9.t [new file with mode: 0644]