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     return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
     96   }
     97   return m_pSymInfo->outSymbol()->value();
     98 }
     99 
    100 void 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 (at) 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 
    131 void Relocation::setType(Type pType)
    132 {
    133   m_Type = pType;
    134 }
    135 
    136 void Relocation::setAddend(Address pAddend)
    137 {
    138   m_Addend = pAddend;
    139 }
    140 
    141 void Relocation::setSymInfo(ResolveInfo* pSym)
    142 {
    143   m_pSymInfo = pSym;
    144 }
    145 
    146 Relocation::Size Relocation::size(Relocator& pRelocator) const
    147 {
    148   return pRelocator.getSize(m_Type);
    149 }
    150 
    151 void 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