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 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 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 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 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