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