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