X86LDBackend.cpp revision 6f75755c9204b1d8817ae5a65a2f7e5af0ec3f70
15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- X86LDBackend.cpp ---------------------------------------------------===// 25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// The MCLinker Project 45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source 65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details. 75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// 85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 95460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86.h" 105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86ELFDynamic.h" 115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include "X86LDBackend.h" 12d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "X86Relocator.h" 13d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "X86GNUInfo.h" 145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Triple.h> 16cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include <llvm/Support/Casting.h> 17cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao 1822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/LinkerConfig.h> 1922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/IRBuilder.h> 2022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FillFragment.h> 2122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/RegionFragment.h> 2222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Fragment/FragmentLinker.h> 23affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MemoryRegion.h> 24affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/MsgHandling.h> 25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang#include <mcld/Support/TargetRegistry.h> 2622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao#include <mcld/Object/ObjectBuilder.h> 275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <cstring> 295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaousing namespace mcld; 315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 3322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// X86GNULDBackend 3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86GNULDBackend::X86GNULDBackend(const LinkerConfig& pConfig, 366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines GNUInfo* pInfo, 376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation::Type pCopyRel) 38d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao : GNULDBackend(pConfig, pInfo), 39d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelocator(NULL), 405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pPLT(NULL), 415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pRelDyn(NULL), 425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pRelPLT(NULL), 4367e37f1be98c926645219cfb47fab9e90d8c725cShih-wei Liao m_pDynamic(NULL), 446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTSymbol(NULL), 456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_CopyRel(pCopyRel) 466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Triple::ArchType arch = pConfig.targets().triple().getArch(); 486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert (arch == Triple::x86 || arch == Triple::x86_64); 496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (arch == Triple::x86 || 506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pConfig.targets().triple().getEnvironment() == Triple::GNUX32) { 516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_RelEntrySize = 8; 526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_RelaEntrySize = 12; 536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (arch == Triple::x86) 546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_PointerRel = llvm::ELF::R_386_32; 556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_PointerRel = llvm::ELF::R_X86_64_32; 576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_RelEntrySize = 16; 606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_RelaEntrySize = 24; 616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_PointerRel = llvm::ELF::R_X86_64_64; 626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86GNULDBackend::~X86GNULDBackend() 665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 67d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao delete m_pRelocator; 6822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete m_pPLT; 6922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete m_pRelDyn; 7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete m_pRelPLT; 7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao delete m_pDynamic; 725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 74d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoRelocator* X86GNULDBackend::getRelocator() 755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 76d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao assert(NULL != m_pRelocator); 77d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao return m_pRelocator; 785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86GNULDBackend::doPreLayout(IRBuilder& pBuilder) 815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .dynamic data 836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!config().isCodeStatic() && NULL == m_pDynamic) 846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pDynamic = new X86ELFDynamic(*this, config()); 856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .got.plt and .got sizes 8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // when building shared object, the .got section is must 8822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::Object != config().codeGenType()) { 896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines setGOTSectionSize(pBuilder); 9022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set .plt size 9222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (m_pPLT->hasPLT1()) 9322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pPLT->finalizeSectionSize(); 9422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .rel.dyn/.rela.dyn size 966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!m_pRelDyn->empty()) { 976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(!config().isCodeStatic() && 986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "static linkage should not result in a dynamic relocation section"); 996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines setRelDynSize(); 1006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 1016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .rel.plt/.rela.plt size 1026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!m_pRelPLT->empty()) { 1036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(!config().isCodeStatic() && 1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "static linkage should not result in a dynamic relocation section"); 1056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines setRelPLTSize(); 1066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 107affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 1085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaovoid X86GNULDBackend::doPostLayout(Module& pModule, 1116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder) 1125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine. 1165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section. 1175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoX86ELFDynamic& X86GNULDBackend::dynamic() 1185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pDynamic); 1205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return *m_pDynamic; 1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine. 1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section. 1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaoconst X86ELFDynamic& X86GNULDBackend::dynamic() const 1265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pDynamic); 1285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return *m_pDynamic; 1295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 1316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86GNULDBackend::defineGOTSymbol(IRBuilder& pBuilder, 1326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Fragment& pFrag) 1335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // define symbol _GLOBAL_OFFSET_TABLE_ 135affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (m_pGOTSymbol != NULL) { 1366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( 1375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "_GLOBAL_OFFSET_TABLE_", 1385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Object, 1395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Define, 1405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Local, 1415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0x0, // size 1425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0x0, // value 1436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines FragmentRef::Create(pFrag, 0x0), 1445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Hidden); 1455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao else { 1476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 1485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao "_GLOBAL_OFFSET_TABLE_", 1495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Object, 1505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Define, 1515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Local, 1525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0x0, // size 1535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 0x0, // value 1546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines FragmentRef::Create(pFrag, 0x0), 1555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo::Hidden); 1565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 159affc150dc44fab1911775a49636d0ce85333b634Zonr Changvoid X86GNULDBackend::addCopyReloc(ResolveInfo& pSym) 1605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 16122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Relocation& rel_entry = *m_pRelDyn->consumeEntry(); 1626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry.setType(m_CopyRel); 163affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(pSym.outSymbol()->hasFragRef()); 164affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); 165affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rel_entry.setSymInfo(&pSym); 1665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 16822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// defineSymbolforCopyReloc 16922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// For a symbol needing copy relocation, define a copy symbol in the BSS 17022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// section and all other reference to this symbol should refer to this 17122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// copy. 17222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// @note This is executed at `scan relocation' stage. 1736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesLDSymbol& X86GNULDBackend::defineSymbolforCopyReloc(IRBuilder& pBuilder, 174affc150dc44fab1911775a49636d0ce85333b634Zonr Chang const ResolveInfo& pSym) 1755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 176affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // get or create corresponding BSS LDSection 177affc150dc44fab1911775a49636d0ce85333b634Zonr Chang LDSection* bss_sect_hdr = NULL; 17822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = getOutputFormat(); 17922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (ResolveInfo::ThreadLocal == pSym.type()) 18022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bss_sect_hdr = &file_format->getTBSS(); 18122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 18222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bss_sect_hdr = &file_format->getBSS(); 1835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao // get or create corresponding BSS SectionData 185affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != bss_sect_hdr); 18622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao SectionData* bss_section = NULL; 18722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (bss_sect_hdr->hasSectionData()) 18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bss_section = bss_sect_hdr->getSectionData(); 18922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao bss_section = IRBuilder::CreateSectionData(*bss_sect_hdr); 191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 192affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Determine the alignment by the symbol value 193affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // FIXME: here we use the largest alignment 194d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao uint32_t addralign = config().targets().bitclass() / 8; 195affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 196affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // allocate space in BSS for the copy symbol 197cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao Fragment* frag = new FillFragment(0x0, 1, pSym.size()); 19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao uint64_t size = ObjectBuilder::AppendFragment(*frag, 19922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao *bss_section, 20022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao addralign); 201affc150dc44fab1911775a49636d0ce85333b634Zonr Chang bss_sect_hdr->setSize(bss_sect_hdr->size() + size); 202affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 203affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // change symbol binding to Global if it's a weak symbol 204affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo::Binding binding = (ResolveInfo::Binding)pSym.binding(); 205affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (binding == ResolveInfo::Weak) 206affc150dc44fab1911775a49636d0ce85333b634Zonr Chang binding = ResolveInfo::Global; 207affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 208affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Define the copy symbol in the bss section and resolve it 2096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSymbol* cpy_sym = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>( 210affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pSym.name(), 211affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (ResolveInfo::Type)pSym.type(), 212affc150dc44fab1911775a49636d0ce85333b634Zonr Chang ResolveInfo::Define, 213affc150dc44fab1911775a49636d0ce85333b634Zonr Chang binding, 214affc150dc44fab1911775a49636d0ce85333b634Zonr Chang pSym.size(), // size 215affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 0x0, // value 21622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao FragmentRef::Create(*frag, 0x0), 217affc150dc44fab1911775a49636d0ce85333b634Zonr Chang (ResolveInfo::Visibility)pSym.other()); 218affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 219affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return *cpy_sym; 2205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 2215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 2226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86GNULDBackend::scanRelocation(Relocation& pReloc, 2236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pLinker, 22422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao Module& pModule, 2256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 2266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 2276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::Object == config().codeGenType()) 2286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 2306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 2316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != rsym && 2326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "ResolveInfo of relocation not set while scanRelocation"); 2336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.updateAddend(); 2356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != pSection.getLink()); 2366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) 2376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 2386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Scan relocation type to determine if the GOT/PLT/Dynamic Relocation 2406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // entries should be created. 2416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isLocal()) // rsym is local 2426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines scanLocalReloc(pReloc, pLinker, pModule, pSection); 2436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else // rsym is external 2446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines scanGlobalReloc(pReloc, pLinker, pModule, pSection); 2456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // check if we should issue undefined reference for the relocation target 2476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // symbol 2486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) 2496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::undefined_reference) << rsym->name(); 2506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 2516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection, 2536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines MemoryRegion& pRegion) const 2546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 2556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(pRegion.size() && "Size of MemoryRegion is zero!"); 2566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const ELFFileFormat* FileFormat = getOutputFormat(); 2586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(FileFormat && 2596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!"); 2606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int EntrySize = 0; 2626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t RegionSize = 0; 2636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (&pSection == &(FileFormat->getPLT())) { 2656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); 2666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned char* buffer = pRegion.getBuffer(); 2686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT->applyPLT0(); 2706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT->applyPLT1(); 2716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86PLT::iterator it = m_pPLT->begin(); 2726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size(); 2736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size); 2756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += plt0_size; 2766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++it; 2776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines PLTEntryBase* plt1 = 0; 2796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86PLT::iterator ie = m_pPLT->end(); 2806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines while (it != ie) { 2816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines plt1 = &(llvm::cast<PLTEntryBase>(*it)); 2826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines EntrySize = plt1->size(); 2836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines memcpy(buffer + RegionSize, plt1->getValue(), EntrySize); 2846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += EntrySize; 2856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ++it; 2866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 2876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 2886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else if (&pSection == &(FileFormat->getGOT())) { 2906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += emitGOTSectionData(pRegion); 2916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 2926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else if (&pSection == &(FileFormat->getGOTPLT())) { 2946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += emitGOTPLTSectionData(pRegion, FileFormat); 2956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 2966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 2976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 2986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::unrecognized_output_sectoin) 2996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines << pSection.name() 3006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines << "mclinker@googlegroups.com"; 3016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 3026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return RegionSize; 3036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86PLT& X86GNULDBackend::getPLT() 3066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pPLT && "PLT section not exist"); 3086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pPLT; 3096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst X86PLT& X86GNULDBackend::getPLT() const 3126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pPLT && "PLT section not exist"); 3146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pPLT; 3156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesOutputRelocSection& X86GNULDBackend::getRelDyn() 3186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 3206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pRelDyn; 3216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst OutputRelocSection& X86GNULDBackend::getRelDyn() const 3246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pRelDyn && ".rel.dyn/.rela.dyn section not exist"); 3266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pRelDyn; 3276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesOutputRelocSection& X86GNULDBackend::getRelPLT() 3306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 3326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pRelPLT; 3336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst OutputRelocSection& X86GNULDBackend::getRelPLT() const 3366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pRelPLT && ".rel.plt/.rela.plt section not exist"); 3386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pRelPLT; 3396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesunsigned int 3426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86GNULDBackend::getTargetSectionOrder(const LDSection& pSectHdr) const 3436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const ELFFileFormat* file_format = getOutputFormat(); 3456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (&pSectHdr == &file_format->getGOT()) { 3476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().options().hasNow()) 3486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_RELRO; 3496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_RELRO_LAST; 3506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 3516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (&pSectHdr == &file_format->getGOTPLT()) { 3536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().options().hasNow()) 3546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_RELRO; 3556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_NON_RELRO_FIRST; 3566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 3576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (&pSectHdr == &file_format->getPLT()) 3596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_PLT; 3606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return SHO_UNDEFINED; 3626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86GNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) 3656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::Object != config().codeGenType()) { 3676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the 3686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // same name in input 3696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTSymbol = 3706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>( 3716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines "_GLOBAL_OFFSET_TABLE_", 3726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo::Object, 3736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo::Define, 3746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo::Local, 3756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 0x0, // size 3766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 0x0, // value 3776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines FragmentRef::Null(), // FragRef 3786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo::Hidden); 3796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 3806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// finalizeSymbol - finalize the symbol value 3836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool X86GNULDBackend::finalizeTargetSymbols() 3846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return true; 3866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// doCreateProgramHdrs - backend can implement this function to create the 3896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// target-dependent segments 3906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86GNULDBackend::doCreateProgramHdrs(Module& pModule) 3916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 3926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // TODO 3936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 3946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 3956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GNULDBackend::X86_32GNULDBackend(const LinkerConfig& pConfig, 3966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines GNUInfo* pInfo) 3976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_386_COPY), 3986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT (NULL), 3996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT (NULL) { 4006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 4016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 4026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GNULDBackend::~X86_32GNULDBackend() 4036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 4046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pGOT; 4056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pGOTPLT; 4066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 4076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 4086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool X86_32GNULDBackend::initRelocator() 4096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 4106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL == m_pRelocator) { 4116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelocator = new X86_32Relocator(*this); 4126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 4136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return true; 4146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 4156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 4166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::scanLocalReloc(Relocation& pReloc, 4176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 4186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Module& pModule, 4196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 4205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 4215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 4225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 4235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(pReloc.type()){ 4255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_32: 42722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_16: 42822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_8: 4295460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If buiding PIC object (shared library or PIC executable), 4305460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // a dynamic relocations with RELATIVE type to this location is needed. 4315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Reserve an entry in .rel.dyn 4326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeIndep()) { 433d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 4345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // set Rel bit 4355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveRel); 4366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 4375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 4385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_GOTOFF: 4415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_GOTPC: 44222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: A GOT section is needed 44322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 44422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 44522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_GOT32: 44622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // Symbol needs GOT entry, reserve entry in .got 44722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // return if we already create GOT for this symbol 44822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & (ReserveGOT | GOTRel)) 44922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 45022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: check STT_GNU_IFUNC symbol 45122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 4526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 4536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the GOT is used in statically linked binaries, 4546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // the GOT entry is enough and no relocation is needed. 4556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeStatic()) { 4566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 4576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 4586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 45922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // If building shared object or the symbol is undefined, a dynamic 46022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // relocation is needed to relocate this GOT entry. Reserve an 46122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // entry in .rel.dyn 46222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == 46322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 464d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 46522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 46622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 46722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 46822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 46922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOT bit 47022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveGOT); 4715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 4725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 4735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_PC32: 47422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_PC16: 47522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_PC8: 47622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 47722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 47822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_GD: { 47922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 48022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 48122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 48222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(2); 48322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve an rel entry 484d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 48522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 48622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 48722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // define the section symbol for .tdata or .tbss 48822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the target symbol of the created dynamic relocation should be the 48922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // section symbol of the section which this symbol defined. so we 49022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // need to define that section symbol here 49122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = getOutputFormat(); 49222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const LDSection* sym_sect = 49322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao &rsym->outSymbol()->fragRef()->frag()->getParent()->getSection(); 49422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (&file_format->getTData() == sym_sect) { 49522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == f_pTDATA) 49622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao f_pTDATA = pModule.getSectionSymbolSet().get(*sym_sect); 49722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 49822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else if (&file_format->getTBSS() == sym_sect || rsym->isCommon()) { 49922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (NULL == f_pTBSS) 50022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao f_pTBSS = pModule.getSectionSymbolSet().get(*sym_sect); 50122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 50222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao else 50322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao error(diag::invalid_tls) << rsym->name() << sym_sect->name(); 50422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 50522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 50622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 50722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LDM: 50822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao getTLSModuleID(); 50922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 51022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 51122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LDO_32: 51222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 51322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 51422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_IE: 51522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 51622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // if buildint shared object, a RELATIVE dynamic relocation is needed 51722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == config().codeGenType()) { 518d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 51922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveRel); 5206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 5216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } else { 5226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // for local sym, we can convert ie to le if not building shared object 5236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines convertTLSIEtoLE(pReloc, pSection); 5246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 52522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 52622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 52722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 52822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve got and dyn relocation entries for tp-relative offset 52922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 530d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 53122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 53222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 53322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol()); 53422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 53522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 53622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_GOTIE: 53722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 53822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 53922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 54022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve got and dyn relocation entries for tp-relative offset 54122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 542d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 54322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 54422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 54522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol()); 54622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 54722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 54822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LE: 54922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LE_32: 55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 55122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // if buildint shared object, a dynamic relocation is needed 55222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == config().codeGenType()) { 553d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 55422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveRel); 5556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 55622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // the target symbol of the dynamic relocation is rsym, so we need to 55722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // emit it into .dynsym 55822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao assert(NULL != rsym->outSymbol()); 55922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pRelDyn->addSymbolToDynSym(*rsym->outSymbol()); 56022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 5615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 5625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: 564affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::unsupported_relocation) << (int)pReloc.type() 565affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << "mclinker@googlegroups.com"; 5665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } // end switch 5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 5695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::scanGlobalReloc(Relocation& pReloc, 5716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 5726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Module& pModule, 5736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 5745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 5755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // rsym - The relocation target symbol 5765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao ResolveInfo* rsym = pReloc.symInfo(); 5775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao switch(pReloc.type()) { 5795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_32: 58022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_16: 58122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_8: 5825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Absolute relocation type, symbol may needs PLT entry or 5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // dynamic relocation entry 5846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsPLT(*rsym)) { 5855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // create plt for this symbol if it does not have one 586affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(rsym->reserved() & ReservePLT)){ 5875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Symbol needs PLT entry, we need to reserve a PLT entry 5885460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // and the corresponding GOT and dynamic relocation entry 5895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // in .got and .rel.plt. (GOT entry will be reserved simultaneously 5905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // when calling X86PLT->reserveEntry()) 5915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pPLT->reserveEntry(); 59222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOTPLT->reserve(); 593d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelPLT->reserveEntry(); 5945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // set PLT bit 5955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rsym->setReserved(rsym->reserved() | ReservePLT); 5965460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 5985460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 5996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) { 6005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 601d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 6026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsCopyReloc(pReloc, *rsym)) { 6036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 604affc150dc44fab1911775a49636d0ce85333b634Zonr Chang addCopyReloc(*cpy_sym.resolveInfo()); 605affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 606affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 607affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // set Rel bit 608affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rsym->setReserved(rsym->reserved() | ReserveRel); 6096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(pSection); 610affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 6115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_GOTOFF: 6155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_GOTPC: { 61622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: A GOT section is needed 6175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_PLT32: 6215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // A PLT entry is needed when building shared library 6225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // return if we already create plt for this symbol 624affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & ReservePLT) 6255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6265460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 62722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // if the symbol's value can be decided at link time, then no need plt 6286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolFinalValueIsKnown(*rsym)) 62922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 63022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 6315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // if symbol is defined in the ouput file and it's not 6325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // preemptible, no need plt 633affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->isDefine() && !rsym->isDyn() && 63422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao !isSymbolPreemptible(*rsym)) { 6355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Symbol needs PLT entry, we need to reserve a PLT entry 6395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // and the corresponding GOT and dynamic relocation entry 6405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // in .got and .rel.plt. (GOT entry will be reserved simultaneously 6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // when calling X86PLT->reserveEntry()) 6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao m_pPLT->reserveEntry(); 64322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOTPLT->reserve(); 644d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelPLT->reserveEntry(); 6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // set PLT bit 6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rsym->setReserved(rsym->reserved() | ReservePLT); 6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_GOT32: 6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Symbol needs GOT entry, reserve entry in .got 6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // return if we already create GOT for this symbol 652affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (rsym->reserved() & (ReserveGOT | GOTRel)) 6535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 65422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 6556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 6566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the GOT is used in statically linked binaries, 6576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // the GOT entry is enough and no relocation is needed. 6586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeStatic()) { 6596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 6606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 6616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 6625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // If building shared object or the symbol is undefined, a dynamic 6635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // relocation is needed to relocate this GOT entry. Reserve an 6645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // entry in .rel.dyn 66522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == 66622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 667d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // set GOTRel bit 6695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 6705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6715460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 6725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // set GOT bit 6735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveGOT); 6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return; 6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao case llvm::ELF::R_386_PC32: 67722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_PC16: 67822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_PC8: 6795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 6806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsPLT(*rsym) && 6816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 682affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // create plt for this symbol if it does not have one 683affc150dc44fab1911775a49636d0ce85333b634Zonr Chang if (!(rsym->reserved() & ReservePLT)){ 684affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // Symbol needs PLT entry, we need to reserve a PLT entry 685affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // and the corresponding GOT and dynamic relocation entry 686affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // in .got and .rel.plt. (GOT entry will be reserved simultaneously 687affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // when calling X86PLT->reserveEntry()) 688affc150dc44fab1911775a49636d0ce85333b634Zonr Chang m_pPLT->reserveEntry(); 68922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOTPLT->reserve(); 690d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelPLT->reserveEntry(); 691affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // set PLT bit 692affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rsym->setReserved(rsym->reserved() | ReservePLT); 693affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 694affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 695affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false)) { 697affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn 698d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 6996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsCopyReloc(pReloc, *rsym)) { 7006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 701affc150dc44fab1911775a49636d0ce85333b634Zonr Chang addCopyReloc(*cpy_sym.resolveInfo()); 702affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 703affc150dc44fab1911775a49636d0ce85333b634Zonr Chang else { 704affc150dc44fab1911775a49636d0ce85333b634Zonr Chang // set Rel bit 705affc150dc44fab1911775a49636d0ce85333b634Zonr Chang rsym->setReserved(rsym->reserved() | ReserveRel); 7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(pSection); 707affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 708affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 709affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return; 71022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 71122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_GD: { 71222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // FIXME: no linker optimization for TLS relocation 71322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 71422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 71522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve two pairs of got entry and dynamic relocation 71622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(2); 717d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(2); 71822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 71922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 72022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 72122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 72222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 72322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LDM: 72422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao getTLSModuleID(); 72522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 72622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 72722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LDO_32: 72822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 72922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 73022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_IE: 73122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 73222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // if buildint shared object, a RELATIVE dynamic relocation is needed 73322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == config().codeGenType()) { 734d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 73522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveRel); 7366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 7376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } else { 7386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // for global sym, we can convert ie to le if its final value is known 7396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolFinalValueIsKnown(*rsym)) { 7406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines convertTLSIEtoLE(pReloc, pSection); 7416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 7426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 74322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 74422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 74522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 74622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve got and dyn relocation entries for tp-relative offset 74722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 748d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 74922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 75022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 75122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 75222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 75322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_GOTIE: 75422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 75522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (rsym->reserved() & GOTRel) 75622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 75722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // reserve got and dyn relocation entries for tp-relative offset 75822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao m_pGOT->reserve(); 759d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 76022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // set GOTRel bit 76122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | GOTRel); 76222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 76322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 76422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LE: 76522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao case llvm::ELF::R_386_TLS_LE_32: 76622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao setHasStaticTLS(); 76722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // if buildint shared object, a dynamic relocation is needed 76822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::DynObj == config().codeGenType()) { 769d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn->reserveEntry(); 77022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao rsym->setReserved(rsym->reserved() | ReserveRel); 7716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 77222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 77322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao return; 77422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 7755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao default: { 776affc150dc44fab1911775a49636d0ce85333b634Zonr Chang fatal(diag::unsupported_relocation) << (int)pReloc.type() 777affc150dc44fab1911775a49636d0ce85333b634Zonr Chang << "mclinker@googlegroups.com"; 7785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao break; 7795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 7805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } // end switch 7815460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 7825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::initTargetSections(Module& pModule, 7846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ObjectBuilder& pBuilder) 7855460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 7866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::Object != config().codeGenType()) { 7876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ELFFileFormat* file_format = getOutputFormat(); 7886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .got 7896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& got = file_format->getGOT(); 7906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT = new X86_32GOT(got); 7915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 7926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .got.plt 7936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& gotplt = file_format->getGOTPLT(); 7946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT = new X86_32GOTPLT(gotplt); 795affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 7966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .plt 7976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& plt = file_format->getPLT(); 7986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT = new X86_32PLT(plt, 7996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *m_pGOTPLT, 8006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines config()); 80122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .rel.plt 8036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& relplt = file_format->getRelPlt(); 8046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines relplt.setLink(&plt); 8056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelPLT = new OutputRelocSection(pModule, relplt); 8066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .rel.dyn 8086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& reldyn = file_format->getRelDyn(); 8096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn = new OutputRelocSection(pModule, reldyn); 81022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 8115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 8135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOT& X86_32GNULDBackend::getGOT() 8155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 8166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pGOT); 8176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pGOT; 8186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst X86_32GOT& X86_32GNULDBackend::getGOT() const 8216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pGOT); 8236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pGOT; 8246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() 8276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pGOTPLT); 8296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pGOTPLT; 8306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8315460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst X86_32GOTPLT& X86_32GNULDBackend::getGOTPLT() const 8336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != m_pGOTPLT); 8356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *m_pGOTPLT; 8366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::setRelDynSize() 8396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ELFFileFormat* file_format = getOutputFormat(); 8416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines file_format->getRelDyn().setSize 8426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (m_pRelDyn->numOfRelocs() * getRelEntrySize()); 8436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::setRelPLTSize() 8466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ELFFileFormat* file_format = getOutputFormat(); 8486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines file_format->getRelPlt().setSize 8496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (m_pRelPLT->numOfRelocs() * getRelEntrySize()); 8506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 8536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .got.plt size 8556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::DynObj == config().codeGenType() || 8566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->hasGOT1() || 8576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines NULL != m_pGOTSymbol) { 8586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->finalizeSectionSize(); 8596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 8605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .got size 8636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!m_pGOT->empty()) 8646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->finalizeSectionSize(); 8656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 8665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86_32GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 8686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 8705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 8725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got = 0; 8746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int EntrySize = X86_32GOTEntry::EntrySize; 8756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t RegionSize = 0; 8766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 8776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines for (X86_32GOT::iterator it = m_pGOT->begin(), 8786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 8796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got = &(llvm::cast<X86_32GOTEntry>((*it))); 8806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *buffer = static_cast<uint32_t>(got->getValue()); 8816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += EntrySize; 8825460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 8835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return RegionSize; 8856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 886affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 8876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86_32GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 8886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const ELFFileFormat* FileFormat) const 8896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 8906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 8916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 8926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 893affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 8946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint32_t* buffer = reinterpret_cast<uint32_t*>(pRegion.getBuffer()); 8955460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 8966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_32GOTEntry* got = 0; 8976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int EntrySize = X86_32GOTEntry::EntrySize; 8986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t RegionSize = 0; 8996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines for (X86_32GOTPLT::iterator it = m_pGOTPLT->begin(), 9016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 9026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got = &(llvm::cast<X86_32GOTEntry>((*it))); 9036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *buffer = static_cast<uint32_t>(got->getValue()); 9046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += EntrySize; 9056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 9066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return RegionSize; 9086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines/// convert R_386_TLS_IE to R_386_TLS_LE 9116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_32GNULDBackend::convertTLSIEtoLE(Relocation& pReloc, 9126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 9136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(pReloc.type() == llvm::ELF::R_386_TLS_IE); 9156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(NULL != pReloc.targetRef().frag()); 9166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // 1. create the fragment references and new relocs 9186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t off = pReloc.targetRef().offset(); 9196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (off >= 4) 9206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines off -= 4; 9216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else 9226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines off = 0; 9236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines FragmentRef* fragref = FragmentRef::Create(*pReloc.targetRef().frag(), off); 9256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // TODO: add symbols for R_386_TLS_OPT relocs 9266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation* reloc = Relocation::Create(X86_32Relocator::R_386_TLS_OPT, 9276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *fragref, 9286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 0x0); 9296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // 2. modify the opcodes to the appropriate ones 9316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint8_t* op = (reinterpret_cast<uint8_t*>(&reloc->target())); 9326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines off = pReloc.targetRef().offset() - reloc->targetRef().offset() - 1; 9336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (op[off] == 0xa1) { 9346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines op[off] = 0xb8; 9356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } else { 9366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines switch (op[off - 1]) { 9376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case 0x8b: 9386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert((op[off] & 0xc7) == 0x05); 9396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines op[off - 1] = 0xc7; 9406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines op[off] = 0xc0 | ((op[off] >> 3) & 7); 9416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines break; 9426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case 0x03: 9436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert((op[off] & 0xc7) == 0x05); 9446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines op[off - 1] = 0x81; 9456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines op[off] = 0xc0 | ((op[off] >> 3) & 7); 9466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines break; 9476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines default: 9486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(0); 9496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines break; 950affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 951affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 952affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 9536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // 3. insert the new relocs "BEFORE" the original reloc. 9546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pSection.getRelocData()->getRelocationList().insert( 9556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RelocData::iterator(pReloc), reloc); 9566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // 4. change the type of the original reloc 9586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines pReloc.setType(llvm::ELF::R_386_TLS_LE); 9596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines// Create a GOT entry for the TLS module index 9626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_32GOTEntry& X86_32GNULDBackend::getTLSModuleID() 9636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines static X86_32GOTEntry* got_entry = NULL; 9656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL != got_entry) 9666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 9676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Allocate 2 got entries and 1 dynamic reloc for R_386_TLS_LDM 9696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->reserve(2); 9706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got_entry = m_pGOT->consume(); 9716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->consume()->setValue(0x0); 9726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 9746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Relocation* rel_entry = m_pRelDyn->consumeEntry(); 9756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry->setType(llvm::ELF::R_386_TLS_DTPMOD32); 9766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry->targetRef().assign(*got_entry, 0x0); 9776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rel_entry->setSymInfo(NULL); 9786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return *got_entry; 9806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GNULDBackend::X86_64GNULDBackend(const LinkerConfig& pConfig, 9836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines GNUInfo* pInfo) 9846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines : X86GNULDBackend(pConfig, pInfo, llvm::ELF::R_X86_64_COPY), 9856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT (NULL), 9866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT (NULL) { 9876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GNULDBackend::~X86_64GNULDBackend() 9906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pGOT; 9926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines delete m_pGOTPLT; 9936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines} 9946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 9956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesbool X86_64GNULDBackend::initRelocator() 9966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines{ 9976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (NULL == m_pRelocator) { 9986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelocator = new X86_64Relocator(*this); 999affc150dc44fab1911775a49636d0ce85333b634Zonr Chang } 10006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return true; 10015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 100222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOT& X86_64GNULDBackend::getGOT() 10045460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != m_pGOT); 10065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return *m_pGOT; 10075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10085460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst X86_64GOT& X86_64GNULDBackend::getGOT() const 10105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(NULL != m_pGOT); 10125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return *m_pGOT; 10135460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen HinesX86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() 1016affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 1017affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != m_pGOTPLT); 1018affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return *m_pGOTPLT; 1019affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 1020affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 10216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesconst X86_64GOTPLT& X86_64GNULDBackend::getGOTPLT() const 1022affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 1023affc150dc44fab1911775a49636d0ce85333b634Zonr Chang assert(NULL != m_pGOTPLT); 1024affc150dc44fab1911775a49636d0ce85333b634Zonr Chang return *m_pGOTPLT; 1025affc150dc44fab1911775a49636d0ce85333b634Zonr Chang} 1026affc150dc44fab1911775a49636d0ce85333b634Zonr Chang 10276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::setRelDynSize() 10285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ELFFileFormat* file_format = getOutputFormat(); 10306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines file_format->getRelaDyn().setSize 10316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (m_pRelDyn->numOfRelocs() * getRelaEntrySize()); 10325460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10335460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::setRelPLTSize() 10355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ELFFileFormat* file_format = getOutputFormat(); 10376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines file_format->getRelaPlt().setSize 10386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines (m_pRelPLT->numOfRelocs() * getRelaEntrySize()); 10395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 10405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::scanLocalReloc(Relocation& pReloc, 10426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 10436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Module& pModule, 10446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 10455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 10466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 10476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 10485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines switch(pReloc.type()){ 10506f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_64: 10516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_32: 10526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_16: 10536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_8: 10546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_32S: 10556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If buiding PIC object (shared library or PIC executable), 10566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // a dynamic relocations with RELATIVE type to this location is needed. 10576f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Reserve an entry in .rela.dyn 10586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeIndep()) { 10596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 10606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set Rel bit 10616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 10626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 10636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 10646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 10655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 10666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC32: 10676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC16: 10686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC8: 10696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 107022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 10726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Symbol needs GOT entry, reserve entry in .got 10736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // return if we already create GOT for this symbol 10746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 10756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 10766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->reserve(); 107722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the GOT is used in statically linked binaries, 10796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // the GOT entry is enough and no relocation is needed. 10806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeStatic()) { 10816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 10826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 10836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 10846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If building shared object or the symbol is undefined, a dynamic 10856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 10866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // entry in .rela.dyn 10876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::DynObj == 10886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 10896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 10906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set GOTRel bit 10916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 10926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 10936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 10946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set GOT bit 10956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 10966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 109722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 10986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines default: 10996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 11006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines << "mclinker@googlegroups.com"; 11016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines break; 11026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } // end switch 110322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao} 110422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 11056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::scanGlobalReloc(Relocation& pReloc, 11066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines IRBuilder& pBuilder, 11076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Module& pModule, 11086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& pSection) 11095460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 11106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // rsym - The relocation target symbol 11116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ResolveInfo* rsym = pReloc.symInfo(); 11125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines switch(pReloc.type()) { 11146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_64: 11156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_32: 11166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_16: 11176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_8: 11186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_32S: 11196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Absolute relocation type, symbol may needs PLT entry or 11206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // dynamic relocation entry 11216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsPLT(*rsym)) { 11226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // create plt for this symbol if it does not have one 11236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 11246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 11256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // and the corresponding GOT and dynamic relocation entry 11266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // in .got and .rela.plt. (GOT entry will be reserved simultaneously 11276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // when calling X86PLT->reserveEntry()) 11286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT->reserveEntry(); 11296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->reserve(); 11306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelPLT->reserveEntry(); 11316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set PLT bit 11326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 11336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), true)) { 11376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // symbol needs dynamic relocation entry, reserve an entry in .rela.dyn 11386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 11396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsCopyReloc(pReloc, *rsym)) { 11406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 11416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 11426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines else { 11446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set Rel bit 11456f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveRel); 11466f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines checkAndSetHasTextRel(*pSection.getLink()); 11476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11496f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11516f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_GOTPCREL: 11526f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Symbol needs GOT entry, reserve entry in .got 11536f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // return if we already create GOT for this symbol 11546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & (ReserveGOT | GOTRel)) 11556f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11566f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->reserve(); 11575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If the GOT is used in statically linked binaries, 11596f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // the GOT entry is enough and no relocation is needed. 11606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (config().isCodeStatic()) { 11616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 11626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // If building shared object or the symbol is undefined, a dynamic 11656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // relocation is needed to relocate this GOT entry. Reserve an 11666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // entry in .rela.dyn 11676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::DynObj == 11686f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines config().codeGenType() || rsym->isUndef() || rsym->isDyn()) { 11696f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 11706f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set GOTRel bit 11716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | GOTRel); 11726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11736f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11746f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set GOT bit 11756f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReserveGOT); 11766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PLT32: 11796f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // A PLT entry is needed when building shared library 11805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 11816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // return if we already create plt for this symbol 11826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->reserved() & ReservePLT) 11836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // if the symbol's value can be decided at link time, then no need plt 11866f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolFinalValueIsKnown(*rsym)) 11876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // if symbol is defined in the ouput file and it's not 11906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // preemptible, no need plt 11916f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (rsym->isDefine() && !rsym->isDyn() && 11926f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines !isSymbolPreemptible(*rsym)) { 11936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 11946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 11956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 11966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 11976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // and the corresponding GOT and dynamic relocation entry 11986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 11996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // when calling X86PLT->reserveEntry()) 12006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT->reserveEntry(); 12016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->reserve(); 12026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelPLT->reserveEntry(); 12036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set PLT bit 12046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 12056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 12066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC32: 12086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC16: 12096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines case llvm::ELF::R_X86_64_PC8: 12106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (symbolNeedsPLT(*rsym) && 12116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LinkerConfig::DynObj != config().codeGenType()) { 12126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // create plt for this symbol if it does not have one 12136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!(rsym->reserved() & ReservePLT)){ 12146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Symbol needs PLT entry, we need to reserve a PLT entry 12156f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // and the corresponding GOT and dynamic relocation entry 12166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // in .got and .rel.plt. (GOT entry will be reserved simultaneously 12176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // when calling X86PLT->reserveEntry()) 12186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT->reserveEntry(); 12196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->reserve(); 12206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelPLT->reserveEntry(); 12216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set PLT bit 12226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines rsym->setReserved(rsym->reserved() | ReservePLT); 12236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 12246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 12256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // Only PC relative relocation against dynamic symbol needs a 12276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // dynamic relocation. Only dynamic copy relocation is allowed 12286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // and PC relative relocation will be resolved to the local copy. 12296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // All other dynamic relocations may lead to run-time relocation 12306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // overflow. 12316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (isDynamicSymbol(*rsym) && 12326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines symbolNeedsDynRel(*rsym, (rsym->reserved() & ReservePLT), false) && 12336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines symbolNeedsCopyReloc(pReloc, *rsym)) { 12346f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pRelDyn->reserveEntry(); 12356f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym); 12366f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines addCopyReloc(*cpy_sym.resolveInfo()); 12376f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 12386f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return; 12396f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12406f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines default: 12416f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines fatal(diag::unsupported_relocation) << (int)pReloc.type() 12426f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines << "mclinker@googlegroups.com"; 12436f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines break; 12446f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } // end switch 12455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12476f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::initTargetSections(Module& pModule, 12486f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ObjectBuilder& pBuilder) 124922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 125022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao if (LinkerConfig::Object != config().codeGenType()) { 125122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao ELFFileFormat* file_format = getOutputFormat(); 125222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // initialize .got 125322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& got = file_format->getGOT(); 12546f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT = new X86_64GOT(got); 125522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 125622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // initialize .got.plt 125722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& gotplt = file_format->getGOTPLT(); 12586f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT = new X86_64GOTPLT(gotplt); 125922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 126022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao // initialize .plt 126122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao LDSection& plt = file_format->getPLT(); 12626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pPLT = new X86_64PLT(plt, 12636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *m_pGOTPLT, 12646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines config()); 126522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao 12666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .rela.plt 12676f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& relplt = file_format->getRelaPlt(); 126822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao relplt.setLink(&plt); 1269d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelPLT = new OutputRelocSection(pModule, relplt); 1270d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 12716f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // initialize .rela.dyn 12726f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines LDSection& reldyn = file_format->getRelaDyn(); 1273d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao m_pRelDyn = new OutputRelocSection(pModule, reldyn); 1274d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao 127522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12786f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesvoid X86_64GNULDBackend::setGOTSectionSize(IRBuilder& pBuilder) 127922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao{ 12806f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .got.plt size 12816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (LinkerConfig::DynObj == config().codeGenType() || 12826f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->hasGOT1() || 12836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines NULL != m_pGOTSymbol) { 12846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->finalizeSectionSize(); 12856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines defineGOTSymbol(pBuilder, *(m_pGOTPLT->begin())); 128622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao } 12876f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12886f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines // set .got size 12896f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (!m_pGOT->empty()) 12906f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOT->finalizeSectionSize(); 12915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 12925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 12936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86_64GNULDBackend::emitGOTSectionData(MemoryRegion& pRegion) const 12945460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 12956f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_pGOT && "emitGOTSectionData failed, m_pGOT is NULL!"); 12966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12976f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer()); 12986f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 12996f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* got = 0; 13006f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int EntrySize = X86_64GOTEntry::EntrySize; 13016f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t RegionSize = 0; 13026f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13036f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines for (X86_64GOT::iterator it = m_pGOT->begin(), 13046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ie = m_pGOT->end(); it != ie; ++it, ++buffer) { 13056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got = &(llvm::cast<X86_64GOTEntry>((*it))); 13066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *buffer = static_cast<uint64_t>(got->getValue()); 13076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += EntrySize; 13086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 13096f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return RegionSize; 13115460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 13125460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesuint64_t X86_64GNULDBackend::emitGOTPLTSectionData(MemoryRegion& pRegion, 13146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines const ELFFileFormat* FileFormat) const 1315affc150dc44fab1911775a49636d0ce85333b634Zonr Chang{ 13166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert(m_pGOTPLT && "emitGOTPLTSectionData failed, m_pGOTPLT is NULL!"); 13176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->applyGOT0(FileFormat->getDynamic().addr()); 13186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines m_pGOTPLT->applyAllGOTPLT(*m_pPLT); 13196f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t* buffer = reinterpret_cast<uint64_t*>(pRegion.getBuffer()); 13216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines X86_64GOTEntry* got = 0; 13236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines unsigned int EntrySize = X86_64GOTEntry::EntrySize; 13246f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines uint64_t RegionSize = 0; 13256f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines for (X86_64GOTPLT::iterator it = m_pGOTPLT->begin(), 13276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines ie = m_pGOTPLT->end(); it != ie; ++it, ++buffer) { 13286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines got = &(llvm::cast<X86_64GOTEntry>((*it))); 13296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines *buffer = static_cast<uint64_t>(got->getValue()); 13306f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines RegionSize += EntrySize; 13316f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines } 13326f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines 13336f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return RegionSize; 13345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 13355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liaonamespace mcld { 13375460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===// 13395460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createX86LDBackend - the help funtion to create corresponding X86LDBackend 13405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// 13415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei LiaoTargetLDBackend* createX86LDBackend(const llvm::Target& pTarget, 134222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao const LinkerConfig& pConfig) 13435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao{ 1344d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (pConfig.targets().triple().isOSDarwin()) { 13455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "MachO linker is not supported yet"); 13465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /** 13475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return new X86MachOLDBackend(createX86MachOArchiveReader, 13485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao createX86MachOObjectReader, 13495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao createX86MachOObjectWriter); 13505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao **/ 13515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 1352d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao if (pConfig.targets().triple().isOSWindows()) { 13535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao assert(0 && "COFF linker is not supported yet"); 13545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao /** 13555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao return new X86COFFLDBackend(createX86COFFArchiveReader, 13565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao createX86COFFObjectReader, 13575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao createX86COFFObjectWriter); 13585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao **/ 13595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao } 13606f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines Triple::ArchType arch = pConfig.targets().triple().getArch(); 13616f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines if (arch == Triple::x86) 13626f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return new X86_32GNULDBackend(pConfig, 13636f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines new X86_32GNUInfo(pConfig.targets().triple())); 13646f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines assert (arch == Triple::x86_64); 13656f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines return new X86_64GNULDBackend(pConfig, 13666f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines new X86_64GNUInfo(pConfig.targets().triple())); 13675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 13685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 13695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} // namespace of mcld 13705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao 137122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 13725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization. 137322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===// 137422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoextern "C" void MCLDInitializeX86LDBackend() { 13755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao // Register the linker backend 13766f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_32Target, createX86LDBackend); 13776f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines mcld::TargetRegistry::RegisterTargetLDBackend(TheX86_64Target, createX86LDBackend); 13785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao} 1379