[LLD] Placing more sections in same segment as data?

I’ve noticed that lld keeps the data section more isolated than the gold or bfd linkers. For example, readelf -l applied to the “same” executable linked with those three linkers reveals the following under “Section to Segment mapping”:

lld:
05 .data .got.plt .bss

gold:
03 .eh_frame .init_array .fini_array .preinit_array .dynamic .got .got.plt .data .bss

bfd:
05 .eh_frame .preinit_array .init_array .fini_array .dynamic .got .got.plt .data .bss

This separation seems to result in lld creating two LOAD RW segments whenever gold or bfd would create only one. For example, also from readelf -l output:

LOAD 0x0000000000001a80 0x0000000000203a80 0x0000000000203a80

0x00000000000002a8 0x00000000000002a8 RW 0x1000

LOAD 0x0000000000001d28 0x0000000000204d28 0x0000000000204d28

0x0000000000000060 0x000000000000015c RW 0x1000

Could someone explain why the lld behavior is different? Is there a way to make it match the gold/bfd behavior? I’ve looked through the options list and read some of the lld code, but so far have not been able to find a solution.

Thanks,

Outlook-signature_.png

Outlook-signature_.png

Outlook-signature_.png

I’ve noticed that lld keeps the data section more isolated than the gold or bfd linkers. For example, readelf -l applied to the “same” executable linked with those three linkers reveals the following under “Section to Segment mapping”:

lld:
05 .data .got.plt .bss

gold:
03 .eh_frame .init_array .fini_array .preinit_array .dynamic .got .got.plt .data .bss

bfd:
05 .eh_frame .preinit_array .init_array .fini_array .dynamic .got .got.plt .data .bss

This separation seems to result in lld creating two LOAD RW segments whenever gold or bfd would create only one. For example, also from readelf -l output:

LOAD 0x0000000000001a80 0x0000000000203a80 0x0000000000203a80

0x00000000000002a8 0x00000000000002a8 RW 0x1000

LOAD 0x0000000000001d28 0x0000000000204d28 0x0000000000204d28

0x0000000000000060 0x000000000000015c RW 0x1000

Could someone explain why the lld behavior is different? Is there a way to make it match the gold/bfd behavior? I’ve looked through the options list and read some of the lld code, but so far have not been able to find a solution.

I think this is likely to be https://reviews.llvm.org/D58892 “Split RW PT_LOAD on the PT_GNU_RELRO boundary”, which was made as part of a suggestion in a comment for a related change https://reviews.llvm.org/D56828 . The root cause of the justification is that it enables better use of .bss.rel.ro sections. Unfortunately other than turning off RELRO with -znorelo I’m not aware of an easier way to change this behaviour. It may be possible to write a linker script with a PHDRS command but I’ve not tried it. If I were to try I’d start by getting the linker script from ld.bfd --verbose, and then add a PHDRS command to it.

If there is a good case for needing the ld.bfd behaviour I suggest raising a PR, I’m thinking that this could be configurable via a command line option.

Hope this helps

Peter

Outlook-signature_.png

Outlook-signature_.png

Outlook-signature_.png

Thanks, Peter. That patch pointed me to the exact line of code that I needed to know about!

I don’t think it needs to be configurable via the command line unless others run into a problem with this change, too. I happened to be working with some other software (that I can’t change) that made some overly strict assumptions about how things were linked and it did not like having the segments split up.

-Troy

Outlook-signature_.png

Outlook-signature_.png

Outlook-signature_.png

Another thing is that 2 RW can avoid an alignment at the cost of an extra PT_LOAD (sizeof(Elf64_Phdr) = 56). You can find more information on https://reviews.llvm.org/D64906

GNU ld pads the tail of RELRO to commonpagesize (see DATA_SEGMENT_RELRO_END(, )). gold has a similar behavior.

Outlook-signature_.png

Outlook-signature_.png

Outlook-signature_.png