llvm-project/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h

150 lines
4.6 KiB
C++

//===- lib/ReaderWriter/ELF/HexagonELFFile.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_HEXAGON_ELF_FILE_H
#define LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H
#include "ELFReader.h"
#include "HexagonLinkingContext.h"
namespace lld {
namespace elf {
class HexagonELFFile;
class HexagonELFDefinedAtom : public ELFDefinedAtom<ELF32LE> {
typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
public:
template <typename... T>
HexagonELFDefinedAtom(T &&... args)
: ELFDefinedAtom(std::forward<T>(args)...) {}
DefinedAtom::ContentType contentType() const override {
if (_contentType != DefinedAtom::typeUnknown)
return _contentType;
if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) {
if (_section->sh_type == llvm::ELF::SHT_NOBITS)
return (_contentType = DefinedAtom::typeZeroFillFast);
return (_contentType = DefinedAtom::typeDataFast);
}
return ELFDefinedAtom::contentType();
}
DefinedAtom::ContentPermissions permissions() const override {
if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL)
return DefinedAtom::permRW_;
return ELFDefinedAtom::permissions();
}
};
class HexagonELFCommonAtom : public ELFCommonAtom<ELF32LE> {
typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
public:
HexagonELFCommonAtom(const ELFFile<ELF32LE> &file, StringRef symbolName,
const Elf_Sym *symbol)
: ELFCommonAtom(file, symbolName, symbol) {}
virtual bool isSmallCommonSymbol() const {
switch (_symbol->st_shndx) {
// Common symbols
case llvm::ELF::SHN_HEXAGON_SCOMMON:
case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
return true;
default:
break;
}
return false;
}
uint64_t size() const override {
if (isSmallCommonSymbol())
return _symbol->st_size;
return ELFCommonAtom::size();
}
DefinedAtom::Merge merge() const override {
if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
return DefinedAtom::mergeAsWeak;
if (isSmallCommonSymbol())
return DefinedAtom::mergeAsTentative;
return ELFCommonAtom::merge();
}
DefinedAtom::ContentType contentType() const override {
if (isSmallCommonSymbol())
return DefinedAtom::typeZeroFillFast;
return ELFCommonAtom::contentType();
}
DefinedAtom::Alignment alignment() const override {
if (isSmallCommonSymbol())
return DefinedAtom::Alignment(_symbol->st_value);
return 1;
}
DefinedAtom::ContentPermissions permissions() const override {
if (isSmallCommonSymbol())
return DefinedAtom::permRW_;
return ELFCommonAtom::permissions();
}
};
class HexagonELFFile : public ELFFile<ELF32LE> {
typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
public:
HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
: ELFFile(std::move(mb), ctx) {}
bool isCommonSymbol(const Elf_Sym *symbol) const override {
switch (symbol->st_shndx) {
// Common symbols
case llvm::ELF::SHN_HEXAGON_SCOMMON:
case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
return true;
default:
break;
}
return ELFFile::isCommonSymbol(symbol);
}
/// Process the Defined symbol and create an atom for it.
ELFDefinedAtom<ELF32LE> *createDefinedAtom(
StringRef symName, StringRef sectionName, const Elf_Sym *sym,
const Elf_Shdr *sectionHdr, ArrayRef<uint8_t> contentData,
unsigned int referenceStart, unsigned int referenceEnd,
std::vector<ELFReference<ELF32LE> *> &referenceList) override {
return new (_readerStorage) HexagonELFDefinedAtom(
*this, symName, sectionName, sym, sectionHdr, contentData,
referenceStart, referenceEnd, referenceList);
}
/// Process the Common symbol and create an atom for it.
ELFCommonAtom<ELF32LE> *createCommonAtom(StringRef symName,
const Elf_Sym *sym) override {
return new (_readerStorage) HexagonELFCommonAtom(*this, symName, sym);
}
};
} // elf
} // lld
#endif // LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H