From e0f738354ca48db495bb9c395f1cb394154d6dc4 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Thu, 28 Nov 2024 23:06:39 -0800 Subject: [PATCH 1/2] [ObjectYAML][ELF] Take alignment into account when generating notes The [System V ABI](https://www.sco.com/developers/gabi/latest/ch5.pheader.html#note_section) states that the note entries and their descriptor fields must be aligned to 4 or 8 bytes for 32-bit and 64-bit objects respectively. In practice, 64-bit systems can use both alignments, with the actual format being distinguished by the alignment of the segment. For example, the [Linux gABI extension](https://github.com/hjl-tools/linux-abi/wiki/linux-abi-draft.pdf) contains a special note on this, see 2.1.7 "Alignment of Note Sections". This patch adjusts the format of the generated notes to the specified section alignment. Since `llvm-readobj` was fixed in a similar way in [D150022](https://reviews.llvm.org/D150022], `[Object] Fix handling of Elf_Nhdr with sh_addralign=8`, the generated notes can now be parsed successfully by the tool. --- llvm/lib/ObjectYAML/ELFEmitter.cpp | 18 ++++- .../test/tools/yaml2obj/ELF/note-section.yaml | 71 +++++++++++++++++++ 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 476334024151a..8603f2f73b858 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1799,6 +1799,20 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, if (!Section.Notes) return; + unsigned Align; + switch (SHeader.sh_addralign) { + case 0: + case 4: + Align = 4; + break; + case 8: + Align = 8; + break; + default: + reportError(Section.Name + ": invalid alignment for a note section: 0x" + + Twine::utohexstr(SHeader.sh_addralign)); + } + uint64_t Offset = CBA.tell(); for (const ELFYAML::NoteEntry &NE : *Section.Notes) { // Write name size. @@ -1820,13 +1834,13 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, if (!NE.Name.empty()) { CBA.write(NE.Name.data(), NE.Name.size()); CBA.write('\0'); - CBA.padToAlignment(4); + CBA.padToAlignment(Align); } // Write description and padding. if (NE.Desc.binary_size() != 0) { CBA.writeAsBinary(NE.Desc); - CBA.padToAlignment(4); + CBA.padToAlignment(Align); } } diff --git a/llvm/test/tools/yaml2obj/ELF/note-section.yaml b/llvm/test/tools/yaml2obj/ELF/note-section.yaml index 80359c4ec0183..067690f8f25b0 100644 --- a/llvm/test/tools/yaml2obj/ELF/note-section.yaml +++ b/llvm/test/tools/yaml2obj/ELF/note-section.yaml @@ -333,3 +333,74 @@ Sections: - Name: ABC Desc: '123456' Type: NT_VERSION + +## Check that an incorrect alignment is reported + +# RUN: not yaml2obj --docnum=16 %s 2>&1 | FileCheck %s --check-prefix=ERR_ALIGN1 +# ERR_ALIGN1: error: .note.foo: invalid alignment for a note section: 0x1 + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .note.foo + Type: SHT_NOTE + AddressAlign: 1 + Notes: + - Type: 0x1 + +## Check that note entries and their `Desc` fields are aligned according to the +## specified section alignment + +# RUN: yaml2obj --docnum=17 %s -o - | \ +# RUN: llvm-readobj --sections --section-data - | \ +# RUN: FileCheck %s --check-prefix=TEST17 + +# TEST17: Name: .note.foo4 +# TEST17: SectionData ( +# TEST17-NEXT: 0000: 05000000 02000000 01000000 41424344 |............ABCD| +# TEST17-NEXT: 0010: 00000000 01020000 03000000 03000000 |................| +# TEST17-NEXT: 0020: 02000000 41420000 03040500 03000000 |....AB..........| +# TEST17-NEXT: 0030: 00000000 03000000 41420000 |........AB..| +# TEST17-NEXT: ) +# TEST17: Name: .note.foo8 +# TEST17: SectionData ( +# TEST17-NEXT: 0000: 05000000 02000000 01000000 41424344 |............ABCD| +# TEST17-NEXT: 0010: 00000000 00000000 01020000 00000000 |................| +# TEST17-NEXT: 0020: 03000000 03000000 02000000 41420000 |............AB..| +# TEST17-NEXT: 0030: 03040500 00000000 03000000 00000000 |................| +# TEST17-NEXT: 0040: 03000000 41420000 |....AB..| +# TEST17-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC +Sections: + - Name: .note.foo4 + Type: SHT_NOTE + AddressAlign: 4 + Notes: + - Name: ABCD + Desc: 0102 + Type: NT_VERSION + - Name: AB + Desc: 030405 + Type: NT_ARCH + - Name: AB + Type: NT_GNU_BUILD_ID + - Name: .note.foo8 + Type: SHT_NOTE + AddressAlign: 8 + Notes: + - Name: ABCD + Desc: 0102 + Type: NT_VERSION + - Name: AB + Desc: 030405 + Type: NT_ARCH + - Name: AB + Type: NT_GNU_BUILD_ID From d02318674b2a49a61de1e4f422ce1616aa5cf2f4 Mon Sep 17 00:00:00 2001 From: Igor Kudrin Date: Fri, 29 Nov 2024 23:50:05 -0800 Subject: [PATCH 2/2] fixup: Fix the alignment of the description if the name is empty --- llvm/lib/ObjectYAML/ELFEmitter.cpp | 5 +- .../test/tools/yaml2obj/ELF/note-section.yaml | 88 +++++++++++++++---- 2 files changed, 76 insertions(+), 17 deletions(-) diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index 8603f2f73b858..001e701bd0b80 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -1834,14 +1834,15 @@ void ELFState::writeSectionContent(Elf_Shdr &SHeader, if (!NE.Name.empty()) { CBA.write(NE.Name.data(), NE.Name.size()); CBA.write('\0'); - CBA.padToAlignment(Align); } // Write description and padding. if (NE.Desc.binary_size() != 0) { - CBA.writeAsBinary(NE.Desc); CBA.padToAlignment(Align); + CBA.writeAsBinary(NE.Desc); } + + CBA.padToAlignment(Align); } SHeader.sh_size = CBA.tell() - Offset; diff --git a/llvm/test/tools/yaml2obj/ELF/note-section.yaml b/llvm/test/tools/yaml2obj/ELF/note-section.yaml index 067690f8f25b0..26b95e1c2379b 100644 --- a/llvm/test/tools/yaml2obj/ELF/note-section.yaml +++ b/llvm/test/tools/yaml2obj/ELF/note-section.yaml @@ -355,24 +355,84 @@ Sections: ## specified section alignment # RUN: yaml2obj --docnum=17 %s -o - | \ -# RUN: llvm-readobj --sections --section-data - | \ +# RUN: llvm-readobj --sections --section-data --notes - | \ # RUN: FileCheck %s --check-prefix=TEST17 # TEST17: Name: .note.foo4 # TEST17: SectionData ( # TEST17-NEXT: 0000: 05000000 02000000 01000000 41424344 |............ABCD| -# TEST17-NEXT: 0010: 00000000 01020000 03000000 03000000 |................| -# TEST17-NEXT: 0020: 02000000 41420000 03040500 03000000 |....AB..........| -# TEST17-NEXT: 0030: 00000000 03000000 41420000 |........AB..| +# TEST17-NEXT: 0010: 00000000 01020000 00000000 03000000 |................| +# TEST17-NEXT: 0020: 02000000 03040500 04000000 00000000 |................| +# TEST17-NEXT: 0030: 03000000 474E5500 |....GNU.| # TEST17-NEXT: ) # TEST17: Name: .note.foo8 # TEST17: SectionData ( # TEST17-NEXT: 0000: 05000000 02000000 01000000 41424344 |............ABCD| # TEST17-NEXT: 0010: 00000000 00000000 01020000 00000000 |................| -# TEST17-NEXT: 0020: 03000000 03000000 02000000 41420000 |............AB..| -# TEST17-NEXT: 0030: 03040500 00000000 03000000 00000000 |................| -# TEST17-NEXT: 0040: 03000000 41420000 |....AB..| +# TEST17-NEXT: 0020: 00000000 03000000 02000000 00000000 |................| +# TEST17-NEXT: 0030: 03040500 00000000 04000000 00000000 |................| +# TEST17-NEXT: 0040: 03000000 474E5500 |....GNU.| # TEST17-NEXT: ) +# TEST17: NoteSections [ +# TEST17-NEXT: NoteSection { +# TEST17-NEXT: Name: .note.foo4 +# TEST17-NEXT: Offset: +# TEST17-NEXT: Size: +# TEST17-NEXT: Notes [ +# TEST17-NEXT: { +# TEST17-NEXT: Owner: ABCD +# TEST17-NEXT: Data size: 0x2 +# TEST17-NEXT: Type: NT_VERSION (version) +# TEST17-NEXT: Description data ( +# TEST17-NEXT: 0000: 0102 |..| +# TEST17-NEXT: ) +# TEST17-NEXT: } +# TEST17-NEXT: { +# TEST17-NEXT: Owner: +# TEST17-NEXT: Data size: 0x3 +# TEST17-NEXT: Type: NT_ARCH (architecture) +# TEST17-NEXT: Description data ( +# TEST17-NEXT: 0000: 030405 |...| +# TEST17-NEXT: ) +# TEST17-NEXT: } +# TEST17-NEXT: { +# TEST17-NEXT: Owner: GNU +# TEST17-NEXT: Data size: 0x0 +# TEST17-NEXT: Type: NT_GNU_BUILD_ID (unique build ID bitstring) +# TEST17-NEXT: Build ID: +# TEST17-NEXT: } +# TEST17-NEXT: ] +# TEST17-NEXT: } +# TEST17-NEXT: NoteSection { +# TEST17-NEXT: Name: .note.foo8 +# TEST17-NEXT: Offset: +# TEST17-NEXT: Size: +# TEST17-NEXT: Notes [ +# TEST17-NEXT: { +# TEST17-NEXT: Owner: ABCD +# TEST17-NEXT: Data size: 0x2 +# TEST17-NEXT: Type: NT_VERSION (version) +# TEST17-NEXT: Description data ( +# TEST17-NEXT: 0000: 0102 |..| +# TEST17-NEXT: ) +# TEST17-NEXT: } +# TEST17-NEXT: { +# TEST17-NEXT: Owner: +# TEST17-NEXT: Data size: 0x3 +# TEST17-NEXT: Type: NT_ARCH (architecture) +# TEST17-NEXT: Description data ( +# TEST17-NEXT: 0000: 030405 |...| +# TEST17-NEXT: ) +# TEST17-NEXT: } +# TEST17-NEXT: { +# TEST17-NEXT: Owner: GNU +# TEST17-NEXT: Data size: 0x0 +# TEST17-NEXT: Type: NT_GNU_BUILD_ID (unique build ID bitstring) +# TEST17-NEXT: Build ID: +# TEST17-NEXT: } +# TEST17-NEXT: ] +# TEST17-NEXT: } +# TEST17-NEXT: ] --- !ELF FileHeader: @@ -385,22 +445,20 @@ Sections: AddressAlign: 4 Notes: - Name: ABCD - Desc: 0102 Type: NT_VERSION - - Name: AB + Desc: 0102 + - Type: NT_ARCH Desc: 030405 - Type: NT_ARCH - - Name: AB + - Name: GNU Type: NT_GNU_BUILD_ID - Name: .note.foo8 Type: SHT_NOTE AddressAlign: 8 Notes: - Name: ABCD - Desc: 0102 Type: NT_VERSION - - Name: AB + Desc: 0102 + - Type: NT_ARCH Desc: 030405 - Type: NT_ARCH - - Name: AB + - Name: GNU Type: NT_GNU_BUILD_ID