LLD: location counter inside objects

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 the SECTIONS 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?

The majority of linker scripts that I’ve seen explicitly add to the location counter, this should give the same behaviour on ld.bfd and ld.lld.

SECTIONS {
  .text 0x2000 : {
    . = .+ 0x10;
    *(.text)
  }

For lld we already know that every . = will error if is lower than the current location counter so we can rule those cases out. We would be left with cases where is greater than the location counter where a discrepancy could be observed.

Personally I think the set of LLD only linker scripts where that occurs are likely rare enough that fixing the incompatibility is worthwhile. If the patch is simple then it may just be worth submitting it for review. If it turns out not to be worthwhile we can add to the known discrepancies.