| //===- 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); |
| } |