[llvm] 24129fb - [LLD] Adding support for RELA for CG Profile.

Alexander Yermolovich via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 13 13:56:53 PDT 2021


Author: Alexander Yermolovich
Date: 2021-07-13T13:56:30-07:00
New Revision: 24129fbc9aa006badc2e6e8432980cb94aba090c

URL: https://github.com/llvm/llvm-project/commit/24129fbc9aa006badc2e6e8432980cb94aba090c
DIFF: https://github.com/llvm/llvm-project/commit/24129fbc9aa006badc2e6e8432980cb94aba090c.diff

LOG: [LLD] Adding support for RELA for CG Profile.

This is a follow up to https://reviews.llvm.org/D104080, and https://github.com/llvm/llvm-project/commit/ca3bdb57fa1ac98b711a735de048c12b5fdd8086#diff-e64a48fabe31db213a631fdc5f2acb51bdddf3f16a8fb2928784f4c579229585. The implementation of  call graph profile was changed from a black box section to relocation approach. This was done to be compatible with post processing tools like strip/objcopy, and llvm equivalent. When they are invoked on object file before the final linking step with this new approach the symbol indices correctness is preserved.

The GNU binutils tools change the REL section to RELA section, unlike llvm tools. For example when strip -S is run on the ELF object files, as an intermediate step before linking. To preserve compatibility this patch extends implementation in LLD and ELFDumper to support both REL and RELA sections for call graph profile.

Reviewed By: MaskRay, jhenderson

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

Added: 
    lld/test/ELF/cgprofile-rela.test

Modified: 
    lld/ELF/Driver.cpp
    lld/ELF/InputFiles.cpp
    lld/ELF/InputFiles.h
    llvm/test/tools/llvm-readobj/ELF/call-graph-profile.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index ef486370ce78..a15959158653 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -855,22 +855,64 @@ static void readCallGraph(MemoryBufferRef mb) {
   }
 }
 
