• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SetUp(const LinkerConfig & pConfig)28 void Relocation::SetUp(const LinkerConfig& pConfig)
29 {
30   g_RelocationFactory->setConfig(pConfig);
31 }
32 
33 /// Clear - Clean up the relocation factory
Clear()34 void Relocation::Clear()
35 {
36   g_RelocationFactory->clear();
37 }
38 
39 /// Create - produce an empty relocation entry
Create()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
Create(Type pType,FragmentRef & pFragRef,Address pAddend)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
Destroy(Relocation * & pRelocation)55 void Relocation::Destroy(Relocation*& pRelocation)
56 {
57   g_RelocationFactory->destroy(pRelocation);
58   pRelocation = NULL;
59 }
60 
61 //===----------------------------------------------------------------------===//
62 // Relocation
63 //===----------------------------------------------------------------------===//
Relocation()64 Relocation::Relocation()
65   : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) {
66 }
67 
Relocation(Relocation::Type pType,FragmentRef * pTargetRef,Relocation::Address pAddend,Relocation::DWord pTargetData)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 
~Relocation()81 Relocation::~Relocation()
82 {
83 }
84 
place() const85 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 
symValue() const91 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 
apply(Relocator & pRelocator)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@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 
setType(Type pType)133 void Relocation::setType(Type pType)
134 {
135   m_Type = pType;
136 }
137 
setAddend(Address pAddend)138 void Relocation::setAddend(Address pAddend)
139 {
140   m_Addend = pAddend;
141 }
142 
setSymInfo(ResolveInfo * pSym)143 void Relocation::setSymInfo(ResolveInfo* pSym)
144 {
145   m_pSymInfo = pSym;
146 }
147 
size(Relocator & pRelocator) const148 Relocation::Size Relocation::size(Relocator& pRelocator) const
149 {
150   return pRelocator.getSize(m_Type);
151 }
152 
updateAddend()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