[lld] 689715f - [Object] Fix handling of Elf_Nhdr with sh_addralign=8

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed May 10 09:37:04 PDT 2023


Author: Fangrui Song
Date: 2023-05-10T09:36:58-07:00
New Revision: 689715f335aeffc0e9583ac1b2a5629b6dd47876

URL: https://github.com/llvm/llvm-project/commit/689715f335aeffc0e9583ac1b2a5629b6dd47876
DIFF: https://github.com/llvm/llvm-project/commit/689715f335aeffc0e9583ac1b2a5629b6dd47876.diff

LOG: [Object] Fix handling of Elf_Nhdr with sh_addralign=8

The generic ABI says:

> Padding is present, if necessary, to ensure 8 or 4-byte alignment for the next note entry (depending on whether the file is a 64-bit or 32-bit object). Such padding is not included in descsz.

Our parsing code currently aligns n_namesz. Fix the bug by aligning the start
offset of the descriptor instead. This issue has been benign because the primary
uses of sh_addralign=8 notes are `.note.gnu.property`, where
`sizeof(Elf_Nhdr) + sizeof("GNU") = 16` (already aligned by 8).

In practice, many 64-bit systems incorrectly use sh_addralign=4 notes.
We can use sh_addralign (= p_align) to decide the descriptor padding.
Treat an alignment of 0 and 1 as 4. This approach matches modern GNU readelf
(since 2018).

We have a few tests incorrectly using sh_addralign=0. We may make our behavior
stricter after fixing these tests.

Linux kernel dumped core files use `p_align=0` notes, so we need to support the
case for compatibility.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D150022

Added: 
    llvm/test/tools/llvm-readobj/ELF/note-alignment-invalid.test

Modified: 
    lld/ELF/InputFiles.cpp
    llvm/include/llvm/Object/ELF.h
    llvm/include/llvm/Object/ELFTypes.h
    llvm/lib/Object/BuildID.cpp
    llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s
    llvm/test/tools/llvm-readobj/ELF/note-gnu-property2.s
    llvm/test/tools/llvm-readobj/ELF/note-unknown.s
    llvm/tools/llvm-readobj/ELFDumper.cpp
    llvm/tools/obj2yaml/elf2yaml.cpp
    llvm/unittests/Object/ELFTypesTest.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index b8291fb4307bc..311e2c9a9e54f 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -885,12 +885,13 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
   while (!data.empty()) {
     // Read one NOTE record.
     auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
-    if (data.size() < sizeof(Elf_Nhdr) || data.size() < nhdr->getSize())
+    if (data.size() < sizeof(Elf_Nhdr) ||
+        data.size() < nhdr->getSize(sec.addralign))
       reportFatal(data.data(), "data is too short");
 
     Elf_Note note(*nhdr);
     if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") {
-      data = data.slice(nhdr->getSize());
+      data = data.slice(nhdr->getSize(sec.addralign));
       continue;
     }
 
@@ -899,7 +900,7 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
                                   : GNU_PROPERTY_X86_FEATURE_1_AND;
 
     // Read a body of a NOTE record, which consists of type-length-value fields.
-    ArrayRef<uint8_t> desc = note.getDesc();
+    ArrayRef<uint8_t> desc = note.getDesc(sec.addralign);
     while (!desc.empty()) {
       const uint8_t *place = desc.data();
       if (desc.size() < 8)
@@ -924,7 +925,7 @@ template <class ELFT> static uint32_t readAndFeatures(const InputSection &sec) {
     }
 
     // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
-    data = data.slice(nhdr->getSize());
+    data = data.slice(nhdr->getSize(sec.addralign));
   }
 
   return featuresSet;

diff  --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index 2ae2e9fbdf354..a1cf47a1c4a61 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -316,7 +316,16 @@ class ELFFile {
                       ") or size (0x" + Twine::utohexstr(Phdr.p_filesz) + ")");
       return Elf_Note_Iterator(Err);
     }
