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
SetUp(const LinkerConfig & pConfig)29 void Relocation::SetUp(const LinkerConfig& pConfig) {
30 g_RelocationFactory->setConfig(pConfig);
31 }
32
33 /// Clear - Clean up the relocation factory
Clear()34 void Relocation::Clear() {
35 g_RelocationFactory->clear();
36 }
37
38 /// Create - produce an empty relocation entry
Create()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
Create(Type pType,FragmentRef & pFragRef,Address pAddend)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
Destroy(Relocation * & pRelocation)54 void Relocation::Destroy(Relocation*& pRelocation) {
55 g_RelocationFactory->destroy(pRelocation);
56 pRelocation = NULL;
57 }
58
59 //===----------------------------------------------------------------------===//
60 // Relocation
61 //===----------------------------------------------------------------------===//
Relocation()62 Relocation::Relocation()
63 : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) {
64 }
65
Relocation(Relocation::Type pType,FragmentRef * pTargetRef,Relocation::Address pAddend,Relocation::DWord pTargetData)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
~Relocation()78 Relocation::~Relocation() {
79 }
80
place() const81 Relocation::Address Relocation::place() const {
82 Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
83 return sect_addr + m_TargetAddress.getOutputOffset();
84 }
85
symValue() const86 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
apply(Relocator & pRelocator)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@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
setType(Type pType)126 void Relocation::setType(Type pType) {
127 m_Type = pType;
128 }
129
setAddend(Address pAddend)130 void Relocation::setAddend(Address pAddend) {
131 m_Addend = pAddend;
132 }
133
setSymInfo(ResolveInfo * pSym)134 void Relocation::setSymInfo(ResolveInfo* pSym) {
135 m_pSymInfo = pSym;
136 }
137
size(Relocator & pRelocator) const138 Relocation::Size Relocation::size(Relocator& pRelocator) const {
139 return pRelocator.getSize(m_Type);
140 }
141
updateAddend()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