1affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===- EhFrame.cpp --------------------------------------------------------===//
2affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
3affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//                     The MCLinker Project
4affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
5affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// This file is distributed under the University of Illinois Open Source
6affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// License. See LICENSE.TXT for details.
7affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//
8affc150dc44fab1911775a49636d0ce85333b634Zonr Chang//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/EhFrame.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/Relocation.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSymbol.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/RelocData.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ResolveInfo.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/GCFactory.h"
216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines#include <llvm/Support/ManagedStatic.h>
23cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
25affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinestypedef GCFactory<EhFrame, MCLD_SECTIONS_PER_INPUT> EhFrameFactory;
276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hinesstatic llvm::ManagedStatic<EhFrameFactory> g_EhFrameFactory;
296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
3022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// EhFrame::Record
3222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
3337b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::Record::Record(llvm::StringRef pRegion) : RegionFragment(pRegion) {
3422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
35cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
3637b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::Record::~Record() {
37f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // llvm::iplist will manage and delete the fragments
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// EhFrame::CIE
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesEhFrame::CIE::CIE(llvm::StringRef pRegion)
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : EhFrame::Record(pRegion),
4537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_FDEEncode(0u),
4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_Mergeable(false),
4737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pReloc(0),
4837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_PersonalityOffset(0) {
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
5137b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::CIE::~CIE() {
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
5422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
5522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// EhFrame::FDE
5622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesEhFrame::FDE::FDE(llvm::StringRef pRegion, EhFrame::CIE& pCIE)
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : EhFrame::Record(pRegion), m_pCIE(&pCIE) {
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
6137b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::FDE::~FDE() {
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::FDE::setCIE(EhFrame::CIE& pCIE) {
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_pCIE = &pCIE;
66f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_pCIE->add(*this);
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// EhFrame::GeneratedCIE
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen HinesEhFrame::GeneratedCIE::GeneratedCIE(llvm::StringRef pRegion)
7337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : EhFrame::CIE(pRegion) {
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
7637b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::GeneratedCIE::~GeneratedCIE() {
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// EhFrame::GeneratedFDE
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
8237b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::GeneratedFDE::GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE)
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : EhFrame::FDE(pRegion, pCIE) {
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
8637b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::GeneratedFDE::~GeneratedFDE() {
8722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao}
88affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
8922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
90affc150dc44fab1911775a49636d0ce85333b634Zonr Chang// EhFrame
9122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
9237b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::EhFrame() : m_pSection(NULL), m_pSectionData(NULL) {
936f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
946f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
9522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei LiaoEhFrame::EhFrame(LDSection& pSection)
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : m_pSection(&pSection), m_pSectionData(NULL) {
9722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_pSectionData = SectionData::Create(pSection);
98affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
99affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
10037b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame::~EhFrame() {
101affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
102affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
10337b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame* EhFrame::Create(LDSection& pSection) {
1046f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  EhFrame* result = g_EhFrameFactory->allocate();
1056f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  new (result) EhFrame(pSection);
1066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return result;
1076f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1086f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
10937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::Destroy(EhFrame*& pSection) {
1106f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pSection->~EhFrame();
1116f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  g_EhFrameFactory->deallocate(pSection);
1126f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  pSection = NULL;
1136f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1146f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::Clear() {
1166f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  g_EhFrameFactory->clear();
1176f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1186f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst LDSection& EhFrame::getSection() const {
12037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pSection != NULL);
1216f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pSection;
1226f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1236f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12437b74a387bb3993387029859c2d9d051c41c724eStephen HinesLDSection& EhFrame::getSection() {
12537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pSection != NULL);
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  return *m_pSection;
1276f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines}
1286f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::addFragment(Fragment& pFrag) {
13022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint32_t offset = 0;
13122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (!m_pSectionData->empty())
13222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    offset = m_pSectionData->back().getOffset() + m_pSectionData->back().size();
133affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
13422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  m_pSectionData->getFragmentList().push_back(&pFrag);
135f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pFrag.setParent(m_pSectionData);
13622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  pFrag.setOffset(offset);
137affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
138affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::addCIE(EhFrame::CIE& pCIE, bool pAlsoAddFragment) {
140f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  m_CIEs.push_back(&pCIE);
141f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pAlsoAddFragment)
142f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    addFragment(pCIE);
143f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
144f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::addFDE(EhFrame::FDE& pFDE, bool pAlsoAddFragment) {
146f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pFDE.getCIE().add(pFDE);
147f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pAlsoAddFragment)
148f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    addFragment(pFDE);
149affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
150affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t EhFrame::numOfFDEs() const {
152f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // FDE number only used by .eh_frame_hdr computation, and the number of CIE
153f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // is usually not too many. It is worthy to compromise space by time
154f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  size_t size = 0u;
155f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (const_cie_iterator i = cie_begin(), e = cie_end(); i != e; ++i)
156f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    size += (*i)->numOfFDEs();
157f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return size;
158affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
159affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
16037b74a387bb3993387029859c2d9d051c41c724eStephen HinesEhFrame& EhFrame::merge(const Input& pInput, EhFrame& pFrame) {
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(this != &pFrame);
162f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pFrame.emptyCIEs()) {
163f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // May be a partial linking, or the eh_frame has no data.
164f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Just append the fragments.
165f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    moveInputFragments(pFrame);
166f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return *this;
167f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
168affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
169f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const LDContext& ctx = *pInput.context();
170f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const LDSection* rel_sec = 0;
171f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (LDContext::const_sect_iterator ri = ctx.relocSectBegin(),
17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      re = ctx.relocSectEnd();
17337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ri != re;
17437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++ri) {
175f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if ((*ri)->getLink() == &pFrame.getSection()) {
176f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      rel_sec = *ri;
177f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      break;
178f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
179f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
180f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pFrame.setupAttributes(rel_sec);
181affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
182f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // Most CIE will be merged, so we don't reserve space first.
183f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (cie_iterator i = pFrame.cie_begin(), e = pFrame.cie_end(); i != e; ++i) {
184f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    CIE& input_cie = **i;
185f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // CIE number is usually very few, so we just use vector sequential search.
186f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (!input_cie.getMergeable()) {
187f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      moveInputFragments(pFrame, input_cie);
188f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      addCIE(input_cie, /*AlsoAddFragment=*/false);
189f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      continue;
190f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
191affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
192f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    cie_iterator out_i = cie_begin();
193f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (cie_iterator out_e = cie_end(); out_i != out_e; ++out_i) {
194f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      CIE& output_cie = **out_i;
195f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (output_cie == input_cie) {
196f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // This input CIE can be merged
197f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        moveInputFragments(pFrame, input_cie, &output_cie);
198f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        removeAndUpdateCIEForFDE(pFrame, input_cie, output_cie, rel_sec);
199f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
200f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
201f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
202f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (out_i == cie_end()) {
203f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      moveInputFragments(pFrame, input_cie);
204f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      addCIE(input_cie, /*AlsoAddFragment=*/false);
205f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
206f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
20722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  return *this;
208affc150dc44fab1911775a49636d0ce85333b634Zonr Chang}
209affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
21037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::setupAttributes(const LDSection* rel_sec) {
211f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (cie_iterator i = cie_begin(), e = cie_end(); i != e; ++i) {
212f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    CIE* cie = *i;
213f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    removeDiscardedFDE(*cie, rel_sec);
214f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
215f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (cie->getPersonalityName().size() == 0) {
216f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      // There's no personality data encoding inside augmentation string.
217f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      cie->setMergeable();
218f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    } else {
219f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (!rel_sec) {
220f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        // No relocation to eh_frame section
22137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        assert(cie->getPersonalityName() != "" &&
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hines               "PR name should be a symbol address or offset");
223f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        continue;
224f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
225f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      const RelocData* reloc_data = rel_sec->getRelocData();
226f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      for (RelocData::const_iterator ri = reloc_data->begin(),
22737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     re = reloc_data->end();
22837b74a387bb3993387029859c2d9d051c41c724eStephen Hines           ri != re;
22937b74a387bb3993387029859c2d9d051c41c724eStephen Hines           ++ri) {
230f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        const Relocation& rel = *ri;
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        if (rel.targetRef().getOutputOffset() ==
23237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            cie->getOffset() + cie->getPersonalityOffset()) {
233f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          cie->setMergeable();
234f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          cie->setPersonalityName(rel.symInfo()->outSymbol()->name());
235f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          cie->setRelocation(rel);
236f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          break;
237f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        }
238f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
239f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(cie->getPersonalityName() != "" &&
24137b74a387bb3993387029859c2d9d051c41c724eStephen Hines             "PR name should be a symbol address or offset");
242f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
243f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
244f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
245f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
24637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocSect) {
247f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!pRelocSect)
248f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return;
249f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
250f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  typedef std::vector<FDE*> FDERemoveList;
251f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  FDERemoveList to_be_removed_fdes;
252f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  const RelocData* reloc_data = pRelocSect->getRelocData();
253f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (fde_iterator i = pCIE.begin(), e = pCIE.end(); i != e; ++i) {
254f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    FDE& fde = **i;
255f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (RelocData::const_iterator ri = reloc_data->begin(),
25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   re = reloc_data->end();
25737b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ri != re;
25837b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ++ri) {
259f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      const Relocation& rel = *ri;
26037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      if (rel.targetRef().getOutputOffset() ==
26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          fde.getOffset() + getDataStartOffset<32>()) {
262f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        bool has_section = rel.symInfo()->outSymbol()->hasFragRef();
263f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        if (!has_section)
264f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // The section was discarded, just ignore this FDE.
265f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          // This may happen when redundant group section was read.
266f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          to_be_removed_fdes.push_back(&fde);
267f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        break;
268f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
269f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
270f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
271f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
272f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (FDERemoveList::iterator i = to_be_removed_fdes.begin(),
27337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               e = to_be_removed_fdes.end();
27437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       i != e;
27537b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++i) {
276f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    FDE& fde = **i;
277f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    fde.getCIE().remove(fde);
278f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
279f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // FIXME: This traverses relocations from the beginning on each FDE, which
280f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // may cause performance degration. Actually relocations will be sequential
281f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // order, so we can bookkeep the previously found relocation for next use.
282f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Note: We must ensure FDE order is ordered.
283f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (RelocData::const_iterator ri = reloc_data->begin(),
28437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                   re = reloc_data->end();
28537b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ri != re;) {
286f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      Relocation& rel = const_cast<Relocation&>(*ri++);
287f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      if (rel.targetRef().getOutputOffset() >= fde.getOffset() &&
288f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines          rel.targetRef().getOutputOffset() < fde.getOffset() + fde.size()) {
289f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines        const_cast<RelocData*>(reloc_data)->remove(rel);
290f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      }
291f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
292f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
293f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
294f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
29537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::removeAndUpdateCIEForFDE(EhFrame& pInFrame,
29637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       CIE& pInCIE,
29737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       CIE& pOutCIE,
29837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       const LDSection* rel_sect) {
299f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // Make this relocation to be ignored.
300f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  Relocation* rel = const_cast<Relocation*>(pInCIE.getRelocation());
301f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (rel && rel_sect)
302f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    const_cast<RelocData*>(rel_sect->getRelocData())->remove(*rel);
303f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
304f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // Update the CIE-pointed FDEs
305f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i)
306f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    (*i)->setCIE(pOutCIE);
307f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
308f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // We cannot know whether there are references to this fragment, so just
309f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // keep it in input fragment list instead of memory deallocation
310f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pInCIE.clearFDEs();
311f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
312f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
31337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::moveInputFragments(EhFrame& pInFrame) {
314f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData& in_sd = *pInFrame.getSectionData();
315f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList();
316f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData& out_sd = *getSectionData();
317f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList();
318f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
319f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  while (!in_frag_list.empty()) {
320f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Fragment* frag = in_frag_list.remove(in_frag_list.begin());
321f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    out_frag_list.push_back(frag);
322f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    frag->setParent(&out_sd);
323f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
324f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
325f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
32637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid EhFrame::moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE) {
327f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData& in_sd = *pInFrame.getSectionData();
328f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData::FragmentListType& in_frag_list = in_sd.getFragmentList();
329f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData& out_sd = *getSectionData();
330f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData::FragmentListType& out_frag_list = out_sd.getFragmentList();
331f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
332f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (!pOutCIE) {
333f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Newly inserted
334f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Fragment* frag = in_frag_list.remove(SectionData::iterator(pInCIE));
335f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    out_frag_list.push_back(frag);
336f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    frag->setParent(&out_sd);
337f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
338f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      frag = in_frag_list.remove(SectionData::iterator(**i));
339f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      out_frag_list.push_back(frag);
340f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      frag->setParent(&out_sd);
341f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    }
342f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return;
343f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
344f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
345f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  SectionData::iterator cur_iter(*pOutCIE);
34637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(cur_iter != out_frag_list.end());
347f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  for (fde_iterator i = pInCIE.begin(), e = pInCIE.end(); i != e; ++i) {
348f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Fragment* frag = in_frag_list.remove(SectionData::iterator(**i));
349f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    cur_iter = out_frag_list.insertAfter(cur_iter, frag);
350f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    frag->setParent(&out_sd);
351f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
352f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
353f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
35437b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t EhFrame::computeOffsetSize() {
355f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  size_t offset = 0u;
35637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  SectionData::FragmentListType& frag_list =
35737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      getSectionData()->getFragmentList();
35837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  for (SectionData::iterator i = frag_list.begin(), e = frag_list.end(); i != e;
35937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++i) {
360f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    Fragment& frag = *i;
361f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    frag.setOffset(offset);
362f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    offset += frag.size();
363f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
364f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  getSection().setSize(offset);
365f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return offset;
366f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
367f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
36837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool operator==(const EhFrame::CIE& p1, const EhFrame::CIE& p2) {
369f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return p1.getPersonalityName() == p2.getPersonalityName() &&
370f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines         p1.getAugmentationData() == p2.getAugmentationData();
371f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
37237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
37337b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
374