blob: 96afbdebe72d9b140b96f8f44513a187e5f326d3 [file] [log] [blame]
//===- 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 <llvm/ADT/PointerUnion.h>
#include <llvm/ADT/StringRef.h>
#include <map>
#include <memory>
#include <string>
namespace mcld {
class Fragment;
class Input;
class LDSection;
class RegionFragment;
class RelocData;
/// ARMExSectionTuple - Tuple of associated exception handling sections
class ARMExSectionTuple {
public:
ARMExSectionTuple()
: m_pTextSection(NULL),
m_pExIdxSection(NULL),
m_pExTabSection(NULL),
m_pRelExIdxSection(NULL),
m_pRelExTabSection(NULL) {
}
LDSection* getTextSection() const {
return m_pTextSection;
}
LDSection* getExIdxSection() const {
return m_pExIdxSection;
}
LDSection* getExTabSection() const {
return m_pExTabSection;
}
LDSection* getRelExIdxSection() const {
return m_pRelExIdxSection;
}
LDSection* getRelExTabSection() const {
return m_pRelExTabSection;
}
void setTextSection(LDSection* pSection) {
m_pTextSection = pSection;
}
void setExIdxSection(LDSection* pSection) {
m_pExIdxSection = pSection;
}
void setExTabSection(LDSection* pSection) {
m_pExTabSection = pSection;
}
void setRelExIdxSection(LDSection* pSection) {
m_pRelExIdxSection = pSection;
}
void setRelExTabSection(LDSection* pSection) {
m_pRelExTabSection = pSection;
}
RegionFragment* getTextFragment() const {
return m_pTextFragment;
}
RegionFragment* getExIdxFragment() const {
return m_pExIdxFragment;
}
RegionFragment* getExTabFragment() const {
return m_pExTabFragment;
}
RelocData* getExIdxRelocData() const {
return m_pExIdxRelocData;
}
RelocData* getExTabRelocData() const {
return m_pExTabRelocData;
}
void setTextFragment(RegionFragment* pFragment) {
m_pTextFragment = pFragment;
}
void setExIdxFragment(RegionFragment* pFragment) {
m_pExIdxFragment = pFragment;
}
void setExTabFragment(RegionFragment* pFragment) {
m_pExTabFragment = pFragment;
}
void setExIdxRelocData(RelocData* pRelocData) {
m_pExIdxRelocData = pRelocData;
}
void setExTabRelocData(RelocData* pRelocData) {
m_pExTabRelocData = pRelocData;
}
private:
// .text section
union {
LDSection* m_pTextSection;
RegionFragment* m_pTextFragment;
};
// .ARM.exidx section
union {
LDSection* m_pExIdxSection;
RegionFragment* m_pExIdxFragment;
};
// .ARM.extab section
union {
LDSection* m_pExTabSection;
RegionFragment* m_pExTabFragment;
};
// .rel.ARM.exidx section
union {
LDSection* m_pRelExIdxSection;
RelocData* m_pExIdxRelocData;
};
// .rel.ARM.extab section
union {
LDSection* m_pRelExTabSection;
RelocData* m_pExTabRelocData;
};
};
/// ARMInputExMap - ARM exception handling data of an Input
class ARMInputExMap {
public:
typedef std::map<std::string, std::unique_ptr<ARMExSectionTuple> > NameMap;
typedef NameMap::iterator iterator;
typedef NameMap::const_iterator const_iterator;
public:
ARMInputExMap() { }
/// get - Get the ARMExSectionTuple by the corresponding text section name.
/// As an exception, to get the ARMExSectionTuple for .text section, use ""
/// as the section name instead.
ARMExSectionTuple* get(const char* pName) const {
NameMap::const_iterator it = m_NameToExData.find(pName);
if (it == m_NameToExData.end()) {
return NULL;
}
return it->second.get();
}
ARMExSectionTuple* getByExSection(llvm::StringRef pName) const {
assert((pName.startswith(".ARM.exidx") ||
pName.startswith(".ARM.extab")) &&
"Not a .ARM.exidx section name");
return get(pName.data() + sizeof(".ARM.ex***") - 1);
}
ARMExSectionTuple* getByRelExSection(llvm::StringRef pName) const {
assert((pName.startswith(".rel.ARM.exidx") ||
pName.startswith(".rel.ARM.extab")) &&
"Not a .rel.ARM.exidx section name");
return get(pName.data() + sizeof(".rel.ARM.ex***") - 1);
}
/// getOrCreate - Get an existing or create a new ARMExSectionTuple which is
/// associated with the text section name. As an exception, use "" as the
/// section name for .text section.
ARMExSectionTuple* getOrCreate(const char* pName) {
std::unique_ptr<ARMExSectionTuple>& result = m_NameToExData[pName];
if (!result) {
result.reset(new ARMExSectionTuple());
}
return result.get();
}
ARMExSectionTuple* getOrCreateByExSection(llvm::StringRef pName) {
assert((pName.startswith(".ARM.exidx") ||
pName.startswith(".ARM.extab")) &&
"Not a .ARM.exidx section name");
return getOrCreate(pName.data() + sizeof(".ARM.ex***") - 1);
}
ARMExSectionTuple* getOrCreateByRelExSection(llvm::StringRef pName) {
assert((pName.startswith(".rel.ARM.exidx") ||
pName.startswith(".rel.ARM.extab")) &&
"Not a .rel.ARM.exidx section name");
return getOrCreate(pName.data() + sizeof(".rel.ARM.ex***") - 1);
}
/// begin - return the iterator to the begin of the map
iterator begin() { return m_NameToExData.begin(); }
const_iterator begin() const { return m_NameToExData.begin(); }
/// end - return the iterator to the end of the map
iterator end() { return m_NameToExData.end(); }
const_iterator end() const { return m_NameToExData.end(); }
/// erase - remove an entry from the map
void erase(iterator it) { m_NameToExData.erase(it); }
private:
NameMap m_NameToExData;
};
/// ARMExData - ARM exception handling data of a module
class ARMExData {
private:
typedef std::map<Input*, std::unique_ptr<ARMInputExMap> > InputMap;
typedef std::map<const Fragment*, ARMExSectionTuple*> ExIdxMap;
public:
ARMExData() { }
// 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:
// 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_