1 //===- ARMException.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
10 #include "ARMException.h"
11
12 #include "ARMLDBackend.h"
13
14 #include "mcld/Fragment/RegionFragment.h"
15 #include "mcld/LD/ELFFileFormat.h"
16 #include "mcld/LD/LDContext.h"
17 #include "mcld/Support/MsgHandling.h"
18
19 #include <memory>
20
21 namespace mcld {
22
findRegionFragment(LDSection & pSection)23 static RegionFragment* findRegionFragment(LDSection& pSection) {
24 SectionData* sectData = pSection.getSectionData();
25 for (SectionData::iterator it = sectData->begin(),
26 end = sectData->end(); it != end; ++it) {
27 if (it->getKind() == Fragment::Region) {
28 return static_cast<RegionFragment*>(&*it);
29 }
30 }
31 return NULL;
32 }
33
addInputMap(Input * pInput,std::unique_ptr<ARMInputExMap> pExMap)34 void ARMExData::addInputMap(Input* pInput,
35 std::unique_ptr<ARMInputExMap> pExMap) {
36 assert(m_Inputs.find(pInput) == m_Inputs.end() &&
37 "multiple maps for an input");
38
39 ARMInputExMap* exMap = pExMap.get();
40
41 // Add mapping to the input-to-exdata map.
42 m_Inputs.insert(std::make_pair(pInput, std::move(pExMap)));
43
44 // Add mapping to the fragment-to-exdata map.
45 for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end();
46 it != end; ++it) {
47 ARMExSectionTuple* exTuple = it->second.get();
48 m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple;
49 }
50 }
51
create(Module & pModule)52 std::unique_ptr<ARMExData> ARMExData::create(Module& pModule) {
53 std::unique_ptr<ARMExData> exData(new ARMExData());
54 for (Module::obj_iterator it = pModule.obj_begin(),
55 end = pModule.obj_end(); it != end; ++it) {
56 Input* input = *it;
57 exData->addInputMap(input, ARMInputExMap::create(*input));
58 }
59 return exData;
60 }
61
create(Input & pInput)62 std::unique_ptr<ARMInputExMap> ARMInputExMap::create(Input& pInput) {
63 std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap());
64
65 // Scan the input and collect all related sections.
66 LDContext* ctx = pInput.context();
67 for (LDContext::sect_iterator it = ctx->sectBegin(),
68 end = ctx->sectEnd(); it != end; ++it) {
69 LDSection* sect = *it;
70 if (sect->type() == llvm::ELF::SHT_ARM_EXIDX) {
71 ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(*sect);
72 exTuple->setExIdxSection(sect);
73 exTuple->setTextSection(sect->getLink());
74 if (sect->getLink() == NULL) {
75 fatal(diag::eh_missing_text_section) << sect->name() << pInput.name();
76 }
77 }
78 }
79
80 // Remove the invalid exception tuples and convert LDSection to RegionFragment
81 // or RelocData.
82 ARMInputExMap::iterator it = exMap->begin();
83 ARMInputExMap::iterator end = exMap->end();
84 while (it != end) {
85 ARMExSectionTuple* exTuple = it->second.get();
86 LDSection* const text = exTuple->getTextSection();
87 LDSection* const exIdx = exTuple->getExIdxSection();
88
89 // Ignore the exception section if the text section is ignored.
90 if ((text->kind() == LDFileFormat::Ignore) ||
91 (text->kind() == LDFileFormat::Folded)) {
92 // Set the related exception sections as LDFileFormat::Ignore.
93 exIdx->setKind(LDFileFormat::Ignore);
94 // Remove this tuple from the input exception map.
95 ARMInputExMap::iterator deadIt = it++;
96 exMap->erase(deadIt);
97 continue;
98 }
99
100 // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections.
101 RegionFragment* textFrag = findRegionFragment(*text);
102 RegionFragment* exIdxFrag = findRegionFragment(*exIdx);
103
104 exTuple->setTextFragment(textFrag);
105 exTuple->setExIdxFragment(exIdxFrag);
106
107 // If there is no region fragment in the .ARM.extab section, then we can
108 // skip this tuple.
109 if (exIdxFrag == NULL) {
110 ARMInputExMap::iterator deadIt = it++;
111 exMap->erase(deadIt);
112 continue;
113 }
114
115 // Check next tuple
116 ++it;
117 }
118
119 return exMap;
120 }
121
122 } // namespace mcld
123