//===- HexagonLDBackend.cpp -----------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Hexagon.h"
#include "HexagonELFDynamic.h"
#include "HexagonLDBackend.h"
#include "HexagonRelocator.h"
#include "HexagonGNUInfo.h"
#include <llvm/ADT/Triple.h>
#include <llvm/Support/Casting.h>
#include <mcld/LinkerConfig.h>
#include <mcld/IRBuilder.h>
#include <mcld/Fragment/FillFragment.h>
#include <mcld/Fragment/RegionFragment.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/MsgHandling.h>
#include <mcld/Support/TargetRegistry.h>
#include <mcld/Object/ObjectBuilder.h>
#include <cstring>
using namespace mcld;
//===----------------------------------------------------------------------===//
// HexagonLDBackend
//===----------------------------------------------------------------------===//
HexagonLDBackend::HexagonLDBackend(const LinkerConfig& pConfig,
HexagonGNUInfo* pInfo)
: GNULDBackend(pConfig, pInfo),
m_pRelocator(NULL),
m_pGOT(NULL),
m_pPLT(NULL),
m_pRelDyn(NULL),
m_pRelPLT(NULL),
m_pDynamic(NULL),
m_pGOTSymbol(NULL) {
}
HexagonLDBackend::~HexagonLDBackend()
{
delete m_pRelocator;
delete m_pGOT;
delete m_pPLT;
delete m_pRelDyn;
delete m_pRelPLT;
delete m_pDynamic;
}
bool HexagonLDBackend::initRelocator()
{
if (NULL == m_pRelocator) {
m_pRelocator = new HexagonRelocator(*this);
}
return true;
}
Relocator* HexagonLDBackend::getRelocator()
{
assert(NULL != m_pRelocator);
return m_pRelocator;
}
void HexagonLDBackend::doPreLayout(IRBuilder& pBuilder)
{
// initialize .dynamic data
if (!config().isCodeStatic() && NULL == m_pDynamic)
m_pDynamic = new HexagonELFDynamic(*this, config());
}
void HexagonLDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
{
}
/// dynamic - the dynamic section of the target machine.
/// Use co-variant return type to return its own dynamic section.
HexagonELFDynamic& HexagonLDBackend::dynamic()
{
assert(NULL != m_pDynamic);
return *m_pDynamic;
}
/// dynamic - the dynamic section of the target machine.
/// Use co-variant return type to return its own dynamic section.
const HexagonELFDynamic& HexagonLDBackend::dynamic() const
{
assert(NULL != m_pDynamic);
return *m_pDynamic;
}
void HexagonLDBackend::scanRelocation(Relocation& pReloc,
IRBuilder& pBuilder,
Module& pModule,
LDSection& pSection)
{
pReloc.updateAddend();
}
uint64_t HexagonLDBackend::emitSectionData(const LDSection& pSection,
MemoryRegion& pRegion) const
{
return 0;
}
HexagonGOT& HexagonLDBackend::getGOT()
{
assert(NULL != m_pGOT);
return *m_pGOT;
}
const HexagonGOT& HexagonLDBackend::getGOT() const
{
assert(NULL != m_pGOT);
return *m_pGOT;
}
HexagonPLT& HexagonLDBackend::getPLT()
{
assert(NULL != m_pPLT && "PLT section not exist");
return *m_pPLT;
}
const HexagonPLT& HexagonLDBackend::getPLT() const
{
assert(NULL != m_pPLT && "PLT section not exist");
return *m_pPLT;
}
OutputRelocSection& HexagonLDBackend::getRelDyn()
{
assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
return *m_pRelDyn;
}
const OutputRelocSection& HexagonLDBackend::getRelDyn() const
{
assert(NULL != m_pRelDyn && ".rel.dyn section not exist");
return *m_pRelDyn;
}
OutputRelocSection& HexagonLDBackend::getRelPLT()
{
assert(NULL != m_pRelPLT && ".rel.plt section not exist");
return *m_pRelPLT;
}
const OutputRelocSection& HexagonLDBackend::getRelPLT() const
{
assert(NULL != m_pRelPLT && ".rel.plt section not exist");
return *m_pRelPLT;
}
unsigned int
HexagonLDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
{
const ELFFileFormat* file_format = getOutputFormat();
if (&pSectHdr == &file_format->getGOT()) {
if (config().options().hasNow())
return SHO_RELRO;
return SHO_RELRO_LAST;
}
if (&pSectHdr == &file_format->getPLT())
return SHO_PLT;
return SHO_UNDEFINED;
}
void HexagonLDBackend::initTargetSections(Module& pModule,
ObjectBuilder& pBuilder)
{
if (LinkerConfig::Object != config().codeGenType()) {
ELFFileFormat* file_format = getOutputFormat();
// initialize .got
LDSection& got = file_format->getGOT();
m_pGOT = new HexagonGOT(got);
// initialize .plt
LDSection& plt = file_format->getPLT();
m_pPLT = new HexagonPLT(plt,
*m_pGOT,
config());
// initialize .rel.plt
LDSection& relplt = file_format->getRelPlt();
relplt.setLink(&plt);
m_pRelPLT = new OutputRelocSection(pModule, relplt);
// initialize .rel.dyn
LDSection& reldyn = file_format->getRelDyn();
m_pRelDyn = new OutputRelocSection(pModule, reldyn);
}
}
void HexagonLDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule)
{
if (LinkerConfig::Object != config().codeGenType()) {
// Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
// same name in input
m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
"_GLOBAL_OFFSET_TABLE_",
ResolveInfo::Object,
ResolveInfo::Define,
ResolveInfo::Local,
0x0, // size
0x0, // value
FragmentRef::Null(),
ResolveInfo::Hidden);
}
}
/// finalizeSymbol - finalize the symbol value
bool HexagonLDBackend::finalizeTargetSymbols()
{
return true;
}
/// doCreateProgramHdrs - backend can implement this function to create the
/// target-dependent segments
void HexagonLDBackend::doCreateProgramHdrs(Module& pModule)
{
// TODO
}
namespace mcld {
//===----------------------------------------------------------------------===//
/// createHexagonLDBackend - the help funtion to create corresponding
/// HexagonLDBackend
TargetLDBackend* createHexagonLDBackend(const llvm::Target& pTarget,
const LinkerConfig& pConfig)
{
if (pConfig.targets().triple().isOSDarwin()) {
assert(0 && "MachO linker is not supported yet");
/**
return new HexagonMachOLDBackend(createHexagonMachOArchiveReader,
createHexagonMachOObjectReader,
createHexagonMachOObjectWriter);
**/
}
if (pConfig.targets().triple().isOSWindows()) {
assert(0 && "COFF linker is not supported yet");
/**
return new HexagonCOFFLDBackend(createHexagonCOFFArchiveReader,
createHexagonCOFFObjectReader,
createHexagonCOFFObjectWriter);
**/
}
return new HexagonLDBackend(pConfig,
new HexagonGNUInfo(pConfig.targets().triple()));
}
} // namespace of mcld
//===----------------------------------------------------------------------===//
// Force static initialization.
//===----------------------------------------------------------------------===//
extern "C" void MCLDInitializeHexagonLDBackend() {
// Register the linker backend
mcld::TargetRegistry::RegisterTargetLDBackend(TheHexagonTarget,
createHexagonLDBackend);
}