Files
clang-p2996/lld/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
Shankar Easwaran 9e07346679 [ELF] Add section group/COMDAT support.
SHF_GROUP: Group Member Sections
----------------------------------
A section which is part of a group, and is to be retained or discarded with the
group as a whole, is identified by a new section header attribute: SHF_GROUP
This section is a member (perhaps the only one) of a group of sections, and the
linker should retain or discard all or none of the members. This section must be
referenced in a SHT_GROUP section. This attribute flag may be set in any section
header, and no other modification or indication is made in the grouped sections.
All additional information is contained in the associated SHT_GROUP section.

SHT_GROUP: Section Group Definition
-------------------------------------
Represents a group section.

The section group's sh_link field identifies a symbol table section, and its
sh_info field the index of a symbol in that section. The name of that symbol is
treated as the identifier of the section group.

More information: https://mentorembedded.github.io/cxx-abi/abi/prop-72-comdat.html

Added a lot of extensive tests, that tests functionality.

llvm-svn: 230195
2015-02-23 00:30:00 +00:00

135 lines
4.1 KiB
C++

//===- lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h ----------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_SECTION_CHUNKS_H
namespace lld {
namespace elf {
template <typename ELFT> class MipsTargetLayout;
class MipsLinkingContext;
/// \brief Handle Mips GOT section
template <class ELFType> class MipsGOTSection : public AtomSection<ELFType> {
public:
MipsGOTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFType>(ctx, ".got", DefinedAtom::typeGOT,
DefinedAtom::permRW_,
MipsTargetLayout<ELFType>::ORDER_GOT),
_hasNonLocal(false), _localCount(0) {
this->_flags |= SHF_MIPS_GPREL;
this->_alignment = 4;
}
/// \brief Number of local GOT entries.
std::size_t getLocalCount() const { return _localCount; }
/// \brief Number of global GOT entries.
std::size_t getGlobalCount() const { return _posMap.size(); }
/// \brief Does the atom have a global GOT entry?
bool hasGlobalGOTEntry(const Atom *a) const {
return _posMap.count(a) || _tlsMap.count(a);
}
/// \brief Compare two atoms accordingly theirs positions in the GOT.
bool compare(const Atom *a, const Atom *b) const {
auto ia = _posMap.find(a);
auto ib = _posMap.find(b);
if (ia != _posMap.end() && ib != _posMap.end())
return ia->second < ib->second;
return ia == _posMap.end() && ib != _posMap.end();
}
const lld::AtomLayout *appendAtom(const Atom *atom) override {
const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != lld::Reference::KindNamespace::ELF)
continue;
assert(r->kindArch() == Reference::KindArch::Mips);
switch (r->kindValue()) {
case LLD_R_MIPS_GLOBAL_GOT:
_hasNonLocal = true;
_posMap[r->target()] = _posMap.size();
return AtomSection<ELFType>::appendAtom(atom);
case R_MIPS_TLS_TPREL32:
case R_MIPS_TLS_DTPREL32:
_hasNonLocal = true;
_tlsMap[r->target()] = _tlsMap.size();
return AtomSection<ELFType>::appendAtom(atom);
case R_MIPS_TLS_DTPMOD32:
_hasNonLocal = true;
break;
}
}
if (!_hasNonLocal)
++_localCount;
return AtomSection<ELFType>::appendAtom(atom);
}
private:
/// \brief True if the GOT contains non-local entries.
bool _hasNonLocal;
/// \brief Number of local GOT entries.
std::size_t _localCount;
/// \brief Map TLS Atoms to their GOT entry index.
llvm::DenseMap<const Atom *, std::size_t> _tlsMap;
/// \brief Map Atoms to their GOT entry index.
llvm::DenseMap<const Atom *, std::size_t> _posMap;
};
/// \brief Handle Mips PLT section
template <class ELFType> class MipsPLTSection : public AtomSection<ELFType> {
public:
MipsPLTSection(const MipsLinkingContext &ctx)
: AtomSection<ELFType>(ctx, ".plt", DefinedAtom::typeGOT,
DefinedAtom::permR_X,
MipsTargetLayout<ELFType>::ORDER_PLT) {}
const AtomLayout *findPLTLayout(const Atom *plt) const {
auto it = _pltLayoutMap.find(plt);
return it != _pltLayoutMap.end() ? it->second : nullptr;
}
const lld::AtomLayout *appendAtom(const Atom *atom) override {
const auto *layout = AtomSection<ELFType>::appendAtom(atom);
const DefinedAtom *da = cast<DefinedAtom>(atom);
for (const auto &r : *da) {
if (r->kindNamespace() != lld::Reference::KindNamespace::ELF)
continue;
assert(r->kindArch() == Reference::KindArch::Mips);
if (r->kindValue() == LLD_R_MIPS_STO_PLT) {
_pltLayoutMap[r->target()] = layout;
break;
}
}
return layout;
}
private:
/// \brief Map PLT Atoms to their layouts.
std::unordered_map<const Atom *, const AtomLayout *> _pltLayoutMap;
};
} // elf
} // lld
#endif