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