[lld] r181288 - [lld][ELF] split ELF reader into multiple functions for readability (no change in functionality)
Shankar Easwaran
shankare at codeaurora.org
Mon May 6 21:58:09 PDT 2013
Author: shankare
Date: Mon May 6 23:58:09 2013
New Revision: 181288
URL: http://llvm.org/viewvc/llvm-project?rev=181288&view=rev
Log:
[lld][ELF] split ELF reader into multiple functions for readability (no change in functionality)
Modified:
lld/trunk/lib/ReaderWriter/ELF/File.h
Modified: lld/trunk/lib/ReaderWriter/ELF/File.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/ELF/File.h?rev=181288&r1=181287&r2=181288&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/ELF/File.h (original)
+++ lld/trunk/lib/ReaderWriter/ELF/File.h Mon May 6 23:58:09 2013
@@ -121,14 +121,13 @@ public:
ELFFile(const ELFTargetInfo &ti, std::unique_ptr<llvm::MemoryBuffer> MB,
llvm::error_code &EC)
- : File(MB->getBufferIdentifier(), kindObject), _elfTargetInfo(ti) {
+ : File(MB->getBufferIdentifier(), kindObject), _elfTargetInfo(ti),
+ _doStringsMerge(false) {
llvm::OwningPtr<llvm::object::Binary> binaryFile;
EC = createBinary(MB.release(), binaryFile);
if (EC)
return;
- int ordinal = 0;
-
// Point Obj to correct class and bitwidth ELF object
_objFile.reset(
llvm::dyn_cast<llvm::object::ELFObjectFile<ELFT> >(binaryFile.get()));
@@ -140,13 +139,32 @@ public:
binaryFile.take();
- std::map<const Elf_Shdr *, std::vector<const Elf_Sym *> > sectionSymbols;
+ _doStringsMerge = _elfTargetInfo.mergeCommonStrings();
+
+ // Read input sections from the input file
+ // that need to be converted to
+ // atoms
+ if (createAtomizableSections(EC))
+ return;
+
+ // For mergeable strings, we would need to split the section
+ // into various atoms
+ if (createMergeableAtoms(EC))
+ return;
- // Sections that have merge string property
- std::vector<const Elf_Shdr *> mergeStringSections;
+ // Create the necessary symbols that are part of the section
+ // that we created in createAtomizableSections function
+ if (createSymbolsFromAtomizableSections(EC))
+ return;
- bool doStringsMerge = _elfTargetInfo.mergeCommonStrings();
+ // Create the appropriate atoms fom the file
+ if (createAtoms(EC))
+ return;
+ }
+ /// \brief Read input sections and populate necessary data structures
+ /// to read them later and create atoms
+ bool createAtomizableSections(llvm::error_code &EC) {
// Handle: SHT_REL and SHT_RELA sections:
// Increment over the sections, when REL/RELA section types are found add
// the contents to the RelocationReferences map.
@@ -156,41 +174,26 @@ public:
uint64_t totalRelocs = 0;
for (; sit != sie; sit.increment(EC)) {
if (EC)
- return;
+ return true;
const Elf_Shdr *section = _objFile->getElfSection(sit);
- switch (section->sh_type) {
- case llvm::ELF::SHT_NOTE:
- case llvm::ELF::SHT_STRTAB:
- case llvm::ELF::SHT_SYMTAB:
- case llvm::ELF::SHT_SYMTAB_SHNDX:
- continue;
- }
- if (section->sh_size == 0)
+
+ if (isIgnoredSection(section))
continue;
- if (doStringsMerge) {
- int64_t sectionFlags = section->sh_flags;
- sectionFlags &= ~llvm::ELF::SHF_ALLOC;
-
- // If the section have mergeable strings, the linker would
- // need to split the section into multiple atoms and mark them
- // mergeByContent
- if ((section->sh_entsize < 2) &&
- (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) {
- mergeStringSections.push_back(section);
- continue;
- }
+ if (isMergeableSection(section)) {
+ _mergeStringSections.push_back(section);
+ continue;
}
// Create a sectionSymbols entry for every progbits section.
if (section->sh_type == llvm::ELF::SHT_PROGBITS)
- sectionSymbols[section];
+ _sectionSymbols[section];
if (section->sh_type == llvm::ELF::SHT_RELA) {
StringRef sectionName;
if ((EC = _objFile->getSectionName(section, sectionName)))
- return;
+ return true;
// Get rid of the leading .rela so Atoms can use their own section
// name to find the relocs.
sectionName = sectionName.drop_front(5);
@@ -198,14 +201,14 @@ public:
auto rai(_objFile->beginELFRela(section));
auto rae(_objFile->endELFRela(section));
- _relocationAddendRefences[sectionName] = make_range(rai, rae);
+ _relocationAddendReferences[sectionName] = make_range(rai, rae);
totalRelocs += std::distance(rai, rae);
}
if (section->sh_type == llvm::ELF::SHT_REL) {
StringRef sectionName;
if ((EC = _objFile->getSectionName(section, sectionName)))
- return;
+ return true;
// Get rid of the leading .rel so Atoms can use their own section
// name to find the relocs.
sectionName = sectionName.drop_front(4);
@@ -218,20 +221,26 @@ public:
}
}
_references.reserve(totalRelocs);
+ return false;
+ }
+
+ /// \brief Create mergeable atoms from sections that have the merge attribute
+ /// set
+ bool createMergeableAtoms(llvm::error_code &EC) {
// Divide the section that contains mergeable strings into tokens
// TODO
// a) add resolver support to recognize multibyte chars
// b) Create a seperate section chunk to write mergeable atoms
std::vector<MergeString *> tokens;
- for (auto msi : mergeStringSections) {
+ for (auto msi : _mergeStringSections) {
StringRef sectionContents;
StringRef sectionName;
if ((EC = _objFile->getSectionName(msi, sectionName)))
- return;
+ return true;
if ((EC = _objFile->getSectionContents(msi, sectionContents)))
- return;
+ return true;
unsigned int prev = 0;
for (std::size_t i = 0, e = sectionContents.size(); i != e; ++i) {
@@ -255,6 +264,15 @@ public:
_definedAtoms._atoms.push_back(mergeAtom);
_mergeAtoms.push_back(mergeAtom);
}
+ return false;
+ }
+
+ /// \brief Add the symbols that the sections contain. The symbols will be
+ /// converted to atoms for
+ /// Undefined symbols, absolute symbols
+ bool createSymbolsFromAtomizableSections(llvm::error_code &EC) {
+ llvm::object::section_iterator sit(_objFile->begin_sections());
+ llvm::object::section_iterator sie(_objFile->end_sections());
// Increment over all the symbols collecting atoms and symbol names for
// later use.
@@ -263,17 +281,17 @@ public:
for (; it != ie; it.increment(EC)) {
if (EC)
- return;
+ return true;
if ((EC = it->getSection(sit)))
- return;
+ return true;
const Elf_Shdr *section = _objFile->getElfSection(sit);
const Elf_Sym *symbol = _objFile->getElfSymbol(it);
StringRef symbolName;
if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
- return;
+ return true;
if (symbol->st_shndx == llvm::ELF::SHN_ABS) {
// Create an absolute atom.
@@ -292,25 +310,38 @@ public:
} else {
// This is actually a defined symbol. Add it to its section's list of
// symbols.
- if (symbol->getType() == llvm::ELF::STT_NOTYPE || symbol->getType() ==
- llvm::ELF::STT_OBJECT || symbol->getType() == llvm::ELF::STT_FUNC ||
+ if (symbol->getType() == llvm::ELF::STT_NOTYPE ||
+ symbol->getType() == llvm::ELF::STT_OBJECT ||
+ symbol->getType() == llvm::ELF::STT_FUNC ||
symbol->getType() == llvm::ELF::STT_GNU_IFUNC ||
- symbol->getType() == llvm::ELF::STT_SECTION || symbol->getType() ==
- llvm::ELF::STT_FILE || symbol->getType() == llvm::ELF::STT_TLS ||
+ symbol->getType() == llvm::ELF::STT_SECTION ||
+ symbol->getType() == llvm::ELF::STT_FILE ||
+ symbol->getType() == llvm::ELF::STT_TLS ||
symbol->getType() == llvm::ELF::STT_COMMON ||
symbol->st_shndx == llvm::ELF::SHN_COMMON) {
- sectionSymbols[section].push_back(symbol);
+ _sectionSymbols[section].push_back(symbol);
} else {
llvm::errs() << "Unable to create atom for: " << symbolName << "\n";
EC = llvm::object::object_error::parse_failed;
- return;
+ return true;
}
}
}
+ return false;
+ }
+
+ /// \brief Create individual atoms
+ bool createAtoms(llvm::error_code &EC) {
+
+ int64_t ordinal = 0;
- for (auto &i : sectionSymbols) {
+ // Cached value of the targetHandler
+ TargetHandler<ELFT> &targetHandler =
+ _elfTargetInfo.template getTargetHandler<ELFT>();
+
+ for (auto &i : _sectionSymbols) {
auto &symbols = i.second;
- // Sort symbols by position.
+ // Sort symbols by position.
std::stable_sort(symbols.begin(), symbols.end(),
[](const Elf_Sym * A, const Elf_Sym * B) {
return A->st_value < B->st_value;
@@ -318,11 +349,11 @@ public:
StringRef sectionContents;
if ((EC = _objFile->getSectionContents(i.first, sectionContents)))
- return;
+ return true;
StringRef sectionName;
if ((EC = _objFile->getSectionName(i.first, sectionName)))
- return;
+ return true;
// If the section has no symbols, create a custom atom for it.
if (i.first->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() &&
@@ -355,28 +386,22 @@ public:
StringRef symbolName = "";
if ((*si)->getType() != llvm::ELF::STT_SECTION)
if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
- return;
+ return true;
const Elf_Shdr *section = _objFile->getSection(*si);
bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON ||
(*si)->st_shndx == llvm::ELF::SHN_COMMON;
- if ((section && section->sh_flags & llvm::ELF::SHF_MASKPROC) ||
- (((*si)->st_shndx >= llvm::ELF::SHN_LOPROC) &&
- ((*si)->st_shndx <= llvm::ELF::SHN_HIPROC))) {
- TargetHandler<ELFT> &TargetHandler =
- _elfTargetInfo.template getTargetHandler<ELFT>();
- TargetAtomHandler<ELFT> &elfAtomHandler =
- TargetHandler.targetAtomHandler();
- int64_t targetSymType = elfAtomHandler.getType(*si);
-
- if (targetSymType == llvm::ELF::STT_COMMON)
- isCommon = true;
+ if (isTargetAtom(section, *si)) {
+ TargetAtomHandler<ELFT> &_targetAtomHandler =
+ targetHandler.targetAtomHandler();
+ isCommon =
+ ((_targetAtomHandler.getType(*si)) == llvm::ELF::STT_COMMON);
}
- // Get the symbol's content:
- uint64_t contentSize;
+ // Get the symbol's content size
+ uint64_t contentSize = 0;
if (si + 1 == se) {
// if this is the last symbol, take up the remaining data.
contentSize = isCommon ? 0 : i.first->sh_size - (*si)->st_value;
@@ -442,12 +467,7 @@ public:
// mergeable section, treat them as defined atoms as they shouldnt be
// merged away as well as these symbols have to be part of symbol
// resolution
- int64_t sectionFlags = 0;
- if (section)
- sectionFlags = section->sh_flags;
- sectionFlags &= ~llvm::ELF::SHF_ALLOC;
- if (doStringsMerge && section && (section->sh_entsize < 2) &&
- (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) {
+ if (isMergeableSection(section)) {
if ((*si)->getBinding() == llvm::ELF::STB_GLOBAL) {
auto definedMergeAtom = new (_readerStorage) ELFDefinedAtom<ELFT>(
*this, symbolName, sectionName, (*si), section, symbolData,
@@ -504,45 +524,8 @@ public:
}
}
- // All the Atoms and References are created. Now update each Reference's
- // target with the Atom pointer it refers to.
- for (auto &ri : _references) {
- if (ri->kind() >= lld::Reference::kindTargetLow) {
- const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
- const Elf_Shdr *shdr = _objFile->getSection(Symbol);
- int64_t sectionFlags = 0;
- if (shdr)
- sectionFlags = shdr->sh_flags;
- sectionFlags &= ~llvm::ELF::SHF_ALLOC;
-
- // If the section has mergeable strings, then make the relocation
- // refer to the MergeAtom to allow deduping
- if (doStringsMerge && shdr && (shdr->sh_entsize < 2) &&
- (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) {
- const TargetRelocationHandler<ELFT> &relHandler = _elfTargetInfo
- .template getTargetHandler<ELFT>().getRelocationHandler();
- int64_t relocAddend = relHandler.relocAddend(*ri);
- uint64_t addend = ri->addend() + relocAddend;
- const MergeSectionKey ms(shdr, addend);
- auto msec = _mergedSectionMap.find(ms);
- if (msec == _mergedSectionMap.end()) {
- if (Symbol->getType() != llvm::ELF::STT_SECTION)
- addend = Symbol->st_value + addend;
- MergeAtomsIter mai = findMergeAtom(shdr, addend);
- if (mai != _mergeAtoms.end()) {
- ri->setOffset(addend - ((*mai)->offset()));
- ri->setAddend(0);
- ri->setTarget(*mai);
- } // check
- else
- llvm_unreachable("unable to find a merge atom");
- } // find
- else
- ri->setTarget(msec->second);
- } else
- ri->setTarget(findAtom(Symbol));
- }
- }
+ updateReferences();
+ return false;
}
virtual const atom_collection<DefinedAtom> &defined() const {
@@ -577,9 +560,9 @@ private:
// Only relocations that are inside the domain of the atom are added.
// Add Rela (those with r_addend) references:
- auto rari = _relocationAddendRefences.find(sectionName);
+ auto rari = _relocationAddendReferences.find(sectionName);
auto rri = _relocationReferences.find(sectionName);
- if (rari != _relocationAddendRefences.end())
+ if (rari != _relocationAddendReferences.end())
for (auto &rai : rari->second) {
if (!((rai.r_offset >= symbol->st_value) &&
(rai.r_offset < symbol->st_value + content.size())))
@@ -622,6 +605,86 @@ private:
return ret;
}
+ /// \brief After all the Atoms and References are created, update each
+ /// Reference's target with the Atom pointer it refers to.
+ void updateReferences() {
+
+ /// cached value of target relocation handler
+ const TargetRelocationHandler<ELFT> &_targetRelocationHandler =
+ _elfTargetInfo.template getTargetHandler<ELFT>().getRelocationHandler();
+
+ for (auto &ri : _references) {
+ if (ri->kind() >= lld::Reference::kindTargetLow) {
+ const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
+ const Elf_Shdr *shdr = _objFile->getSection(Symbol);
+ if (isMergeableSection(shdr)) {
+ int64_t relocAddend = _targetRelocationHandler.relocAddend(*ri);
+ uint64_t addend = ri->addend() + relocAddend;
+ const MergeSectionKey ms(shdr, addend);
+ auto msec = _mergedSectionMap.find(ms);
+ if (msec == _mergedSectionMap.end()) {
+ if (Symbol->getType() != llvm::ELF::STT_SECTION)
+ addend = Symbol->st_value + addend;
+ MergeAtomsIter mai = findMergeAtom(shdr, addend);
+ if (mai != _mergeAtoms.end()) {
+ ri->setOffset(addend - ((*mai)->offset()));
+ ri->setAddend(0);
+ ri->setTarget(*mai);
+ } // check
+ else
+ llvm_unreachable("unable to find a merge atom");
+ } // find
+ else
+ ri->setTarget(msec->second);
+ } else
+ ri->setTarget(findAtom(Symbol));
+ }
+ }
+ }
+
+ /// \brief Is the atom corresponding to the value of the section and the
+ /// symbol a targetAtom ? If so, let the target determine its contentType
+ inline bool isTargetAtom(const Elf_Shdr *shdr, const Elf_Sym *sym) {
+ if ((shdr && shdr->sh_flags & llvm::ELF::SHF_MASKPROC) ||
+ ((sym->st_shndx >= llvm::ELF::SHN_LOPROC) &&
+ (sym->st_shndx <= llvm::ELF::SHN_HIPROC)))
+ return true;
+ return false;
+ }
+
+ /// \brief Do we want to ignore the section. Ignored sections are
+ /// not processed to create atoms
+ bool isIgnoredSection(const Elf_Shdr *section) {
+ if (section->sh_size == 0)
+ return true;
+ switch (section->sh_type) {
+ case llvm::ELF::SHT_NOTE:
+ case llvm::ELF::SHT_STRTAB:
+ case llvm::ELF::SHT_SYMTAB:
+ case llvm::ELF::SHT_SYMTAB_SHNDX:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ /// \brief Is the current section be treated as a mergeable string section
+ bool isMergeableSection(const Elf_Shdr *section) {
+ if (_doStringsMerge && section) {
+ int64_t sectionFlags = section->sh_flags;
+ sectionFlags &= ~llvm::ELF::SHF_ALLOC;
+ // If the section have mergeable strings, the linker would
+ // need to split the section into multiple atoms and mark them
+ // mergeByContent
+ if ((section->sh_entsize < 2) &&
+ (sectionFlags == (llvm::ELF::SHF_MERGE | llvm::ELF::SHF_STRINGS))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
llvm::BumpPtrAllocator _readerStorage;
std::unique_ptr<llvm::object::ELFObjectFile<ELFT> > _objFile;
atom_collection_vector<DefinedAtom> _definedAtoms;
@@ -629,24 +692,37 @@ private:
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
- /// \brief _relocationAddendRefences and _relocationReferences contain the
+ /// \brief _relocationAddendReferences and _relocationReferences contain the
/// 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. -- .rel or .rela is prepended to create
/// the SHT_REL(A) section name.
std::unordered_map<
StringRef,
- range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rela_Iter>>
- _relocationAddendRefences;
+ range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rela_Iter> >
+ _relocationAddendReferences;
MergedSectionMapT _mergedSectionMap;
std::unordered_map<
StringRef,
- range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rel_Iter>>
- _relocationReferences;
+ range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rel_Iter> >
+ _relocationReferences;
std::vector<ELFReference<ELFT> *> _references;
llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
const ELFTargetInfo &_elfTargetInfo;
+
+ /// \brief Atoms that are created for a section that has the merge property
+ /// set
MergeAtomsT _mergeAtoms;
+
+ /// \brief the section and the symbols that are contained within it to create
+ /// used to create atoms
+ std::map<const Elf_Shdr *, std::vector<const Elf_Sym *> > _sectionSymbols;
+
+ /// \brief Sections that have merge string property
+ std::vector<const Elf_Shdr *> _mergeStringSections;
+
+ /// \brief the cached options relevant while reading the ELF File
+ bool _doStringsMerge : 1;
};
} // end namespace elf
} // end namespace lld
More information about the llvm-commits
mailing list