summaryrefslogtreecommitdiff
path: root/lib/LD/EhFrame.cpp
blob: 9d496302872d5405cacb93c1db51365e2764b8e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//===- EhFrame.cpp --------------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/LD/EhFrame.h>
#include <mcld/LD/LDSection.h>
#include <mcld/LD/SectionData.h>
#include <mcld/Object/ObjectBuilder.h>
#include <mcld/Support/MemoryRegion.h>
#include <mcld/Support/GCFactory.h>

#include <llvm/Support/ManagedStatic.h>

using namespace mcld;

typedef GCFactory<EhFrame, MCLD_SECTIONS_PER_INPUT> EhFrameFactory;

static llvm::ManagedStatic<EhFrameFactory> g_EhFrameFactory;

//===----------------------------------------------------------------------===//
// EhFrame::CIE
//===----------------------------------------------------------------------===//
EhFrame::CIE::CIE(MemoryRegion& pRegion)
  : RegionFragment(pRegion) {
}

//===----------------------------------------------------------------------===//
// EhFrame::FDE
//===----------------------------------------------------------------------===//
EhFrame::FDE::FDE(MemoryRegion& pRegion,
                  const EhFrame::CIE& pCIE,
                  uint32_t pDataStart)
  : RegionFragment(pRegion),
    m_CIE(pCIE),
    m_DataStart(pDataStart) {
}

//===----------------------------------------------------------------------===//
// EhFrame
//===----------------------------------------------------------------------===//
EhFrame::EhFrame()
  : m_pSection(NULL), m_pSectionData(NULL) {
}

EhFrame::EhFrame(LDSection& pSection)
  : m_pSection(&pSection),
    m_pSectionData(NULL) {
  m_pSectionData = SectionData::Create(pSection);
}

EhFrame::~EhFrame()
{
  // Since all CIEs, FDEs and regular fragments are stored in iplist, iplist
  // will delete the fragments and we do not need to handle with it.
}

EhFrame* EhFrame::Create(LDSection& pSection)
{
  EhFrame* result = g_EhFrameFactory->allocate();
  new (result) EhFrame(pSection);
  return result;
}

void EhFrame::Destroy(EhFrame*& pSection)
{
  pSection->~EhFrame();
  g_EhFrameFactory->deallocate(pSection);
  pSection = NULL;
}

void EhFrame::Clear()
{
  g_EhFrameFactory->clear();
}

const LDSection& EhFrame::getSection() const
{
  assert(NULL != m_pSection);
  return *m_pSection;
}

LDSection& EhFrame::getSection()
{
  assert(NULL != m_pSection);
  return *m_pSection;
}

void EhFrame::addFragment(RegionFragment& pFrag)
{
  uint32_t offset = 0;
  if (!m_pSectionData->empty())
    offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();

  m_pSectionData->getFragmentList().push_back(&pFrag);
  pFrag.setOffset(offset);
}

void EhFrame::addCIE(EhFrame::CIE& pCIE)
{
  m_CIEs.push_back(&pCIE);
  addFragment(pCIE);
}

void EhFrame::addFDE(EhFrame::FDE& pFDE)
{
  m_FDEs.push_back(&pFDE);
  addFragment(pFDE);
}

EhFrame& EhFrame::merge(EhFrame& pOther)
{
  ObjectBuilder::MoveSectionData(pOther.getSectionData(), *m_pSectionData);

  m_CIEs.reserve(pOther.numOfCIEs() + m_CIEs.size());
  for (cie_iterator cie = pOther.cie_begin(); cie != pOther.cie_end(); ++cie)
    m_CIEs.push_back(*cie);

  m_FDEs.reserve(pOther.numOfFDEs() + m_FDEs.size());
  for (fde_iterator fde = pOther.fde_begin(); fde != pOther.fde_end(); ++fde)
    m_FDEs.push_back(*fde);

  pOther.m_CIEs.clear();
  pOther.m_FDEs.clear();
  return *this;
}