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
18namespace mcld {
19
20/** \class ARMELFAttributeData
21 *  \brief ARMELFAttributeData handles public ("aeabi") attributes subsection in
22 *  ARM ELF.
23 *
24 */
25class ARMELFAttributeData : public ELFAttributeData {
26public:
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
147public:
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
153public:
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
187private:
188  /// GetAttributeValueType - obtain the value type of the indicated tag.
189  static unsigned int GetAttributeValueType(TagType pTag);
190
191private:
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