-template <class ELFT> static void readCallGraphsFromObjectFiles() {
-  auto getIndex = [&](ObjFile<ELFT> *obj, uint32_t index) {
-    const Elf_Rel_Impl<ELFT, false> &rel = obj->cgProfileRel[index];
-    return rel.getSymbol(config->isMips64EL);
-  };
+// If SHT_LLVM_CALL_GRAPH_PROFILE and its relocation section exist, returns
+// true and populates cgProfile and symbolIndices.
+template <class ELFT>
+static bool
+processCallGraphRelocations(SmallVector<uint32_t, 32> &symbolIndices,
+                            ArrayRef<typename ELFT::CGProfile> &cgProfile,
+                            ObjFile<ELFT> *inputObj) {
+  symbolIndices.clear();
+  const ELFFile<ELFT> &obj = inputObj->getObj();
+  ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
+      CHECK(obj.sections(), "could not retrieve object sections");
+
+  if (inputObj->cgProfileSectionIndex == SHN_UNDEF)
+    return false;
 
+  cgProfile =
+      check(obj.template getSectionContentsAsArray<typename ELFT::CGProfile>(
+          objSections[inputObj->cgProfileSectionIndex]));
+
+  for (size_t i = 0, e = objSections.size(); i < e; ++i) {
+    const Elf_Shdr_Impl<ELFT> &sec = objSections[i];
+    if (sec.sh_info == inputObj->cgProfileSectionIndex) {
+      if (sec.sh_type == SHT_RELA) {
+        ArrayRef<typename ELFT::Rela> relas =
+            CHECK(obj.relas(sec), "could not retrieve cg profile rela section");
+        for (const typename ELFT::Rela &rel : relas)
+          symbolIndices.push_back(rel.getSymbol(config->isMips64EL));
+        break;
+      }
+      if (sec.sh_type == SHT_REL) {
+        ArrayRef<typename ELFT::Rel> rels =
+            CHECK(obj.rels(sec), "could not retrieve cg profile rel section");
+        for (const typename ELFT::Rel &rel : rels)
+          symbolIndices.push_back(rel.getSymbol(config->isMips64EL));
+        break;
+      }
+    }
+  }
+  if (symbolIndices.empty())
+    warn("SHT_LLVM_CALL_GRAPH_PROFILE exists, but relocation section doesn't");
+  return !symbolIndices.empty();
+}
+
+template <class ELFT> static void readCallGraphsFromObjectFiles() {
+  SmallVector<uint32_t, 32> symbolIndices;
+  ArrayRef<typename ELFT::CGProfile> cgProfile;
   for (auto file : objectFiles) {
     auto *obj = cast<ObjFile<ELFT>>(file);
-    if (obj->cgProfileRel.empty())
+    if (!processCallGraphRelocations(symbolIndices, cgProfile, obj))
       continue;
-    if (obj->cgProfileRel.size() != obj->cgProfile.size() * 2)
+
+    if (symbolIndices.size() != cgProfile.size() * 2)
       fatal("number of relocations doesn't match Weights");
-    for (uint32_t i = 0, size = obj->cgProfile.size(); i < size; ++i) {
-      const Elf_CGProfile_Impl<ELFT> &cgpe = obj->cgProfile[i];
-      uint32_t fromIndex = getIndex(obj, i * 2);
-      uint32_t toIndex = getIndex(obj, i * 2 + 1);
+
+    for (uint32_t i = 0, size = cgProfile.size(); i < size; ++i) {
+      const Elf_CGProfile_Impl<ELFT> &cgpe = cgProfile[i];
+      uint32_t fromIndex = symbolIndices[i * 2];
+      uint32_t toIndex = symbolIndices[i * 2 + 1];
       auto *fromSym = dyn_cast<Defined>(&obj->getSymbol(fromIndex));
       auto *toSym = dyn_cast<Defined>(&obj->getSymbol(toIndex));
       if (!fromSym || !toSym)

diff  --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 93ca1f1f265c..83a3788e0dc6 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -571,19 +571,14 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
       CHECK(obj.getSectionStringTable(objSections), this);
 
   std::vector<ArrayRef<Elf_Word>> selectedGroups;
-  // SHT_LLVM_CALL_GRAPH_PROFILE Section Index.
-  size_t cgProfileSectionIndex = 0;
 
   for (size_t i = 0, e = objSections.size(); i < e; ++i) {
     if (this->sections[i] == &InputSection::discarded)
       continue;
     const Elf_Shdr &sec = objSections[i];
 
-    if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) {
-      cgProfile =
-          check(obj.template getSectionContentsAsArray<Elf_CGProfile>(sec));
+    if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
       cgProfileSectionIndex = i;
-    }
 
     // SHF_EXCLUDE'ed sections are discarded by the linker. However,
     // if -r is given, we'll let the final link discard such sections.
@@ -669,13 +664,8 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
       continue;
     const Elf_Shdr &sec = objSections[i];
 
-    if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) {
+    if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA)
       this->sections[i] = createInputSection(sec);
-      if (cgProfileSectionIndex && sec.sh_info == cgProfileSectionIndex) {
-        if (sec.sh_type == SHT_REL)
-          cgProfileRel = CHECK(getObj().rels(sec), this);
-      }
-    }
 
     // A SHF_LINK_ORDER section with sh_link=0 is handled as if it did not have
     // the flag.

diff  --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h
index 7b35fd7ea98d..bd72cfcdd050 100644
--- a/lld/ELF/InputFiles.h
+++ b/lld/ELF/InputFiles.h
@@ -249,10 +249,8 @@ template <class ELFT> class ObjFile : public ELFFileBase {
   // Pointer to this input file's .llvm_addrsig section, if it has one.
   const Elf_Shdr *addrsigSec = nullptr;
 
-  // SHT_LLVM_CALL_GRAPH_PROFILE table.
-  ArrayRef<Elf_CGProfile> cgProfile;
-  // SHT_LLVM_CALL_GRAPH_PROFILE relocations, always in the REL format.
-  ArrayRef<Elf_Rel> cgProfileRel;
+  // SHT_LLVM_CALL_GRAPH_PROFILE section index.
+  uint32_t cgProfileSectionIndex = 0;
 
   // Get cached DWARF information.
   DWARFCache *getDwarf();

diff  --git a/lld/test/ELF/cgprofile-rela.test b/lld/test/ELF/cgprofile-rela.test
new file mode 100644
index 000000000000..189f169e6548
--- /dev/null
+++ b/lld/test/ELF/cgprofile-rela.test
@@ -0,0 +1,117 @@
+## Under some circumstances, GNU tools strip/objcopy change REL to RELA. https://sourceware.org/bugzilla/show_bug.cgi?id=28035
+## Test that LLD can handle call graph profile data relocated with RELA relocations.
+# REQUIRES: x86
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: llvm-nm --no-sort %t | FileCheck %s
+# RUN: ld.lld --no-call-graph-profile-sort %t.o -o %t
+# RUN: llvm-nm --no-sort %t | FileCheck %s --check-prefix=NO-CG
+
+# CHECK: 0000000000201124 t D
+# CHECK: 0000000000201122 t C
+# CHECK: 0000000000201128 t B
+# CHECK: 0000000000201120 t A
+# CHECK: 0000000000201126 T _start
+
+# NO-CG: 0000000000201120 t D
+# NO-CG: 0000000000201122 t C
+# NO-CG: 0000000000201124 t B
+# NO-CG: 0000000000201126 t A
+# NO-CG: 0000000000201128 T _start
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name: .text.D
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size: 2
+  - Name: .text.C
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size: 2
+  - Name: .text.B
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size: 2
+  - Name: .text.A
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size: 2
+  - Name: .text._start
+    Type: SHT_PROGBITS
+    Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size: 2
+  - Name: .llvm.call-graph-profile
+    Type: SHT_LLVM_CALL_GRAPH_PROFILE
+    Flags: [ SHF_EXCLUDE ]
+    Link: .symtab
+    AddressAlign: 0x1
+    Entries:
+      - Weight: 10
+      - Weight: 10
+      - Weight: 80
+      - Weight: 40
+      - Weight: 30
+      - Weight: 90
+  - Name: .rela.llvm.call-graph-profile
+    Type: SHT_RELA
+    Info: .llvm.call-graph-profile
+    Relocations:
+      - Offset: 0x0
+        Symbol: A
+        Type:   R_X86_64_NONE
+      - Offset: 0x0
+        Symbol: B
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: A
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: B
+        Type:   R_X86_64_NONE
+      - Offset: 0x10
+        Symbol: _start
+        Type:   R_X86_64_NONE
+      - Offset: 0x10
+        Symbol: B
+        Type:   R_X86_64_NONE
+      - Offset: 0x18
+        Symbol: A
+        Type:   R_X86_64_NONE
+      - Offset: 0x18
+        Symbol: C
+        Type:   R_X86_64_NONE
+      - Offset: 0x20
+        Symbol: B
+        Type:   R_X86_64_NONE
+      - Offset: 0x20
+        Symbol: C
+        Type:   R_X86_64_NONE
+      - Offset: 0x28
+        Symbol: C
+        Type:   R_X86_64_NONE
+      - Offset: 0x28
+        Symbol: D
+        Type:   R_X86_64_NONE
+Symbols:
+  - Name: D
+    Type: STT_FUNC
+    Section: .text.D
+  - Name: C
+    Type: STT_FUNC
+    Section: .text.C
+  - Name: B
+    Type: STT_FUNC
+    Section: .text.B
+  - Name: A
+    Type: STT_FUNC
+    Section: .text.A
+  - Name: _start
+    Binding: STB_GLOBAL
+    Section: .text._start

diff  --git a/llvm/test/tools/llvm-readobj/ELF/call-graph-profile.test b/llvm/test/tools/llvm-readobj/ELF/call-graph-profile.test
index 9ddc8e540571..99532a62957f 100644
--- a/llvm/test/tools/llvm-readobj/ELF/call-graph-profile.test
+++ b/llvm/test/tools/llvm-readobj/ELF/call-graph-profile.test
@@ -40,13 +40,13 @@ Sections:
     Relocations:
       - Symbol: foo
         Type:   R_X86_64_NONE
-      - Offset: 0x1
+      - Offset: 0x0
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x2
+      - Offset: 0x8
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x3
+      - Offset: 0x8
         Symbol: foo
         Type:   R_X86_64_NONE
 Symbols:
@@ -104,19 +104,19 @@ Sections:
     Relocations:
       - Symbol: 1
         Type:   R_X86_64_NONE
-      - Offset: 0x1
+      - Offset: 0x0
         Symbol: 2
         Type:   R_X86_64_NONE
-      - Offset: 0x2
+      - Offset: 0x8
         Symbol: 2
         Type:   R_X86_64_NONE
-      - Offset: 0x3
+      - Offset: 0x8
         Symbol: 3
         Type:   R_X86_64_NONE
-      - Offset: 0x4
+      - Offset: 0x10
         Symbol: 0x0 ## Null symbol.
         Type:   R_X86_64_NONE
-      - Offset: 0x5
+      - Offset: 0x10
         Symbol: 0x4 ## This index goes past the end of the symbol table.
         Type:   R_X86_64_NONE
   - Name:    .strtab
@@ -153,7 +153,6 @@ Sections:
     Entries:
       - Weight: 89
       - Weight: 98
-    EntSize: [[ENTSIZE=<none>]]
 Symbols:
   - Name: foo
   - Name: bar
@@ -185,30 +184,29 @@ Sections:
     Entries:
       - Weight: 89
       - Weight: 98
-    EntSize: [[ENTSIZE=<none>]]
   - Name: .rel.llvm.call-graph-profile
     Type: SHT_REL
     Info: .llvm.call-graph-profile
     Relocations:
       - Symbol: foo
         Type:   R_X86_64_NONE
-      - Offset: 0x1
+      - Offset: 0x0
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x2
+      - Offset: 0x8
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x3
+      - Offset: 0x8
         Symbol: foo
         Type:   R_X86_64_NONE
-      - Offset: 0x4
+      - Offset: 0x10
         Symbol: foo
         Type:   R_X86_64_NONE
 Symbols:
   - Name: foo
   - Name: bar
 
-## Check we report a warning when a relocation section cant't be loaded.
+## Check we report a warning when a REL relocation section can't be loaded.
 # RUN: yaml2obj %s --docnum=5 -o %t6.o
 # RUN: llvm-readobj %t6.o --cg-profile 2>&1 | FileCheck %s -DFILE=%t6.o --check-prefix=LLVM-RELOC-WRONG-SIZE
 # RUN: llvm-readobj %t6.o --elf-cg-profile 2>&1 | FileCheck %s -DFILE=%t6.o --check-prefix=LLVM-RELOC-WRONG-SIZE
@@ -235,23 +233,120 @@ Sections:
     Entries:
       - Weight: 89
       - Weight: 98
-    EntSize: [[ENTSIZE=<none>]]
   - Name: .rel.llvm.call-graph-profile
     Type: SHT_REL
     Info: .llvm.call-graph-profile
     Relocations:
       - Symbol: foo
         Type:   R_X86_64_NONE
-      - Offset: 0x1
+      - Offset: 0x0
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x2
+      - Offset: 0x8
         Symbol: bar
         Type:   R_X86_64_NONE
-      - Offset: 0x3
+      - Offset: 0x8
         Symbol: foo
         Type:   R_X86_64_NONE
     EntSize: 24
 Symbols:
   - Name: foo
   - Name: bar
+
+## GNU strip may convert SHT_REL to SHT_RELA. Test we can handle SHT_RELA.
+# RUN: yaml2obj %s --docnum=6 -o %t7.o
+# RUN: llvm-readobj %t7.o --cg-profile | FileCheck %s --check-prefix=LLVM-RELA
+# RUN: llvm-readelf %t7.o --cg-profile | FileCheck %s --check-prefix=GNU-RELA
+
+# LLVM-RELA:      CGProfile [
+# LLVM-RELA-NEXT:  CGProfileEntry {
+# LLVM-RELA-NEXT:    From: foo (1)
+# LLVM-RELA-NEXT:    To: bar (2)
+# LLVM-RELA-NEXT:    Weight: 89
+# LLVM-RELA-NEXT:  }
+# LLVM-RELA-NEXT:  CGProfileEntry {
+# LLVM-RELA-NEXT:    From: bar (2)
+# LLVM-RELA-NEXT:    To: foo (1)
+# LLVM-RELA-NEXT:    Weight: 98
+# LLVM-RELA-NEXT:  }
+# LLVM-RELA-NEXT: ]
+
+# GNU-RELA: GNUStyle::printCGProfile not implemented
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name: .llvm.call-graph-profile
+    Type: SHT_LLVM_CALL_GRAPH_PROFILE
+    Entries:
+      - Weight: 89
+      - Weight: 98
+  - Name: .rela.llvm.call-graph-profile
+    Type: SHT_RELA
+    Info: .llvm.call-graph-profile
+    Relocations:
+      - Symbol: foo
+        Type:   R_X86_64_NONE
+      - Offset: 0x0
+        Symbol: bar
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: bar
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: foo
+        Type:   R_X86_64_NONE
+Symbols:
+  - Name: foo
+  - Name: bar
+
+## Check we report a warning when a RELA relocation section can't be loaded.
+# RUN: yaml2obj %s --docnum=7 -o %t8.o
+# RUN: llvm-readobj %t8.o --cg-profile 2>&1 | FileCheck %s -DFILE=%t8.o --check-prefix=LLVM-RELOC-WRONG-SIZE-RELA
+# RUN: llvm-readobj %t8.o --elf-cg-profile 2>&1 | FileCheck %s -DFILE=%t8.o --check-prefix=LLVM-RELOC-WRONG-SIZE-RELA
+
+# LLVM-RELOC-WRONG-SIZE-RELA:      warning: '[[FILE]]': unable to load relocations for SHT_LLVM_CALL_GRAPH_PROFILE section: section [index 2] has invalid sh_entsize: expected 24, but got 16
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT: CGProfile [
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:  CGProfileEntry {
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:    Weight: 89
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:  }
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:  CGProfileEntry {
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:    Weight: 98
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT:  }
+# LLVM-RELOC-WRONG-SIZE-RELA-NEXT: ]
+
+--- !ELF
+FileHeader:
+  Class: ELFCLASS64
+  Data:  ELFDATA2LSB
+  Type:  ET_DYN
+  Machine: EM_X86_64
+Sections:
+  - Name: .llvm.call-graph-profile
+    Type: SHT_LLVM_CALL_GRAPH_PROFILE
+    Entries:
+      - Weight: 89
+      - Weight: 98
+  - Name: .rela.llvm.call-graph-profile
+    Type: SHT_RELA
+    Info: .llvm.call-graph-profile
+    Relocations:
+      - Symbol: foo
+        Type:   R_X86_64_NONE
+      - Offset: 0x0
+        Symbol: bar
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: bar
+        Type:   R_X86_64_NONE
+      - Offset: 0x8
+        Symbol: foo
+        Type:   R_X86_64_NONE
+    EntSize: 16
+Symbols:
+  - Name: foo
+  - Name: bar

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index 79824728982d..3e2dc17cef2b 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -6702,6 +6702,55 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printHashHistograms() {
   W.startLine() << "Hash Histogram not implemented!\n";
 }
 
+// Returns true if rel/rela section exists, and populates SymbolIndices.
+// Otherwise returns false.
+template <class ELFT>
+static bool getSymbolIndices(const typename ELFT::Shdr *CGRelSection,
+                             const ELFFile<ELFT> &Obj,
+                             const LLVMELFDumper<ELFT> *Dumper,
+                             SmallVector<uint32_t, 128> &SymbolIndices) {
+  if (!CGRelSection) {
+    Dumper->reportUniqueWarning(
+        "relocation section for a call graph section doesn't exist");
+    return false;
+  }
+
+  if (CGRelSection->sh_type == SHT_REL) {
+    typename ELFT::RelRange CGProfileRel;
+    Expected<typename ELFT::RelRange> CGProfileRelOrError =
+        Obj.rels(*CGRelSection);
+    if (!CGProfileRelOrError) {
+      Dumper->reportUniqueWarning("unable to load relocations for "
+                                  "SHT_LLVM_CALL_GRAPH_PROFILE section: " +
+                                  toString(CGProfileRelOrError.takeError()));
+      return false;
+    }
+
+    CGProfileRel = *CGProfileRelOrError;
+    for (const typename ELFT::Rel &Rel : CGProfileRel)
+      SymbolIndices.push_back(Rel.getSymbol(Obj.isMips64EL()));
+  } else {
+    // MC unconditionally produces SHT_REL, but GNU strip/objcopy may convert
+    // the format to SHT_RELA
+    // (https://sourceware.org/bugzilla/show_bug.cgi?id=28035)
+    typename ELFT::RelaRange CGProfileRela;
+    Expected<typename ELFT::RelaRange> CGProfileRelaOrError =
+        Obj.relas(*CGRelSection);
+    if (!CGProfileRelaOrError) {
+      Dumper->reportUniqueWarning("unable to load relocations for "
+                                  "SHT_LLVM_CALL_GRAPH_PROFILE section: " +
+                                  toString(CGProfileRelaOrError.takeError()));
+      return false;
+    }
+
+    CGProfileRela = *CGProfileRelaOrError;
+    for (const typename ELFT::Rela &Rela : CGProfileRela)
+      SymbolIndices.push_back(Rela.getSymbol(Obj.isMips64EL()));
+  }
+
+  return true;
+}
+
 template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
   llvm::MapVector<const Elf_Shdr *, const Elf_Shdr *> SecToRelocMap;
 
@@ -6723,40 +6772,22 @@ template <class ELFT> void LLVMELFDumper<ELFT>::printCGProfile() {
       return;
     }
 
-    Elf_Rel_Range CGProfileRel;
-    bool UseReloc = (CGRelSection != nullptr);
-    if (UseReloc) {
-      Expected<Elf_Rel_Range> CGProfileRelaOrError =
-          this->Obj.rels(*CGRelSection);
-      if (!CGProfileRelaOrError) {
-        this->reportUniqueWarning("unable to load relocations for "
-                                  "SHT_LLVM_CALL_GRAPH_PROFILE section: " +
-                                  toString(CGProfileRelaOrError.takeError()));
-        UseReloc = false;
-      } else
-        CGProfileRel = *CGProfileRelaOrError;
-
-      if (UseReloc && CGProfileRel.size() != (CGProfileOrErr->size() * 2)) {
-        this->reportUniqueWarning(
-            "number of from/to pairs does not match number of frequencies");
-        UseReloc = false;
-      }
-    } else
+    SmallVector<uint32_t, 128> SymbolIndices;
+    bool UseReloc =
+        getSymbolIndices<ELFT>(CGRelSection, this->Obj, this, SymbolIndices);
+    if (UseReloc && SymbolIndices.size() != CGProfileOrErr->size() * 2) {
       this->reportUniqueWarning(
-          "relocation section for a call graph section doesn't exist");
-
-    auto GetIndex = [&](uint32_t Index) {
-      const Elf_Rel_Impl<ELFT, false> &Rel = CGProfileRel[Index];
-      return Rel.getSymbol(this->Obj.isMips64EL());
-    };
+          "number of from/to pairs does not match number of frequencies");
+      UseReloc = false;
+    }
 
     ListScope L(W, "CGProfile");
     for (uint32_t I = 0, Size = CGProfileOrErr->size(); I != Size; ++I) {
       const Elf_CGProfile &CGPE = (*CGProfileOrErr)[I];
       DictScope D(W, "CGProfileEntry");
       if (UseReloc) {
-        uint32_t From = GetIndex(I * 2);
-        uint32_t To = GetIndex(I * 2 + 1);
+        uint32_t From = SymbolIndices[I * 2];
+        uint32_t To = SymbolIndices[I * 2 + 1];
         W.printNumber("From", this->getStaticSymbolName(From), From);
         W.printNumber("To", this->getStaticSymbolName(To), To);
       }


        


More information about the llvm-commits mailing list