This change implements the solution to PR41000 proposed in the bug
by sorting notes by alignment in decreasing order to close the gap
that might occur when notes use different alignments and to ensure
that PT_NOTE is packed correctly.
Would be nice to have a test where 2 sections are out of order, and this change puts them into the correct order. It's not clear from this if the build ID section is naturally placed at the end or not.
An alternative solution might be to create a PT_NOTE for each note upfront, and opportunistically merge them if they end up being laid out contiguously. This would also handle the case where a note's size is not a multiple of its alignment.
if just .note.gnu.property require 64-bit alignment, I think it time to change the alignment of this section.
I think we need change the .note.gnu.property section alignment to 4-byte in Clang-TableGen, because all its element is 4-byte required now. The old ABI required some of note.gnu.property' elements be 8-byte aligned in 64-bit machine, so the section required 8-byte alignment. Last year, I found a bug about this alignment between GCC and CLANG, Then I discussed with the ABI designer and changed its element's alignment in https://reviews.llvm.org/D56080 . I think there are already no ‘significance’ of 8 byte alignment for this section, we can change it now in LLVM.
I personally favour a separate PT_NOTE section per alignment, that gives a note parser simple rule to iterate through the section (the p_align field). I think ordering by decreasing alignment will work in practice for the note sections that we have now, but it may not be in the future. I also think that this is worth doing even if clang is changed to generate .note.gnu.property sections that are 4-byte aligned; clang will often use libraries compiled by gcc (or some other compiler) that does use 8-byte aligned sections.
There is a long glibc thread that covers a similar discussion in the gnu community https://sourceware.org/ml/libc-alpha/2018-08/msg00340.html , it is quite long so I've pulled out a few bits of it here:
- https://sourceware.org/ml/libc-alpha/2018-08/msg00344.html and follow-up https://sourceware.org/ml/libc-alpha/2018-08/msg00347.html on why two separate PT_NOTE sections were needed.
- https://sourceware.org/ml/libc-alpha/2018-08/msg00468.html rejection of changing ld bfd to that of gold and just setting the alignment of .gnu.property to 4-bytes. Ostensibly due to presence of large number of binaries with 8-byte aligned sections.
From what I can tell:
- ld.bfd outputs a separate PT_NOTE per p_align.
- ld.gold ignores the 8-byte alignment of the .note.gnu.property in the input object and changes it to 4 so that only one PT_NOTE is required.
- glibc works for both, given that .note.gnu.property doesn't strictly need 8 byte alignment.
ld.bfd outputs a separate PT_NOTE per p_align.
No, it merges adjacent SHT_NOTE in some circumstances. The rule is complicated, though.
We can place adjacent SHT_NOTE|SHF_ALLOC sections with the same section alignment into the same PT_NOTE segment, as what the ld.bfd patch does
I'm not sure if a separate PT_NOTE section per alignment would work for all cases. I don't think the size of a note section with 8-byte alignment is guaranteed to be a multiple of 8 byte.
I believe valid SHF_NOTE sections are either 4-byte or 8-byte aligned and the size is guaranteed to be a multiple of its section alignment. The input is broken if it isn't. It doesn't look wrong for me if lld produces a PT_NOTE that cannot be parsed by ld.so or other tools. Such check may still be nice to have, though.
.section .note.a, "a", @note .p2align 2 .space 1 .section .note.b, "a", @note .p2align 2 .space 2
In this example, .note.a's size is not aligned but ld.bfd places .note.a .note.b in the same PT_NOTE segment.