Home | History | Annotate | Download | only in Fragment
      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