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 
     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