ARMException.cpp revision a6c24dff8b7fa2551a3a885e77a2e814f5b764a2
1a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//===- ARMException.cpp ---------------------------------------------------===//
2a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//
3a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//                     The MCLinker Project
4a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//
5a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// This file is distributed under the University of Illinois Open Source
6a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines// License. See LICENSE.TXT for details.
7a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//
8a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines//===----------------------------------------------------------------------===//
9a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
10a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "ARMException.h"
11a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
12a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "ARMLDBackend.h"
13a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
14a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/ADT/ilist_sort.h"
15a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/Fragment/RegionFragment.h"
16a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/LD/ELFFileFormat.h"
17a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/LD/LDContext.h"
18a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include "mcld/Support/MsgHandling.h"
19a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
20a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines#include <memory>
21a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
22a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesnamespace mcld {
23a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
24a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMExData::addInputMap(Input* pInput,
25a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                            std::unique_ptr<ARMInputExMap>&& pExMap) {
26a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  assert(m_Inputs.find(pInput) == m_Inputs.end() &&
27a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines         "multiple maps for an input");
28a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
29a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap* exMap = pExMap.get();
30a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
31a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add mapping to the input-to-exdata map.
32a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  m_Inputs.insert(std::make_pair(pInput, std::move(pExMap)));
33a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
34a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add mapping to the fragment-to-exdata map.
35a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end();
36a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines       it != end; ++it) {
37a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* exTuple = it->second.get();
38a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple;
39a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
40a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
41a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
42a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule) {
43a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (Module::obj_iterator it = pModule.obj_begin(),
44a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                            end = pModule.obj_end(); it != end; ++it) {
45a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Input* input = *it;
46a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    scanInputExceptionSections(pModule, *input);
47a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
48a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
49a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
50a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesstatic RegionFragment* findRegionFragment(LDSection& pSection) {
51a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData* sectData = pSection.getSectionData();
52a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (SectionData::iterator it = sectData->begin(),
53a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                             end = sectData->end(); it != end; ++it) {
54a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (it->getKind() == Fragment::Region) {
55a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      return static_cast<RegionFragment*>(&*it);
56a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
57a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
58a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  return NULL;
59a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
60a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
61a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule,
62a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                                 Input& pInput) {
63a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap());
64a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
65a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Scan the input and collect all related sections.
66a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  LDContext* ctx = pInput.context();
67a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (LDContext::sect_iterator it = ctx->sectBegin(),
68a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                end = ctx->sectEnd(); it != end; ++it) {
69a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* sect = *it;
70a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    llvm::StringRef name(sect->name());
71a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
72a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (name.startswith(".ARM.exidx")) {
73a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
74a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setExIdxSection(sect);
75a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setTextSection(sect->getLink());
76a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".ARM.extab")) {
77a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
78a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setExTabSection(sect);
79a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".rel.ARM.exidx")) {
80a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
81a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setRelExIdxSection(sect);
82a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".rel.ARM.extab")) {
83a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
84a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setRelExIdxSection(sect);
85a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
86a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
87a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
88a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Remove the invalid exception tuples and convert LDSection to RegionFragment
89a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // or RelocData.
90a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap::iterator it = exMap->begin();
91a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap::iterator end = exMap->end();
92a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  while (it != end) {
93a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* exTuple = it->second.get();
94a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const text = exTuple->getTextSection();
95a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const exIdx = exTuple->getExIdxSection();
96a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const exTab = exTuple->getExTabSection();
97a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const relExIdx = exTuple->getRelExIdxSection();
98a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const relExTab = exTuple->getRelExTabSection();
99a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
100a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check the .ARM.exidx section.
101a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!exIdx) {
102a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      if (exTab) {
103a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name();
104a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else if (relExIdx) {
105a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << relExIdx->name()
106a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                              << pInput.name();
107a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else if (relExTab) {
108a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << relExTab->name()
109a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                              << pInput.name();
110a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else {
111a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        llvm_unreachable("unexpected bad exception tuple");
112a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
113a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
114a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
115a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check the text section.
116a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!text) {
117a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name();
118a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
119a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
120a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Ignore the exception section if the text section is ignored.
121a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if ((text->kind() == LDFileFormat::Ignore) ||
122a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        (text->kind() == LDFileFormat::Folded)) {
123a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Set the related exception sections as LDFileFormat::Ignore.
124a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exIdx->setKind(LDFileFormat::Ignore);
125a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      if (exTab) {
126a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        exTab->setKind(LDFileFormat::Ignore);
127a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
128a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Remove this tuple from the input exception map.
129a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exMap->erase(it++);
130a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      continue;
131a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
132a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
133a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections.
134a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* textFrag = findRegionFragment(*text);
135a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* exIdxFrag = findRegionFragment(*exIdx);
136a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL;
137a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
138a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setTextFragment(textFrag);
139a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExIdxFragment(exIdxFrag);
140a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExTabFragment(exTabFrag);
141a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
142a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections.
143a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL;
144a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL;
145a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
146a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExIdxRelocData(exIdxRD);
147a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExTabRelocData(exTabRD);
148a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
149a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // If there is no region fragment in the .ARM.extab section, then we can
150a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // skip this tuple.
151a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!exIdxFrag) {
152a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exMap->erase(it++);
153a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      continue;
154a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
155a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
156a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // TODO: Sort the RelocData w.r.t. the fixup offset.
157a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
158a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check next tuple
159a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ++it;
160a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
161a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
162a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add input map
163a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  m_ExData.addInputMap(&pInput, std::move(exMap));
164a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
165a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
166a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesclass ExIdxFragmentComparator {
167a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines private:
168a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  const ARMExData& m_ExData;
169a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
170a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines public:
171a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ExIdxFragmentComparator(const ARMExData& pExData)
172a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      : m_ExData(pExData) {
173a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
174a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
175a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  bool operator()(const Fragment& a, const Fragment& b) {
176a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* tupleA = m_ExData.getTupleByExIdx(&a);
177a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* tupleB = m_ExData.getTupleByExIdx(&b);
178a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
179a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Fragment* textFragA = tupleA->getTextFragment();
180a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Fragment* textFragB = tupleB->getTextFragment();
181a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
182a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    uint64_t addrA = textFragA->getParent()->getSection().addr() +
183a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                     textFragA->getOffset();
184a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    uint64_t addrB = textFragB->getParent()->getSection().addr() +
185a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                     textFragB->getOffset();
186a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    return (addrA < addrB);
187a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
188a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines};
189a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
190a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
191a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  if (!m_pEXIDX->hasSectionData()) {
192a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Return if this is empty section.
193a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    return;
194a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
195a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
196a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData* sectData = m_pEXIDX->getSectionData();
197a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData::FragmentListType& list = sectData->getFragmentList();
198a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
199a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Move the first and last fragment to temporary list.
200a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData::FragmentListType tmp;
201a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  {
202a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    SectionData::iterator first = sectData->begin();
203a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    SectionData::iterator last = sectData->end();
204a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    --last;
205a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
206a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    assert(first->getKind() == Fragment::Alignment);
207a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    assert(last->getKind() == Fragment::Null);
208a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
209a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    tmp.splice(tmp.end(), list, first);
210a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    tmp.splice(tmp.end(), list, last);
211a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
212a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
213a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Sort the region fragments in the .ARM.exidx output section.
214a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  sort(list, ExIdxFragmentComparator(m_ExData));
215a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
216a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add the first and last fragment back.
217a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  list.splice(list.begin(), tmp, tmp.begin());
218a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  list.splice(list.end(), tmp, tmp.begin());
219a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
220a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Update the fragment offsets.
221a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  uint64_t offset = 0;
222a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (SectionData::iterator it = sectData->begin(), end = sectData->end();
223a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines       it != end; ++it) {
224a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    it->setOffset(offset);
225a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    offset += it->size();
226a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
227a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
228a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Rebuild the section header.
229a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  setOutputSectionAddress(pModule);
230a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
231a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
232a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}  // namespace mcld
233