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
10#include <mcld/LD/Relocation.h>
11#include <mcld/LD/RelocationFactory.h>
12#include <mcld/LD/Layout.h>
13#include <mcld/Support/MsgHandling.h>
14
15using namespace mcld;
16
17Relocation::Relocation(Relocation::Type pType,
18                       FragmentRef* pTargetRef,
19                       Relocation::Address pAddend,
20                       Relocation::DWord pTargetData)
21  : Fragment(Fragment::Relocation),
22    m_Type(pType),
23    m_TargetData(pTargetData),
24    m_pSymInfo(NULL),
25    m_Addend(pAddend)
26{
27  if(NULL != pTargetRef)
28     m_TargetAddress.assign(*pTargetRef->frag(), pTargetRef->offset()) ;
29}
30
31Relocation::~Relocation()
32{
33}
34
35Relocation::Address Relocation::place(const Layout& pLayout) const
36{
37  Address sect_addr = pLayout.getOutputLDSection(*(m_TargetAddress.frag()))->addr();
38  return sect_addr + pLayout.getOutputOffset(m_TargetAddress);
39}
40
41Relocation::Address Relocation::symValue() const
42{
43  if (m_pSymInfo->type() == ResolveInfo::Section &&
44     m_pSymInfo->outSymbol()->hasFragRef()) {
45    return m_pSymInfo->outSymbol()->fragRef()->frag()->getParent()->getSection().addr();
46  }
47  return m_pSymInfo->outSymbol()->value();
48}
49
50void Relocation::apply(RelocationFactory& pRelocFactory,
51                       const MCLDInfo& pLDInfo)
52{
53  RelocationFactory::Result result =
54                                 pRelocFactory.applyRelocation(*this, pLDInfo);
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  } // end of switch
77}
78
79void Relocation::setType(Type pType)
80{
81  m_Type = pType;
82}
83
84void Relocation::setAddend(Address pAddend)
85{
86  m_Addend = pAddend;
87}
88
89void Relocation::setSymInfo(ResolveInfo* pSym)
90{
91  m_pSymInfo = pSym;
92}
93
94Relocation::DWord& Relocation::target()
95{
96  return m_TargetData;
97}
98
99const Relocation::DWord& Relocation::target() const
100{
101  return m_TargetData;
102}
103
104