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
2204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hinesstatic const char g_CantUnwindEntry[8] = {
2304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Relocation to text section.
2404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  0, 0, 0, 0,
2504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // EXIDX_CANTUNWIND (little endian.)
2604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  1, 0, 0, 0,
2704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines};
2804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
29a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesnamespace mcld {
30a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
31a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMExData::addInputMap(Input* pInput,
32a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                            std::unique_ptr<ARMInputExMap>&& pExMap) {
33a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  assert(m_Inputs.find(pInput) == m_Inputs.end() &&
34a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines         "multiple maps for an input");
35a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
36a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap* exMap = pExMap.get();
37a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
38a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add mapping to the input-to-exdata map.
39a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  m_Inputs.insert(std::make_pair(pInput, std::move(pExMap)));
40a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
41a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add mapping to the fragment-to-exdata map.
42a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end();
43a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines       it != end; ++it) {
44a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* exTuple = it->second.get();
45a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple;
46a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
47a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
48a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
49a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule) {
50a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (Module::obj_iterator it = pModule.obj_begin(),
51a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                            end = pModule.obj_end(); it != end; ++it) {
52a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Input* input = *it;
53a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    scanInputExceptionSections(pModule, *input);
54a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
55a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
56a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
57a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesstatic RegionFragment* findRegionFragment(LDSection& pSection) {
58a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData* sectData = pSection.getSectionData();
59a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (SectionData::iterator it = sectData->begin(),
60a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                             end = sectData->end(); it != end; ++it) {
61a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (it->getKind() == Fragment::Region) {
62a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      return static_cast<RegionFragment*>(&*it);
63a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
64a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
65a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  return NULL;
66a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
67a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
68a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::scanInputExceptionSections(Module& pModule,
69a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                                 Input& pInput) {
70a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap());
71a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
72a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Scan the input and collect all related sections.
73a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  LDContext* ctx = pInput.context();
74a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (LDContext::sect_iterator it = ctx->sectBegin(),
75a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                end = ctx->sectEnd(); it != end; ++it) {
76a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* sect = *it;
77a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    llvm::StringRef name(sect->name());
78a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
79a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (name.startswith(".ARM.exidx")) {
80a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
81a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setExIdxSection(sect);
82a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setTextSection(sect->getLink());
83a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".ARM.extab")) {
84a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name);
85a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setExTabSection(sect);
86a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".rel.ARM.exidx")) {
87a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
88a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setRelExIdxSection(sect);
89a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    } else if (name.startswith(".rel.ARM.extab")) {
90a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name);
91a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exTuple->setRelExIdxSection(sect);
92a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
93a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
94a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
95a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Remove the invalid exception tuples and convert LDSection to RegionFragment
96a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // or RelocData.
97a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap::iterator it = exMap->begin();
98a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  ARMInputExMap::iterator end = exMap->end();
99a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  while (it != end) {
100a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* exTuple = it->second.get();
101a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const text = exTuple->getTextSection();
102a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const exIdx = exTuple->getExIdxSection();
103a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const exTab = exTuple->getExTabSection();
104a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const relExIdx = exTuple->getRelExIdxSection();
105a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    LDSection* const relExTab = exTuple->getRelExTabSection();
106a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
107a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check the .ARM.exidx section.
108a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!exIdx) {
109a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      if (exTab) {
110a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name();
111a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else if (relExIdx) {
112a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << relExIdx->name()
113a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                              << pInput.name();
114a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else if (relExTab) {
115a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        fatal(diag::eh_missing_exidx_section) << relExTab->name()
116a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                                              << pInput.name();
117a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      } else {
118a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        llvm_unreachable("unexpected bad exception tuple");
119a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
120a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
121a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
122a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check the text section.
123a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!text) {
124a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name();
125a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
126a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
127a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Ignore the exception section if the text section is ignored.
128a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if ((text->kind() == LDFileFormat::Ignore) ||
129a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        (text->kind() == LDFileFormat::Folded)) {
130a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Set the related exception sections as LDFileFormat::Ignore.
131a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exIdx->setKind(LDFileFormat::Ignore);
132a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      if (exTab) {
133a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines        exTab->setKind(LDFileFormat::Ignore);
134a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      }
135a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      // Remove this tuple from the input exception map.
136a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exMap->erase(it++);
137a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      continue;
138a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
139a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
140a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections.
141a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* textFrag = findRegionFragment(*text);
142a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* exIdxFrag = findRegionFragment(*exIdx);
143a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL;
144a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
145a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setTextFragment(textFrag);
146a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExIdxFragment(exIdxFrag);
147a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExTabFragment(exTabFrag);
148a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
149a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections.
150a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL;
151a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL;
152a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
153a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExIdxRelocData(exIdxRD);
154a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    exTuple->setExTabRelocData(exTabRD);
155a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
156a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // If there is no region fragment in the .ARM.extab section, then we can
157a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // skip this tuple.
158a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    if (!exIdxFrag) {
159a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      exMap->erase(it++);
160a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      continue;
161a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    }
162a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
163a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // TODO: Sort the RelocData w.r.t. the fixup offset.
164a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
165a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Check next tuple
166a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ++it;
167a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
168a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
169a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Add input map
170a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  m_ExData.addInputMap(&pInput, std::move(exMap));
171a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
172a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
173a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesclass ExIdxFragmentComparator {
174a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines private:
175a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  const ARMExData& m_ExData;
176a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
177a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines public:
17804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  explicit ExIdxFragmentComparator(const ARMExData& pExData)
179a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines      : m_ExData(pExData) {
180a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
181a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
182a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  bool operator()(const Fragment& a, const Fragment& b) {
183a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* tupleA = m_ExData.getTupleByExIdx(&a);
184a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    ARMExSectionTuple* tupleB = m_ExData.getTupleByExIdx(&b);
185a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
186a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Fragment* textFragA = tupleA->getTextFragment();
187a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    Fragment* textFragB = tupleB->getTextFragment();
188a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
189a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    uint64_t addrA = textFragA->getParent()->getSection().addr() +
190a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                     textFragA->getOffset();
191a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    uint64_t addrB = textFragB->getParent()->getSection().addr() +
192a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines                     textFragB->getOffset();
193a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    return (addrA < addrB);
194a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
195a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines};
196a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
19704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hinesstatic mcld::ResolveInfo*
19804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen HinesCreateLocalSymbolToFragmentEnd(mcld::Module& pModule, mcld::Fragment& pFrag) {
19904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Create and add symbol to the name pool.
20004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  mcld::ResolveInfo* resolveInfo =
20104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      pModule.getNamePool().createSymbol(/* pName */"",
20204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         /* pIsDyn */false,
20304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         mcld::ResolveInfo::Section,
20404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         mcld::ResolveInfo::Define,
20504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         mcld::ResolveInfo::Local,
20604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         /* pSize */0,
20704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                         mcld::ResolveInfo::Hidden);
20804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  if (resolveInfo == nullptr) {
20904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    return nullptr;
21004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  }
21104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
21204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Create input symbol.
21304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  mcld::LDSymbol* inputSym = mcld::LDSymbol::Create(*resolveInfo);
21404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  if (inputSym == nullptr) {
21504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    return nullptr;
21604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  }
21704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
21804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  inputSym->setFragmentRef(mcld::FragmentRef::Create(pFrag, pFrag.size()));
21904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  inputSym->setValue(/* pValue */0);
22004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
22104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // The output symbol is simply an alias to the input symbol.
22204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  resolveInfo->setSymPtr(inputSym);
22304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
22404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  return resolveInfo;
22504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines}
22604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
227a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hinesvoid ARMGNULDBackend::rewriteARMExIdxSection(Module& pModule) {
228a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  if (!m_pEXIDX->hasSectionData()) {
229a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    // Return if this is empty section.
230a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    return;
231a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
232a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
233a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData* sectData = m_pEXIDX->getSectionData();
234a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData::FragmentListType& list = sectData->getFragmentList();
235a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
23604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Move the first fragment (align fragment) and last fragment (null fragment)
23704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // to temporary list because we would only like to sort the region fragment.
238a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  SectionData::FragmentListType tmp;
239a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  {
240a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    SectionData::iterator first = sectData->begin();
241a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    SectionData::iterator last = sectData->end();
242a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    --last;
243a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
244a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    assert(first->getKind() == Fragment::Alignment);
245a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    assert(last->getKind() == Fragment::Null);
246a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
247a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    tmp.splice(tmp.end(), list, first);
248a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    tmp.splice(tmp.end(), list, last);
249a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
250a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
251a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Sort the region fragments in the .ARM.exidx output section.
252a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  sort(list, ExIdxFragmentComparator(m_ExData));
253a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
25404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Fix the coverage of the .ARM.exidx table.
25504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  llvm::StringRef cantUnwindRegion(g_CantUnwindEntry,
25604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                                   sizeof(g_CantUnwindEntry));
25704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
25804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  SectionData::FragmentListType::iterator it = list.begin();
25904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  if (it != list.end()) {
26004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    Fragment* prevTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
26104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    uint64_t prevTextEnd = prevTextFrag->getParent()->getSection().addr() +
26204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                           prevTextFrag->getOffset() +
26304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                           prevTextFrag->size();
26404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    ++it;
26504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    while (it != list.end()) {
26604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      Fragment* currTextFrag = m_ExData.getTupleByExIdx(it)->getTextFragment();
26704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      uint64_t currTextBegin = currTextFrag->getParent()->getSection().addr() +
26804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                               currTextFrag->getOffset();
26904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
27004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      if (currTextBegin > prevTextEnd) {
27104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        // Found a gap. Insert a can't unwind entry.
27204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
27304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        frag->setParent(sectData);
27404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        list.insert(it, frag);
27504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
27604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        // Add PREL31 reference to the beginning of the uncovered region.
27704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        Relocation* reloc =
27804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines            Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
27904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                               *FragmentRef::Create(*frag, /* pOffset */0),
28004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                               /* pAddend */0);
28104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        reloc->setSymInfo(
28204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines            CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
28304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        addExtraRelocation(reloc);
28404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      }
28504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
28604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      prevTextEnd = currTextBegin + currTextFrag->size();
28704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      prevTextFrag = currTextFrag;
28804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines      ++it;
28904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    }
29004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
29104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    // Add a can't unwind entry to terminate .ARM.exidx section.
29204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    RegionFragment* frag = new RegionFragment(cantUnwindRegion, nullptr);
29304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    frag->setParent(sectData);
29404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    list.push_back(frag);
29504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
29604c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    // Add PREL31 reference to the end of the .text section.
29704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    Relocation* reloc =
29804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines        Relocation::Create(static_cast<uint32_t>(llvm::ELF::R_ARM_PREL31),
29904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                           *FragmentRef::Create(*frag, /* pOffset */0),
30004c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines                           /* pAddend */0);
30104c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    reloc->setSymInfo(CreateLocalSymbolToFragmentEnd(pModule, *prevTextFrag));
30204c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines    addExtraRelocation(reloc);
30304c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  }
30404c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
30504c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Add the first and the last fragment back.
306a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  list.splice(list.begin(), tmp, tmp.begin());
307a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  list.splice(list.end(), tmp, tmp.begin());
308a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
309a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Update the fragment offsets.
310a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  uint64_t offset = 0;
311a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  for (SectionData::iterator it = sectData->begin(), end = sectData->end();
312a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines       it != end; ++it) {
313a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    it->setOffset(offset);
314a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines    offset += it->size();
315a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  }
316a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
31704c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  // Update the section size.
31804c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines  m_pEXIDX->setSize(offset);
31904c59f3b00def22b7c75f5a490c323cec58a7c71Stephen Hines
320a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  // Rebuild the section header.
321a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines  setOutputSectionAddress(pModule);
322a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}
323a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines
324a6c24dff8b7fa2551a3a885e77a2e814f5b764a2Stephen Hines}  // namespace mcld
325