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 43namespace 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_pDynamic(NULL), 58 m_pGOTSymbol(NULL) { 59} 60 61AArch64GNULDBackend::~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 83void 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 120void 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 138bool AArch64GNULDBackend::initRelocator() { 139 if (m_pRelocator == NULL) { 140 m_pRelocator = new AArch64Relocator(*this, config()); 141 } 142 return true; 143} 144 145const Relocator* AArch64GNULDBackend::getRelocator() const { 146 assert(m_pRelocator != NULL); 147 return m_pRelocator; 148} 149 150Relocator* AArch64GNULDBackend::getRelocator() { 151 assert(m_pRelocator != NULL); 152 return m_pRelocator; 153} 154 155void 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 180void 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 230void 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 253AArch64ELFDynamic& AArch64GNULDBackend::dynamic() { 254 assert(m_pDynamic != NULL); 255 return *m_pDynamic; 256} 257 258const AArch64ELFDynamic& AArch64GNULDBackend::dynamic() const { 259 assert(m_pDynamic != NULL); 260 return *m_pDynamic; 261} 262 263uint64_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 288unsigned 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 307bool AArch64GNULDBackend::doRelax(Module& pModule, 308 IRBuilder& pBuilder, 309 bool& pFinished) { 310 // TODO 311 return false; 312} 313 314bool AArch64GNULDBackend::initTargetStubs() { 315 // TODO 316 return true; 317} 318 319void AArch64GNULDBackend::doCreateProgramHdrs(Module& pModule) { 320 // TODO 321} 322 323bool AArch64GNULDBackend::finalizeTargetSymbols() { 324 // TODO 325 return true; 326} 327 328bool AArch64GNULDBackend::mergeSection(Module& pModule, 329 const Input& pInput, 330 LDSection& pSection) { 331 // TODO 332 return true; 333} 334 335bool AArch64GNULDBackend::readSection(Input& pInput, SectionData& pSD) { 336 // TODO 337 return true; 338} 339 340AArch64GOT& AArch64GNULDBackend::getGOT() { 341 assert(m_pGOT != NULL && "GOT section not exist"); 342 return *m_pGOT; 343} 344 345const AArch64GOT& AArch64GNULDBackend::getGOT() const { 346 assert(m_pGOT != NULL && "GOT section not exist"); 347 return *m_pGOT; 348} 349 350AArch64GOT& AArch64GNULDBackend::getGOTPLT() { 351 assert(m_pGOTPLT != NULL && "GOTPLT section not exist"); 352 return *m_pGOTPLT; 353} 354 355const AArch64GOT& AArch64GNULDBackend::getGOTPLT() const { 356 assert(m_pGOTPLT != NULL && "GOTPLT section not exist"); 357 return *m_pGOTPLT; 358} 359 360AArch64PLT& AArch64GNULDBackend::getPLT() { 361 assert(m_pPLT != NULL && "PLT section not exist"); 362 return *m_pPLT; 363} 364 365const AArch64PLT& AArch64GNULDBackend::getPLT() const { 366 assert(m_pPLT != NULL && "PLT section not exist"); 367 return *m_pPLT; 368} 369 370OutputRelocSection& AArch64GNULDBackend::getRelaDyn() { 371 assert(m_pRelaDyn != NULL && ".rela.dyn section not exist"); 372 return *m_pRelaDyn; 373} 374 375const OutputRelocSection& AArch64GNULDBackend::getRelaDyn() const { 376 assert(m_pRelaDyn != NULL && ".rela.dyn section not exist"); 377 return *m_pRelaDyn; 378} 379 380OutputRelocSection& AArch64GNULDBackend::getRelaPLT() { 381 assert(m_pRelaPLT != NULL && ".rela.plt section not exist"); 382 return *m_pRelaPLT; 383} 384 385const 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//===----------------------------------------------------------------------===// 394TargetLDBackend* 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//===----------------------------------------------------------------------===// 420extern "C" void MCLDInitializeAArch64LDBackend() { 421 // Register the linker backend 422 mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheAArch64Target, 423 mcld::createAArch64LDBackend); 424} 425