Home | History | Annotate | Download | only in ARM
      1 //===- ARMELFAttributeData.h ----------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #ifndef TARGET_ARM_ARMELFATTRIBUTEDATA_H
     10 #define TARGET_ARM_ARMELFATTRIBUTEDATA_H
     11 
     12 #include <mcld/Target/ELFAttributeData.h>
     13 #include <mcld/Target/ELFAttributeValue.h>
     14 
     15 #include <map>
     16 #include <string>
     17 
     18 namespace mcld {
     19 
     20 /** \class ARMELFAttributeData
     21  *  \brief ARMELFAttributeData handles public ("aeabi") attributes subsection in
     22  *  ARM ELF.
     23  *
     24  */
     25 class ARMELFAttributeData : public ELFAttributeData {
     26 public:
     27   enum Tag {
     28     // 0-3 are generic and are defined in ELFAttributeData.
     29     Tag_CPU_raw_name                = 4,
     30     Tag_CPU_name                    = 5,
     31     Tag_CPU_arch                    = 6,
     32     Tag_CPU_arch_profile            = 7,
     33     Tag_ARM_ISA_use                 = 8,
     34     Tag_THUMB_ISA_use               = 9,
     35     Tag_FP_arch                     = 10,
     36     Tag_WMMX_arch                   = 11,
     37     Tag_Advanced_SIMD_arch          = 12,
     38     Tag_PCS_config                  = 13,
     39     Tag_ABI_PCS_R9_use              = 14,
     40     Tag_ABI_PCS_RW_data             = 15,
     41     Tag_ABI_PCS_RO_data             = 16,
     42     Tag_ABI_PCS_GOT_use             = 17,
     43     Tag_ABI_PCS_wchar_t             = 18,
     44     Tag_ABI_FP_rounding             = 19,
     45     Tag_ABI_FP_denormal             = 20,
     46     Tag_ABI_FP_exceptions           = 21,
     47     Tag_ABI_FP_user_exceptions      = 22,
     48     Tag_ABI_FP_number_model         = 23,
     49     Tag_ABI_align_needed            = 24,
     50     Tag_ABI_align_preserved         = 25,
     51     Tag_ABI_enum_size               = 26,
     52     Tag_ABI_HardFP_use              = 27,
     53     Tag_ABI_VFP_args                = 28,
     54     Tag_ABI_WMMX_args               = 29,
     55     Tag_ABI_optimization_goals      = 30,
     56     Tag_ABI_FP_optimization_goals   = 31,
     57     Tag_compatibility               = 32,
     58 
     59     Tag_CPU_unaligned_access        = 34,
     60 
     61     Tag_FP_HP_extension             = 36,
     62 
     63     Tag_ABI_FP_16bit_format         = 38,
     64 
     65     Tag_MPextension_use             = 42,
     66 
     67     Tag_DIV_use                     = 44,
     68 
     69     Tag_nodefaults                  = 64,
     70     Tag_also_compatible_with        = 65,
     71     Tag_T2EE_use                    = 66,
     72     Tag_conformance                 = 67,
     73     Tag_Virtualization_use          = 68,
     74 
     75     Tag_MPextension_use_legacy      = 70,
     76 
     77     Tag_Max = Tag_MPextension_use_legacy,
     78 
     79     // Alias
     80     Tag_VFP_arch                    = Tag_FP_arch,
     81     Tag_ABI_align8_needed           = Tag_ABI_align_needed,
     82     Tag_ABI_align8_preserved        = Tag_ABI_align_preserved,
     83     Tag_VFP_HP_extension            = Tag_FP_HP_extension
     84   };
     85 
     86   // For Tag_CPU_arch
     87   enum {
     88     CPU_Arch_ARM_Pre_V4,
     89     CPU_Arch_ARM_V4,    // e.g., SA110
     90     CPU_Arch_ARM_V4T,   // e.g., ARM7TDMI
     91     CPU_Arch_ARM_V5T,   // e.g., ARM9TDMI
     92     CPU_Arch_ARM_V5TE,  // e.g., ARM946E-S
     93     CPU_Arch_ARM_V5TEJ, // e.g., ARM926EJ-S
     94     CPU_Arch_ARM_V6,    // e.g., ARM1136J-S
     95     CPU_Arch_ARM_V6KZ,  // e.g., ARM1176JZ-S
     96     CPU_Arch_ARM_V6T2,  // e.g., ARM1156T2F-S
     97     CPU_Arch_ARM_V6K,   // e.g., ARM1136J-S
     98     CPU_Arch_ARM_V7,    // e.g., Cortex A8, Cortex M3
     99     CPU_Arch_ARM_V6_M,  // e.g., Cortex M1
    100     CPU_Arch_ARM_V6S_M, // e.g., v6-M with the value of System extensions
    101     CPU_Arch_ARM_V7E_M, // e.g., v7-M with DSP extensions
    102     CPU_Arch_ARM_V8,
    103 
    104     CPU_Arch_Max = CPU_Arch_ARM_V8,
    105 
    106     // This is a pseudo-architecture to describe an architecture mixed with
    107     // the subset of armv4t and armv6-m. This never appears in the value of
    108     // Tag_CPU_arch.
    109     CPU_Arch_ARM_V4T_Plus_V6_M = (CPU_Arch_Max + 1),
    110 
    111     CPU_Arch_Plus_Pseudo_Max = CPU_Arch_ARM_V4T_Plus_V6_M,
    112   };
    113 
    114   // For Tag_CPU_arch_profile
    115   enum {
    116     Arch_Profile_None             = 0,
    117     Arch_Profile_Application      = 'A',
    118     Arch_Profile_Realtime         = 'R',
    119     Arch_Profile_Microcontroller  = 'M',
    120     Arch_Profile_RealOrApp        = 'S'
    121   };
    122 
    123   // For Tag_ABI_enum_size
    124   enum {
    125     Enum_Unused,
    126     Enum_Smallest_Container,
    127     Enum_32bit_Container,
    128     Enum_Containerized_As_Possible
    129   };
    130 
    131   // For Tag_ABI_PCS_R9_use
    132   enum {
    133     R9_V6,
    134     R9_SB,
    135     R9_TLS,
    136     R9_Unused
    137   };
    138 
    139   // For Tag_ABI_PCS_RW_data
    140   enum {
    141     RW_data_Absolute,
    142     RW_data_PC_Relative,
    143     RW_data_SB_Relative,
    144     RW_data_unused
    145   };
    146 
    147 public:
    148   // ARM [ABI-addenda], 2.2.2: A public attributes subsection is named aeabi.
    149   ARMELFAttributeData()
    150     : ELFAttributeData("aeabi"), m_CurrentCPUArch(-1),
    151       m_DIVUseInitialized(false), m_HardFPUseInitialized(false) { }
    152 
    153 public:
    154   virtual const ELFAttributeValue *getAttributeValue(TagType pTag) const;
    155 
    156   virtual std::pair<ELFAttributeValue*, bool>
    157       getOrCreateAttributeValue(TagType pTag);
    158 
    159   virtual bool preMerge(const Input &pInput)
    160   {
    161     // Reset states.
    162     m_CPUArch = -1;
    163     m_CPUName.clear();
    164     m_CPURawName.clear();
    165     m_SecondaryCPUArch = -1;
    166     m_VFPArgs = -1;
    167     m_FPArch = -1;
    168     m_HardFPUse = -1;
    169     m_MPextensionUse = -1;
    170     m_DIVUse = -1;
    171     return true;
    172   }
    173 
    174   virtual bool merge(const LinkerConfig& pConfig, const Input &pInput,
    175                      TagType pTag, const ELFAttributeValue& pInAttr);
    176 
    177   virtual bool postMerge(const LinkerConfig& pConfig, const Input &pInput);
    178 
    179   virtual size_t sizeOutput() const;
    180 
    181   virtual size_t emit(char *pBuf) const;
    182 
    183   virtual bool usingThumb() const;
    184 
    185   virtual bool usingThumb2() const;
    186 
    187 private:
    188   /// GetAttributeValueType - obtain the value type of the indicated tag.
    189   static unsigned int GetAttributeValueType(TagType pTag);
    190 
    191 private:
    192   // The storage for known tags which is indexed by the tag
    193   ELFAttributeValue m_Attrs[Tag_Max + 1];
    194 
    195   // The storage for unknown tags
    196   typedef std::map<TagType, ELFAttributeValue> UnknownAttrsMap;
    197   UnknownAttrsMap m_UnknownAttrs;
    198 
    199   // This is a cache for the current output architecture calculate from of
    200   // Tag_CPU_arch and Tag_also_compatible_with.
    201   int m_CurrentCPUArch;
    202 
    203   // Value of Tag_DIV_use and Tag_ABI_HardFP_use requires further examination
    204   // for the every time adding to the output. These booleans are initialized to
    205   // false and set to true until the corresponding attribute is initialized.
    206   bool m_DIVUseInitialized;
    207   bool m_HardFPUseInitialized;
    208 
    209   // These attributes have dependency with each other. During the merge, we
    210   // record their attribute values in the associated variables as follows and
    211   // process them in postmerge() (when all other attributes are settled down.)
    212 
    213   // Record the value of input Tag_CPU_arch.
    214   int m_CPUArch;
    215 
    216   // Record the value of input Tag_CPU_name.
    217   std::string m_CPUName;
    218 
    219   // Record the value of input Tag_CPU_raw_name.
    220   std::string m_CPURawName;
    221 
    222   // Record the value of input Tag_FP_arch.
    223   int m_FPArch;
    224 
    225   // Record the value of input Tag_ABI_HardFP_use.
    226   int m_HardFPUse;
    227 
    228   // Record the value of input Tag_also_compatible_with.
    229   int m_SecondaryCPUArch;
    230 
    231   // Record the value of input Tag_ABI_VFP_args.
    232   int m_VFPArgs;
    233 
    234   // Record the value of input Tag_MPextension_use and Tag_MPextension_use_legacy.
    235   int m_MPextensionUse;
    236 
    237   // Record the value of input Tag_DIV_use.
    238   int m_DIVUse;
    239 };
    240 
    241 } // namespace of mcld
    242 
    243 #endif
    244