[llvm-branch-commits] [llvm-objdump] -r: support CREL (PR #97382)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jul 1 22:03:04 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-binary-utilities

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

The decoder code is similar to that for llvm-readelf -r (#<!-- -->91280).

Because the section representation of LLVMObject (`SectionRef`) is
64-bit, insufficient to hold all decoder states, `section_rel_begin` is
modified to decode CREL eagerly and hold the decoded relocations inside
ELFObjectFile<ELFT>.

The test is adapted from llvm/test/tools/llvm-readobj/ELF/crel.test.


---
Full diff: https://github.com/llvm/llvm-project/pull/97382.diff


6 Files Affected:

- (modified) llvm/include/llvm/Object/ELFObjectFile.h (+87-6) 
- (modified) llvm/lib/Object/ELFObjectFile.cpp (+11) 
- (added) llvm/test/tools/llvm-objdump/ELF/crel.test (+213) 
- (modified) llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test (+4) 
- (modified) llvm/tools/llvm-objdump/ELFDump.cpp (+5-1) 
- (modified) llvm/tools/llvm-objdump/llvm-objdump.cpp (+9) 


``````````diff
diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h
index 8cc09e7fd7d55..665d848d5b607 100644
--- a/llvm/include/llvm/Object/ELFObjectFile.h
+++ b/llvm/include/llvm/Object/ELFObjectFile.h
@@ -29,6 +29,7 @@
 #include "llvm/Support/ELFAttributes.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/TargetParser/SubtargetFeature.h"
@@ -122,6 +123,8 @@ class ELFObjectFileBase : public ObjectFile {
   Expected<std::vector<BBAddrMap>>
   readBBAddrMap(std::optional<unsigned> TextSectionIndex = std::nullopt,
                 std::vector<PGOAnalysisMap> *PGOAnalyses = nullptr) const;
+
+  StringRef getCrelError(SectionRef Sec) const;
 };
 
 class ELFSectionRef : public SectionRef {
@@ -292,6 +295,11 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
   const Elf_Shdr *DotSymtabSec = nullptr; // Symbol table section.
   const Elf_Shdr *DotSymtabShndxSec = nullptr; // SHT_SYMTAB_SHNDX section.
 
+  // Hold CREL relocations for SectionRef::relocations().
+  mutable SmallVector<SmallVector<Elf_Crel, 0>, 0> Crels;
+  // Hold CREL decoding errors.
+  mutable SmallVector<std::string, 0> CrelErrs;
+
   Error initContent() override;
 
   void moveSymbolNext(DataRefImpl &Symb) const override;
@@ -446,6 +454,7 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
 
   const Elf_Rel *getRel(DataRefImpl Rel) const;
   const Elf_Rela *getRela(DataRefImpl Rela) const;
+  Elf_Crel getCrel(DataRefImpl Crel) const;
 
   Expected<const Elf_Sym *> getSymbol(DataRefImpl Sym) const {
     return EF.template getEntry<Elf_Sym>(Sym.d.a, Sym.d.b);
@@ -499,6 +508,8 @@ template <class ELFT> class ELFObjectFile : public ELFObjectFileBase {
   bool isRelocatableObject() const override;
 
   void createFakeSections() { EF.createFakeSections(); }
+
+  StringRef getCrelError(DataRefImpl Sec) const;
 };
 
 using ELF32LEObjectFile = ELFObjectFile<ELF32LE>;
@@ -1022,6 +1033,47 @@ ELFObjectFile<ELFT>::section_rel_begin(DataRefImpl Sec) const {
   uintptr_t SHT = reinterpret_cast<uintptr_t>((*SectionsOrErr).begin());
   RelData.d.a = (Sec.p - SHT) / EF.getHeader().e_shentsize;
   RelData.d.b = 0;
+  if (reinterpret_cast<const Elf_Shdr *>(Sec.p)->sh_type == ELF::SHT_CREL) {
+    if (RelData.d.a + 1 > Crels.size()) {
+      Crels.resize(RelData.d.a + 1);
+      CrelErrs.resize(RelData.d.a + 1);
+    }
+    if (Crels[RelData.d.a].empty()) {
+      // Decode SHT_CREL. See ELFFile<ELFT>::decodeCrel.
+      ArrayRef<uint8_t> Content = cantFail(getSectionContents(Sec));
+      DataExtractor Data(Content, ELFT::Endianness == endianness::little,
+                         sizeof(typename ELFT::Addr));
+      DataExtractor::Cursor Cur(0);
+      const uint64_t Hdr = Data.getULEB128(Cur);
+      const size_t Count = Hdr / 8;
+      const size_t FlagBits = Hdr & ELF::CREL_HDR_ADDEND ? 3 : 2;
+      const size_t Shift = Hdr % ELF::CREL_HDR_ADDEND;
+      uintX_t Offset = 0, Addend = 0;
+      uint32_t Symidx = 0, Type = 0;
+      for (size_t i = 0; i != Count; ++i) {
+        const uint8_t B = Data.getU8(Cur);
+        Offset += B >> FlagBits;
+        if (B >= 0x80)
+          Offset +=
+              (Data.getULEB128(Cur) << (7 - FlagBits)) - (0x80 >> FlagBits);
+        if (B & 1)
+          Symidx += Data.getSLEB128(Cur);
+        if (B & 2)
+          Type += Data.getSLEB128(Cur);
+        if (B & 4 && FlagBits == 3)
+          Addend += Data.getSLEB128(Cur);
+        if (!Cur)
+          break;
+        Crels[RelData.d.a].push_back(
+            Elf_Crel{Offset << Shift, uint32_t(Symidx), Type,
+                     std::make_signed_t<typename ELFT::uint>(Addend)});
+      }
+      if (!Cur) {
+        Crels[RelData.d.a].assign(1, Elf_Crel{0, 0, 0, 0});
+        CrelErrs[RelData.d.a] = toString(Cur.takeError());
+      }
+    }
+  }
   return relocation_iterator(RelocationRef(RelData, this));
 }
 
@@ -1030,9 +1082,13 @@ relocation_iterator
 ELFObjectFile<ELFT>::section_rel_end(DataRefImpl Sec) const {
   const Elf_Shdr *S = reinterpret_cast<const Elf_Shdr *>(Sec.p);
   relocation_iterator Begin = section_rel_begin(Sec);
+  DataRefImpl RelData = Begin->getRawDataRefImpl();
+  if (S->sh_type == ELF::SHT_CREL) {
+    RelData.d.b = Crels[RelData.d.a].size();
+    return relocation_iterator(RelocationRef(RelData, this));
+  }
   if (S->sh_type != ELF::SHT_RELA && S->sh_type != ELF::SHT_REL)
     return Begin;
-  DataRefImpl RelData = Begin->getRawDataRefImpl();
   const Elf_Shdr *RelSec = getRelSection(RelData);
 
   // Error check sh_link here so that getRelocationSymbol can just use it.
@@ -1050,7 +1106,7 @@ Expected<section_iterator>
 ELFObjectFile<ELFT>::getRelocatedSection(DataRefImpl Sec) const {
   const Elf_Shdr *EShdr = getSection(Sec);
   uintX_t Type = EShdr->sh_type;
-  if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA)
+  if (Type != ELF::SHT_REL && Type != ELF::SHT_RELA && Type != ELF::SHT_CREL)
     return section_end();
 
   Expected<const Elf_Shdr *> SecOrErr = EF.getSection(EShdr->sh_info);
@@ -1070,7 +1126,9 @@ symbol_iterator
 ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
   uint32_t symbolIdx;
   const Elf_Shdr *sec = getRelSection(Rel);
-  if (sec->sh_type == ELF::SHT_REL)
+  if (sec->sh_type == ELF::SHT_CREL)
+    symbolIdx = getCrel(Rel).r_symidx;
+  else if (sec->sh_type == ELF::SHT_REL)
     symbolIdx = getRel(Rel)->getSymbol(EF.isMips64EL());
   else
     symbolIdx = getRela(Rel)->getSymbol(EF.isMips64EL());
@@ -1087,6 +1145,8 @@ ELFObjectFile<ELFT>::getRelocationSymbol(DataRefImpl Rel) const {
 template <class ELFT>
 uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
   const Elf_Shdr *sec = getRelSection(Rel);
+  if (sec->sh_type == ELF::SHT_CREL)
+    return getCrel(Rel).r_offset;
   if (sec->sh_type == ELF::SHT_REL)
     return getRel(Rel)->r_offset;
 
@@ -1096,6 +1156,8 @@ uint64_t ELFObjectFile<ELFT>::getRelocationOffset(DataRefImpl Rel) const {
 template <class ELFT>
 uint64_t ELFObjectFile<ELFT>::getRelocationType(DataRefImpl Rel) const {
   const Elf_Shdr *sec = getRelSection(Rel);
+  if (sec->sh_type == ELF::SHT_CREL)
+    return getCrel(Rel).r_type;
   if (sec->sh_type == ELF::SHT_REL)
     return getRel(Rel)->getType(EF.isMips64EL());
   else
@@ -1117,9 +1179,11 @@ void ELFObjectFile<ELFT>::getRelocationTypeName(
 template <class ELFT>
 Expected<int64_t>
 ELFObjectFile<ELFT>::getRelocationAddend(DataRefImpl Rel) const {
-  if (getRelSection(Rel)->sh_type != ELF::SHT_RELA)
-    return createError("Section is not SHT_RELA");
-  return (int64_t)getRela(Rel)->r_addend;
+  if (getRelSection(Rel)->sh_type == ELF::SHT_RELA)
+    return (int64_t)getRela(Rel)->r_addend;
+  if (getRelSection(Rel)->sh_type == ELF::SHT_CREL)
+    return (int64_t)getCrel(Rel).r_addend;
+  return createError("Section is not SHT_RELA");
 }
 
 template <class ELFT>
@@ -1142,6 +1206,14 @@ ELFObjectFile<ELFT>::getRela(DataRefImpl Rela) const {
   return *Ret;
 }
 
+template <class ELFT>
+typename ELFObjectFile<ELFT>::Elf_Crel
+ELFObjectFile<ELFT>::getCrel(DataRefImpl Crel) const {
+  assert(getRelSection(Crel)->sh_type == ELF::SHT_CREL);
+  assert(Crel.d.a < Crels.size());
+  return Crels[Crel.d.a][Crel.d.b];
+}
+
 template <class ELFT>
 Expected<ELFObjectFile<ELFT>>
 ELFObjectFile<ELFT>::create(MemoryBufferRef Object, bool InitContent) {
@@ -1453,6 +1525,15 @@ template <class ELFT> bool ELFObjectFile<ELFT>::isRelocatableObject() const {
   return EF.getHeader().e_type == ELF::ET_REL;
 }
 
+template <class ELFT>
+StringRef ELFObjectFile<ELFT>::getCrelError(DataRefImpl Sec) const {
+  uintptr_t SHT = reinterpret_cast<uintptr_t>(cantFail(EF.sections()).begin());
+  auto I = (Sec.p - SHT) / EF.getHeader().e_shentsize;
+  if (I < CrelErrs.size())
+    return CrelErrs[I];
+  return "";
+}
+
 } // end namespace object
 } // end namespace llvm
 
diff --git a/llvm/lib/Object/ELFObjectFile.cpp b/llvm/lib/Object/ELFObjectFile.cpp
index cbc55a145e0e6..3da7da759a145 100644
--- a/llvm/lib/Object/ELFObjectFile.cpp
+++ b/llvm/lib/Object/ELFObjectFile.cpp
@@ -1013,3 +1013,14 @@ Expected<std::vector<BBAddrMap>> ELFObjectFileBase::readBBAddrMap(
   return readBBAddrMapImpl(cast<ELF64BEObjectFile>(this)->getELFFile(),
                            TextSectionIndex, PGOAnalyses);
 }
+
+StringRef ELFObjectFileBase::getCrelError(SectionRef Sec) const {
+  auto Data = Sec.getRawDataRefImpl();
+  if (const auto *Obj = dyn_cast<ELF32LEObjectFile>(this))
+    return Obj->getCrelError(Data);
+  if (const auto *Obj = dyn_cast<ELF32BEObjectFile>(this))
+    return Obj->getCrelError(Data);
+  if (const auto *Obj = dyn_cast<ELF64LEObjectFile>(this))
+    return Obj->getCrelError(Data);
+  return cast<ELF64BEObjectFile>(this)->getCrelError(Data);
+}
diff --git a/llvm/test/tools/llvm-objdump/ELF/crel.test b/llvm/test/tools/llvm-objdump/ELF/crel.test
new file mode 100644
index 0000000000000..7eb435e232ae4
--- /dev/null
+++ b/llvm/test/tools/llvm-objdump/ELF/crel.test
@@ -0,0 +1,213 @@
+# RUN: yaml2obj --docnum=1 %s -o %t
+# RUN: llvm-objdump -r %t | FileCheck %s --strict-whitespace --match-full-lines
+
+#      CHECK:RELOCATION RECORDS FOR [.text]:
+# CHECK-NEXT:OFFSET           TYPE                     VALUE
+# CHECK-NEXT:0000000000000001 R_X86_64_32              g1+0x1
+# CHECK-NEXT:0000000000000002 R_X86_64_64              l1+0x2
+# CHECK-NEXT:0000000000000000 R_X86_64_32S             g1-0x1
+# CHECK-NEXT:0000000000000004 R_X86_64_32S             .text-0x8000000000000000
+#CHECK-EMPTY:
+# CHECK-NEXT:RELOCATION RECORDS FOR [nonalloc]:
+# CHECK-NEXT:OFFSET           TYPE                     VALUE
+# CHECK-NEXT:0000000000000010 R_X86_64_64              g1+0x1
+# CHECK-NEXT:0000000000000020 R_X86_64_64              g2+0x2
+# CHECK-NEXT:0000000000000030 R_X86_64_64              *ABS*
+#  CHECK-NOT:{{.}}
+
+--- !ELF
+FileHeader: !FileHeader
+  Class: ELFCLASS64
+  Data: ELFDATA2LSB
+  Type: ET_REL
+  Machine: EM_X86_64
+
+Sections:
+- Name: .text
+  Type: SHT_PROGBITS
+  Content: "0000000000000000"
+  Flags: [SHF_ALLOC]
+- Name: .crel.text
+  Type: SHT_CREL
+  Info: .text
+  Link: .symtab
+  Relocations:
+    - Offset: 0x1
+      Symbol: g1
+      Type:   R_X86_64_32
+      Addend: 1
+    - Offset: 0x2
+      Symbol: l1
+      Type:   R_X86_64_64
+      Addend: 2
+    - Offset: 0x0
+      Symbol: g1
+      Type:   R_X86_64_32S
+      Addend: 0xffffffffffffffff
+    - Offset: 0x4
+      Symbol: .text
+      Type:   R_X86_64_32S
+      Addend: 0x8000000000000000
+- Name: nonalloc
+  Type: SHT_PROGBITS
+  Size: 0x30
+- Name: .crelnonalloc
+  Type: SHT_CREL
+  Info: nonalloc
+  Link: .symtab
+  Relocations:
+    - Offset: 0x10
+      Symbol: g1
+      Type:   R_X86_64_64
+      Addend: 1
+    - Offset: 0x20
+      Symbol: g2
+      Type:   R_X86_64_64
+      Addend: 2
+    - Offset: 0x30
+      Symbol: 0
+      Type:   R_X86_64_64
+
+Symbols:
+  - Name: .text
+    Type: STT_SECTION
+    Section: .text
+  - Name:    l1
+  - Name:    g1
+    Section: .text
+    Value:   0x0
+    Size:    4
+    Binding: STB_GLOBAL
+  - Name:    g2
+    Binding: STB_GLOBAL
+
+## Check relocation formatting on ELFCLASS32 as well.
+# RUN: yaml2obj --docnum=2 %s > %t2
+# RUN: llvm-objdump -r %t2 | FileCheck %s --check-prefix=ELF32 --strict-whitespace --match-full-lines
+
+#      ELF32:RELOCATION RECORDS FOR [.text]:
+# ELF32-NEXT:OFFSET   TYPE                     VALUE
+# ELF32-NEXT:00000008 R_ARM_REL32              l1+0x1
+# ELF32-NEXT:00000004 R_ARM_ABS32              g1
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS32
+  Data:    ELFDATA2MSB
+  Type:    ET_REL
+  Machine: EM_ARM
+Sections:
+- Name: .text
+  Type: SHT_PROGBITS
+  Size: 0x10
+- Name: .crel.text
+  Type: SHT_CREL
+  Info: .text
+  Link: .symtab
+  Relocations:
+    - Offset: 0x8
+      Symbol: l1
+      Type:   R_ARM_REL32
+      Addend: 1
+    - Offset: 0x4
+      Symbol: g1
+      Type:   R_ARM_ABS32
+Symbols:
+  - Name:    l1
+  - Name:    g1
+    Binding: STB_GLOBAL
+
+## Check CREL with implicit addends.
+# RUN: yaml2obj --docnum=3 %s -o %t3
+# RUN: llvm-objdump -r %t3 | FileCheck %s --check-prefix=IMPLICIT --strict-whitespace --match-full-lines
+#      IMPLICIT:RELOCATION RECORDS FOR [.data]:
+# IMPLICIT-NEXT:OFFSET           TYPE                     VALUE
+# IMPLICIT-NEXT:000000000000001f R_X86_64_32              g1
+# IMPLICIT-NEXT:000000000000003f R_X86_64_64              g1
+# IMPLICIT-NEXT:0000000000000000 R_X86_64_32S             l1
+--- !ELF
+FileHeader:
+  Class:     ELFCLASS64
+  Data:      ELFDATA2LSB
+  Type:      ET_REL
+  Machine:   EM_X86_64
+Sections:
+  - Name:    .text
+    Type:    SHT_PROGBITS
+  - Name:    .data
+    Type:    SHT_PROGBITS
+  - Name:    .crel.data
+    Type:    SHT_CREL
+    Flags:   [ SHF_INFO_LINK ]
+    Link:    .symtab
+    Info:    .data
+    Content: 187f030a82017787feffffffffffffff077f0a
+Symbols:
+  - Name:    .text
+    Type:    STT_SECTION
+    Section: .text
+  - Name:    l1
+    Section: .text
+  - Name:    g1
+    Section: .text
+    Binding: STB_GLOBAL
+
+## Test errors.
+# RUN: yaml2obj --docnum=4 %s -o %t.err
+# RUN: llvm-objdump -r %t.err 2>&1 | FileCheck %s --check-prefix=ERR -DFILE=%t.err
+
+#      ERR:RELOCATION RECORDS FOR [.data]:
+# ERR-NEXT:OFFSET           TYPE                     VALUE
+# ERR-NEXT:warning: '[[FILE]]': unable to decode LEB128 at offset 0x00000000: malformed uleb128, extends past end
+#  ERR-NOT:{{.}}
+
+--- !ELF
+FileHeader:
+  Class:     ELFCLASS64
+  Data:      ELFDATA2LSB
+  Type:      ET_REL
+  Machine:   EM_X86_64
+Sections:
+  - Name:    .text
+    Type:    SHT_PROGBITS
+  - Name:    .data
+    Type:    SHT_PROGBITS
+  - Name:    .crel.data
+    Type:    SHT_CREL
+    Flags:   []
+    Link:    .symtab
+    Info:    .data
+Symbols:
+  - Name:    .text
+    Type:    STT_SECTION
+    Section: .text
+
+# RUN: yaml2obj --docnum=5 %s -o %t.err2
+# RUN: llvm-objdump -r %t.err2 2>&1 | FileCheck %s --check-prefix=ERR2 -DFILE=%t.err2
+
+#      ERR2:RELOCATION RECORDS FOR [.data]:
+# ERR2-NEXT:OFFSET           TYPE                     VALUE
+# ERR2-NEXT:warning: '[[FILE]]': unexpected end of data at offset 0x1 while reading [0x1, 0x2)
+#  ERR-NOT:{{.}}
+
+--- !ELF
+FileHeader:
+  Class:     ELFCLASS32
+  Data:      ELFDATA2MSB
+  Type:      ET_REL
+  Machine:   EM_ARM
+Sections:
+  - Name:    .text
+    Type:    SHT_PROGBITS
+  - Name:    .data
+    Type:    SHT_PROGBITS
+  - Name:    .crel.data
+    Type:    SHT_CREL
+    Flags:   []
+    Link:    .symtab
+    Info:    .data
+    Content: 08
+Symbols:
+  - Name:    .text
+    Type:    STT_SECTION
+    Section: .text
diff --git a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
index cce0712e8fa0d..a6bd09ce3fa24 100644
--- a/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
+++ b/llvm/test/tools/llvm-objdump/X86/elf-disassemble-relocs.test
@@ -6,6 +6,10 @@
 # RUN: llvm-objdump 1.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS"
 # RUN: llvm-objdump 1.o -r --disassemble-symbols=x2,x4 | FileCheck %s --check-prefix=CHECK2
 
+# RUN: llvm-mc -filetype=obj -triple=x86_64 -crel 1.s -o 1leb.o
+# RUN: llvm-objdump 1leb.o -d -r | FileCheck %s --implicit-check-not="RELOCATION RECORDS"
+# RUN: llvm-objdump 1leb.o -r --disassemble-symbols=x2,x4 | FileCheck %s --check-prefix=CHECK2
+
 #--- 1.s
 # CHECK:       0000000000000000 <x1>:
 # CHECK-NEXT:    0: e8 00 00 00 00                callq   0x5 <x1+0x5>
diff --git a/llvm/tools/llvm-objdump/ELFDump.cpp b/llvm/tools/llvm-objdump/ELFDump.cpp
index 8c184fc1fbb66..5ac13495662fa 100644
--- a/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -104,7 +104,11 @@ static Error getRelocationValueString(const ELFObjectFile<ELFT> *Obj,
   // In SHT_REL case we would need to read the addend from section data.
   // GNU objdump does not do that and we just follow for simplicity atm.
   bool Undef = false;
-  if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
+  if ((*SecOrErr)->sh_type == ELF::SHT_CREL) {
+    auto ERela = Obj->getCrel(Rel);
+    Addend = ERela.r_addend;
+    Undef = ERela.getSymbol(false) == 0;
+  } else if ((*SecOrErr)->sh_type == ELF::SHT_RELA) {
     const typename ELFT::Rela *ERela = Obj->getRela(Rel);
     Addend = ERela->r_addend;
     Undef = ERela->getSymbol(false) == 0;
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index 6249be4f332b7..792a27f8d3d3d 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -2687,6 +2687,15 @@ void Dumper::printRelocations() {
            << "VALUE\n";
 
     for (SectionRef Section : P.second) {
+      // CREL requires decoding and has its specific errors.
+      if (O.isELF() && ELFSectionRef(Section).getType() == ELF::SHT_CREL) {
+        const ELFObjectFileBase *ELF = cast<const ELFObjectFileBase>(&O);
+        StringRef Err = ELF->getCrelError(Section);
+        if (!Err.empty()) {
+          reportUniqueWarning(Err);
+          continue;
+        }
+      }
       for (const RelocationRef &Reloc : Section.relocations()) {
         uint64_t Address = Reloc.getOffset();
         SmallString<32> RelocName;

``````````

</details>


https://github.com/llvm/llvm-project/pull/97382


More information about the llvm-branch-commits mailing list