-    return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz, Err);
+    // Allow 4, 8, and (for Linux core dumps) 0.
+    // TODO: Disallow 1 after all tests are fixed.
+    if (Phdr.p_align != 0 && Phdr.p_align != 1 && Phdr.p_align != 4 &&
+        Phdr.p_align != 8) {
+      Err =
+          createError("alignment (" + Twine(Phdr.p_align) + ") is not 4 or 8");
+      return Elf_Note_Iterator(Err);
+    }
+    return Elf_Note_Iterator(base() + Phdr.p_offset, Phdr.p_filesz,
+                             std::max<size_t>(Phdr.p_align, 4), Err);
   }
 
   /// Get an iterator over notes in a section.
@@ -335,7 +344,15 @@ class ELFFile {
                       ") or size (0x" + Twine::utohexstr(Shdr.sh_size) + ")");
       return Elf_Note_Iterator(Err);
     }
-    return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size, Err);
+    // TODO: Allow just 4 and 8 after all tests are fixed.
+    if (Shdr.sh_addralign != 0 && Shdr.sh_addralign != 1 &&
+        Shdr.sh_addralign != 4 && Shdr.sh_addralign != 8) {
+      Err = createError("alignment (" + Twine(Shdr.sh_addralign) +
+                        ") is not 4 or 8");
+      return Elf_Note_Iterator(Err);
+    }
+    return Elf_Note_Iterator(base() + Shdr.sh_offset, Shdr.sh_size,
+                             std::max<size_t>(Shdr.sh_addralign, 4), Err);
   }
 
   /// Get the end iterator for notes.

