blob: b1366bed09eac2f7a688cf4867514e0000bae6a9 [file] [log] [blame]
//===- lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h ----------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef HEXAGON_TARGET_HANDLER_H
#define HEXAGON_TARGET_HANDLER_H
#include "ELFReader.h"
#include "HexagonELFFile.h"
#include "HexagonRelocationHandler.h"
#include "TargetLayout.h"
namespace lld {
namespace elf {
class HexagonLinkingContext;
/// \brief Handle Hexagon SData section
class SDataSection : public AtomSection<ELF32LE> {
public:
SDataSection(const HexagonLinkingContext &ctx);
/// \brief Finalize the section contents before writing
void doPreFlight() override;
/// \brief Does this section have an output segment.
bool hasOutputSegment() const override { return true; }
const AtomLayout *appendAtom(const Atom *atom) override;
};
/// \brief TargetLayout for Hexagon
class HexagonTargetLayout final : public TargetLayout<ELF32LE> {
public:
enum HexagonSectionOrder {
ORDER_SDATA = 205
};
HexagonTargetLayout(HexagonLinkingContext &ctx)
: TargetLayout(ctx), _sdataSection(ctx) {}
/// \brief Return the section order for a input section
TargetLayout::SectionOrder
getSectionOrder(StringRef name, int32_t contentType,
int32_t contentPermissions) override {
if (contentType == DefinedAtom::typeDataFast ||
contentType == DefinedAtom::typeZeroFillFast)
return ORDER_SDATA;
return TargetLayout::getSectionOrder(name, contentType, contentPermissions);
}
/// \brief Return the appropriate input section name.
StringRef getInputSectionName(const DefinedAtom *da) const override {
switch (da->contentType()) {
case DefinedAtom::typeDataFast:
case DefinedAtom::typeZeroFillFast:
return ".sdata";
default:
break;
}
return TargetLayout::getInputSectionName(da);
}
/// \brief Gets or creates a section.
AtomSection<ELF32LE> *
createSection(StringRef name, int32_t contentType,
DefinedAtom::ContentPermissions contentPermissions,
TargetLayout::SectionOrder sectionOrder) override {
if (contentType == DefinedAtom::typeDataFast ||
contentType == DefinedAtom::typeZeroFillFast)
return &_sdataSection;
return TargetLayout::createSection(name, contentType, contentPermissions,
sectionOrder);
}
/// \brief get the segment type for the section thats defined by the target
TargetLayout::SegmentType
getSegmentType(const Section<ELF32LE> *section) const override {
if (section->order() == ORDER_SDATA)
return PT_LOAD;
return TargetLayout::getSegmentType(section);
}
Section<ELF32LE> *getSDataSection() { return &_sdataSection; }
uint64_t getGOTSymAddr() {
std::call_once(_gotOnce, [this]() {
if (AtomLayout *got = findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"))
_gotAddr = got->_virtualAddr;
});
return _gotAddr;
}
private:
SDataSection _sdataSection;
uint64_t _gotAddr = 0;
std::once_flag _gotOnce;
};
/// \brief TargetHandler for Hexagon
class HexagonTargetHandler final : public TargetHandler {
public:
HexagonTargetHandler(HexagonLinkingContext &targetInfo);
const TargetRelocationHandler &getRelocationHandler() const override {
return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
return llvm::make_unique<ELFReader<HexagonELFFile>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
private:
HexagonLinkingContext &_ctx;
std::unique_ptr<HexagonTargetLayout> _targetLayout;
std::unique_ptr<HexagonTargetRelocationHandler> _relocationHandler;
};
void finalizeHexagonRuntimeAtomValues(HexagonTargetLayout &layout);
} // end namespace elf
} // end namespace lld
#endif