diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -60,6 +60,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" +#include #include #include @@ -855,22 +856,34 @@ } } +/// Retrieves symbol indices either from REL or RELA section. +template +static void getIndices(SmallVector &symbolIndices, + ArrayRef cgProfileRel) { + for (const ELFTRel &rel : cgProfileRel) { + symbolIndices.push_back(rel.getSymbol(config->isMips64EL)); + } +} + template static void readCallGraphsFromObjectFiles() { - auto getIndex = [&](ObjFile *obj, uint32_t index) { - const Elf_Rel_Impl &rel = obj->cgProfileRel[index]; - return rel.getSymbol(config->isMips64EL); - }; + SmallVector symbolIndices; for (auto file : objectFiles) { auto *obj = cast>(file); - if (obj->cgProfileRel.empty()) + if (obj->cgProfileRel.empty() && obj->cgProfileRela.empty()) continue; - if (obj->cgProfileRel.size() != obj->cgProfile.size() * 2) + symbolIndices.clear(); + if (!obj->cgProfileRel.empty()) + getIndices(symbolIndices, obj->cgProfileRel); + else + getIndices(symbolIndices, obj->cgProfileRela); + + if (symbolIndices.size() != obj->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 &cgpe = obj->cgProfile[i]; - uint32_t fromIndex = getIndex(obj, i * 2); - uint32_t toIndex = getIndex(obj, i * 2 + 1); + uint32_t fromIndex = symbolIndices[i * 2]; + uint32_t toIndex = symbolIndices[i * 2 + 1]; auto *fromSym = dyn_cast(&obj->getSymbol(fromIndex)); auto *toSym = dyn_cast(&obj->getSymbol(toIndex)); if (!fromSym || !toSym) diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -253,6 +253,8 @@ ArrayRef cgProfile; // SHT_LLVM_CALL_GRAPH_PROFILE relocations, always in the REL format. ArrayRef cgProfileRel; + // SHT_LLVM_CALL_GRAPH_PROFILE relocations, always in the RELA format. + ArrayRef cgProfileRela; // Get cached DWARF information. DWARFCache *getDwarf(); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -674,6 +674,8 @@ if (cgProfileSectionIndex && sec.sh_info == cgProfileSectionIndex) { if (sec.sh_type == SHT_REL) cgProfileRel = CHECK(getObj().rels(sec), this); + else + cgProfileRela = CHECK(getObj().relas(sec), this); } }