diff  --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 62c251e59b459..608b15b48ad6c 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -599,15 +599,13 @@ struct Elf_Nhdr_Impl {
   Elf_Word n_descsz;
   Elf_Word n_type;
 
-  /// The alignment of the name and descriptor.
-  ///
-  /// Implementations 
diff er from the specification here: in practice all
-  /// variants align both the name and descriptor to 4-bytes.
-  static const unsigned int Align = 4;
-
-  /// Get the size of the note, including name, descriptor, and padding.
-  size_t getSize() const {
-    return sizeof(*this) + alignTo<Align>(n_namesz) + alignTo<Align>(n_descsz);
+  /// Get the size of the note, including name, descriptor, and padding. Both
+  /// the start and the end of the descriptor are aligned by the section
+  /// alignment. In practice many 64-bit systems deviate from the generic ABI by
+  /// using sh_addralign=4.
+  size_t getSize(size_t Align) const {
+    return alignToPowerOf2(sizeof(*this) + n_namesz, Align) +
+           alignToPowerOf2(n_descsz, Align);
   }
 };
 
@@ -635,18 +633,18 @@ class Elf_Note_Impl {
   }
 
   /// Get the note's descriptor.
-  ArrayRef<uint8_t> getDesc() const {
+  ArrayRef<uint8_t> getDesc(size_t Align) const {
     if (!Nhdr.n_descsz)
       return ArrayRef<uint8_t>();
     return ArrayRef<uint8_t>(
-        reinterpret_cast<const uint8_t *>(&Nhdr) + sizeof(Nhdr) +
-          alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr.n_namesz),
+        reinterpret_cast<const uint8_t *>(&Nhdr) +
+            alignToPowerOf2(sizeof(Nhdr) + Nhdr.n_namesz, Align),
         Nhdr.n_descsz);
   }
 
   /// Get the note's descriptor as StringRef
-  StringRef getDescAsStringRef() const {
-    ArrayRef<uint8_t> Desc = getDesc();
+  StringRef getDescAsStringRef(size_t Align) const {
+    ArrayRef<uint8_t> Desc = getDesc(Align);
     return StringRef(reinterpret_cast<const char *>(Desc.data()), Desc.size());
   }
 
@@ -666,6 +664,7 @@ template <class ELFT> class Elf_Note_Iterator_Impl {
   // Nhdr being a nullptr marks the end of iteration.
   const Elf_Nhdr_Impl<ELFT> *Nhdr = nullptr;
   size_t RemainingSize = 0u;
+  size_t Align = 0;
   Error *Err = nullptr;
 
   template <class ELFFileELFT> friend class ELFFile;
@@ -693,7 +692,7 @@ template <class ELFT> class Elf_Note_Iterator_Impl {
       stopWithOverflowError();
     else {
       Nhdr = reinterpret_cast<const Elf_Nhdr_Impl<ELFT> *>(NhdrPos + NoteSize);
-      if (Nhdr->getSize() > RemainingSize)
+      if (Nhdr->getSize(Align) > RemainingSize)
         stopWithOverflowError();
       else
         *Err = Error::success();
@@ -702,8 +701,9 @@ template <class ELFT> class Elf_Note_Iterator_Impl {
 
   Elf_Note_Iterator_Impl() = default;
   explicit Elf_Note_Iterator_Impl(Error &Err) : Err(&Err) {}
-  Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, Error &Err)
-      : RemainingSize(Size), Err(&Err) {
+  Elf_Note_Iterator_Impl(const uint8_t *Start, size_t Size, size_t Align,
+                         Error &Err)
+      : RemainingSize(Size), Align(Align), Err(&Err) {
     consumeError(std::move(Err));
     assert(Start && "ELF note iterator starting at NULL");
     advanceNhdr(Start, 0u);
@@ -713,7 +713,7 @@ template <class ELFT> class Elf_Note_Iterator_Impl {
   Elf_Note_Iterator_Impl &operator++() {
     assert(Nhdr && "incremented ELF note end iterator");
     const uint8_t *NhdrPos = reinterpret_cast<const uint8_t *>(Nhdr);
-    size_t NoteSize = Nhdr->getSize();
+    size_t NoteSize = Nhdr->getSize(Align);
     advanceNhdr(NhdrPos, NoteSize);
     return *this;
   }

diff  --git a/llvm/lib/Object/BuildID.cpp b/llvm/lib/Object/BuildID.cpp
index 887798a26b90f..ef21458060abd 100644
--- a/llvm/lib/Object/BuildID.cpp
+++ b/llvm/lib/Object/BuildID.cpp
@@ -36,7 +36,7 @@ template <typename ELFT> BuildIDRef getBuildID(const ELFFile<ELFT> &Obj) {
     for (auto N : Obj.notes(P, Err))
       if (N.getType() == ELF::NT_GNU_BUILD_ID &&
           N.getName() == ELF::ELF_NOTE_GNU)
-        return N.getDesc();
+        return N.getDesc(P.p_align);
     consumeError(std::move(Err));
   }
   return {};

diff  --git a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s
index 4f280ff41a91b..872a3f150fdf6 100644
--- a/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s
+++ b/llvm/test/tools/llvm-readobj/ELF/AArch64/aarch64-note-gnu-property.s
@@ -24,7 +24,6 @@
 // LLVM-NEXT: ]
 
 .section ".note.gnu.property", "a"
-.align 4
   .long 4           /* Name length is always 4 ("GNU") */
   .long end - begin /* Data length */
   .long 5           /* Type: NT_GNU_PROPERTY_TYPE_0 */

diff  --git a/llvm/test/tools/llvm-readobj/ELF/note-alignment-invalid.test b/llvm/test/tools/llvm-readobj/ELF/note-alignment-invalid.test
new file mode 100644
index 0000000000000..2b7221c91c0f8
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/note-alignment-invalid.test
@@ -0,0 +1,21 @@
+# RUN: yaml2obj --docnum=1 %s -o %t1.so
+# RUN: llvm-readelf --notes %t1.so 2>&1 | FileCheck %s -DFILE=%t1.so
+# RUN: llvm-readobj --notes %t1.so 2>&1 | FileCheck %s -DFILE=%t1.so
+
+# CHECK: warning: '[[FILE]]': unable to read notes from the SHT_NOTE section with index 1: alignment (6) is not 4 or 8
+
+--- !ELF
+FileHeader:
+  Class:      ELFCLASS64
+  Data:       ELFDATA2LSB
+  Type:       ET_EXEC
+Sections:
+  - Name:         .note.invalid
+    Type:         SHT_NOTE
+    AddressAlign: 0x0000000000000006
+    Content:      0400000004000000cdab0000474E550061626364
+ProgramHeaders:
+  - Type:     PT_NOTE
+    FileSize: 0x20
+    FirstSec: .note.invalid
+    LastSec:  .note.invalid

diff  --git a/llvm/test/tools/llvm-readobj/ELF/note-gnu-property2.s b/llvm/test/tools/llvm-readobj/ELF/note-gnu-property2.s
index b6c0104077de4..5ac35d45725c0 100644
--- a/llvm/test/tools/llvm-readobj/ELF/note-gnu-property2.s
+++ b/llvm/test/tools/llvm-readobj/ELF/note-gnu-property2.s
@@ -6,13 +6,13 @@
 // GNU:      Displaying notes found in: .note.gnu.property
 // GNU-NEXT:   Owner                 Data size       Description
 // GNU-NEXT:   GNU                   0x00000004      NT_GNU_PROPERTY_TYPE_0 (property note)
-// GNU-NEXT:     Properties:  <corrupted GNU_PROPERTY_TYPE_0>
+// GNU-NEXT:     Properties:    <corrupted GNU_PROPERTY_TYPE_0>
 
 // LLVM:      Notes [
 // LLVM-NEXT:   NoteSection {
 // LLVM-NEXT:     Name: .note.gnu.property
 // LLVM-NEXT:     Offset: 0x40
-// LLVM-NEXT:     Size: 0x14
+// LLVM-NEXT:     Size: 0x18
 // LLVM-NEXT:     Note {
 // LLVM-NEXT:       Owner: GNU
 // LLVM-NEXT:       Data size: 0x4
@@ -29,10 +29,11 @@
 .section ".note.gnu.property", "a"
 .align 4 
   .long 4           /* Name length is always 4 ("GNU") */
-  .long end - begin /* Data length */
+  .long 4           /* Data length (corrupted) */
   .long 5           /* Type: NT_GNU_PROPERTY_TYPE_0 */
   .asciz "GNU"      /* Name */
   .p2align 3
 begin:
   .long 1           /* Type: GNU_PROPERTY_STACK_SIZE */
+  .p2align 3
 end:

diff  --git a/llvm/test/tools/llvm-readobj/ELF/note-unknown.s b/llvm/test/tools/llvm-readobj/ELF/note-unknown.s
index 27f8f8e923422..aa74b51a3541b 100644
--- a/llvm/test/tools/llvm-readobj/ELF/note-unknown.s
+++ b/llvm/test/tools/llvm-readobj/ELF/note-unknown.s
@@ -39,21 +39,63 @@
 // LLVM-NEXT:       )
 // LLVM-NEXT:     }
 // LLVM-NEXT:   }
+// LLVM-NEXT:   NoteSection {
+// LLVM-NEXT:     Name: .note.8
+// LLVM-NEXT:     Offset: 0x80
+// LLVM-NEXT:     Size: 0x40
+// LLVM-NEXT:     Note {
+// LLVM-NEXT:       Owner: WXYZ
+// LLVM-NEXT:       Data size: 0x8
+// LLVM-NEXT:       Type: Unknown (0x00000006)
+// LLVM-NEXT:       Description data (
+// LLVM-NEXT:         0000: 4C6F7265 6D000000                    |Lorem...|
+// LLVM-NEXT:       )
+// LLVM-NEXT:     }
+// LLVM-NEXT:     Note {
+// LLVM-NEXT:       Owner: VWXYZ
+// LLVM-NEXT:       Data size: 0x8
+// LLVM-NEXT:       Type: Unknown (0x00000006)
+// LLVM-NEXT:       Description data (
+// LLVM-NEXT:         0000: 78787800 00000000                    |xxx.....|
+// LLVM-NEXT:       )
+// LLVM-NEXT:     }
+// LLVM-NEXT:   }
 // LLVM-NEXT: ]
 
 .section ".note.foo", "a"
-	.align 4
 	.long 4 /* namesz */
 	.long 0 /* descsz */
 	.long 3 /* type */
 	.asciz "XYZ"
+	.align 4
 .section ".note.bar", "a"
-       .align 4
        .long 4 /* namesz */
        .long end - begin /* descsz */
        .long 3 /* type */
        .asciz "XYZ"
+       .align 4
 begin:
        .asciz "Lorem ipsum dolor sit amet"
        .align 4
 end:
+
+.section ".note.8", "a"
+       .long 5 /* namesz */
+       .long 2f - 1f /* descsz */
+       .long 6 /* type */
+       .asciz "WXYZ"
+       .align 8
+1:
+       .asciz "Lorem"
+       .align 8
+2:
+
+       .long 6 /* namesz */
+       .long 2f - 1f /* descsz */
+       .long 6 /* type */
+       .asciz "VWXYZ"
+       .align 8
+1:
+       .asciz "xxx"
+       .align 8
+2:

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index eddffa08cd7bd..b2b835d92ff8a 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -5828,7 +5828,7 @@ template <class ELFT>
 static void processNotesHelper(
     const ELFDumper<ELFT> &Dumper,
     llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,
-                            typename ELFT::Addr)>
+                            typename ELFT::Addr, size_t)>
         StartNotesFn,
     llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
     llvm::function_ref<void()> FinishNotesFn) {
@@ -5841,7 +5841,7 @@ static void processNotesHelper(
       if (S.sh_type != SHT_NOTE)
         continue;
       StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,
-                   S.sh_size);
+                   S.sh_size, S.sh_addralign);
       Error Err = Error::success();
       size_t I = 0;
       for (const typename ELFT::Note Note : Obj.notes(S, Err)) {
@@ -5872,7 +5872,7 @@ static void processNotesHelper(
     const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];
     if (P.p_type != PT_NOTE)
       continue;
-    StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz);
+    StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz, P.p_align);
     Error Err = Error::success();
     size_t Index = 0;
     for (const typename ELFT::Note Note : Obj.notes(P, Err)) {
@@ -5892,10 +5892,12 @@ static void processNotesHelper(
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
+  size_t Align = 0;
   bool IsFirstHeader = true;
   auto PrintHeader = [&](std::optional<StringRef> SecName,
                          const typename ELFT::Off Offset,
-                         const typename ELFT::Addr Size) {
+                         const typename ELFT::Addr Size, size_t Al) {
+    Align = std::max<size_t>(Al, 4);
     // Print a newline between notes sections to match GNU readelf.
     if (!IsFirstHeader) {
       OS << '\n';
@@ -5916,7 +5918,7 @@ template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
 
   auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
     StringRef Name = Note.getName();
-    ArrayRef<uint8_t> Descriptor = Note.getDesc();
+    ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
     Elf_Word Type = Note.getType();
 
     // Print the note owner/type.
@@ -6048,7 +6050,7 @@ template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {
   auto FindAndroidNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
     if (Note.getName() == "Android" &&
         Note.getType() == ELF::NT_ANDROID_TYPE_MEMTAG)
-      AndroidNoteDesc = Note.getDesc();
+      AndroidNoteDesc = Note.getDesc(4);
     return Error::success();
   };
 
@@ -6056,7 +6058,7 @@ template <typename ELFT> void ELFDumper<ELFT>::printMemtag() {
       *this,
       /*StartNotesFn=*/
       [](std::optional<StringRef>, const typename ELFT::Off,
-         const typename ELFT::Addr) {},
+         const typename ELFT::Addr, size_t) {},
       /*ProcessNoteFn=*/FindAndroidNote, /*FinishNotesFn=*/[]() {});
 
   ArrayRef<uint8_t> Contents = getMemtagGlobalsSectionContents(MemtagGlobals);
@@ -7590,9 +7592,11 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
   ListScope L(W, "Notes");
 
   std::unique_ptr<DictScope> NoteScope;
+  size_t Align = 0;
   auto StartNotes = [&](std::optional<StringRef> SecName,
                         const typename ELFT::Off Offset,
-                        const typename ELFT::Addr Size) {
+                        const typename ELFT::Addr Size, size_t Al) {
+    Align = std::max<size_t>(Al, 4);
     NoteScope = std::make_unique<DictScope>(W, "NoteSection");
     W.printString("Name", SecName ? *SecName : "<?>");
     W.printHex("Offset", Offset);
@@ -7604,7 +7608,7 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printNotes() {
   auto ProcessNote = [&](const Elf_Note &Note, bool IsCore) -> Error {
     DictScope D2(W, "Note");
     StringRef Name = Note.getName();
-    ArrayRef<uint8_t> Descriptor = Note.getDesc();
+    ArrayRef<uint8_t> Descriptor = Note.getDesc(Align);
     Elf_Word Type = Note.getType();
 
     // Print the note owner/type.

diff  --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index 9df483bec7c85..b261b9dc6f6e3 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -1221,6 +1221,7 @@ ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) {
 
   std::vector<ELFYAML::NoteEntry> Entries;
   ArrayRef<uint8_t> Content = *ContentOrErr;
+  size_t Align = std::max<size_t>(Shdr->sh_addralign, 4);
   while (!Content.empty()) {
     if (Content.size() < sizeof(Elf_Nhdr)) {
       S->Content = yaml::BinaryRef(*ContentOrErr);
@@ -1228,16 +1229,16 @@ ELFDumper<ELFT>::dumpNoteSection(const Elf_Shdr *Shdr) {
     }
 
     const Elf_Nhdr *Header = reinterpret_cast<const Elf_Nhdr *>(Content.data());
-    if (Content.size() < Header->getSize()) {
+    if (Content.size() < Header->getSize(Align)) {
       S->Content = yaml::BinaryRef(*ContentOrErr);
       return S.release();
     }
 
     Elf_Note Note(*Header);
     Entries.push_back(
-        {Note.getName(), Note.getDesc(), (ELFYAML::ELF_NT)Note.getType()});
+        {Note.getName(), Note.getDesc(Align), (ELFYAML::ELF_NT)Note.getType()});
 
-    Content = Content.drop_front(Header->getSize());
+    Content = Content.drop_front(Header->getSize(Align));
   }
 
   S->Notes = std::move(Entries);

diff  --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp
index 265f8a7cb812d..aae71ef385a72 100644
--- a/llvm/unittests/Object/ELFTypesTest.cpp
+++ b/llvm/unittests/Object/ELFTypesTest.cpp
@@ -19,9 +19,9 @@ template <class ELFT> struct NoteTestData {
 
   const Elf_Note_Impl<ELFT> getElfNote(StringRef Name, uint32_t Type,
                                        ArrayRef<uint8_t> Desc) {
-    Data.resize(sizeof(Elf_Nhdr_Impl<ELFT>) +
-                    alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Name.size()) +
-                    alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Desc.size()),
+    constexpr uint64_t Align = 4;
+    Data.resize(alignTo(sizeof(Elf_Nhdr_Impl<ELFT>) + Name.size(), Align) +
+                    alignTo(Desc.size(), Align),
                 0);
 
     Elf_Nhdr_Impl<ELFT> *Nhdr =
@@ -34,7 +34,7 @@ template <class ELFT> struct NoteTestData {
     std::copy(Name.begin(), Name.end(), NameOffset);
 
     auto DescOffset =
-        NameOffset + alignTo<Elf_Nhdr_Impl<ELFT>::Align>(Nhdr->n_namesz);
+        Data.begin() + alignTo(sizeof(*Nhdr) + Nhdr->n_namesz, Align);
     std::copy(Desc.begin(), Desc.end(), DescOffset);
 
     return Elf_Note_Impl<ELFT>(*Nhdr);
@@ -50,8 +50,8 @@ TEST(ELFTypesTest, NoteTest) {
                                    RandomData);
   EXPECT_EQ(Note1.getName(), "AMD");
   EXPECT_EQ(Note1.getType(), ELF::NT_AMDGPU_METADATA);
-  EXPECT_EQ(Note1.getDesc(), RandomData);
-  EXPECT_EQ(Note1.getDescAsStringRef(),
+  EXPECT_EQ(Note1.getDesc(4), RandomData);
+  EXPECT_EQ(Note1.getDescAsStringRef(4),
             StringRef(reinterpret_cast<const char *>(Random), sizeof(Random)));
 
   auto Note2 = TestData.getElfNote("", ELF::NT_AMDGPU_METADATA, RandomData);
@@ -59,5 +59,5 @@ TEST(ELFTypesTest, NoteTest) {
 
   auto Note3 =
       TestData.getElfNote("AMD", ELF::NT_AMDGPU_METADATA, ArrayRef<uint8_t>());
-  EXPECT_EQ(Note3.getDescAsStringRef(), StringRef(""));
+  EXPECT_EQ(Note3.getDescAsStringRef(4), StringRef(""));
 }


        


More information about the llvm-commits mailing list