parent
00fcf2e169
commit
238cc72ec5
|
@ -584,6 +584,122 @@ private:
|
|||
uint64_t _offset;
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
class ELFCommonAtom LLVM_FINAL : public DefinedAtom {
|
||||
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
|
||||
public:
|
||||
ELFCommonAtom(const ELFFile<ELFT> &file,
|
||||
StringRef symbolName,
|
||||
const Elf_Sym *symbol)
|
||||
: _owningFile(file),
|
||||
_symbolName(symbolName),
|
||||
_symbol(symbol) {}
|
||||
|
||||
virtual const ELFFile<ELFT> &file() const {
|
||||
return _owningFile;
|
||||
}
|
||||
|
||||
virtual StringRef name() const {
|
||||
return _symbolName;
|
||||
}
|
||||
|
||||
virtual uint64_t ordinal() const {
|
||||
return _ordinal;
|
||||
}
|
||||
|
||||
void setOrdinal(uint64_t ord) {
|
||||
_ordinal = ord;
|
||||
}
|
||||
|
||||
virtual uint64_t size() const {
|
||||
return _symbol->st_size;
|
||||
}
|
||||
|
||||
virtual Scope scope() const {
|
||||
if (_symbol->st_other == llvm::ELF::STV_HIDDEN)
|
||||
return scopeLinkageUnit;
|
||||
else if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
|
||||
return scopeGlobal;
|
||||
else
|
||||
return scopeTranslationUnit;
|
||||
}
|
||||
|
||||
virtual Interposable interposable() const {
|
||||
return interposeNo;
|
||||
}
|
||||
|
||||
virtual Merge merge() const {
|
||||
return mergeAsTentative;
|
||||
}
|
||||
|
||||
virtual ContentType contentType() const {
|
||||
if (_symbol->st_shndx >= llvm::ELF::SHN_LORESERVE &&
|
||||
_symbol->st_shndx <= llvm::ELF::SHN_HIOS)
|
||||
return _owningFile.getLinkingContext().template getTargetHandler<ELFT>().
|
||||
targetAtomHandler().contentType(nullptr, _symbol);
|
||||
return typeZeroFill;
|
||||
}
|
||||
|
||||
virtual Alignment alignment() const {
|
||||
return Alignment(llvm::Log2_64(_symbol->st_value));
|
||||
}
|
||||
|
||||
virtual SectionChoice sectionChoice() const {
|
||||
return sectionBasedOnContent;
|
||||
}
|
||||
|
||||
virtual StringRef customSectionName() const {
|
||||
return ".bss";
|
||||
}
|
||||
|
||||
virtual SectionPosition sectionPosition() const {
|
||||
return sectionPositionAny;
|
||||
}
|
||||
|
||||
virtual DeadStripKind deadStrip() const {
|
||||
return deadStripNormal;
|
||||
}
|
||||
|
||||
virtual ContentPermissions permissions() const {
|
||||
return permRW_;
|
||||
}
|
||||
|
||||
virtual bool isAlias() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>();
|
||||
}
|
||||
|
||||
virtual DefinedAtom::reference_iterator begin() const {
|
||||
uintptr_t index = 0;
|
||||
const void *it = reinterpret_cast<const void *>(index);
|
||||
return reference_iterator(*this, it);
|
||||
}
|
||||
|
||||
virtual DefinedAtom::reference_iterator end() const {
|
||||
uintptr_t index = 0;
|
||||
const void *it = reinterpret_cast<const void *>(index);
|
||||
return reference_iterator(*this, it);
|
||||
}
|
||||
protected:
|
||||
|
||||
virtual ~ELFCommonAtom() {}
|
||||
|
||||
virtual const Reference *derefIterator(const void *iter) const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void incrementIterator(const void *&iter) const {}
|
||||
|
||||
private:
|
||||
const ELFFile<ELFT> &_owningFile;
|
||||
StringRef _symbolName;
|
||||
const Elf_Sym *_symbol;
|
||||
uint64_t _ordinal;
|
||||
};
|
||||
|
||||
/// \brief An atom from a shared library.
|
||||
template <class ELFT>
|
||||
class ELFDynamicAtom LLVM_FINAL : public SharedLibraryAtom {
|
||||
|
|
|
@ -28,22 +28,16 @@ public:
|
|||
create(const ELFLinkingContext &ti, std::unique_ptr<llvm::MemoryBuffer> mb) {
|
||||
std::unique_ptr<DynamicFile> file(
|
||||
new DynamicFile(ti, mb->getBufferIdentifier()));
|
||||
llvm::OwningPtr<llvm::object::Binary> binaryFile;
|
||||
|
||||
bool useShlibUndefines = ti.useShlibUndefines();
|
||||
|
||||
if (error_code ec = createBinary(mb.release(), binaryFile))
|
||||
error_code ec;
|
||||
file->_objFile.reset(new llvm::object::ELFFile<ELFT>(mb.release(), ec));
|
||||
|
||||
if (ec)
|
||||
return ec;
|
||||
|
||||
// Point Obj to correct class and bitwidth ELF object
|
||||
file->_objFile.reset(
|
||||
dyn_cast<llvm::object::ELFObjectFile<ELFT>>(binaryFile.get()));
|
||||
|
||||
if (!file->_objFile)
|
||||
return make_error_code(llvm::object::object_error::invalid_file_type);
|
||||
|
||||
binaryFile.take();
|
||||
|
||||
llvm::object::ELFObjectFile<ELFT> &obj = *file->_objFile;
|
||||
llvm::object::ELFFile<ELFT> &obj = *file->_objFile;
|
||||
|
||||
file->_soname = obj.getLoadName();
|
||||
if (file->_soname.empty())
|
||||
|
@ -52,13 +46,12 @@ public:
|
|||
// Create a map from names to dynamic symbol table entries.
|
||||
// TODO: This should use the object file's build in hash table instead if
|
||||
// it exists.
|
||||
for (auto i = obj.begin_elf_dynamic_symbols(),
|
||||
e = obj.end_elf_dynamic_symbols();
|
||||
for (auto i = obj.begin_dynamic_symbols(),
|
||||
e = obj.end_dynamic_symbols();
|
||||
i != e; ++i) {
|
||||
StringRef name;
|
||||
if (error_code ec = obj.getSymbolName(
|
||||
obj.getDynamicSymbolTableSectionHeader(), &*i, name))
|
||||
return ec;
|
||||
auto name = obj.getSymbolName(i);
|
||||
if (!name)
|
||||
return error_code(name);
|
||||
|
||||
// TODO: Add absolute symbols
|
||||
if (i->st_shndx == llvm::ELF::SHN_ABS)
|
||||
|
@ -66,14 +59,14 @@ public:
|
|||
|
||||
if (useShlibUndefines && (i->st_shndx == llvm::ELF::SHN_UNDEF)) {
|
||||
// Create an undefined atom.
|
||||
if (!name.empty()) {
|
||||
if (!name->empty()) {
|
||||
auto *newAtom =
|
||||
new (file->_alloc) ELFUndefinedAtom<ELFT>(*file.get(), name, &*i);
|
||||
new (file->_alloc) ELFUndefinedAtom<ELFT>(*file.get(), *name, &*i);
|
||||
file->_undefinedAtoms._atoms.push_back(newAtom);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
file->_nameToSym[name]._symbol = &*i;
|
||||
file->_nameToSym[*name]._symbol = &*i;
|
||||
}
|
||||
|
||||
return std::move(file);
|
||||
|
@ -120,7 +113,7 @@ private:
|
|||
|
||||
mutable llvm::BumpPtrAllocator _alloc;
|
||||
const ELFLinkingContext &_context;
|
||||
std::unique_ptr<llvm::object::ELFObjectFile<ELFT> > _objFile;
|
||||
std::unique_ptr<llvm::object::ELFFile<ELFT>> _objFile;
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
|
@ -130,7 +123,7 @@ private:
|
|||
|
||||
struct SymAtomPair {
|
||||
SymAtomPair() : _symbol(nullptr), _atom(nullptr) {}
|
||||
const typename llvm::object::ELFObjectFile<ELFT>::Elf_Sym *_symbol;
|
||||
const typename llvm::object::ELFFile<ELFT>::Elf_Sym *_symbol;
|
||||
const SharedLibraryAtom *_atom;
|
||||
};
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ ELFLinkingContext::ELFLinkingContext(
|
|||
_isStaticExecutable(false), _outputYAML(false), _noInhibitExec(false),
|
||||
_mergeCommonStrings(false), _runLayoutPass(true),
|
||||
_useShlibUndefines(false), _dynamicLinkerArg(false),
|
||||
_noAllowDynamicLibraries(false),
|
||||
_outputMagic(OutputMagic::DEFAULT) {}
|
||||
|
||||
bool ELFLinkingContext::is64Bits() const { return getTriple().isArch64Bit(); }
|
||||
|
|
|
@ -47,6 +47,7 @@ template <class ELFT> class ELFFile : public File {
|
|||
typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
|
||||
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
|
||||
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
|
||||
typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Iter Elf_Sym_Iter;
|
||||
|
||||
// A Map is used to hold the atoms that have been divided up
|
||||
// after reading the section that contains Merge String attributes
|
||||
|
@ -124,59 +125,52 @@ public:
|
|||
std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
|
||||
: File(MB->getBufferIdentifier(), kindObject),
|
||||
_elfLinkingContext(context), _ordinal(0), _doStringsMerge(false) {
|
||||
llvm::OwningPtr<llvm::object::Binary> binaryFile;
|
||||
EC = createBinary(MB.release(), binaryFile);
|
||||
_objFile.reset(new llvm::object::ELFFile<ELFT>(MB.release(), EC));
|
||||
|
||||
if (EC)
|
||||
return;
|
||||
|
||||
// Point Obj to correct class and bitwidth ELF object
|
||||
_objFile.reset(
|
||||
llvm::dyn_cast<llvm::object::ELFObjectFile<ELFT> >(binaryFile.get()));
|
||||
|
||||
if (!_objFile) {
|
||||
EC = make_error_code(llvm::object::object_error::invalid_file_type);
|
||||
return;
|
||||
}
|
||||
|
||||
binaryFile.take();
|
||||
|
||||
_doStringsMerge = _elfLinkingContext.mergeCommonStrings();
|
||||
|
||||
// Read input sections from the input file that need to be converted to
|
||||
// atoms
|
||||
if (createAtomizableSections(EC))
|
||||
if (auto err = createAtomizableSections()) ; else {
|
||||
EC = err;
|
||||
return;
|
||||
}
|
||||
|
||||
// For mergeable strings, we would need to split the section into various
|
||||
// atoms
|
||||
if (createMergeableAtoms(EC))
|
||||
if (auto err = createMergeableAtoms()) ; else {
|
||||
EC = err;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the necessary symbols that are part of the section that we
|
||||
// created in createAtomizableSections function
|
||||
if (createSymbolsFromAtomizableSections(EC))
|
||||
if (auto err = createSymbolsFromAtomizableSections()) ; else {
|
||||
EC = err;
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the appropriate atoms from the file
|
||||
if (createAtoms(EC))
|
||||
if (auto err = createAtoms()) ; else {
|
||||
EC = err;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Read input sections and populate necessary data structures
|
||||
/// to read them later and create atoms
|
||||
bool createAtomizableSections(llvm::error_code &EC) {
|
||||
ErrorOr<void> createAtomizableSections() {
|
||||
// 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.
|
||||
llvm::object::section_iterator sit(_objFile->begin_sections());
|
||||
llvm::object::section_iterator sie(_objFile->end_sections());
|
||||
// Record the number of relocs to guess at preallocating the buffer.
|
||||
uint64_t totalRelocs = 0;
|
||||
for (; sit != sie; sit.increment(EC)) {
|
||||
if (EC)
|
||||
return true;
|
||||
|
||||
const Elf_Shdr *section = _objFile->getElfSection(sit);
|
||||
for (auto sit = _objFile->begin_sections(),
|
||||
sie = _objFile->end_sections(); sit != sie; ++sit) {
|
||||
const Elf_Shdr *section = &*sit;
|
||||
|
||||
if (isIgnoredSection(section))
|
||||
continue;
|
||||
|
@ -191,61 +185,67 @@ public:
|
|||
_sectionSymbols[section];
|
||||
|
||||
if (section->sh_type == llvm::ELF::SHT_RELA) {
|
||||
StringRef sectionName;
|
||||
if ((EC = _objFile->getSectionName(section, sectionName)))
|
||||
return true;
|
||||
auto sectionName = _objFile->getSectionName(section);
|
||||
if (!sectionName)
|
||||
return error_code(sectionName);
|
||||
|
||||
// Get rid of the leading .rela so Atoms can use their own section
|
||||
// name to find the relocs.
|
||||
sectionName = sectionName.drop_front(5);
|
||||
*sectionName = sectionName->drop_front(5);
|
||||
|
||||
auto rai(_objFile->beginELFRela(section));
|
||||
auto rae(_objFile->endELFRela(section));
|
||||
auto rai(_objFile->begin_rela(section));
|
||||
auto rae(_objFile->end_rela(section));
|
||||
|
||||
_relocationAddendReferences[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 true;
|
||||
auto sectionName = _objFile->getSectionName(section);
|
||||
if (!sectionName)
|
||||
return error_code(sectionName);
|
||||
|
||||
// Get rid of the leading .rel so Atoms can use their own section
|
||||
// name to find the relocs.
|
||||
sectionName = sectionName.drop_front(4);
|
||||
*sectionName = sectionName->drop_front(4);
|
||||
|
||||
auto ri(_objFile->beginELFRel(section));
|
||||
auto re(_objFile->endELFRel(section));
|
||||
auto ri(_objFile->begin_rel(section));
|
||||
auto re(_objFile->end_rel(section));
|
||||
|
||||
_relocationReferences[sectionName] = make_range(ri, re);
|
||||
_relocationReferences[*sectionName] = make_range(ri, re);
|
||||
totalRelocs += std::distance(ri, re);
|
||||
}
|
||||
}
|
||||
_references.reserve(totalRelocs);
|
||||
return false;
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
/// \brief Create mergeable atoms from sections that have the merge attribute
|
||||
/// set
|
||||
bool createMergeableAtoms(llvm::error_code &EC) {
|
||||
ErrorOr<void> createMergeableAtoms() {
|
||||
// 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 (const Elf_Shdr *msi : _mergeStringSections) {
|
||||
StringRef sectionContents;
|
||||
StringRef sectionName;
|
||||
if ((EC = _objFile->getSectionName(msi, sectionName)))
|
||||
return true;
|
||||
auto sectionName = _objFile->getSectionName(msi);
|
||||
if (!sectionName)
|
||||
return error_code(sectionName);
|
||||
|
||||
if ((EC = _objFile->getSectionContents(msi, sectionContents)))
|
||||
return true;
|
||||
auto sectionContents = _objFile->getSectionContents(msi);
|
||||
if (!sectionContents)
|
||||
return error_code(sectionContents);
|
||||
|
||||
StringRef secCont(
|
||||
reinterpret_cast<const char *>(sectionContents->begin()),
|
||||
sectionContents->size());
|
||||
|
||||
unsigned int prev = 0;
|
||||
for (std::size_t i = 0, e = sectionContents.size(); i != e; ++i) {
|
||||
if (sectionContents[i] == '\0') {
|
||||
for (std::size_t i = 0, e = sectionContents->size(); i != e; ++i) {
|
||||
if ((*sectionContents)[i] == '\0') {
|
||||
tokens.push_back(new (_readerStorage) MergeString(
|
||||
prev, sectionContents.slice(prev, i + 1), msi, sectionName));
|
||||
prev, secCont.slice(prev, i + 1), msi, *sectionName));
|
||||
prev = i + 1;
|
||||
}
|
||||
}
|
||||
|
@ -264,99 +264,100 @@ public:
|
|||
_definedAtoms._atoms.push_back(mergeAtom);
|
||||
_mergeAtoms.push_back(mergeAtom);
|
||||
}
|
||||
return false;
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
/// \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());
|
||||
|
||||
ErrorOr<void> createSymbolsFromAtomizableSections() {
|
||||
// Increment over all the symbols collecting atoms and symbol names for
|
||||
// later use.
|
||||
llvm::object::symbol_iterator it(_objFile->begin_symbols());
|
||||
llvm::object::symbol_iterator ie(_objFile->end_symbols());
|
||||
auto SymI = _objFile->begin_symbols(),
|
||||
SymE = _objFile->end_symbols();
|
||||
|
||||
// Skip ELF's first dummy symbol if we have one.
|
||||
if (it != ie)
|
||||
it.increment(EC);
|
||||
// Skip over dummy sym.
|
||||
if (SymI != SymE)
|
||||
++SymI;
|
||||
|
||||
for (; it != ie; it.increment(EC)) {
|
||||
if (EC)
|
||||
return true;
|
||||
for (; SymI != SymE; ++SymI) {
|
||||
const Elf_Shdr *section = _objFile->getSection(&*SymI);
|
||||
|
||||
if ((EC = it->getSection(sit)))
|
||||
return true;
|
||||
auto symbolName = _objFile->getSymbolName(SymI);
|
||||
if (!symbolName)
|
||||
return error_code(symbolName);
|
||||
|
||||
const Elf_Shdr *section = _objFile->getElfSection(sit);
|
||||
const Elf_Sym *symbol = _objFile->getElfSymbol(it);
|
||||
|
||||
StringRef symbolName;
|
||||
if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
|
||||
return true;
|
||||
|
||||
if (symbol->st_shndx == llvm::ELF::SHN_ABS) {
|
||||
if (SymI->st_shndx == llvm::ELF::SHN_ABS) {
|
||||
// Create an absolute atom.
|
||||
auto *newAtom = new (_readerStorage)
|
||||
ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, symbol->st_value);
|
||||
ELFAbsoluteAtom<ELFT>(*this, *symbolName, &*SymI, SymI->st_value);
|
||||
|
||||
_absoluteAtoms._atoms.push_back(newAtom);
|
||||
_symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
|
||||
} else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) {
|
||||
_symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom));
|
||||
} else if (SymI->st_shndx == llvm::ELF::SHN_UNDEF) {
|
||||
// Create an undefined atom.
|
||||
auto *newAtom = new (_readerStorage)
|
||||
ELFUndefinedAtom<ELFT>(*this, symbolName, symbol);
|
||||
ELFUndefinedAtom<ELFT>(*this, *symbolName, &*SymI);
|
||||
|
||||
_undefinedAtoms._atoms.push_back(newAtom);
|
||||
_symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
|
||||
_symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom));
|
||||
} else if (isCommonSymbol(&*SymI)) {
|
||||
auto *newAtom = new (_readerStorage)
|
||||
ELFCommonAtom<ELFT>(*this, *symbolName, &*SymI);
|
||||
_definedAtoms._atoms.push_back(newAtom);
|
||||
_symbolToAtomMapping.insert(std::make_pair(&*SymI, newAtom));
|
||||
} else {
|
||||
assert(section && "Symbol not defined in a section!");
|
||||
// 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 ||
|
||||
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_COMMON ||
|
||||
symbol->st_shndx == llvm::ELF::SHN_COMMON) {
|
||||
_sectionSymbols[section].push_back(symbol);
|
||||
if (SymI->getType() == llvm::ELF::STT_NOTYPE ||
|
||||
SymI->getType() == llvm::ELF::STT_OBJECT ||
|
||||
SymI->getType() == llvm::ELF::STT_FUNC ||
|
||||
SymI->getType() == llvm::ELF::STT_GNU_IFUNC ||
|
||||
SymI->getType() == llvm::ELF::STT_SECTION ||
|
||||
SymI->getType() == llvm::ELF::STT_FILE ||
|
||||
SymI->getType() == llvm::ELF::STT_TLS) {
|
||||
_sectionSymbols[section].push_back(SymI);
|
||||
} else {
|
||||
llvm::errs() << "Unable to create atom for: " << symbolName << "\n";
|
||||
EC = llvm::object::object_error::parse_failed;
|
||||
return true;
|
||||
llvm::errs() << "Unable to create atom for: " << *symbolName << "\n";
|
||||
return llvm::object::object_error::parse_failed;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
/// \brief Create individual atoms
|
||||
bool createAtoms(llvm::error_code &EC) {
|
||||
ErrorOr<void> createAtoms() {
|
||||
for (auto &i : _sectionSymbols) {
|
||||
const Elf_Shdr *section = i.first;
|
||||
std::vector<const Elf_Sym *> &symbols = i.second;
|
||||
std::vector<Elf_Sym_Iter> &symbols = i.second;
|
||||
|
||||
// Sort symbols by position.
|
||||
std::stable_sort(symbols.begin(), symbols.end(),
|
||||
[](const Elf_Sym *A, const Elf_Sym *B) {
|
||||
[](Elf_Sym_Iter A, Elf_Sym_Iter B) {
|
||||
return A->st_value < B->st_value;
|
||||
});
|
||||
|
||||
StringRef sectionName;
|
||||
StringRef sectionContents;
|
||||
if ((EC = _objFile->getSectionName(section, sectionName)))
|
||||
return true;
|
||||
if ((EC = _objFile->getSectionContents(section, sectionContents)))
|
||||
return true;
|
||||
auto sectionName = section ? _objFile->getSectionName(section)
|
||||
: StringRef();
|
||||
if (!sectionName)
|
||||
return error_code(sectionName);
|
||||
|
||||
auto sectionContents = section ? _objFile->getSectionContents(section)
|
||||
: ArrayRef<uint8_t>();
|
||||
if (!sectionContents)
|
||||
return error_code(sectionContents);
|
||||
|
||||
StringRef secCont(
|
||||
reinterpret_cast<const char *>(sectionContents->begin()),
|
||||
sectionContents->size());
|
||||
|
||||
// If the section has no symbols, create a custom atom for it.
|
||||
if (section->sh_type == llvm::ELF::SHT_PROGBITS && symbols.empty() &&
|
||||
!sectionContents.empty()) {
|
||||
if (section && section->sh_type == llvm::ELF::SHT_PROGBITS &&
|
||||
symbols.empty() && !sectionContents->empty()) {
|
||||
ELFDefinedAtom<ELFT> *newAtom = createSectionAtom(
|
||||
section, sectionName, sectionContents);
|
||||
section, *sectionName, secCont);
|
||||
_definedAtoms._atoms.push_back(newAtom);
|
||||
continue;
|
||||
}
|
||||
|
@ -365,21 +366,21 @@ public:
|
|||
ELFReference<ELFT> *anonFollowedBy = nullptr;
|
||||
|
||||
for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
|
||||
const Elf_Sym *symbol = *si;
|
||||
auto symbol = *si;
|
||||
StringRef symbolName = "";
|
||||
if (symbol->getType() != llvm::ELF::STT_SECTION)
|
||||
if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
|
||||
return true;
|
||||
if (symbol->getType() != llvm::ELF::STT_SECTION) {
|
||||
auto symName = _objFile->getSymbolName(symbol);
|
||||
if (!symName)
|
||||
return error_code(symName);
|
||||
symbolName = *symName;
|
||||
}
|
||||
|
||||
bool isCommon = isCommonSymbol(section, symbol);
|
||||
uint64_t contentSize = isCommon ? 0 : symbolContentSize(
|
||||
section, symbol, (si + 1 == se) ? nullptr : *(si + 1));
|
||||
uint64_t contentSize = symbolContentSize(
|
||||
section, &*symbol, (si + 1 == se) ? nullptr : &**(si + 1));
|
||||
|
||||
// Check to see if we need to add the FollowOn Reference
|
||||
// We dont want to do for symbols that are
|
||||
// a) common symbols
|
||||
ELFReference<ELFT> *followOn = nullptr;
|
||||
if (!isCommon && previousAtom) {
|
||||
if (previousAtom) {
|
||||
// Replace the followon atom with the anonymous atom that we created,
|
||||
// so that the next symbol that we create is a followon from the
|
||||
// anonymous atom.
|
||||
|
@ -393,7 +394,7 @@ public:
|
|||
}
|
||||
|
||||
ArrayRef<uint8_t> symbolData(
|
||||
(uint8_t *)sectionContents.data() + symbol->st_value, contentSize);
|
||||
(uint8_t *)sectionContents->data() + symbol->st_value, contentSize);
|
||||
|
||||
// If the linker finds that a section has global atoms that are in a
|
||||
// mergeable section, treat them as defined atoms as they shouldnt be
|
||||
|
@ -402,7 +403,7 @@ public:
|
|||
if (isMergeableStringSection(section)) {
|
||||
if (symbol->getBinding() == llvm::ELF::STB_GLOBAL) {
|
||||
auto definedMergeAtom = new (_readerStorage) ELFDefinedAtom<ELFT>(
|
||||
*this, symbolName, sectionName, (*si), section, symbolData,
|
||||
*this, symbolName, *sectionName, &**si, section, symbolData,
|
||||
_references.size(), _references.size(), _references);
|
||||
_definedAtoms._atoms.push_back(definedMergeAtom);
|
||||
}
|
||||
|
@ -419,7 +420,7 @@ public:
|
|||
auto sym = new (_readerStorage) Elf_Sym(*symbol);
|
||||
sym->setBinding(llvm::ELF::STB_GLOBAL);
|
||||
anonAtom = createDefinedAtomAndAssignRelocations(
|
||||
"", sectionName, sym, section, symbolData);
|
||||
"", *sectionName, sym, section, symbolData);
|
||||
anonAtom->setOrdinal(++_ordinal);
|
||||
symbolData = ArrayRef<uint8_t>();
|
||||
|
||||
|
@ -429,7 +430,7 @@ public:
|
|||
}
|
||||
|
||||
ELFDefinedAtom<ELFT> *newAtom = createDefinedAtomAndAssignRelocations(
|
||||
symbolName, sectionName, symbol, section, symbolData);
|
||||
symbolName, *sectionName, &*symbol, section, symbolData);
|
||||
newAtom->setOrdinal(++_ordinal);
|
||||
|
||||
// If this is the last atom, lets not create a followon reference.
|
||||
|
@ -444,7 +445,7 @@ public:
|
|||
if (anonAtom)
|
||||
createEdge(newAtom, anonAtom, lld::Reference::kindLayoutAfter);
|
||||
|
||||
if (!isCommon && previousAtom) {
|
||||
if (previousAtom) {
|
||||
// Set the followon atom to the weak atom that we have created, so
|
||||
// that they would alias when the file gets written.
|
||||
followOn->setTarget(anonAtom ? anonAtom : newAtom);
|
||||
|
@ -461,14 +462,14 @@ public:
|
|||
previousAtom = anonAtom ? anonAtom : newAtom;
|
||||
|
||||
_definedAtoms._atoms.push_back(newAtom);
|
||||
_symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
|
||||
_symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom));
|
||||
if (anonAtom)
|
||||
_definedAtoms._atoms.push_back(anonAtom);
|
||||
}
|
||||
}
|
||||
|
||||
updateReferences();
|
||||
return false;
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
|
@ -536,7 +537,7 @@ private:
|
|||
kind, symbolIndex);
|
||||
// Read the addend from the section contents
|
||||
// TODO : We should move the way lld reads relocations totally from
|
||||
// ELFObjectFile
|
||||
// ELFFile
|
||||
int32_t addend = *(content.data() + ri.r_offset - symbol->st_value);
|
||||
ERef->setAddend(addend);
|
||||
_references.push_back(ERef);
|
||||
|
@ -559,7 +560,7 @@ private:
|
|||
|
||||
for (auto &ri : _references) {
|
||||
if (ri->kind() >= lld::Reference::kindTargetLow) {
|
||||
const Elf_Sym *symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
|
||||
const Elf_Sym *symbol = _objFile->getSymbol(ri->targetSymbolIndex());
|
||||
const Elf_Shdr *shdr = _objFile->getSection(symbol);
|
||||
|
||||
// If the atom is not in mergeable string section, the target atom is
|
||||
|
@ -598,7 +599,7 @@ private:
|
|||
/// specific section. We will let the TargetHandler handle such atoms.
|
||||
inline bool isTargetSpecificAtom(const Elf_Shdr *shdr,
|
||||
const Elf_Sym *sym) {
|
||||
return ((shdr->sh_flags & llvm::ELF::SHF_MASKPROC) ||
|
||||
return ((shdr && (shdr->sh_flags & llvm::ELF::SHF_MASKPROC)) ||
|
||||
(sym->st_shndx >= llvm::ELF::SHN_LOPROC &&
|
||||
sym->st_shndx <= llvm::ELF::SHN_HIPROC));
|
||||
}
|
||||
|
@ -664,11 +665,11 @@ private:
|
|||
/// actual storage has not yet been allocated. (The linker will allocate
|
||||
/// storage for them in the later pass after coalescing tentative symbols by
|
||||
/// name.)
|
||||
bool isCommonSymbol(const Elf_Shdr *section, const Elf_Sym *symbol) {
|
||||
bool isCommonSymbol(const Elf_Sym *symbol) {
|
||||
// This method handles only architecture independent stuffs, and don't know
|
||||
// whether an architecture dependent section is for common symbols or
|
||||
// not. Let the TargetHandler to make a decision if that's the case.
|
||||
if (isTargetSpecificAtom(section, symbol)) {
|
||||
if (isTargetSpecificAtom(nullptr, symbol)) {
|
||||
TargetHandler<ELFT> &targetHandler =
|
||||
_elfLinkingContext.template getTargetHandler<ELFT>();
|
||||
TargetAtomHandler<ELFT> &targetAtomHandler =
|
||||
|
@ -697,7 +698,7 @@ private:
|
|||
}
|
||||
|
||||
llvm::BumpPtrAllocator _readerStorage;
|
||||
std::unique_ptr<llvm::object::ELFObjectFile<ELFT> > _objFile;
|
||||
std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
|
@ -710,12 +711,12 @@ private:
|
|||
/// the SHT_REL(A) section name.
|
||||
std::unordered_map<
|
||||
StringRef,
|
||||
range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rela_Iter> >
|
||||
range<typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter> >
|
||||
_relocationAddendReferences;
|
||||
MergedSectionMapT _mergedSectionMap;
|
||||
std::unordered_map<
|
||||
StringRef,
|
||||
range<typename llvm::object::ELFObjectFile<ELFT>::Elf_Rel_Iter> >
|
||||
range<typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter> >
|
||||
_relocationReferences;
|
||||
std::vector<ELFReference<ELFT> *> _references;
|
||||
llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
|
||||
|
@ -727,7 +728,7 @@ private:
|
|||
|
||||
/// \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;
|
||||
std::map<const Elf_Shdr *, std::vector<Elf_Sym_Iter>> _sectionSymbols;
|
||||
|
||||
/// \brief Sections that have merge string property
|
||||
std::vector<const Elf_Shdr *> _mergeStringSections;
|
||||
|
|
|
@ -7,6 +7,16 @@ RUN: lld -flavor gnu -target hexagon -e global_func --noinhibit-exec -emit-yaml
|
|||
RUN: %p/Inputs/object-test.elf-hexagon | FileCheck %s -check-prefix ELF-hexagon
|
||||
|
||||
ELF-i386:defined-atoms:
|
||||
ELF-i386: - name: common_symbol
|
||||
ELF-i386: scope: global
|
||||
ELF-i386: type: zero-fill
|
||||
ELF-i386: merge: as-tentative
|
||||
|
||||
ELF-i386: - name: tentative
|
||||
ELF-i386: scope: global
|
||||
ELF-i386: type: zero-fill
|
||||
ELF-i386: merge: as-tentative
|
||||
|
||||
ELF-i386: - name: global_func
|
||||
ELF-i386: scope: global
|
||||
ELF-i386: content: [ 55, 89, E5, 83, EC, 18, C7, 04, 24, 00, 00, 00,
|
||||
|
@ -41,16 +51,6 @@ ELF-i386: content: [ 55, 89, E5, 5D, C3 ]
|
|||
ELF-i386: section-choice: custom-required
|
||||
ELF-i386: section-name: special_section
|
||||
|
||||
ELF-i386: - name: tentative
|
||||
ELF-i386: scope: global
|
||||
ELF-i386: type: zero-fill
|
||||
ELF-i386: merge: as-tentative
|
||||
|
||||
ELF-i386: - name: common_symbol
|
||||
ELF-i386: scope: global
|
||||
ELF-i386: type: zero-fill
|
||||
ELF-i386: merge: as-tentative
|
||||
|
||||
|
||||
ELF-i386:undefined-atoms:
|
||||
ELF-i386: - name: puts
|
||||
|
@ -61,6 +61,16 @@ ELF-i386: value: 0x0
|
|||
|
||||
ELF-hexagon:defined-atoms:
|
||||
|
||||
ELF-hexagon: - name: common_symbol
|
||||
ELF-hexagon: scope: global
|
||||
ELF-hexagon: type: zero-fill
|
||||
ELF-hexagon: merge: as-tentative
|
||||
|
||||
ELF-hexagon: - name: tentative
|
||||
ELF-hexagon: scope: global
|
||||
ELF-hexagon: type: zero-fill
|
||||
ELF-hexagon: merge: as-tentative
|
||||
|
||||
ELF-hexagon: - name: global_func
|
||||
ELF-hexagon: scope: global
|
||||
ELF-hexagon: content: [ 00, C0, 9D, A0, 00, 40, 00, 00, 00, C0, 00, 78,
|
||||
|
@ -95,16 +105,6 @@ ELF-hexagon: content: [ 00, C0, 9D, A0, 1E, C0, 1E, 96 ]
|
|||
ELF-hexagon: section-choice: custom-required
|
||||
ELF-hexagon: section-name: special_section
|
||||
|
||||
ELF-hexagon: - name: tentative
|
||||
ELF-hexagon: scope: global
|
||||
ELF-hexagon: type: zero-fill
|
||||
ELF-hexagon: merge: as-tentative
|
||||
|
||||
ELF-hexagon: - name: common_symbol
|
||||
ELF-hexagon: scope: global
|
||||
ELF-hexagon: type: zero-fill
|
||||
ELF-hexagon: merge: as-tentative
|
||||
|
||||
ELF-hexagon: undefined-atoms:
|
||||
ELF-hexagon: - name: puts
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
RUN: lld -flavor gnu -target hexagon -o %t1 --noinhibit-exec \
|
||||
RUN: %p/Inputs/quickdata-sortcommon-test.o.elf-hexagon
|
||||
RUN: llvm-nm -n %t1 | FileCheck %s -check-prefix=quickdataSortCommon
|
||||
XFAIL: *
|
||||
|
||||
quickdataSortCommon: 00002000 D A1
|
||||
quickdataSortCommon: 00002001 D AA1
|
||||
|
|
|
@ -63,7 +63,7 @@ I386-NEXT: Offset: 0x4000
|
|||
I386-NEXT: VirtualAddress: 0x4000
|
||||
I386-NEXT: PhysicalAddress: 0x4000
|
||||
I386-NEXT: FileSize: 4
|
||||
I386-NEXT: MemSize: 16389
|
||||
I386-NEXT: MemSize: 16392
|
||||
I386-NEXT: Flags [ (0x6)
|
||||
I386-NEXT: PF_R (0x4)
|
||||
I386-NEXT: PF_W (0x2)
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
RUN: lld -flavor gnu -target hexagon -emit-yaml %p/Inputs/quickdata-test.elf-hexagon \
|
||||
RUN: | FileCheck %s -check-prefix hexagon
|
||||
|
||||
hexagon: - name: ac1
|
||||
hexagon: scope: global
|
||||
hexagon: type: zero-fill-quick
|
||||
hexagon: size: 1
|
||||
hexagon: merge: as-tentative
|
||||
hexagon: - name: init
|
||||
hexagon: scope: global
|
||||
hexagon: type: quick-data
|
||||
hexagon: - name: bss1
|
||||
hexagon: scope: global
|
||||
hexagon: type: quick-data
|
||||
hexagon: - name: ac1
|
||||
hexagon: scope: global
|
||||
hexagon: type: zero-fill-quick
|
||||
hexagon: size: 1
|
||||
hexagon: merge: as-tentative
|
||||
|
|
|
@ -10,7 +10,7 @@ OBJDUMP: 1 .text 0000000a 0000000000000074 TEXT DATA
|
|||
OBJDUMP: 2 .data 00000004 0000000000001000 DATA
|
||||
OBJDUMP: 3 .special 00000004 0000000000001004 DATA
|
||||
OBJDUMP: 4 .anotherspecial 00000004 0000000000001008 DATA
|
||||
OBJDUMP: 5 .bss 00000001 000000000000100c BSS
|
||||
OBJDUMP: 5 .bss 00000004 000000000000100c BSS
|
||||
OBJDUMP: 6 .shstrtab {{[0-9a-f]+}} 0000000000000000
|
||||
OBJDUMP: 7 .symtab {{[0-9a-f]+}} 0000000000000000
|
||||
OBJDUMP: 8 .strtab {{[0-9a-f]+}} 0000000000000000
|
||||
|
@ -90,7 +90,7 @@ READOBJ: SHF_ALLOC
|
|||
READOBJ: SHF_WRITE
|
||||
READOBJ: ]
|
||||
READOBJ: Address: 0x100C
|
||||
READOBJ: Size: 1
|
||||
READOBJ: Size: 4
|
||||
READOBJ: }
|
||||
READOBJ: Section {
|
||||
READOBJ: Index: 6
|
||||
|
|
Loading…
Reference in New Issue