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 { R9_V6, R9_SB, R9_TLS, R9_Unused };
133 
134   // For Tag_ABI_PCS_RW_data
135   enum {
136     RW_data_Absolute,
137     RW_data_PC_Relative,
138     RW_data_SB_Relative,
139     RW_data_unused
140   };
141 
142  public:
143   // ARM [ABI-addenda], 2.2.2: A public attributes subsection is named aeabi.
ARMELFAttributeData()144   ARMELFAttributeData()
145       : ELFAttributeData("aeabi"),
146         m_CurrentCPUArch(-1),
147         m_DIVUseInitialized(false),
148         m_HardFPUseInitialized(false) {}
149 
150  public:
151   virtual const ELFAttributeValue* getAttributeValue(TagType pTag) const;
152 
153   virtual std::pair<ELFAttributeValue*, bool> getOrCreateAttributeValue(
154       TagType pTag);
155 
preMerge(const Input & pInput)156   virtual bool preMerge(const Input& pInput) {
157     // Reset states.
158     m_CPUArch = -1;
159     m_CPUName.clear();
160     m_CPURawName.clear();
161     m_SecondaryCPUArch = -1;
162     m_VFPArgs = -1;
163     m_FPArch = -1;
164     m_HardFPUse = -1;
165     m_MPextensionUse = -1;
166     m_DIVUse = -1;
167     return true;
168   }
169 
170   virtual bool merge(const LinkerConfig& pConfig,
171                      const Input& pInput,
172                      TagType pTag,
173                      const ELFAttributeValue& pInAttr);
174 
175   virtual bool postMerge(const LinkerConfig& pConfig, const Input& pInput);
176 
177   virtual size_t sizeOutput() const;
178 
179   virtual size_t emit(char* pBuf) const;
180 
181   virtual bool usingThumb() const;
182 
183   virtual bool usingThumb2() const;
184 
185  private:
186   /// GetAttributeValueType - obtain the value type of the indicated tag.
187   static unsigned int GetAttributeValueType(TagType pTag);
188 
189  private:
190   // The storage for known tags which is indexed by the tag
191   ELFAttributeValue m_Attrs[Tag_Max + 1];
192 
193   // The storage for unknown tags
194   typedef std::map<TagType, ELFAttributeValue> UnknownAttrsMap;
195   UnknownAttrsMap m_UnknownAttrs;
196 
197   // This is a cache for the current output architecture calculate from of
198   // Tag_CPU_arch and Tag_also_compatible_with.
199   int m_CurrentCPUArch;
200 
201   // Value of Tag_DIV_use and Tag_ABI_HardFP_use requires further examination
202   // for the every time adding to the output. These booleans are initialized to
203   // false and set to true until the corresponding attribute is initialized.
204   bool m_DIVUseInitialized;
205   bool m_HardFPUseInitialized;
206 
207   // These attributes have dependency with each other. During the merge, we
208   // record their attribute values in the associated variables as follows and
209   // process them in postmerge() (when all other attributes are settled down.)
210 
211   // Record the value of input Tag_CPU_arch.
212   int m_CPUArch;
213 
214   // Record the value of input Tag_CPU_name.
215   std::string m_CPUName;
216 
217   // Record the value of input Tag_CPU_raw_name.
218   std::string m_CPURawName;
219 
220   // Record the value of input Tag_FP_arch.
221   int m_FPArch;
222 
223   // Record the value of input Tag_ABI_HardFP_use.
224   int m_HardFPUse;
225 
226   // Record the value of input Tag_also_compatible_with.
227   int m_SecondaryCPUArch;
228 
229   // Record the value of input Tag_ABI_VFP_args.
230   int m_VFPArgs;
231 
232   // Record the value of input Tag_MPextension_use and
233   // Tag_MPextension_use_legacy.
234   int m_MPextensionUse;
235 
236   // Record the value of input Tag_DIV_use.
237   int m_DIVUse;
238 };
239 
240 }  // namespace mcld
241 
242 #endif  // TARGET_ARM_ARMELFATTRIBUTEDATA_H_
243