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