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