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