1 //===- Relocation.cpp -----------------------------------------------------===// 2 // 3 // The MCLinker Project 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include <mcld/Fragment/Relocation.h> 10 #include <mcld/LD/Relocator.h> 11 #include <mcld/LD/ResolveInfo.h> 12 #include <mcld/LD/LDSymbol.h> 13 #include <mcld/LD/LDSection.h> 14 #include <mcld/LD/SectionData.h> 15 #include <mcld/Support/MsgHandling.h> 16 #include <mcld/LD/RelocationFactory.h> 17 18 #include <llvm/Support/ManagedStatic.h> 19 20 using namespace mcld; 21 22 static llvm::ManagedStatic<RelocationFactory> g_RelocationFactory; 23 24 //===----------------------------------------------------------------------===// 25 // Relocation Factory Methods 26 //===----------------------------------------------------------------------===// 27 /// Initialize - set up the relocation factory 28 void Relocation::SetUp(const LinkerConfig& pConfig) 29 { 30 g_RelocationFactory->setConfig(pConfig); 31 } 32 33 /// Clear - Clean up the relocation factory 34 void Relocation::Clear() 35 { 36 g_RelocationFactory->clear(); 37 } 38 39 /// Create - produce an empty relocation entry 40 Relocation* Relocation::Create() 41 { 42 return g_RelocationFactory->produceEmptyEntry(); 43 } 44 45 /// Create - produce a relocation entry 46 /// @param pType [in] the type of the relocation entry 47 /// @param pFragRef [in] the place to apply the relocation 48 /// @param pAddend [in] the addend of the relocation entry 49 Relocation* Relocation::Create(Type pType, FragmentRef& pFragRef, Address pAddend) 50 { 51 return g_RelocationFactory->produce(pType, pFragRef, pAddend); 52 } 53 54 /// Destroy - destroy a relocation entry 55 void Relocation::Destroy(Relocation*& pRelocation) 56 { 57 g_RelocationFactory->destroy(pRelocation); 58 pRelocation = NULL; 59 } 60 61 //===----------------------------------------------------------------------===// 62 // Relocation 63 //===----------------------------------------------------------------------===// 64 Relocation::Relocation() 65 : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) { 66 } 67 68 Relocation::Relocation(Relocation::Type pType, 69 FragmentRef* pTargetRef, 70 Relocation::Address pAddend, 71 Relocation::DWord pTargetData) 72 : m_Type(pType), 73 m_TargetData(pTargetData), 74 m_pSymInfo(NULL), 75 m_Addend(pAddend) 76 { 77 if(NULL != pTargetRef) 78 m_TargetAddress.assign(*pTargetRef->frag(), pTargetRef->offset()) ; 79 } 80 81 Relocation::~Relocation() 82 { 83 } 84 85 Relocation::Address Relocation::place() const 86 { 87 Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr(); 88 return sect_addr + m_TargetAddress.getOutputOffset(); 89 } 90 91 Relocation::Address Relocation::symValue() const 92 { 93 if (m_pSymInfo->type() == ResolveInfo::Section && 94 m_pSymInfo->outSymbol()->hasFragRef()) { 95 const FragmentRef* fragRef = m_pSymInfo->outSymbol()->fragRef(); 96 return fragRef->frag()->getParent()->getSection().addr() + 97 fragRef->getOutputOffset(); 98 } 99 return m_pSymInfo->outSymbol()->value(); 100 } 101 102 void Relocation::apply(Relocator& pRelocator) 103 { 104 Relocator::Result result = pRelocator.applyRelocation(*this); 105 106 switch (result) { 107 case Relocator::OK: { 108 // do nothing 109 return; 110 } 111 case Relocator::Overflow: { 112 error(diag::result_overflow) << pRelocator.getName(type()) 113 << symInfo()->name(); 114 return; 115 } 116 case Relocator::BadReloc: { 117 error(diag::result_badreloc) << pRelocator.getName(type()) 118 << symInfo()->name(); 119 return; 120 } 121 case Relocator::Unsupport: { 122 fatal(diag::unsupported_relocation) << type() 123 << "mclinker (at) googlegroups.com"; 124 return; 125 } 126 case Relocator::Unknown: { 127 fatal(diag::unknown_relocation) << type() << symInfo()->name(); 128 return; 129 } 130 } // end of switch 131 } 132 133 void Relocation::setType(Type pType) 134 { 135 m_Type = pType; 136 } 137 138 void Relocation::setAddend(Address pAddend) 139 { 140 m_Addend = pAddend; 141 } 142 143 void Relocation::setSymInfo(ResolveInfo* pSym) 144 { 145 m_pSymInfo = pSym; 146 } 147 148 Relocation::Size Relocation::size(Relocator& pRelocator) const 149 { 150 return pRelocator.getSize(m_Type); 151 } 152 153 void Relocation::updateAddend() 154 { 155 // Update value keep in addend if we meet a section symbol 156 if (m_pSymInfo->type() == ResolveInfo::Section) { 157 uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset(); 158 m_Addend += offset; 159 } 160 } 161