Home | History | Annotate | Download | only in ARM
      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