Home | History | Annotate | Download | only in AArch64
      1 //===- AArch64LDBackend.cpp -----------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include "AArch64.h"
     10 #include "AArch64ELFDynamic.h"
     11 #include "AArch64GNUInfo.h"
     12 #include "AArch64LDBackend.h"
     13 #include "AArch64Relocator.h"
     14 
     15 #include <cstring>
     16 
     17 #include <llvm/ADT/Triple.h>
     18 #include <llvm/ADT/Twine.h>
     19 #include <llvm/Support/ELF.h>
     20 #include <llvm/Support/Casting.h>
     21 
     22 #include <mcld/IRBuilder.h>
     23 #include <mcld/LinkerConfig.h>
     24 #include <mcld/Fragment/FillFragment.h>
     25 #include <mcld/Fragment/AlignFragment.h>
     26 #include <mcld/Fragment/RegionFragment.h>
     27 #include <mcld/Fragment/Stub.h>
     28 #include <mcld/Fragment/NullFragment.h>
     29 #include <mcld/Support/MemoryRegion.h>
     30 #include <mcld/Support/MemoryArea.h>
     31 #include <mcld/Support/MsgHandling.h>
     32 #include <mcld/Support/TargetRegistry.h>
     33 #include <mcld/LD/BranchIslandFactory.h>
     34 #include <mcld/LD/StubFactory.h>
     35 #include <mcld/LD/LDContext.h>
     36 #include <mcld/LD/ELFFileFormat.h>
     37 #include <mcld/LD/ELFSegmentFactory.h>
     38 #include <mcld/LD/ELFSegment.h>
     39 #include <mcld/Target/ELFAttribute.h>
     40 #include <mcld/Target/GNUInfo.h>
     41 #include <mcld/Object/ObjectBuilder.h>
     42 
     43 using namespace mcld;
     44 
     45 //===----------------------------------------------------------------------===//
     46 // AArch64GNULDBackend
     47 //===----------------------------------------------------------------------===//
     48 AArch64GNULDBackend::AArch64GNULDBackend(const LinkerConfig& pConfig,
     49                                          GNUInfo* pInfo)
     50   : GNULDBackend(pConfig, pInfo),
     51     m_pRelocator(NULL),
     52     m_pGOT(NULL),
     53     m_pGOTPLT(NULL),
     54     m_pPLT(NULL),
     55     m_pRelaDyn(NULL),
     56     m_pRelaPLT(NULL),
     57     // m_pAttrData(NULL),
     58     m_pDynamic(NULL),
     59     m_pGOTSymbol(NULL)
     60     // m_pAttributes(NULL)
     61 {
     62 }
     63 
     64 AArch64GNULDBackend::~AArch64GNULDBackend()
     65 {
     66   if (m_pRelocator != NULL)
     67     delete m_pRelocator;
     68   if (m_pGOT == m_pGOTPLT) {
     69     if (m_pGOT != NULL)
     70       delete m_pGOT;
     71   } else {
     72     if (m_pGOT != NULL)
     73       delete m_pGOT;
     74     if (m_pGOTPLT != NULL)
     75       delete m_pGOTPLT;
     76   }
     77   if (m_pPLT != NULL)
     78     delete m_pPLT;
     79   if (m_pRelaDyn != NULL)
     80     delete m_pRelaDyn;
     81   if (m_pRelaPLT != NULL)
     82     delete m_pRelaPLT;
     83   if (m_pDynamic != NULL)
     84     delete m_pDynamic;
     85 }
     86 
     87 void AArch64GNULDBackend::initTargetSections(Module& pModule,
     88                                              ObjectBuilder& pBuilder)
     89 {
     90   // TODO
     91 
     92   if (LinkerConfig::Object != config().codeGenType()) {
     93     ELFFileFormat* file_format = getOutputFormat();
     94 
     95     // initialize .got
     96     LDSection& got = file_format->getGOT();
     97     m_pGOT = new AArch64GOT(got);
     98     if (config().options().hasNow()) {
     99       // when -z now is given, there will be only one .got section (contains
    100       // both GOTPLT and normal GOT entries), create GOT0 for .got section and
    101       // set m_pGOTPLT to the same .got
    102       m_pGOT->createGOT0();
    103       m_pGOTPLT = m_pGOT;
    104     }
    105     else {
    106       // Otherwise, got should be seperated to two sections, .got and .got.plt
    107       // initialize .got.plt
    108       LDSection& gotplt = file_format->getGOTPLT();
    109       m_pGOTPLT = new AArch64GOT(gotplt);
    110       m_pGOTPLT->createGOT0();
    111     }
    112 
    113     // initialize .plt
    114     LDSection& plt = file_format->getPLT();
    115     m_pPLT = new AArch64PLT(plt, *m_pGOTPLT);
    116 
    117     // initialize .rela.plt
    118     LDSection& relaplt = file_format->getRelaPlt();
    119     relaplt.setLink(&plt);
    120     m_pRelaPLT = new OutputRelocSection(pModule, relaplt);
    121 
    122     // initialize .rela.dyn
    123     LDSection& reladyn = file_format->getRelaDyn();
    124     m_pRelaDyn = new OutputRelocSection(pModule, reladyn);
    125   }
    126 }
    127 
    128 void AArch64GNULDBackend::initTargetSymbols(IRBuilder& pBuilder,
    129                                             Module& pModule)
    130 {
    131   // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
    132   // same name in input
    133   if (LinkerConfig::Object != config().codeGenType()) {
    134     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
    135                                                   "_GLOBAL_OFFSET_TABLE_",
    136                                                   ResolveInfo::Object,
    137                                                   ResolveInfo::Define,
    138                                                   ResolveInfo::Local,
    139                                                   0x0,  // size
    140                                                   0x0,  // value
    141                                                   FragmentRef::Null(),
    142                                                   ResolveInfo::Hidden);
    143   }
    144   // TODO
    145 }
    146 
    147 bool AArch64GNULDBackend::initRelocator()
    148 {
    149   if (NULL == m_pRelocator) {
    150     m_pRelocator = new AArch64Relocator(*this, config());
    151   }
    152   return true;
    153 }
    154 
    155 const Relocator* AArch64GNULDBackend::getRelocator() const
    156 {
    157   assert(NULL != m_pRelocator);
    158   return m_pRelocator;
    159 }
    160 
    161 Relocator* AArch64GNULDBackend::getRelocator()
    162 {
    163   assert(NULL != m_pRelocator);
    164   return m_pRelocator;
    165 }
    166 
    167 void AArch64GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder)
    168 {
    169   // define symbol _GLOBAL_OFFSET_TABLE_ when .got create
    170   if (m_pGOTSymbol != NULL) {
    171     pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
    172                      "_GLOBAL_OFFSET_TABLE_",
    173                      ResolveInfo::Object,
    174                      ResolveInfo::Define,
    175                      ResolveInfo::Local,
    176                      0x0, // size
    177                      0x0, // value
    178                      FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
    179                      ResolveInfo::Hidden);
    180   }
    181   else {
    182     m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
    183                      "_GLOBAL_OFFSET_TABLE_",
    184                      ResolveInfo::Object,
    185                      ResolveInfo::Define,
    186                      ResolveInfo::Local,
    187                      0x0, // size
    188                      0x0, // value
    189                      FragmentRef::Create(*(m_pGOTPLT->begin()), 0x0),
    190                      ResolveInfo::Hidden);
    191   }
    192 }
    193 
    194 void AArch64GNULDBackend::doPreLayout(IRBuilder& pBuilder)
    195 {
    196   // initialize .dynamic data
    197   if (!config().isCodeStatic() && NULL == m_pDynamic)
    198     m_pDynamic = new AArch64ELFDynamic(*this, config());
    199 
    200   if (LinkerConfig::Object != config().codeGenType()) {
    201     // set .got size
    202     if (config().options().hasNow()) {
    203       // when building shared object, the GOTPLT section is must
    204       if (LinkerConfig::DynObj == config().codeGenType() ||
    205           m_pGOT->hasGOT1() ||
    206           NULL != m_pGOTSymbol) {
    207         m_pGOT->finalizeSectionSize();
    208         defineGOTSymbol(pBuilder);
    209       }
    210     }
    211     else {
    212       // when building shared object, the GOTPLT section is must
    213       if (LinkerConfig::DynObj == config().codeGenType() ||
    214           m_pGOTPLT->hasGOT1() ||
    215           NULL != m_pGOTSymbol) {
    216         m_pGOTPLT->finalizeSectionSize();
    217         defineGOTSymbol(pBuilder);
    218       }
    219       if (m_pGOT->hasGOT1())
    220         m_pGOT->finalizeSectionSize();
    221     }
    222 
    223     // set .plt size
    224     if (m_pPLT->hasPLT1())
    225       m_pPLT->finalizeSectionSize();
    226 
    227     ELFFileFormat* file_format = getOutputFormat();
    228     // set .rela.dyn size
    229     if (!m_pRelaDyn->empty()) {
    230       assert(!config().isCodeStatic() &&
    231             "static linkage should not result in a dynamic relocation section");
    232       file_format->getRelaDyn().setSize(
    233                                 m_pRelaDyn->numOfRelocs() * getRelaEntrySize());
    234     }
    235 
    236     // set .rela.plt size
    237     if (!m_pRelaPLT->empty()) {
    238       assert(!config().isCodeStatic() &&
    239             "static linkage should not result in a dynamic relocation section");
    240       file_format->getRelaPlt().setSize(
    241                                 m_pRelaPLT->numOfRelocs() * getRelaEntrySize());
    242     }
    243   }
    244 }
    245 
    246 void AArch64GNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder)
    247 {
    248   const ELFFileFormat *file_format = getOutputFormat();
    249 
    250   // apply PLT
    251   if (file_format->hasPLT()) {
    252     assert(NULL != m_pPLT);
    253     m_pPLT->applyPLT0();
    254     m_pPLT->applyPLT1();
    255   }
    256 
    257   // apply GOTPLT
    258   if ((config().options().hasNow() && file_format->hasGOT()) ||
    259        file_format->hasGOTPLT()) {
    260     assert(NULL != m_pGOTPLT);
    261     if (LinkerConfig::DynObj == config().codeGenType())
    262       m_pGOTPLT->applyGOT0(file_format->getDynamic().addr());
    263     else {
    264       // executable file and object file? should fill with zero.
    265       m_pGOTPLT->applyGOT0(0);
    266     }
    267   }
    268 }
    269 
    270 AArch64ELFDynamic& AArch64GNULDBackend::dynamic()
    271 {
    272   assert(NULL != m_pDynamic);
    273   return *m_pDynamic;
    274 }
    275 
    276 const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const
    277 {
    278   assert(NULL != m_pDynamic);
    279   return *m_pDynamic;
    280 }
    281 
    282 uint64_t AArch64GNULDBackend::emitSectionData(const LDSection& pSection,
    283                                               MemoryRegion& pRegion) const
    284 {
    285   assert(pRegion.size() && "Size of MemoryRegion is zero!");
    286 
    287   const ELFFileFormat* file_format = getOutputFormat();
    288 
    289   if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
    290     uint64_t result = m_pPLT->emit(pRegion);
    291     return result;
    292   }
    293 
    294   if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
    295     uint64_t result = m_pGOT->emit(pRegion);
    296     return result;
    297   }
    298 
    299   if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
    300     uint64_t result = m_pGOT->emit(pRegion);
    301     return result;
    302   }
    303 
    304   // TODO
    305   return pRegion.size();
    306 }
    307 
    308 unsigned int
    309 AArch64GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const
    310 {
    311   const ELFFileFormat* file_format = getOutputFormat();
    312 
    313   if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT())) {
    314     if (config().options().hasNow())
    315       return SHO_RELRO;
    316     return SHO_RELRO_LAST;
    317   }
    318 
    319   if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
    320     return SHO_NON_RELRO_FIRST;
    321 
    322   if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
    323     return SHO_PLT;
    324 
    325   return SHO_UNDEFINED;
    326 }
    327 
    328 bool AArch64GNULDBackend::doRelax(Module& pModule,
    329                                   IRBuilder& pBuilder,
    330                                   bool& pFinished)
    331 {
    332   // TODO
    333   return false;
    334 }
    335 
    336 bool AArch64GNULDBackend::initTargetStubs()
    337 {
    338   // TODO
    339   return true;
    340 }
    341 
    342 void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule)
    343 {
    344   // TODO
    345 }
    346 
    347 bool AArch64GNULDBackend::finalizeTargetSymbols()
    348 {
    349   // TODO
    350   return true;
    351 }
    352 
    353 bool AArch64GNULDBackend::mergeSection(Module& pModule,
    354                                        const Input& pInput,
    355                                        LDSection& pSection)
    356 {
    357   // TODO
    358   return true;
    359 }
    360 
    361 bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD)
    362 {
    363   // TODO
    364   return true;
    365 }
    366 
    367 AArch64GOT& AArch64GNULDBackend::getGOT()
    368 {
    369   assert(NULL != m_pGOT && "GOT section not exist");
    370   return *m_pGOT;
    371 }
    372 
    373 const AArch64GOT& AArch64GNULDBackend::getGOT() const
    374 {
    375   assert(NULL != m_pGOT && "GOT section not exist");
    376   return *m_pGOT;
    377 }
    378 
    379 AArch64GOT& AArch64GNULDBackend::getGOTPLT()
    380 {
    381   assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
    382   return *m_pGOTPLT;
    383 }
    384 
    385 const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const
    386 {
    387   assert(NULL != m_pGOTPLT && "GOTPLT section not exist");
    388   return *m_pGOTPLT;
    389 }
    390 
    391 AArch64PLT& AArch64GNULDBackend::getPLT()
    392 {
    393   assert(NULL != m_pPLT && "PLT section not exist");
    394   return *m_pPLT;
    395 }
    396 
    397 const AArch64PLT& AArch64GNULDBackend::getPLT() const
    398 {
    399   assert(NULL != m_pPLT && "PLT section not exist");
    400   return *m_pPLT;
    401 }
    402 
    403 OutputRelocSection& AArch64GNULDBackend::getRelaDyn()
    404 {
    405   assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
    406   return *m_pRelaDyn;
    407 }
    408 
    409 const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const
    410 {
    411   assert(NULL != m_pRelaDyn && ".rela.dyn section not exist");
    412   return *m_pRelaDyn;
    413 }
    414 
    415 OutputRelocSection& AArch64GNULDBackend::getRelaPLT()
    416 {
    417   assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
    418   return *m_pRelaPLT;
    419 }
    420 
    421 const OutputRelocSection& AArch64GNULDBackend::getRelaPLT() const
    422 {
    423   assert(NULL != m_pRelaPLT && ".rela.plt section not exist");
    424   return *m_pRelaPLT;
    425 }
    426 
    427 namespace mcld {
    428 
    429 //===----------------------------------------------------------------------===//
    430 //  createAArch64LDBackend - the help funtion to create corresponding
    431 //  AArch64LDBackend
    432 //===----------------------------------------------------------------------===//
    433 TargetLDBackend* createAArch64LDBackend(const LinkerConfig& pConfig)
    434 {
    435   if (pConfig.targets().triple().isOSDarwin()) {
    436     assert(0 && "MachO linker is not supported yet");
    437     /**
    438     return new AArch64MachOLDBackend(createAArch64MachOArchiveReader,
    439                                      createAArch64MachOObjectReader,
    440                                      createAArch64MachOObjectWriter);
    441     **/
    442   }
    443   if (pConfig.targets().triple().isOSWindows()) {
    444     assert(0 && "COFF linker is not supported yet");
    445     /**
    446     return new AArch64COFFLDBackend(createAArch64COFFArchiveReader,
    447                                     createAArch64COFFObjectReader,
    448                                     createAArch64COFFObjectWriter);
    449     **/
    450   }
    451   return new AArch64GNULDBackend(pConfig,
    452      new AArch64GNUInfo(pConfig.targets().triple()));
    453 }
    454 
    455 } // namespace of mcld
    456 
    457 //===----------------------------------------------------------------------===//
    458 // Force static initialization.
    459 //===----------------------------------------------------------------------===//
    460 extern "C" void MCLDInitializeAArch64LDBackend() {
    461   // Register the linker backend
    462   mcld::TargetRegistry::RegisterTargetLDBackend(TheAArch64Target,
    463                                                 createAArch64LDBackend);
    464 }
    465 
    466