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