Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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 | |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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 | |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 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 | |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 34 | void ARMExData::addInputMap(Input* pInput, |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 35 | std::unique_ptr<ARMInputExMap> pExMap) { |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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 | |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 52 | std::unique_ptr<ARMExData> ARMExData::create(Module& pModule) { |
| 53 | std::unique_ptr<ARMExData> exData(new ARMExData()); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 54 | for (Module::obj_iterator it = pModule.obj_begin(), |
| 55 | end = pModule.obj_end(); it != end; ++it) { |
| 56 | Input* input = *it; |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 57 | exData->addInputMap(input, ARMInputExMap::create(*input)); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 58 | } |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 59 | return exData; |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 60 | } |
| 61 | |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 62 | std::unique_ptr<ARMInputExMap> ARMInputExMap::create(Input& pInput) { |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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; |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 70 | if (sect->type() == llvm::ELF::SHT_ARM_EXIDX) { |
| 71 | ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(*sect); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 72 | exTuple->setExIdxSection(sect); |
| 73 | exTuple->setTextSection(sect->getLink()); |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 74 | if (sect->getLink() == NULL) { |
| 75 | fatal(diag::eh_missing_text_section) << sect->name() << pInput.name(); |
| 76 | } |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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(); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 94 | // Remove this tuple from the input exception map. |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 95 | ARMInputExMap::iterator deadIt = it++; |
| 96 | exMap->erase(deadIt); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 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); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 103 | |
| 104 | exTuple->setTextFragment(textFrag); |
| 105 | exTuple->setExIdxFragment(exIdxFrag); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 106 | |
| 107 | // If there is no region fragment in the .ARM.extab section, then we can |
| 108 | // skip this tuple. |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 109 | if (exIdxFrag == NULL) { |
| 110 | ARMInputExMap::iterator deadIt = it++; |
| 111 | exMap->erase(deadIt); |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 112 | continue; |
| 113 | } |
| 114 | |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 115 | // Check next tuple |
| 116 | ++it; |
| 117 | } |
| 118 | |
Stephen Hines | cfcb224 | 2016-03-08 00:18:09 -0800 | [diff] [blame^] | 119 | return exMap; |
Stephen Hines | a6c24df | 2015-03-18 14:53:18 -0700 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | } // namespace mcld |