You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
3.9 KiB
123 lines
3.9 KiB
//===- 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
|