diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -855,22 +855,68 @@ } } +/// 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)); + } +} + +/// If SHT_LLVM_CALL_GRAPH_PROFILE exists "returns" symbol indices +template +static void +processRelocationsCGSection(SmallVector &symbolIndices, + ObjFile *InputObj) { + const ELFFile &obj = InputObj->getObj(); + ArrayRef> objSections = + CHECK(obj.sections(), "could not retrieve object sections"); + + // SHT_LLVM_CALL_GRAPH_PROFILE Section Index. + size_t cgProfileSectionIndex = 0; + for (size_t i = 0, e = objSections.size(); i < e; ++i) { + const Elf_Shdr_Impl &sec = objSections[i]; + if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) { + cgProfileSectionIndex = i; + break; + } + } + + for (size_t i = 0, e = objSections.size(); i < e; ++i) { + const Elf_Shdr_Impl &sec = objSections[i]; + if (sec.sh_type == SHT_REL || sec.sh_type == SHT_RELA) { + if (cgProfileSectionIndex && sec.sh_info == cgProfileSectionIndex) { + if (sec.sh_type == SHT_RELA) + getIndices(symbolIndices, + CHECK(obj.relas(sec), + "could not retrieve cg profile rela section")); + else + getIndices(symbolIndices, + CHECK(obj.rels(sec), + "could not retrieve cg profile rel section")); + break; + } + } + } +} + 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()) + symbolIndices.clear(); + processRelocationsCGSection(symbolIndices, obj); + if (symbolIndices.empty()) continue; - if (obj->cgProfileRel.size() != obj->cgProfile.size() * 2) + + 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 @@ -251,8 +251,6 @@ // SHT_LLVM_CALL_GRAPH_PROFILE table. ArrayRef cgProfile; - // SHT_LLVM_CALL_GRAPH_PROFILE relocations, always in the REL format. - ArrayRef cgProfileRel; // 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 @@ -571,19 +571,15 @@ CHECK(obj.getSectionStringTable(objSections), this); std::vector> 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) { + if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) cgProfile = check(obj.template getSectionContentsAsArray(sec)); - 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 +665,8 @@ 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.