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