15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- ARMLDBackend.cpp ---------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
9cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "ARM.h"
10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "ARMGNUInfo.h"
1187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "ARMELFAttributeData.h"
12cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "ARMELFDynamic.h"
13cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "ARMException.h"
14cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "ARMLDBackend.h"
15d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "ARMRelocator.h"
1622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARMToARMStub.h"
1722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "ARMToTHMStub.h"
1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "THMToTHMStub.h"
1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include "THMToARMStub.h"
20cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
23cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/ADT/ilist_sort.h"
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/AlignFragment.h"
2537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FillFragment.h"
2637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/NullFragment.h"
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/RegionFragment.h"
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Stub.h"
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h"
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFSegment.h"
32cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/ELFSegmentFactory.h"
33cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/LDContext.h"
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/StubFactory.h"
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryRegion.h"
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
3937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/TargetRegistry.h"
4037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/ELFAttribute.h"
4137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNUInfo.h"
425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
430dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <llvm/ADT/StringRef.h>
440dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <llvm/ADT/Triple.h>
450dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <llvm/ADT/Twine.h>
460dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <llvm/Support/Casting.h>
4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <llvm/Support/ELF.h>
480dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
490dea6bc96bb52346737966839ac68644f7939f58Stephen Hines#include <cstring>
50cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <vector>
510dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines/// Fragment data for EXIDX_CANTUNWIND.
55cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic const char g_CantUnwindEntry[8] = {
56cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Relocation to text section.
57cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  0, 0, 0, 0,
58cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // EXIDX_CANTUNWIND (little endian.)
59cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  1, 0, 0, 0,
60cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines};
61cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
62cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines/// Helper function to create a local symbol at the end of the fragment.
63cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic mcld::ResolveInfo*
64cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen HinesCreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) {
65cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Create and add symbol to the name pool.
66cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  mcld::ResolveInfo* resolveInfo =
67cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      pModule.getNamePool().createSymbol(/* pName */"",
68cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         /* pIsDyn */false,
69cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         mcld::ResolveInfo::Section,
70cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         mcld::ResolveInfo::Define,
71cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         mcld::ResolveInfo::Local,
72cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         /* pSize */0,
73cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                         mcld::ResolveInfo::Hidden);
74cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (resolveInfo == nullptr) {
75cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return nullptr;
76cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
77cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
78cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Create input symbol.
79cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo);
80cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (inputSym == nullptr) {
81cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return nullptr;
82cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
83cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
84cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size()));
85cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  inputSym->setValue(/* pValue */0);
86cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
87cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // The output symbol is simply an alias to the input symbol.
88cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  resolveInfo->setSymPtr(inputSym);
89cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
90cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return resolveInfo;
91cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
92cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
93cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines/// Comparator to sort .ARM.exidx fragments according to the address of the
94cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines/// corresponding .text fragment.
95cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesclass ExIdxFragmentComparator {
96cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines private:
97cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  const ARMExData& m_pExData;
98cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
99cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines public:
100cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  explicit ExIdxFragmentComparator(const ARMExData& pExData)
101cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      : m_pExData(pExData) {
102cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
103cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
104cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  bool operator()(const Fragment& a, const Fragment& b) {
105cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    ARMExSectionTuple* tupleA = m_pExData.getTupleByExIdx(&a);
106cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    ARMExSectionTuple* tupleB = m_pExData.getTupleByExIdx(&b);
107cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
108cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* textFragA = tupleA->getTextFragment();
109cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* textFragB = tupleB->getTextFragment();
110cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
111cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    uint64_t addrA = textFragA->getParent()->getSection().addr() +
112cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                     textFragA->getOffset();
113cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    uint64_t addrB = textFragB->getParent()->getSection().addr() +
114cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                     textFragB->getOffset();
115cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return (addrA < addrB);
116cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
117cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines};
118cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
119cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
120cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao// ARMGNULDBackend
121cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao//===----------------------------------------------------------------------===//
122d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoARMGNULDBackend::ARMGNULDBackend(const LinkerConfig& pConfig, GNUInfo* pInfo)
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : GNULDBackend(pConfig, pInfo),
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelocator(NULL),
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOT(NULL),
12637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pPLT(NULL),
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelDyn(NULL),
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelPLT(NULL),
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pAttrData(NULL),
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pDynamic(NULL),
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTSymbol(NULL),
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pEXIDXStart(NULL),
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pEXIDXEnd(NULL),
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pEXIDX(NULL),
13537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pEXTAB(NULL),
13637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pAttributes(NULL) {
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
13937b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMGNULDBackend::~ARMGNULDBackend() {
140d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  delete m_pRelocator;
14122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pGOT;
14222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pPLT;
14322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelDyn;
14422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelPLT;
14522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pDynamic;
14687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  delete m_pAttrData;
1475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::initTargetSections(Module& pModule,
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         ObjectBuilder& pBuilder) {
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // FIXME: Currently we set exidx and extab to "Exception" and directly emit
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  // them from input
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_pEXIDX =
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pBuilder.CreateSection(".ARM.exidx",
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             LDFileFormat::Target,
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             llvm::ELF::SHT_ARM_EXIDX,
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_LINK_ORDER,
15837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             config().targets().bitclass() / 8);
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_pEXTAB = pBuilder.CreateSection(".ARM.extab",
16037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    LDFileFormat::Target,
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    llvm::ELF::SHT_PROGBITS,
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    llvm::ELF::SHF_ALLOC,
16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                    0x1);
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_pAttributes = pBuilder.CreateSection(".ARM.attributes",
16537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         LDFileFormat::Target,
16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         llvm::ELF::SHT_ARM_ATTRIBUTES,
16737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         0x0,
16837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                         0x1);
16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
17087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize "aeabi" attributes subsection
17187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pAttrData = new ARMELFAttributeData();
17287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  attribute().registerAttributeData(*m_pAttrData);
17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
17422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
17522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    ELFFileFormat* file_format = getOutputFormat();
17622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
17722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .got
17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& got = file_format->getGOT();
17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pGOT = new ARMGOT(got);
18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .plt
18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& plt = file_format->getPLT();
18322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    m_pPLT = new ARMPLT(plt, *m_pGOT);
18422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
18522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .rel.plt
18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& relplt = file_format->getRelPlt();
18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    relplt.setLink(&plt);
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // create SectionData and ARMRelDynSection
189d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pRelPLT = new OutputRelocSection(pModule, relplt);
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
19122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // initialize .rel.dyn
19222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDSection& reldyn = file_format->getRelDyn();
193d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    m_pRelDyn = new OutputRelocSection(pModule, reldyn);
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
19522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
19622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
19737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
1985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
1995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // same name in input
200f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (LinkerConfig::Object != config().codeGenType()) {
20137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_pGOTSymbol =
20237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
20337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "_GLOBAL_OFFSET_TABLE_",
20437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Object,
20537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Define,
20637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Local,
20737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,  // size
20837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,  // value
20937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            FragmentRef::Null(),
21037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Hidden);
211f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  }
21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) {
2136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    FragmentRef* exidx_start =
21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(m_pEXIDX->getSectionData()->front(), 0x0);
21537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    FragmentRef* exidx_end = FragmentRef::Create(
21637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_pEXIDX->getSectionData()->front(), m_pEXIDX->size());
2176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pEXIDXStart =
21837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
21937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "__exidx_start",
22037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Object,
22137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Define,
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Local,
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,          // size
22437b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,          // value
22537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            exidx_start,  // FragRef
22637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Default);
22737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_pEXIDXEnd = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
22937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "__exidx_end",
23037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
23237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
23337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,        // size
23437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,        // value
23537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        exidx_end,  // FragRef
23637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Default);
2376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    // change __exidx_start/_end to local dynamic category
23837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (m_pEXIDXStart != NULL)
239f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pModule.getSymbolTable().changeToDynamic(*m_pEXIDXStart);
24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (m_pEXIDXEnd != NULL)
241f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      pModule.getSymbolTable().changeToDynamic(*m_pEXIDXEnd);
2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  } else {
2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pEXIDXStart =
24437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
24537b74a387bb3993387029859c2d9d051c41c724eStephen Hines            "__exidx_start",
24637b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::NoType,
24737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Define,
24837b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Absolute,
24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,  // size
25037b74a387bb3993387029859c2d9d051c41c724eStephen Hines            0x0,  // value
25137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            FragmentRef::Null(),
25237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            ResolveInfo::Default);
25337b74a387bb3993387029859c2d9d051c41c724eStephen Hines
25437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    m_pEXIDXEnd = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
25537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "__exidx_end",
25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::NoType,
25737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Absolute,
25937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Null(),
26237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Default);
2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  }
2645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::initRelocator() {
26737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pRelocator == NULL) {
268f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pRelocator = new ARMRelocator(*this, config());
269d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  }
270d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return true;
271d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
272d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
27337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst Relocator* ARMGNULDBackend::getRelocator() const {
27437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
2750dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return m_pRelocator;
2760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
2770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
27837b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator* ARMGNULDBackend::getRelocator() {
27937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
280d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return m_pRelocator;
281d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao}
282d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao
28337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // initialize .dynamic data
28537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (!config().isCodeStatic() && m_pDynamic == NULL)
2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pDynamic = new ARMELFDynamic(*this, config());
2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // set attribute section size
28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pAttributes->setSize(attribute().sizeOutput());
29087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
29122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set .got size
29222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // when building shared object, the .got section is must
29322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
29537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_pGOTSymbol != NULL) {
29622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_pGOT->finalizeSectionSize();
2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      defineGOTSymbol(pBuilder);
29822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
29922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
30022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .plt size
30122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (m_pPLT->hasPLT1())
30222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_pPLT->finalizeSectionSize();
30322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
304d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    ELFFileFormat* file_format = getOutputFormat();
30522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .rel.dyn size
3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelDyn->empty()) {
30737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
30837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
30937b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
31037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
31137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       getRelEntrySize());
3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
31322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
31422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .rel.plt size
3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelPLT->empty()) {
31637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
31737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
31837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
31937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      file_format->getRelPlt().setSize(m_pRelPLT->numOfRelocs() *
32037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       getRelEntrySize());
3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
3225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
32537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
32637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const ELFFileFormat* file_format = getOutputFormat();
3275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply PLT
3295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (file_format->hasPLT()) {
3305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // Since we already have the size of LDSection PLT, m_pPLT should not be
3315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // NULL.
33237b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(m_pPLT != NULL);
3335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pPLT->applyPLT0();
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    m_pPLT->applyPLT1();
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // apply GOT
3385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  if (file_format->hasGOT()) {
3395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // Since we already have the size of GOT, m_pGOT should not be NULL.
34037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(m_pGOT != NULL);
34122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (LinkerConfig::DynObj == config().codeGenType())
3425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_pGOT->applyGOT0(file_format->getDynamic().addr());
3435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    else {
3445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // executable file and object file? should fill with zero.
3455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      m_pGOT->applyGOT0(0);
3465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
3475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
3515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
35237b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMELFDynamic& ARMGNULDBackend::dynamic() {
35337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
3545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
3555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
3575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
3585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
35937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst ARMELFDynamic& ARMGNULDBackend::dynamic() const {
36037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
3625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
36437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
3655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
366affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (m_pGOTSymbol != NULL) {
3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
36837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
36937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
37037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
37137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
37337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
37537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
37637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
3776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
37837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
37937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
38037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
38137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
38237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
38337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
38437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
38537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
3865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
38922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaouint64_t ARMGNULDBackend::emitSectionData(const LDSection& pSection,
39037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                          MemoryRegion& pRegion) const {
3915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pRegion.size() && "Size of MemoryRegion is zero!");
3925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
39322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
3945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
39587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
3965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint64_t result = m_pPLT->emit(pRegion);
3975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return result;
3985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
40087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
4015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    uint64_t result = m_pGOT->emit(pRegion);
4025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return result;
4035460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
40487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
40587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (&pSection == m_pAttributes) {
40687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return attribute().emit(pRegion);
40787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
40887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
40987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: Currently Emitting .ARM.attributes, .ARM.exidx, and .ARM.extab
41087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // directly from the input file.
41187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const SectionData* sect_data = pSection.getSectionData();
41287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  SectionData::const_iterator frag_iter, frag_end = sect_data->end();
41387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint8_t* out_offset = pRegion.begin();
41487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
41587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    size_t size = frag_iter->size();
41637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    switch (frag_iter->getKind()) {
41787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case Fragment::Fillment: {
41837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        const FillFragment& fill_frag = llvm::cast<FillFragment>(*frag_iter);
41937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (fill_frag.getValueSize() == 0) {
42087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // virtual fillment, ignore it.
42187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          break;
42287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
42387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
42487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memset(out_offset, fill_frag.getValue(), fill_frag.size());
42587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
42687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
42787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case Fragment::Region: {
42887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        const RegionFragment& region_frag =
42937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            llvm::cast<RegionFragment>(*frag_iter);
43087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        const char* start = region_frag.getRegion().begin();
43187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        memcpy(out_offset, start, size);
43287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
43387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case Fragment::Alignment: {
43587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        const AlignFragment& align_frag = llvm::cast<AlignFragment>(*frag_iter);
43687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        uint64_t count = size / align_frag.getValueSize();
43787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        switch (align_frag.getValueSize()) {
43887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          case 1u:
43987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            std::memset(out_offset, align_frag.getValue(), count);
44087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
44187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          default:
44287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            llvm::report_fatal_error(
44337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                "unsupported value size for align fragment emission yet.\n");
44487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
44537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        }  // end switch
44687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
44787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
44887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case Fragment::Null: {
44987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        assert(0x0 == size);
45087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
45187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
45287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      default:
45387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        llvm::report_fatal_error("unsupported fragment type.\n");
45487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
45537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // end switch
45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    out_offset += size;
45737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end for
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return pRegion.size();
4595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// finalizeSymbol - finalize the symbol value
46237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::finalizeTargetSymbols() {
4635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
4645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
4655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
466a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
467a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines/// preMergeSections - hooks to be executed before merging sections
468a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::preMergeSections(Module& pModule) {
469cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Since the link relationship between .text and .ARM.exidx will be discarded
470cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // after merging sections, we have to build the exception handling section
471cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // mapping before section merge.
472cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_pExData = ARMExData::create(pModule);
473a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
474a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
475a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines/// postMergeSections - hooks to be executed after merging sections
476a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::postMergeSections(Module& pModule) {
477a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  if (m_pEXIDX->hasSectionData()) {
478a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Append the NullFragment so that __exidx_end can be correctly inserted.
479a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    NullFragment* null = new NullFragment(m_pEXIDX->getSectionData());
480a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    null->setOffset(m_pEXIDX->size());
481a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
482a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
483a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
48487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool ARMGNULDBackend::mergeSection(Module& pModule,
48587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                   const Input& pInput,
48637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   LDSection& pSection) {
48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  switch (pSection.type()) {
48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    case llvm::ELF::SHT_ARM_ATTRIBUTES: {
48987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return attribute().merge(pInput, pSection);
49087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
491a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    case llvm::ELF::SHT_ARM_EXIDX: {
49337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(pSection.getLink() != NULL);
49437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if ((pSection.getLink()->kind() == LDFileFormat::Ignore) ||
49537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          (pSection.getLink()->kind() == LDFileFormat::Folded)) {
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // if the target section of the .ARM.exidx is Ignore, then it should be
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // ignored as well
49887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pSection.setKind(LDFileFormat::Ignore);
49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        return true;
50087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
501a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
502a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      if (!m_pEXIDX->hasSectionData()) {
503a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        // Create SectionData for m_pEXIDX.
504a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        SectionData* sectData = IRBuilder::CreateSectionData(*m_pEXIDX);
505a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
506a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        // Initialize the alignment of m_pEXIDX.
507a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        const size_t alignExIdx = 4;
508a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        m_pEXIDX->setAlign(alignExIdx);
509a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
510a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        // Insert an AlignFragment to the beginning of m_pEXIDX.
511a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        AlignFragment* frag =
512a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines            new AlignFragment(/*alignment*/alignExIdx,
513a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                              /*the filled value*/0x0,
514a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                              /*the size of filled value*/1u,
515a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                              /*max bytes to emit*/alignExIdx - 1);
516a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        frag->setOffset(0);
517a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        frag->setParent(sectData);
518a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        sectData->getFragmentList().push_back(frag);
519a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        m_pEXIDX->setSize(frag->size());
520a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
521a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
522a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Move RegionFragment from pSection to m_pEXIDX.
523a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      uint64_t offset = m_pEXIDX->size();
524a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      SectionData::FragmentListType& src =
525a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          pSection.getSectionData()->getFragmentList();
526a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      SectionData::FragmentListType& dst =
527a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          m_pEXIDX->getSectionData()->getFragmentList();
528a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      SectionData::FragmentListType::iterator frag = src.begin();
529a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      SectionData::FragmentListType::iterator fragEnd = src.end();
530a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      while (frag != fragEnd) {
531a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        if (frag->getKind() != Fragment::Region) {
532a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          ++frag;
533a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        } else {
534a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          frag->setParent(m_pEXIDX->getSectionData());
535a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          frag->setOffset(offset);
536a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          offset += frag->size();
537a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines          dst.splice(dst.end(), src, frag++);
538a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        }
539a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
540a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
541a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Update the size of m_pEXIDX.
542a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      m_pEXIDX->setSize(offset);
543a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      return true;
54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
545a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    default: {
547533eae20118036f425f27bf0536ef0ccbb090b65Stephen Hines      ObjectBuilder builder(pModule);
54887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      builder.MergeSection(pInput, pSection);
54987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return true;
55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
55137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // end of switch
55222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return true;
55322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
5545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
55537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::setUpReachedSectionsForGC(
55637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const Module& pModule,
55737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    GarbageCollection::SectionReachedListMap& pSectReachedListMap) const {
55887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // traverse all the input relocations to find the relocation sections applying
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // .ARM.exidx sections
56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  Module::const_obj_iterator input, inEnd = pModule.obj_end();
56187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (input = pModule.obj_begin(); input != inEnd; ++input) {
56287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    LDContext::const_sect_iterator rs,
56337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        rsEnd = (*input)->context()->relocSectEnd();
56487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
56587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // bypass the discarded relocation section
56687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 1. its section kind is changed to Ignore. (The target section is a
56787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // discarded group section.)
56887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // 2. it has no reloc data. (All symbols in the input relocs are in the
56987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // discarded group sections)
57087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      LDSection* reloc_sect = *rs;
57187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      LDSection* apply_sect = reloc_sect->getLink();
57287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
57387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          (!reloc_sect->hasRelocData()))
57487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        continue;
57587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
57687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (llvm::ELF::SHT_ARM_EXIDX == apply_sect->type()) {
57787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // 1. set up the reference according to relocations
57887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        bool add_first = false;
57987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        GarbageCollection::SectionListTy* reached_sects = NULL;
58087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
58187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
58237b74a387bb3993387029859c2d9d051c41c724eStephen Hines             ++reloc_it) {
58387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          Relocation* reloc = llvm::cast<Relocation>(reloc_it);
58487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          ResolveInfo* sym = reloc->symInfo();
58587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // only the target symbols defined in the input fragments can make the
58687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // reference
58737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          if (sym == NULL)
58887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            continue;
58987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
59087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            continue;
59187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
59287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // only the target symbols defined in the concerned sections can make
59387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // the reference
59487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          const LDSection* target_sect =
59537b74a387bb3993387029859c2d9d051c41c724eStephen Hines              &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
5960dea6bc96bb52346737966839ac68644f7939f58Stephen Hines          if (target_sect->kind() != LDFileFormat::TEXT &&
5970dea6bc96bb52346737966839ac68644f7939f58Stephen Hines              target_sect->kind() != LDFileFormat::DATA &&
59887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              target_sect->kind() != LDFileFormat::BSS)
59987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            continue;
60087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
60187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // setup the reached list, if we first add the element to reached list
60287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          // of this section, create an entry in ReachedSections map
60387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (!add_first) {
60487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            reached_sects = &pSectReachedListMap.getReachedList(*apply_sect);
60587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            add_first = true;
60687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
60787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          reached_sects->insert(target_sect);
60887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
60987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        reached_sects = NULL;
61087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        add_first = false;
61187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // 2. set up the reference from XXX to .ARM.exidx.XXX
61287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        assert(apply_sect->getLink() != NULL);
61387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        pSectReachedListMap.addReference(*apply_sect->getLink(), *apply_sect);
61487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
61587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
61687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
61787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
61887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
61937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
620cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  Fragment* frag = NULL;
62122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
62222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t size = pSD.getSection().size();
62322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
62487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef region = pInput.memArea()->request(offset, size);
62587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (region.size() == 0) {
626affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // If the input section's size is zero, we got a NULL region.
627affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // use a virtual fill fragment
628cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    frag = new FillFragment(0x0, 0, 0);
62937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
63087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    frag = new RegionFragment(region);
63122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
632affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
63322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ObjectBuilder::AppendFragment(*frag, pSD);
6345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
63737b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMGOT& ARMGNULDBackend::getGOT() {
63837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL && "GOT section not exist");
6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
6405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
64237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst ARMGOT& ARMGNULDBackend::getGOT() const {
64337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL && "GOT section not exist");
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
64737b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMPLT& ARMGNULDBackend::getPLT() {
64837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL && "PLT section not exist");
6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pPLT;
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst ARMPLT& ARMGNULDBackend::getPLT() const {
65337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL && "PLT section not exist");
6545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pPLT;
6555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
65737b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& ARMGNULDBackend::getRelDyn() {
65837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
6595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
6605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
66237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& ARMGNULDBackend::getRelDyn() const {
66337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL && ".rel.dyn section not exist");
6645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
6655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
66737b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& ARMGNULDBackend::getRelPLT() {
66837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPLT != NULL && ".rel.plt section not exist");
6695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelPLT;
6705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
67237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& ARMGNULDBackend::getRelPLT() const {
67337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPLT != NULL && ".rel.plt section not exist");
6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelPLT;
6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
67737b74a387bb3993387029859c2d9d051c41c724eStephen HinesARMELFAttributeData& ARMGNULDBackend::getAttributeData() {
67837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
67987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pAttrData;
68087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
68187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst ARMELFAttributeData& ARMGNULDBackend::getAttributeData() const {
68337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pAttrData != NULL && ".ARM.attributes section not exist");
68487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pAttrData;
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesunsigned int ARMGNULDBackend::getTargetSectionOrder(
68837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const LDSection& pSectHdr) const {
68922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
6905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
69187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
69222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (config().options().hasNow())
693affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      return SHO_RELRO_LAST;
6945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return SHO_DATA;
695affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
6965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
69787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
6985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return SHO_PLT;
6995460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
700affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  if (&pSectHdr == m_pEXIDX || &pSectHdr == m_pEXTAB) {
701affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    // put ARM.exidx and ARM.extab in the same order of .eh_frame
702affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    return SHO_EXCEPTION;
703affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  }
704affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
7055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return SHO_UNDEFINED;
7065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
708cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesvoid ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
709cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!m_pEXIDX->hasSectionData()) {
710cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Return if this is empty section.
711cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return;
712cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
713cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
714cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData* sectData = m_pEXIDX->getSectionData();
715cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType& list = sectData->getFragmentList();
716cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
717cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Move the first fragment (align fragment) and last fragment (null fragment)
718cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // to temporary list because we would only like to sort the region fragment.
719cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType tmp;
720cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  {
721cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData::iterator first = sectData->begin();
722cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData::iterator last = sectData->end();
723cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    --last;
724cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
725cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    assert(first->getKind() == Fragment::Alignment);
726cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    assert(last->getKind() == Fragment::Null);
727cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
728cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    tmp.splice(tmp.end(), list, first);
729cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    tmp.splice(tmp.end(), list, last);
730cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
731cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
732cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Sort the region fragments in the .ARM.exidx output section.
733cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  sort(list, ExIdxFragmentComparator(*m_pExData));
734cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
735cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Fix the coverage of the .ARM.exidx table.
736cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  llvm::StringRef cantUnwindRegion(g_CantUnwindEntry,
737cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                   sizeof(g_CantUnwindEntry));
738cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
739cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType::iterator it = list.begin();
740cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (it != list.end()) {
741cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* prevTextFrag = m_pExData->getTupleByExIdx(&*it)->getTextFragment();
742cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() +
743cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                           prevTextFrag->getOffset() +
744cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                           prevTextFrag->size();
745cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    ++it;
746cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    while (it != list.end()) {
747cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      Fragment* currTextFrag =
748cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          m_pExData->getTupleByExIdx(&*it)->getTextFragment();
749cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() +
750cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                               currTextFrag->getOffset();
751cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
752cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (currTextBegin > prevTextEnd) {
753cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        // Found a gap. Insert a can't unwind entry.
754cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
755cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        frag->setParent(sectData);
756cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        list.insert(it, frag);
757cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
758cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        // Add PREL31 reference to the beginning of the uncovered region.
759cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        Relocation* reloc =
760cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
761cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                               *FragmentRef::Create(*frag, /* pOffset */0),
762cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                               /* pAddend */0);
763cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        reloc->setSymInfo(
764cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
765cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        addExtraRelocation(reloc);
766cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }
767cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
768cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      prevTextEnd = currTextBegin + currTextFrag->size();
769cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      prevTextFrag = currTextFrag;
770cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      ++it;
771cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
772cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
773cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Add a can't unwind entry to terminate .ARM.exidx section.
774cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
775cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    frag->setParent(sectData);
776cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    list.push_back(frag);
777cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
778cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Add PREL31 reference to the end of the .text section.
779cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Relocation* reloc =
780cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
781cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                           *FragmentRef::Create(*frag, /* pOffset */0),
782cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                           /* pAddend */0);
783cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
784cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    addExtraRelocation(reloc);
785cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
786cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
787cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Add the first and the last fragment back.
788cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  list.splice(list.begin(), tmp, tmp.begin());
789cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  list.splice(list.end(), tmp, tmp.begin());
790cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
791cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Update the fragment offsets.
792cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t offset = 0;
793cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (SectionData::iterator it = sectData->begin(), end = sectData->end();
794cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines       it != end; ++it) {
795cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    it->setOffset(offset);
796cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    offset += it->size();
797cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
798cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
799cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Update the section size.
800cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_pEXIDX->setSize(offset);
801cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
802cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Rebuild the section header.
803cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  setOutputSectionAddress(pModule);
804cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
805cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
806a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines/// relax - the relaxation pass
807a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesbool ARMGNULDBackend::relax(Module& pModule, IRBuilder& pBuilder) {
80804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  if (!GNULDBackend::relax(pModule, pBuilder)) {
80904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    return false;
81004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  }
811a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  rewriteARMExIdxSection(pModule);
81204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  return true;
813a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
814a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
81522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// doRelax
81637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::doRelax(Module& pModule,
81737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              IRBuilder& pBuilder,
81837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                              bool& pFinished) {
81937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
82022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
82122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bool isRelaxed = false;
82222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat();
82322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // check branch relocs and create the related stubs if needed
82422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  Module::obj_iterator input, inEnd = pModule.obj_end();
82522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (input = pModule.obj_begin(); input != inEnd; ++input) {
82622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
82722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
82822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData())
82922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        continue;
83022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      RelocData::iterator reloc, rEnd = (*rs)->getRelocData()->end();
83122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      for (reloc = (*rs)->getRelocData()->begin(); reloc != rEnd; ++reloc) {
83222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        Relocation* relocation = llvm::cast<Relocation>(reloc);
83322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
83422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao        switch (relocation->type()) {
835f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines          case llvm::ELF::R_ARM_PC24:
83622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_CALL:
83722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_JUMP24:
83822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_PLT32:
83922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_THM_CALL:
84022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_THM_XPC22:
84122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          case llvm::ELF::R_ARM_THM_JUMP24:
84287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          case llvm::ELF::R_ARM_THM_JUMP19: {
84322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            // calculate the possible symbol value
84422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            uint64_t sym_value = 0x0;
84522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            LDSymbol* symbol = relocation->symInfo()->outSymbol();
84622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            if (symbol->hasFragRef()) {
84722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              uint64_t value = symbol->fragRef()->getOutputOffset();
84822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              uint64_t addr =
84937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  symbol->fragRef()->frag()->getParent()->getSection().addr();
85022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              sym_value = addr + value;
85122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            }
85237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            if ((relocation->symInfo()->reserved() &
85337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                 ARMRelocator::ReservePLT) != 0x0) {
85437b74a387bb3993387029859c2d9d051c41c724eStephen Hines              // FIXME: we need to find out the address of the specific plt
85537b74a387bb3993387029859c2d9d051c41c724eStephen Hines              // entry
85622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              assert(file_format->hasPLT());
85722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              sym_value = file_format->getPLT().addr();
85822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            }
85937b74a387bb3993387029859c2d9d051c41c724eStephen Hines            Stub* stub = getStubFactory()->create(*relocation,  // relocation
86037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                  sym_value,    // symbol value
8616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines                                                  pBuilder,
86222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao                                                  *getBRIslandFactory());
86337b74a387bb3993387029859c2d9d051c41c724eStephen Hines            if (stub != NULL) {
864cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              assert(stub->symInfo() != NULL);
865cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              // reset the branch target of the reloc to this stub instead
866cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              relocation->setSymInfo(stub->symInfo());
867cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              switch (config().options().getStripSymbolMode()) {
8692bf3f881f79c4d883f379e63725e788c310739a3Pirama Arumuga Nainar                case GeneralOptions::StripSymbolMode::StripAllSymbols:
8702bf3f881f79c4d883f379e63725e788c310739a3Pirama Arumuga Nainar                case GeneralOptions::StripSymbolMode::StripLocals:
87187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  break;
87287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                default: {
87387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  // a stub symbol should be local
87437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  assert(stub->symInfo() != NULL && stub->symInfo()->isLocal());
87587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  LDSection& symtab = file_format->getSymTab();
87687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  LDSection& strtab = file_format->getStrTab();
87787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
87887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  // increase the size of .symtab and .strtab if needed
879cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                  symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
88087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                  symtab.setInfo(symtab.getInfo() + 1);
88137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() +
88237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 1);
88387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                }
88437b74a387bb3993387029859c2d9d051c41c724eStephen Hines              }  // end of switch
88522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao              isRelaxed = true;
88622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            }
88722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            break;
88822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          }
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          case llvm::ELF::R_ARM_V4BX:
89087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            /* FIXME: bypass R_ARM_V4BX relocation now */
89187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
89222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao          default:
89322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao            break;
89437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        }  // end of switch
89537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      }  // for all relocations
89637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    }  // for all relocation section
89737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // for all inputs
89822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
89922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // find the first fragment w/ invalid offset due to stub insertion
900cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  std::vector<Fragment*> invalid_frags;
90122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pFinished = true;
90222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
90337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     island_end = getBRIslandFactory()->end();
90437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       island != island_end;
90537b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++island) {
906cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if ((*island).size() > stubGroupSize()) {
907cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      error(diag::err_no_space_to_place_stubs) << stubGroupSize();
908cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return false;
909cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
910cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
911cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if ((*island).numOfStubs() == 0) {
912cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
913cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
914cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
915cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* exit = &*(*island).end();
916cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (exit == (*island).begin()->getParent()->end()) {
917cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
918cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
91922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
92022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    if (((*island).offset() + (*island).size()) > exit->getOffset()) {
921cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (invalid_frags.empty() ||
922cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          (invalid_frags.back()->getParent() != (*island).getParent())) {
923cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        invalid_frags.push_back(exit);
924cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        pFinished = false;
925cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }
926cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
92722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
92822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
92922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
93022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // reset the offset of invalid fragments
931cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie;
932cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines       ++it) {
933cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* invalid = *it;
934cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    while (invalid != NULL) {
935cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      invalid->setOffset(invalid->getPrevNode()->getOffset() +
936cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                         invalid->getPrevNode()->size());
937cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      invalid = invalid->getNextNode();
938cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
93922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
94022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
941cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // reset the size of section that has stubs inserted.
94222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (isRelaxed) {
943cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData* prev = NULL;
944cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
945cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                       island_end = getBRIslandFactory()->end();
946cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines         island != island_end;
947cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines         ++island) {
948cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      SectionData* sd = (*island).begin()->getParent();
949cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if ((*island).numOfStubs() != 0) {
950cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        if (sd != prev) {
951cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          sd->getSection().setSize(sd->back().getOffset() + sd->back().size());
952cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
953cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }
954cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      prev = sd;
955cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
95622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
95722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return isRelaxed;
95822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
95922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
96022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// initTargetStubs
96137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::initTargetStubs() {
96237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (getStubFactory() != NULL) {
9636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    getStubFactory()->addPrototype(new ARMToARMStub(config().isCodeIndep()));
9646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    getStubFactory()->addPrototype(new ARMToTHMStub(config().isCodeIndep()));
9650dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    getStubFactory()->addPrototype(
9660dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        new THMToTHMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
9670dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    getStubFactory()->addPrototype(
9680dea6bc96bb52346737966839ac68644f7939f58Stephen Hines        new THMToARMStub(config().isCodeIndep(), m_pAttrData->usingThumb2()));
96922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    return true;
97022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  }
97122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return false;
97222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
97322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
9740dea6bc96bb52346737966839ac68644f7939f58Stephen Hines/// maxFwdBranchOffset
975cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesint64_t ARMGNULDBackend::maxFwdBranchOffset() const {
9760dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if (m_pAttrData->usingThumb2()) {
9770dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return THM2_MAX_FWD_BRANCH_OFFSET;
9780dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  } else {
9790dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return THM_MAX_FWD_BRANCH_OFFSET;
9800dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  }
9810dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
9820dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
9830dea6bc96bb52346737966839ac68644f7939f58Stephen Hines/// maxBwdBranchOffset
984cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesint64_t ARMGNULDBackend::maxBwdBranchOffset() const {
9850dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  if (m_pAttrData->usingThumb2()) {
9860dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return THM2_MAX_BWD_BRANCH_OFFSET;
9870dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  } else {
9880dea6bc96bb52346737966839ac68644f7939f58Stephen Hines    return THM_MAX_BWD_BRANCH_OFFSET;
9890dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  }
9900dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
9910dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
99222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// doCreateProgramHdrs - backend can implement this function to create the
99322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// target-dependent segments
99437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ARMGNULDBackend::doCreateProgramHdrs(Module& pModule) {
99537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pEXIDX != NULL && m_pEXIDX->size() != 0x0) {
99637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // make PT_ARM_EXIDX
99737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    ELFSegment* exidx_seg =
99837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        elfSegmentTable().produce(llvm::ELF::PT_ARM_EXIDX, llvm::ELF::PF_R);
99937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    exidx_seg->append(m_pEXIDX);
100037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
100122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
100222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
10030dea6bc96bb52346737966839ac68644f7939f58Stephen Hines/// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe
10040dea6bc96bb52346737966839ac68644f7939f58Stephen Hines/// function pointer access
100537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(
100637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const LDSection& pSection) const {
10070dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  llvm::StringRef name(pSection.name());
100837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return !name.startswith(".ARM.exidx") && !name.startswith(".ARM.extab") &&
10090dea6bc96bb52346737966839ac68644f7939f58Stephen Hines         GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection);
10100dea6bc96bb52346737966839ac68644f7939f58Stephen Hines}
10110dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
10125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
10135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createARMLDBackend - the help funtion to create corresponding ARMLDBackend
10145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
101537b74a387bb3993387029859c2d9d051c41c724eStephen HinesTargetLDBackend* createARMLDBackend(const LinkerConfig& pConfig) {
1016d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().triple().isOSDarwin()) {
10175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "MachO linker is not supported yet");
10185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /**
10195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return new ARMMachOLDBackend(createARMMachOArchiveReader,
10205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createARMMachOObjectReader,
10215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createARMMachOObjectWriter);
10225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    **/
10235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
1024d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  if (pConfig.targets().triple().isOSWindows()) {
10255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "COFF linker is not supported yet");
10265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    /**
10275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return new ARMCOFFLDBackend(createARMCOFFArchiveReader,
10285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createARMCOFFObjectReader,
10295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao                               createARMCOFFObjectWriter);
10305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    **/
10315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
103237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return new ARMGNULDBackend(pConfig,
103337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                             new ARMGNUInfo(pConfig.targets().triple()));
10345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
10355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
103637b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
10375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
103822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
10395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization.
104022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
104122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoextern "C" void MCLDInitializeARMLDBackend() {
10425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Register the linker backend
104337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheARMTarget,
104437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createARMLDBackend);
104537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheThumbTarget,
104637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createARMLDBackend);
10475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1048