blob: ef6446d585626b3431d0e25e99d05ab061bfe449 [file] [log] [blame]
//===- EhFrame.h ----------------------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_LD_EHFRAME_H_
#define MCLD_LD_EHFRAME_H_
#include "mcld/Config/Config.h"
#include "mcld/Fragment/RegionFragment.h"
#include "mcld/LD/SectionData.h"
#include "mcld/Support/Allocators.h"
#include "mcld/Support/Compiler.h"
#include <llvm/ADT/StringRef.h>
#include <list>
#include <map>
#include <vector>
namespace mcld {
class Input;
class LDSection;
class Relocation;
/** \class EhFrame
* \brief EhFrame represents .eh_frame section
*/
class EhFrame {
private:
friend class Chunk<EhFrame, MCLD_SECTIONS_PER_INPUT>;
EhFrame();
explicit EhFrame(LDSection& pSection);
~EhFrame();
public:
enum RecordType { RECORD_UNKNOWN, RECORD_INPUT, RECORD_GENERATED };
class CIE;
class FDE;
typedef std::vector<CIE*> CIEList;
typedef CIEList::iterator cie_iterator;
typedef CIEList::const_iterator const_cie_iterator;
typedef std::list<FDE*> FDEList;
typedef FDEList::iterator fde_iterator;
typedef FDEList::const_iterator const_fde_iterator;
typedef std::map</*offset*/ size_t, CIE*> CIEMap;
// A super class of CIE and FDE, containing the same part
class Record : public RegionFragment {
public:
explicit Record(llvm::StringRef pRegion);
virtual ~Record();
const llvm::StringRef getRegion() const {
return RegionFragment::getRegion();
}
llvm::StringRef getRegion() { return RegionFragment::getRegion(); }
virtual RecordType getRecordType() const { return RECORD_UNKNOWN; }
private:
DISALLOW_COPY_AND_ASSIGN(Record);
};
/** \class CIE
* \brief Common Information Entry.
* The CIE structure refers to LSB Core Spec 4.1, chap.10.6. Exception
* Frames.
*/
class CIE : public Record {
public:
explicit CIE(llvm::StringRef pRegion);
~CIE();
virtual RecordType getRecordType() const { return RECORD_INPUT; }
void setFDEEncode(uint8_t pEncode) { m_FDEEncode = pEncode; }
uint8_t getFDEEncode() const { return m_FDEEncode; }
void setMergeable(bool pVal = true) { m_Mergeable = pVal; }
virtual bool getMergeable() const { return m_Mergeable; }
void setRelocation(const Relocation& pReloc) { m_pReloc = &pReloc; }
const Relocation* getRelocation() const { return m_pReloc; }
void setPersonalityOffset(uint64_t pOffset) {
m_PersonalityOffset = pOffset;
}
uint64_t getPersonalityOffset() const { return m_PersonalityOffset; }
void setPersonalityName(const std::string& pStr) {
m_PersonalityName = pStr;
}
const std::string& getPersonalityName() const { return m_PersonalityName; }
void setAugmentationData(const std::string& pStr) {
m_AugmentationData = pStr;
}
const std::string& getAugmentationData() const {
return m_AugmentationData;
}
void add(FDE& pFDE) { m_FDEs.push_back(&pFDE); }
void remove(FDE& pFDE) { m_FDEs.remove(&pFDE); }
void clearFDEs() { m_FDEs.clear(); }
size_t numOfFDEs() const { return m_FDEs.size(); }
const_fde_iterator begin() const { return m_FDEs.begin(); }
fde_iterator begin() { return m_FDEs.begin(); }
const_fde_iterator end() const { return m_FDEs.end(); }
fde_iterator end() { return m_FDEs.end(); }
private:
uint8_t m_FDEEncode;
bool m_Mergeable;
const Relocation* m_pReloc;
uint64_t m_PersonalityOffset;
std::string m_PersonalityName;
std::string m_AugmentationData;
FDEList m_FDEs;
};
/** \class FDE
* \brief Frame Description Entry
* The FDE structure refers to LSB Core Spec 4.1, chap.10.6. Exception
* Frames.
*/
class FDE : public Record {
public:
FDE(llvm::StringRef pRegion, CIE& pCIE);
~FDE();
void setCIE(CIE& pCIE);
const CIE& getCIE() const { return *m_pCIE; }
CIE& getCIE() { return *m_pCIE; }
private:
CIE* m_pCIE; // Referenced CIE may change when merging.
};
// These are created for PLT
class GeneratedCIE : public CIE {
public:
explicit GeneratedCIE(llvm::StringRef pRegion);
~GeneratedCIE();
virtual RecordType getRecordType() const { return RECORD_GENERATED; }
virtual bool getMergeable() const { return true; }
};
class GeneratedFDE : public FDE {
public:
GeneratedFDE(llvm::StringRef pRegion, CIE& pCIE);
~GeneratedFDE();
virtual RecordType getRecordType() const { return RECORD_GENERATED; }
};
public:
static EhFrame* Create(LDSection& pSection);
static void Destroy(EhFrame*& pSection);
static void Clear();
/// merge - move all data from pOther to this object.
EhFrame& merge(const Input& pInput, EhFrame& pInFrame);
const LDSection& getSection() const;
LDSection& getSection();
const SectionData* getSectionData() const { return m_pSectionData; }
SectionData* getSectionData() { return m_pSectionData; }
// ----- fragment ----- //
void addFragment(Fragment& pFrag);
/// addCIE - add a CIE entry in EhFrame
void addCIE(CIE& pCIE, bool pAlsoAddFragment = true);
/// addFDE - add a FDE entry in EhFrame
void addFDE(FDE& pFDE, bool pAlsoAddFragment = true);
// ----- CIE ----- //
const_cie_iterator cie_begin() const { return m_CIEs.begin(); }
cie_iterator cie_begin() { return m_CIEs.begin(); }
const_cie_iterator cie_end() const { return m_CIEs.end(); }
cie_iterator cie_end() { return m_CIEs.end(); }
const CIE& cie_front() const { return *m_CIEs.front(); }
CIE& cie_front() { return *m_CIEs.front(); }
const CIE& cie_back() const { return *m_CIEs.back(); }
CIE& cie_back() { return *m_CIEs.back(); }
bool emptyCIEs() const { return m_CIEs.empty(); }
size_t numOfCIEs() const { return m_CIEs.size(); }
size_t numOfFDEs() const;
const CIEMap& getCIEMap() const { return m_FoundCIEs; }
CIEMap& getCIEMap() { return m_FoundCIEs; }
public:
size_t computeOffsetSize();
/// getDataStartOffset - Get the offset after length and ID field.
/// The offset is 8byte for 32b, and 16byte for 64b.
/// We can just use "BITCLASS/4" to represent offset.
template <size_t BITCLASS>
static size_t getDataStartOffset() {
return BITCLASS / 4;
}
private:
// We needs to check if it is mergeable and check personality name
// before merging them. The important note is we must do this after
// ALL readSections done, that is the reason why we don't check this
// immediately when reading.
void setupAttributes(const LDSection* reloc_sect);
void removeDiscardedFDE(CIE& pCIE, const LDSection* pRelocEhFrameSect);
private:
void removeAndUpdateCIEForFDE(EhFrame& pInFrame,
CIE& pInCIE,
CIE& pOutCIE,
const LDSection* reloc_sect);
void moveInputFragments(EhFrame& pInFrame);
void moveInputFragments(EhFrame& pInFrame, CIE& pInCIE, CIE* pOutCIE = 0);
private:
LDSection* m_pSection;
SectionData* m_pSectionData;
// Each eh_frame has a list of CIE, and each CIE has a list of FDE
// pointing to the CIE itself. This is used by management when we are
// processing eh_frame merge.
// However, don't forget we need to handle the Fragments inside SectionData
// correctly since they are truly used when output emission.
CIEList m_CIEs;
// We need this map to find the corresponding CIE for FDE. Not all FDE point
// to the nearest CIE.
CIEMap m_FoundCIEs;
private:
DISALLOW_COPY_AND_ASSIGN(EhFrame);
};
bool operator==(const EhFrame::CIE&, const EhFrame::CIE&);
} // namespace mcld
#endif // MCLD_LD_EHFRAME_H_