//===- ARMException.h -----------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_ARM_ARMEXCEPTION_H_
#define TARGET_ARM_ARMEXCEPTION_H_
#include "mcld/LD/LDSection.h"
#include <llvm/ADT/PointerUnion.h>
#include <llvm/ADT/StringRef.h>
#include <llvm/Support/ELF.h>
#include <map>
#include <memory>
#include <string>
namespace mcld {
class Fragment;
class Input;
class LDSection;
class Module;
class RegionFragment;
class RelocData;
/// ARMExSectionTuple - Tuple of associated exception handling sections
class ARMExSectionTuple {
public:
ARMExSectionTuple()
: m_pTextSection(NULL),
m_pExIdxSection(NULL) {
}
LDSection* getTextSection() const {
return m_pTextSection;
}
LDSection* getExIdxSection() const {
return m_pExIdxSection;
}
void setTextSection(LDSection* pSection) {
m_pTextSection = pSection;
}
void setExIdxSection(LDSection* pSection) {
m_pExIdxSection = pSection;
}
RegionFragment* getTextFragment() const {
return m_pTextFragment;
}
RegionFragment* getExIdxFragment() const {
return m_pExIdxFragment;
}
void setTextFragment(RegionFragment* pFragment) {
m_pTextFragment = pFragment;
}
void setExIdxFragment(RegionFragment* pFragment) {
m_pExIdxFragment = pFragment;
}
private:
// .text section
union {
LDSection* m_pTextSection;
RegionFragment* m_pTextFragment;
};
// .ARM.exidx section
union {
LDSection* m_pExIdxSection;
RegionFragment* m_pExIdxFragment;
};
};
/// ARMInputExMap - ARM exception handling section mapping of a mcld::Input.
class ARMInputExMap {
public:
typedef std::map<LDSection*, std::unique_ptr<ARMExSectionTuple> > SectMap;
typedef SectMap::iterator iterator;
typedef SectMap::const_iterator const_iterator;
public:
// create - Build the exception handling section mapping of a mcld::Input.
static std::unique_ptr<ARMInputExMap> create(Input &input);
/// getByExSection - Get the ARMExSectionTuple by the address of the
/// .ARM.exidx section.
ARMExSectionTuple* getByExSection(LDSection &pSect) const {
assert(pSect.type() == llvm::ELF::SHT_ARM_EXIDX);
SectMap::const_iterator it = m_SectToExData.find(&pSect);
if (it == m_SectToExData.end()) {
return NULL;
}
return it->second.get();
}
/// getOrCreate - Get an existing or create a new ARMExSectionTuple which is
/// associated with the address of the .ARM.exidx section.
ARMExSectionTuple* getOrCreateByExSection(LDSection &pSect) {
assert(pSect.type() == llvm::ELF::SHT_ARM_EXIDX);
std::unique_ptr<ARMExSectionTuple>& result = m_SectToExData[&pSect];
if (!result) {
result.reset(new ARMExSectionTuple());
}
return result.get();
}
/// begin - return the iterator to the begin of the map
iterator begin() { return m_SectToExData.begin(); }
const_iterator begin() const { return m_SectToExData.begin(); }
/// end - return the iterator to the end of the map
iterator end() { return m_SectToExData.end(); }
const_iterator end() const { return m_SectToExData.end(); }
/// erase - remove an entry from the map
void erase(iterator it) { m_SectToExData.erase(it); }
private:
ARMInputExMap() = default;
private:
SectMap m_SectToExData;
};
/// ARMExData - ARM exception handling data of a mcld::Module.
class ARMExData {
private:
typedef std::map<Input*, std::unique_ptr<ARMInputExMap> > InputMap;
typedef std::map<const Fragment*, ARMExSectionTuple*> ExIdxMap;
public:
// create - Build the exception handling section mapping of a mcld::Module.
static std::unique_ptr<ARMExData> create(Module &module);
// addInputMap - register the ARMInputExMap with associated pInput
void addInputMap(Input* pInput,
std::unique_ptr<ARMInputExMap> pExMap);
// getInputMap - get the ARMInputExMap corresponding to pInput
ARMInputExMap* getInputMap(Input* pInput) const {
InputMap::const_iterator it = m_Inputs.find(pInput);
if (it == m_Inputs.end()) {
return NULL;
}
return it->second.get();
}
// getTupleByExIdx - get the ARMExSectionTuple corresponding to pExIdxFragment
ARMExSectionTuple* getTupleByExIdx(const Fragment* pExIdxFragment) const {
ExIdxMap::const_iterator it = m_ExIdxToTuple.find(pExIdxFragment);
if (it == m_ExIdxToTuple.end()) {
return NULL;
}
return it->second;
}
private:
ARMExData() = default;
private:
// Map from Input to ARMInputExMap
InputMap m_Inputs;
// Map from .ARM.exidx RegionFragment to ARMExSectionTuple
ExIdxMap m_ExIdxToTuple;
};
} // namespace mcld
#endif // TARGET_ARM_ARMEXCEPTION_H_