Index: lib/ReaderWriter/ELF/ELFFile.h =================================================================== --- lib/ReaderWriter/ELF/ELFFile.h +++ lib/ReaderWriter/ELF/ELFFile.h @@ -13,6 +13,7 @@ #include "Atoms.h" #include "FileCommon.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringExtras.h" #include #include @@ -128,9 +129,12 @@ Atom *findAtom(const Elf_Sym *sourceSym, const Elf_Sym *targetSym); protected: + typedef llvm::DenseMap *>> + AtomsForSectionMap; + ELFDefinedAtom *createDefinedAtomAndAssignRelocations( StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol, - const Elf_Shdr *section, ArrayRef symContent, + const Elf_Shdr *sectionHdr, int sectionIdx, ArrayRef symContent, ArrayRef secContent); std::error_code doParse() override; @@ -212,12 +216,12 @@ /// Handle creation of atoms for .gnu.linkonce sections. std::error_code handleGnuLinkOnceSection( const Elf_Shdr *section, - llvm::StringMap *>> &atomsForSection); + AtomsForSectionMap &atomsForSection); // Handle COMDAT scetions. std::error_code handleSectionGroup( const Elf_Shdr *section, - llvm::StringMap *>> &atomsForSection); + AtomsForSectionMap &atomsForSection); /// Process the Undefined symbol and create an atom for it. ELFUndefinedAtom *createUndefinedAtom(StringRef symName, @@ -338,6 +342,18 @@ return nullptr; } + std::string createSectionKeyWithIndex(StringRef sectionName, + const Elf_Shdr *section, uint32_t idx) { + std::string sectionKey = sectionName; + if (isSectionMemberOfGroup(section)) + sectionKey += llvm::utohexstr(idx); + return sectionKey; + } + + std::string createSectionKey(StringRef sectionName, const Elf_Shdr *section) { + return createSectionKeyWithIndex(sectionName, section, section->sh_info); + } + llvm::BumpPtrAllocator _readerStorage; std::unique_ptr > _objFile; @@ -345,10 +361,11 @@ /// list of relocations references. In ELF, if a section named, ".text" has /// relocations will also have a section named ".rel.text" or ".rela.text" /// which will hold the entries. - std::unordered_map> - _relocationAddendReferences; + std::unordered_map> + _relocationAddendReferences; + std::unordered_map> + _relocationReferences; MergedSectionMapT _mergedSectionMap; - std::unordered_map> _relocationReferences; std::vector *> _references; llvm::DenseMap _symbolToAtomMapping; llvm::DenseMap *, const Elf_Sym *> @@ -364,8 +381,10 @@ MergeAtomsT _mergeAtoms; /// \brief the section and the symbols that are contained within it to create - /// used to create atoms - llvm::MapVector> _sectionSymbols; + /// used to create atoms. Each segment header maps to a pair made of + /// its index and the symbols it contains + llvm::MapVector>> _sectionSymbols; /// \brief Sections that have merge string property std::vector _mergeStringSections; Index: lib/ReaderWriter/ELF/ELFFile.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFFile.cpp +++ lib/ReaderWriter/ELF/ELFFile.cpp @@ -124,7 +124,13 @@ // the contents to the RelocationReferences map. // Record the number of relocs to guess at preallocating the buffer. uint64_t totalRelocs = 0; - for (const Elf_Shdr §ion : _objFile->sections()) { + uint32_t idx = 0; + //for (const Elf_Shdr §ion : _objFile->sections()) { + auto it = _objFile->begin_sections(); + auto ite = _objFile->end_sections(); + for (; it != ite; ++it, ++idx) { + const Elf_Shdr §ion = *it; + if (isIgnoredSection(§ion)) continue; @@ -143,7 +149,9 @@ auto rai(_objFile->begin_rela(§ion)); auto rae(_objFile->end_rela(§ion)); - _relocationAddendReferences[*sectionName] = make_range(rai, rae); + std::string sectionKey = createSectionKey(*sectionName, §ion); + _relocationAddendReferences[sectionKey] = make_range(rai, rae); + totalRelocs += std::distance(rai, rae); } else if (section.sh_type == llvm::ELF::SHT_REL) { auto sHdr = _objFile->getSection(section.sh_info); @@ -155,10 +163,12 @@ auto ri(_objFile->begin_rel(§ion)); auto re(_objFile->end_rel(§ion)); - _relocationReferences[*sectionName] = make_range(ri, re); + std::string sectionKey = createSectionKey(*sectionName, §ion); + _relocationReferences[sectionKey] = make_range(ri, re); + totalRelocs += std::distance(ri, re); } else { - _sectionSymbols[§ion]; + _sectionSymbols[§ion] = std::make_pair(idx, std::vector()); } } _references.reserve(totalRelocs); @@ -246,7 +256,7 @@ addAtom(*commonAtom); _symbolToAtomMapping.insert(std::make_pair(&*SymI, commonAtom)); } else if (isDefinedSymbol(&*SymI)) { - _sectionSymbols[section].push_back(SymI); + _sectionSymbols[section].second.push_back(SymI); } else { llvm::errs() << "Unable to create atom for: " << *symbolName << "\n"; return llvm::object::object_error::parse_failed; @@ -259,12 +269,15 @@ template std::error_code ELFFile::createAtoms() { // Holds all the atoms that are part of the section. They are the targets of // the kindGroupChild reference. - llvm::StringMap *>> atomsForSection; + AtomsForSectionMap atomsForSection; - // Contains a list of comdat sections for a group. + // Contains a list of comdat sections for a group. The sectionIdx is used + // to keep track of section ordering to match group section in the References + // match when creating ElfDefineAtom. for (auto &i : _sectionSymbols) { const Elf_Shdr *section = i.first; - std::vector &symbols = i.second; + uint32_t sectionIdx = i.second.first; + std::vector &symbols = i.second.second; // Sort symbols by position. std::stable_sort(symbols.begin(), symbols.end(), @@ -294,7 +307,7 @@ if (addAtoms) addAtom(*newAtom); else - atomsForSection[*sectionName].push_back(newAtom); + atomsForSection[section].push_back(newAtom); continue; } @@ -347,7 +360,7 @@ if (addAtoms) addAtom(*atom); else - atomsForSection[*sectionName].push_back(atom); + atomsForSection[section].push_back(atom); continue; } @@ -361,7 +374,7 @@ auto sym = new (_readerStorage) Elf_Sym(*symbol); sym->setBinding(llvm::ELF::STB_GLOBAL); anonAtom = createDefinedAtomAndAssignRelocations( - "", *sectionName, sym, section, symbolData, *sectionContents); + "", *sectionName, sym, section, sectionIdx, symbolData, *sectionContents); symbolData = ArrayRef(); // If this is the last atom, let's not create a followon reference. @@ -373,7 +386,7 @@ } ELFDefinedAtom *newAtom = createDefinedAtomAndAssignRelocations( - symbolName, *sectionName, &*symbol, section, symbolData, + symbolName, *sectionName, &*symbol, section, sectionIdx, symbolData, *sectionContents); newAtom->setOrdinal(++_ordinal); @@ -395,7 +408,7 @@ if (addAtoms) addAtom(*newAtom); else - atomsForSection[*sectionName].push_back(newAtom); + atomsForSection[section].push_back(newAtom); _symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom)); if (anonAtom) { @@ -403,7 +416,7 @@ if (addAtoms) addAtom(*anonAtom); else - atomsForSection[*sectionName].push_back(anonAtom); + atomsForSection[section].push_back(anonAtom); } } } @@ -422,7 +435,7 @@ template std::error_code ELFFile::handleGnuLinkOnceSection( const Elf_Shdr *section, - llvm::StringMap *>> &atomsForSection) { + AtomsForSectionMap &atomsForSection) { ErrorOr sectionName = this->getSectionName(section); if (std::error_code ec = sectionName.getError()) return ec; @@ -431,14 +444,14 @@ unsigned int referenceStart = _references.size(); std::vector *> refs; - for (auto ha : atomsForSection[*sectionName]) { + for (auto ha : atomsForSection[section]) { _groupChild[ha->symbol()] = std::make_pair(*sectionName, section); ELFReference *ref = new (_readerStorage) ELFReference(Reference::kindGroupChild); ref->setTarget(ha); refs.push_back(ref); } - atomsForSection[*sectionName].clear(); + atomsForSection[section].clear(); // Create a gnu linkonce atom. ELFDefinedAtom *atom = createDefinedAtom( *sectionName, *sectionName, nullptr, section, ArrayRef(), @@ -453,7 +466,7 @@ template std::error_code ELFFile::handleSectionGroup( const Elf_Shdr *section, - llvm::StringMap *>> &atomsForSection) { + AtomsForSectionMap &atomsForSection) { ErrorOr sectionName = this->getSectionName(section); if (std::error_code ec = sectionName.getError()) return ec; @@ -473,16 +486,13 @@ // member contains the symbol table index of the identifying entry. // The sh_flags member of the section header contains 0. The name of // the section (sh_name) is not specified. - std::vector sectionNames; + std::vector sections; const Elf_Word *groupMembers = reinterpret_cast(sectionContents->data()); const size_t count = section->sh_size / sizeof(Elf_Word); for (size_t i = 1; i < count; i++) { const Elf_Shdr *shdr = _objFile->getSection(groupMembers[i]); - ErrorOr sectionName = _objFile->getSectionName(shdr); - if (std::error_code ec = sectionName.getError()) - return ec; - sectionNames.push_back(*sectionName); + sections.push_back(shdr); } const Elf_Sym *symbol = _objFile->getSymbol(section->sh_info); const Elf_Shdr *symtab = _objFile->getSection(section->sh_link); @@ -492,15 +502,15 @@ unsigned int referenceStart = _references.size(); std::vector *> refs; - for (auto name : sectionNames) { - for (auto ha : atomsForSection[name]) { + for (auto sec : sections) { + for (auto ha : atomsForSection[sec]) { _groupChild[ha->symbol()] = std::make_pair(*symbolName, section); ELFReference *ref = new (_readerStorage) ELFReference(Reference::kindGroupChild); ref->setTarget(ha); refs.push_back(ref); } - atomsForSection[name].clear(); + atomsForSection[sec].clear(); } // Create an atom for comdat signature. @@ -549,17 +559,20 @@ template ELFDefinedAtom *ELFFile::createDefinedAtomAndAssignRelocations( StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol, - const Elf_Shdr *section, ArrayRef symContent, + const Elf_Shdr *section, int sectionIdx, ArrayRef symContent, ArrayRef secContent) { unsigned int referenceStart = _references.size(); + std::string sectionKey = createSectionKeyWithIndex(sectionName, section, + sectionIdx); + // Add Rela (those with r_addend) references: - auto rari = _relocationAddendReferences.find(sectionName); + auto rari = _relocationAddendReferences.find(sectionKey); if (rari != _relocationAddendReferences.end()) createRelocationReferences(symbol, symContent, rari->second); // Add Rel references. - auto rri = _relocationReferences.find(sectionName); + auto rri = _relocationReferences.find(sectionKey); if (rri != _relocationReferences.end()) createRelocationReferences(symbol, symContent, secContent, rri->second); @@ -691,7 +704,7 @@ sym->st_value = 0; sym->st_size = 0; auto *newAtom = createDefinedAtomAndAssignRelocations( - "", sectionName, sym, section, content, content); + "", sectionName, sym, section, -1, content, content); newAtom->setOrdinal(++_ordinal); return newAtom; }