Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -2035,13 +2035,24 @@ if (Config->ZWxneeded) AddHdr(PT_OPENBSD_WXNEEDED, PF_X); - // Create one PT_NOTE per a group of contiguous .note sections. + // Create one PT_NOTE per a group of contiguous .note sections with + // alignment such that notes can be parsed in order. PhdrEntry *Note = nullptr; + OutputSection *LastNote = nullptr; for (OutputSection *Sec : OutputSections) { if (Sec->Type == SHT_NOTE && (Sec->Flags & SHF_ALLOC)) { + bool NewNote = false; + if (LastNote) { + uint64_t Align = MinAlign(LastNote->Alignment, LastNote->Size); + Align = std::max(Align, uint64_t(4)); + NewNote = NewNote || Align < Sec->Alignment; + } if (!Note || Sec->LMAExpr) + NewNote = true; + if (NewNote) Note = AddHdr(PT_NOTE, PF_R); Note->add(Sec); + LastNote = Sec; } else { Note = nullptr; } Index: lld/test/ELF/build-id.s =================================================================== --- lld/test/ELF/build-id.s +++ lld/test/ELF/build-id.s @@ -49,6 +49,19 @@ .section .note.test, "a", @note .quad 42 + .byte 42 + +# ALIGN: Name: .note.test +# ALIGN-NEXT: Type: SHT_NOTE +# ALIGN-NEXT: Flags [ +# ALIGN-NEXT: SHF_ALLOC +# ALIGN-NEXT: ] +# ALIGN-NEXT: Address: +# ALIGN-NEXT: Offset: +# ALIGN-NEXT: Size: +# ALIGN-NEXT: Link: +# ALIGN-NEXT: Info: +# ALIGN-NEXT: AddressAlignment: 1 # ALIGN: Name: .note.gnu.build-id # ALIGN-NEXT: Type: SHT_NOTE @@ -65,15 +78,15 @@ # DEFAULT: Contents of section .note.test: # DEFAULT: Contents of section .note.gnu.build-id: # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. -# DEFAULT-NEXT: 894c04e8 fbf5556b +# DEFAULT-NEXT: 4a1b8629 1147db29 # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. -# MD5-NEXT: 6a51bbd7 9e8ee3f9 2e02d213 711cfec9 +# MD5-NEXT: 0a9aaf86 8158723b 36bf8535 a32e0625 # SHA1: Contents of section .note.gnu.build-id: # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. -# SHA1-NEXT: 9a8618b1 d6fd0e5c eda73dd8 76de5596 +# SHA1-NEXT: f66aa8ea 3fe906c6 99fc5c52 6678d3a8 # UUID: Contents of section .note.gnu.build-id: # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. Index: lld/test/ELF/large-align-notes.s =================================================================== --- /dev/null +++ lld/test/ELF/large-align-notes.s @@ -0,0 +1,79 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: ld.lld %t -o %t2 +# RUN: llvm-readobj -l %t2 | FileCheck %s + +.globl _start +_start: + nop + +# Has 4-byte aligned size and alignment +.section .note.std1, "a", @note + .align 4 + .quad 0 + +# Has > 4-byte alignment but aligned size +.section .note.large, "a", @note + .align 16 + .quad 0 + +# Has 4-byte aligned size and alignment. Should be coalesced. +.section .note.std2, "a", @note + .align 4 + .quad 0 + +# We need a split for the next part of this test +.section .note.split, "a", @note + .align 16 + .quad 0 + +# To test the case where a less algined section that comes first is still +# merged with the section below because the alignment is still less than 4 we +# create a section with alignment 1 and size 1 +.section .note.small, "a", @note + .align 1 + .byte 1 + +# Now because notes bump to 4 byte alignment, the next note section should be +# merged +.section .note.std3, "a", @note + .align 4 + .quad 0 + +#CHECK: ProgramHeader { +#CHECK: Type: PT_NOTE (0x4) +#CHECK-NEXT: Offset: +#CHECK-NEXT: VirtualAddress: +#CHECK-NEXT: PhysicalAddress: +#CHECK-NEXT: FileSize: 8 +#CHECK-NEXT: MemSize: 8 +#CHECK-NEXT: Flags [ (0x4) +#CHECK-NEXT: PF_R (0x4) +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 4 +#CHECK-NEXT: } +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_NOTE (0x4) +#CHECK-NEXT: Offset: +#CHECK-NEXT: VirtualAddress: +#CHECK-NEXT: PhysicalAddress: +#CHECK-NEXT: FileSize: 16 +#CHECK-NEXT: MemSize: 16 +#CHECK-NEXT: Flags [ (0x4) +#CHECK-NEXT: PF_R (0x4) +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 16 +#CHECK-NEXT: } +#CHECK-NEXT: ProgramHeader { +#CHECK-NEXT: Type: PT_NOTE (0x4) +#CHECK-NEXT: Offset: +#CHECK-NEXT: VirtualAddress: +#CHECK-NEXT: PhysicalAddress: +#CHECK-NEXT: FileSize: 20 +#CHECK-NEXT: MemSize: 20 +#CHECK-NEXT: Flags [ (0x4) +#CHECK-NEXT: PF_R (0x4) +#CHECK-NEXT: ] +#CHECK-NEXT: Alignment: 16 +#CHECK-NEXT: } +#CHECK-NEXT:]