| //===- ARMException.cpp ---------------------------------------------------===// |
| // |
| // The MCLinker Project |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "ARMException.h" |
| |
| #include "ARMLDBackend.h" |
| |
| #include "mcld/Fragment/RegionFragment.h" |
| #include "mcld/LD/ELFFileFormat.h" |
| #include "mcld/LD/LDContext.h" |
| #include "mcld/Support/MsgHandling.h" |
| |
| #include <memory> |
| |
| namespace mcld { |
| |
| static RegionFragment* findRegionFragment(LDSection& pSection) { |
| SectionData* sectData = pSection.getSectionData(); |
| for (SectionData::iterator it = sectData->begin(), |
| end = sectData->end(); it != end; ++it) { |
| if (it->getKind() == Fragment::Region) { |
| return static_cast<RegionFragment*>(&*it); |
| } |
| } |
| return NULL; |
| } |
| |
| void ARMExData::addInputMap(Input* pInput, |
| std::unique_ptr<ARMInputExMap> pExMap) { |
| assert(m_Inputs.find(pInput) == m_Inputs.end() && |
| "multiple maps for an input"); |
| |
| ARMInputExMap* exMap = pExMap.get(); |
| |
| // Add mapping to the input-to-exdata map. |
| m_Inputs.insert(std::make_pair(pInput, std::move(pExMap))); |
| |
| // Add mapping to the fragment-to-exdata map. |
| for (ARMInputExMap::iterator it = exMap->begin(), end = exMap->end(); |
| it != end; ++it) { |
| ARMExSectionTuple* exTuple = it->second.get(); |
| m_ExIdxToTuple[exTuple->getExIdxFragment()] = exTuple; |
| } |
| } |
| |
| std::unique_ptr<ARMExData> ARMExData::create(Module& pModule) { |
| std::unique_ptr<ARMExData> exData(new ARMExData()); |
| for (Module::obj_iterator it = pModule.obj_begin(), |
| end = pModule.obj_end(); it != end; ++it) { |
| Input* input = *it; |
| exData->addInputMap(input, ARMInputExMap::create(*input)); |
| } |
| return exData; |
| } |
| |
| std::unique_ptr<ARMInputExMap> ARMInputExMap::create(Input& pInput) { |
| std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap()); |
| |
| // Scan the input and collect all related sections. |
| LDContext* ctx = pInput.context(); |
| for (LDContext::sect_iterator it = ctx->sectBegin(), |
| end = ctx->sectEnd(); it != end; ++it) { |
| LDSection* sect = *it; |
| if (sect->type() == llvm::ELF::SHT_ARM_EXIDX) { |
| ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(*sect); |
| exTuple->setExIdxSection(sect); |
| exTuple->setTextSection(sect->getLink()); |
| if (sect->getLink() == NULL) { |
| fatal(diag::eh_missing_text_section) << sect->name() << pInput.name(); |
| } |
| } |
| } |
| |
| // Remove the invalid exception tuples and convert LDSection to RegionFragment |
| // or RelocData. |
| ARMInputExMap::iterator it = exMap->begin(); |
| ARMInputExMap::iterator end = exMap->end(); |
| while (it != end) { |
| ARMExSectionTuple* exTuple = it->second.get(); |
| LDSection* const text = exTuple->getTextSection(); |
| LDSection* const exIdx = exTuple->getExIdxSection(); |
| |
| // Ignore the exception section if the text section is ignored. |
| if ((text->kind() == LDFileFormat::Ignore) || |
| (text->kind() == LDFileFormat::Folded)) { |
| // Set the related exception sections as LDFileFormat::Ignore. |
| exIdx->setKind(LDFileFormat::Ignore); |
| // Remove this tuple from the input exception map. |
| ARMInputExMap::iterator deadIt = it++; |
| exMap->erase(deadIt); |
| continue; |
| } |
| |
| // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections. |
| RegionFragment* textFrag = findRegionFragment(*text); |
| RegionFragment* exIdxFrag = findRegionFragment(*exIdx); |
| |
| exTuple->setTextFragment(textFrag); |
| exTuple->setExIdxFragment(exIdxFrag); |
| |
| // If there is no region fragment in the .ARM.extab section, then we can |
| // skip this tuple. |
| if (exIdxFrag == NULL) { |
| ARMInputExMap::iterator deadIt = it++; |
| exMap->erase(deadIt); |
| continue; |
| } |
| |
| // Check next tuple |
| ++it; |
| } |
| |
| return exMap; |
| } |
| |
| } // namespace mcld |