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.

243 lines
6.7 KiB

//===- ARMELFAttributeData.h ----------------------------------------------===//
//
// The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_ARM_ARMELFATTRIBUTEDATA_H_
#define TARGET_ARM_ARMELFATTRIBUTEDATA_H_
#include "mcld/Target/ELFAttributeData.h"
#include "mcld/Target/ELFAttributeValue.h"
#include <map>
#include <string>
namespace mcld {
/** \class ARMELFAttributeData
* \brief ARMELFAttributeData handles public ("aeabi") attributes subsection in
* ARM ELF.
*
*/
class ARMELFAttributeData : public ELFAttributeData {
public:
enum Tag {
// 0-3 are generic and are defined in ELFAttributeData.
Tag_CPU_raw_name = 4,
Tag_CPU_name = 5,
Tag_CPU_arch = 6,
Tag_CPU_arch_profile = 7,
Tag_ARM_ISA_use = 8,
Tag_THUMB_ISA_use = 9,
Tag_FP_arch = 10,
Tag_WMMX_arch = 11,
Tag_Advanced_SIMD_arch = 12,
Tag_PCS_config = 13,
Tag_ABI_PCS_R9_use = 14,
Tag_ABI_PCS_RW_data = 15,
Tag_ABI_PCS_RO_data = 16,
Tag_ABI_PCS_GOT_use = 17,
Tag_ABI_PCS_wchar_t = 18,
Tag_ABI_FP_rounding = 19,
Tag_ABI_FP_denormal = 20,
Tag_ABI_FP_exceptions = 21,
Tag_ABI_FP_user_exceptions = 22,
Tag_ABI_FP_number_model = 23,
Tag_ABI_align_needed = 24,
Tag_ABI_align_preserved = 25,
Tag_ABI_enum_size = 26,
Tag_ABI_HardFP_use = 27,
Tag_ABI_VFP_args = 28,
Tag_ABI_WMMX_args = 29,
Tag_ABI_optimization_goals = 30,
Tag_ABI_FP_optimization_goals = 31,
Tag_compatibility = 32,
Tag_CPU_unaligned_access = 34,
Tag_FP_HP_extension = 36,
Tag_ABI_FP_16bit_format = 38,
Tag_MPextension_use = 42,
Tag_DIV_use = 44,
Tag_nodefaults = 64,
Tag_also_compatible_with = 65,
Tag_T2EE_use = 66,
Tag_conformance = 67,
Tag_Virtualization_use = 68,
Tag_MPextension_use_legacy = 70,
Tag_Max = Tag_MPextension_use_legacy,
// Alias
Tag_VFP_arch = Tag_FP_arch,
Tag_ABI_align8_needed = Tag_ABI_align_needed,
Tag_ABI_align8_preserved = Tag_ABI_align_preserved,
Tag_VFP_HP_extension = Tag_FP_HP_extension
};
// For Tag_CPU_arch
enum {
CPU_Arch_ARM_Pre_V4,
CPU_Arch_ARM_V4, // e.g., SA110
CPU_Arch_ARM_V4T, // e.g., ARM7TDMI
CPU_Arch_ARM_V5T, // e.g., ARM9TDMI
CPU_Arch_ARM_V5TE, // e.g., ARM946E-S
CPU_Arch_ARM_V5TEJ, // e.g., ARM926EJ-S
CPU_Arch_ARM_V6, // e.g., ARM1136J-S
CPU_Arch_ARM_V6KZ, // e.g., ARM1176JZ-S
CPU_Arch_ARM_V6T2, // e.g., ARM1156T2F-S
CPU_Arch_ARM_V6K, // e.g., ARM1136J-S
CPU_Arch_ARM_V7, // e.g., Cortex A8, Cortex M3
CPU_Arch_ARM_V6_M, // e.g., Cortex M1
CPU_Arch_ARM_V6S_M, // e.g., v6-M with the value of System extensions
CPU_Arch_ARM_V7E_M, // e.g., v7-M with DSP extensions
CPU_Arch_ARM_V8,
CPU_Arch_Max = CPU_Arch_ARM_V8,
// This is a pseudo-architecture to describe an architecture mixed with
// the subset of armv4t and armv6-m. This never appears in the value of
// Tag_CPU_arch.
CPU_Arch_ARM_V4T_Plus_V6_M = (CPU_Arch_Max + 1),
CPU_Arch_Plus_Pseudo_Max = CPU_Arch_ARM_V4T_Plus_V6_M,
};
// For Tag_CPU_arch_profile
enum {
Arch_Profile_None = 0,
Arch_Profile_Application = 'A',
Arch_Profile_Realtime = 'R',
Arch_Profile_Microcontroller = 'M',
Arch_Profile_RealOrApp = 'S'
};
// For Tag_ABI_enum_size
enum {
Enum_Unused,
Enum_Smallest_Container,
Enum_32bit_Container,
Enum_Containerized_As_Possible
};
// For Tag_ABI_PCS_R9_use
enum { R9_V6, R9_SB, R9_TLS, R9_Unused };
// For Tag_ABI_PCS_RW_data
enum {
RW_data_Absolute,
RW_data_PC_Relative,
RW_data_SB_Relative,
RW_data_unused
};
public:
// ARM [ABI-addenda], 2.2.2: A public attributes subsection is named aeabi.
ARMELFAttributeData()
: ELFAttributeData("aeabi"),
m_CurrentCPUArch(-1),
m_DIVUseInitialized(false),
m_HardFPUseInitialized(false) {}
public:
virtual const ELFAttributeValue* getAttributeValue(TagType pTag) const;
virtual std::pair<ELFAttributeValue*, bool> getOrCreateAttributeValue(
TagType pTag);
virtual bool preMerge(const Input& pInput) {
// Reset states.
m_CPUArch = -1;
m_CPUName.clear();
m_CPURawName.clear();
m_SecondaryCPUArch = -1;
m_VFPArgs = -1;
m_FPArch = -1;
m_HardFPUse = -1;
m_MPextensionUse = -1;
m_DIVUse = -1;
return true;
}
virtual bool merge(const LinkerConfig& pConfig,
const Input& pInput,
TagType pTag,
const ELFAttributeValue& pInAttr);
virtual bool postMerge(const LinkerConfig& pConfig, const Input& pInput);
virtual size_t sizeOutput() const;
virtual size_t emit(char* pBuf) const;
virtual bool usingThumb() const;
virtual bool usingThumb2() const;
private:
/// GetAttributeValueType - obtain the value type of the indicated tag.
static unsigned int GetAttributeValueType(TagType pTag);
private:
// The storage for known tags which is indexed by the tag
ELFAttributeValue m_Attrs[Tag_Max + 1];
// The storage for unknown tags
typedef std::map<TagType, ELFAttributeValue> UnknownAttrsMap;
UnknownAttrsMap m_UnknownAttrs;
// This is a cache for the current output architecture calculate from of
// Tag_CPU_arch and Tag_also_compatible_with.
int m_CurrentCPUArch;
// Value of Tag_DIV_use and Tag_ABI_HardFP_use requires further examination
// for the every time adding to the output. These booleans are initialized to
// false and set to true until the corresponding attribute is initialized.
bool m_DIVUseInitialized;
bool m_HardFPUseInitialized;
// These attributes have dependency with each other. During the merge, we
// record their attribute values in the associated variables as follows and
// process them in postmerge() (when all other attributes are settled down.)
// Record the value of input Tag_CPU_arch.
int m_CPUArch;
// Record the value of input Tag_CPU_name.
std::string m_CPUName;
// Record the value of input Tag_CPU_raw_name.
std::string m_CPURawName;
// Record the value of input Tag_FP_arch.
int m_FPArch;
// Record the value of input Tag_ABI_HardFP_use.
int m_HardFPUse;
// Record the value of input Tag_also_compatible_with.
int m_SecondaryCPUArch;
// Record the value of input Tag_ABI_VFP_args.
int m_VFPArgs;
// Record the value of input Tag_MPextension_use and
// Tag_MPextension_use_legacy.
int m_MPextensionUse;
// Record the value of input Tag_DIV_use.
int m_DIVUse;
};
} // namespace mcld
#endif // TARGET_ARM_ARMELFATTRIBUTEDATA_H_