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 20using namespace mcld; 21 22static llvm::ManagedStatic<RelocationFactory> g_RelocationFactory; 23 24//===----------------------------------------------------------------------===// 25// Relocation Factory Methods 26//===----------------------------------------------------------------------===// 27/// Initialize - set up the relocation factory 28void Relocation::SetUp(const LinkerConfig& pConfig) 29{ 30 g_RelocationFactory->setConfig(pConfig); 31} 32 33/// Clear - Clean up the relocation factory 34void Relocation::Clear() 35{ 36 g_RelocationFactory->clear(); 37} 38 39/// Create - produce an empty relocation entry 40Relocation* 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 49Relocation* 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 55void Relocation::Destroy(Relocation*& pRelocation) 56{ 57 g_RelocationFactory->destroy(pRelocation); 58 pRelocation = NULL; 59} 60 61//===----------------------------------------------------------------------===// 62// Relocation 63//===----------------------------------------------------------------------===// 64Relocation::Relocation() 65 : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) { 66} 67 68Relocation::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 81Relocation::~Relocation() 82{ 83} 84 85Relocation::Address Relocation::place() const 86{ 87 Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr(); 88 return sect_addr + m_TargetAddress.getOutputOffset(); 89} 90 91Relocation::Address Relocation::symValue() const 92{ 93 if (m_pSymInfo->type() == ResolveInfo::Section && 94 m_pSymInfo->outSymbol()->hasFragRef()) { 95 return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr(); 96 } 97 return m_pSymInfo->outSymbol()->value(); 98} 99 100void Relocation::apply(Relocator& pRelocator) 101{ 102 Relocator::Result result = pRelocator.applyRelocation(*this); 103 104 switch (result) { 105 case Relocator::OK: { 106 // do nothing 107 return; 108 } 109 case Relocator::Overflow: { 110 error(diag::result_overflow) << pRelocator.getName(type()) 111 << symInfo()->name(); 112 return; 113 } 114 case Relocator::BadReloc: { 115 error(diag::result_badreloc) << pRelocator.getName(type()) 116 << symInfo()->name(); 117 return; 118 } 119 case Relocator::Unsupport: { 120 fatal(diag::unsupported_relocation) << type() 121 << "mclinker@googlegroups.com"; 122 return; 123 } 124 case Relocator::Unknown: { 125 fatal(diag::unknown_relocation) << type() << symInfo()->name(); 126 return; 127 } 128 } // end of switch 129} 130 131void Relocation::setType(Type pType) 132{ 133 m_Type = pType; 134} 135 136void Relocation::setAddend(Address pAddend) 137{ 138 m_Addend = pAddend; 139} 140 141void Relocation::setSymInfo(ResolveInfo* pSym) 142{ 143 m_pSymInfo = pSym; 144} 145 146Relocation::Size Relocation::size(Relocator& pRelocator) const 147{ 148 return pRelocator.getSize(m_Type); 149} 150 151void Relocation::updateAddend() 152{ 153 // Update value keep in addend if we meet a section symbol 154 if (m_pSymInfo->type() == ResolveInfo::Section) { 155 uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset(); 156 m_Addend += offset; 157 } 158} 159 160