The binutils documentation on linker scripts says:
Note:
.
actually refers to the byte offset from the start of the current containing object. Normally this is theSECTIONS
statement, whose start address is 0, hence.
can be used as an absolute address. If.
is used inside a section description however, it refers to the byte offset from the start of that section, not an absolute address.
The GNU ld behaviour is consistent with that. For instance, given this linker script:
SECTIONS {
.text 0x2000 : {
. = 0x10;
*(.text)
}
}
For GNU LD that means that the .text
output section starts at 0x2000
, contains 0x10
bytes of “padding” (absolute location = 0x2000 + 0x10
) followed by the contents of .text
input section.
LLD interprets that as the .text
output section starts at 0x2000
, set absolute location to 0x10
, and then complains you’re moving the location counter backward. In fact, that linker script is from a test case testing for that error specifically.
This discrepancy becomes quite problematic when moving between ld and lld.
The LLD documentation says:
The LLD implementation policy is to implement linker script features as they are documented in the ld manual We consider it a bug if the lld implementation does not agree with the manual and it is not mentioned in the exceptions below.
I don’t see that discrepancy listed in the “exceptions below”. On the other hand, I’m not sure it’s feasible to change to change that LLD behavior now. Technically it seems easy (I have an unsubmitted patch that seems to fix this issue), but I don’t know if it would be too much of a compatibility concern to change this behavior now.
Any thoughts?