Relocation.cpp revision 22add6ff3426df1a85089fe6a6e1597ee3b6f300
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/RelocationFactory.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
17using namespace mcld;
18
19Relocation::Relocation(Relocation::Type pType,
20                       FragmentRef* pTargetRef,
21                       Relocation::Address pAddend,
22                       Relocation::DWord pTargetData)
23  : Fragment(Fragment::Relocation),
24    m_Type(pType),
25    m_TargetData(pTargetData),
26    m_pSymInfo(NULL),
27    m_Addend(pAddend)
28{
29  if(NULL != pTargetRef)
30     m_TargetAddress.assign(*pTargetRef->frag(), pTargetRef->offset()) ;
31}
32
33Relocation::~Relocation()
34{
35}
36
37Relocation::Address Relocation::place() const
38{
39  Address sect_addr = m_TargetAddress.frag()->getParent()->getSection().addr();
40  return sect_addr + m_TargetAddress.getOutputOffset();
41}
42
43Relocation::Address Relocation::symValue() const
44{
45  if (m_pSymInfo->type() == ResolveInfo::Section &&
46     m_pSymInfo->outSymbol()->hasFragRef()) {
47    return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
48  }
49  return m_pSymInfo->outSymbol()->value();
50}
51
52void Relocation::apply(RelocationFactory& pRelocFactory)
53{
54  RelocationFactory::Result result = pRelocFactory.applyRelocation(*this);
55
56  switch (result) {
57    case RelocationFactory::OK: {
58      // do nothing
59      return;
60    }
61    case RelocationFactory::Overflow: {
62      error(diag::result_overflow) << pRelocFactory.getName(type())
63                                   << symInfo()->name();
64      return;
65    }
66    case RelocationFactory::BadReloc: {
67      error(diag::result_badreloc) << pRelocFactory.getName(type())
68                                   << symInfo()->name();
69      return;
70    }
71    case RelocationFactory::Unsupport: {
72      fatal(diag::unsupported_relocation) << type()
73                                          << "mclinker@googlegroups.com";
74      return;
75    }
76    case RelocationFactory::Unknown: {
77      fatal(diag::unknown_relocation) << type() << symInfo()->name();
78      return;
79    }
80  } // end of switch
81}
82
83void Relocation::setType(Type pType)
84{
85  m_Type = pType;
86}
87
88void Relocation::setAddend(Address pAddend)
89{
90  m_Addend = pAddend;
91}
92
93void Relocation::setSymInfo(ResolveInfo* pSym)
94{
95  m_pSymInfo = pSym;
96}
97
98size_t Relocation::size() const
99{
100  // TODO: the size of Relocation fragment is handled by backend
101  return 0;
102}
103
104void Relocation::updateAddend()
105{
106  // Update value keep in addend if we meet a section symbol
107  if (m_pSymInfo->type() == ResolveInfo::Section) {
108    uint32_t offset = m_pSymInfo->outSymbol()->fragRef()->getOutputOffset();
109    m_Addend += offset;
110  }
111}
112
113