1//===- Stub.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/Stub.h"
10
11#include "mcld/IRBuilder.h"
12#include "mcld/Fragment/Relocation.h"
13#include "mcld/LD/BranchIsland.h"
14#include "mcld/LD/ResolveInfo.h"
15
16#include <cassert>
17
18namespace mcld {
19
20Stub::Stub() : Fragment(Fragment::Stub), m_pSymInfo(NULL) {
21}
22
23Stub::~Stub() {
24  for (fixup_iterator fixup = fixup_begin(); fixup != fixup_end(); ++fixup)
25    delete (*fixup);
26}
27
28void Stub::setSymInfo(ResolveInfo* pSymInfo) {
29  m_pSymInfo = pSymInfo;
30}
31
32void Stub::applyFixup(Relocation& pSrcReloc,
33                      IRBuilder& pBuilder,
34                      BranchIsland& pIsland) {
35  // build a name for stub symbol
36  std::string sym_name("__");
37  sym_name.append(pSrcReloc.symInfo()->name())
38          .append("_")
39          .append(name())
40          .append("@")
41          .append(pIsland.name());
42
43  // create LDSymbol for the stub
44  LDSymbol* symbol =
45      pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
46          sym_name,
47          ResolveInfo::Function,
48          ResolveInfo::Define,
49          ResolveInfo::Local,
50          size(),
51          initSymValue(),
52          FragmentRef::Create(*this, initSymValue()),
53          ResolveInfo::Default);
54  setSymInfo(symbol->resolveInfo());
55
56  // add relocations of this stub (i.e., set the branch target of the stub)
57  for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) {
58    Relocation* reloc =
59        Relocation::Create((*it)->type(),
60                           *(FragmentRef::Create(*this, (*it)->offset())),
61                           (*it)->addend());
62    reloc->setSymInfo(pSrcReloc.symInfo());
63    pIsland.addRelocation(*reloc);
64  }
65}
66
67void Stub::applyFixup(FragmentRef& pSrcFragRef,
68                      IRBuilder& pBuilder,
69                      BranchIsland& pIsland) {
70  // If applying fixups is based on the source FragmentRef, each target stub
71  // probably should override this function.
72  assert(0 && "target stub should override this function");
73}
74
75void Stub::addFixup(DWord pOffset, SWord pAddend, Type pType) {
76  assert(pOffset < size());
77  m_FixupList.push_back(new Fixup(pOffset, pAddend, pType));
78}
79
80void Stub::addFixup(const Fixup& pFixup) {
81  assert(pFixup.offset() < size());
82  m_FixupList.push_back(new Fixup(pFixup));
83}
84
85}  // namespace mcld
86