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