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.
262 lines
7.6 KiB
262 lines
7.6 KiB
//===- 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_
|