Relocation.cpp revision d0fbbb227051be16931a1aa9b4a7722ac039c698
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
20using namespace mcld;
21
22static llvm::ManagedStatic<RelocationFactory> g_RelocationFactory;
23
24//===----------------------------------------------------------------------===//
25// Relocation Factory Methods
26//===----------------------------------------------------------------------===//
27/// Initialize - set up the relocation factory
28void Relocation::SetUp(const LinkerConfig& pConfig)
29{
30  g_RelocationFactory->setConfig(pConfig);
31}
32
33/// Clear - Clean up the relocation factory
34void Relocation::Clear()
35{
36  g_RelocationFactory->clear();
37}
38
39/// Create - produce an empty relocation entry
40Relocation* 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
49Relocation* 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
55void Relocation::Destroy(Relocation*& pRelocation)
56{
57  g_RelocationFactory->destroy(pRelocation);
58  pRelocation = NULL;
59}
60
61//===----------------------------------------------------------------------===//
62// Relocation
63//===----------------------------------------------------------------------===//
64Relocation::Relocation()
65  : m_Type(0x0), m_TargetData(0x0), m_pSymInfo(NULL), m_Addend(0x0) {
66}
67
68Relocation::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
81Relocation::~Relocation()
82{
83}
84
85Relocation::Address Relocation::place() const
86{
87  Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
88  return sect_addr + m_TargetAddress.getOutputOffset();
89}
90
91Relocation::Address Relocation::symValue() const
92{
93  if (m_pSymInfo->type() == ResolveInfo::Section &&
94     m_pSymInfo->outSymbol()->hasFragRef()) {
95    return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
96  }
97  return m_pSymInfo->outSymbol()->value();
98}
99
100void Relocation::apply(Relocator& pRelocator)
101{
102  Relocator::Result result = pRelocator.applyRelocation(*this);
103
104  switch (result) {
105    case Relocator::OK: {
106      // do nothing
107      return;
108    }
109    case Relocator::Overflow: {
110      error(diag::result_overflow) << pRelocator.getName(type())
111                                   << symInfo()->name();
112      return;
113    }
114    case Relocator::BadReloc: {
115      error(diag::result_badreloc) << pRelocator.getName(type())
116                                   << symInfo()->name();
117      return;
118    }
119    case Relocator::Unsupport: {
120      fatal(diag::unsupported_relocation) << type()
121                                          << "mclinker@googlegroups.com";
122      return;
123    }
124    case Relocator::Unknown: {
125      fatal(diag::unknown_relocation) << type() << symInfo()->name();
126      return;
127    }
128  } // end of switch
129}
130
131void Relocation::setType(Type pType)
132{
133  m_Type = pType;
134}
135
136void Relocation::setAddend(Address pAddend)
137{
138  m_Addend = pAddend;
139}
140
141void Relocation::setSymInfo(ResolveInfo* pSym)
142{
143  m_pSymInfo = pSym;
144}
145
146size_t Relocation::size() const
147{
148  // TODO: the size of Relocation fragment is handled by backend
149  return 0;
150}
151
152void Relocation::updateAddend()
153{
154  // Update value keep in addend if we meet a section symbol
155  if (m_pSymInfo->type() == ResolveInfo::Section) {
156    uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset();
157    m_Addend += offset;
158  }
159}
160
161