1 //===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the ELFObjectFile class implementation.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Object/ELFObjectFile.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/MC/SubtargetFeature.h"
18 #include "llvm/Object/ELF.h"
19 #include "llvm/Object/ELFTypes.h"
20 #include "llvm/Object/Error.h"
21 #include "llvm/Support/ARMAttributeParser.h"
22 #include "llvm/Support/ARMBuildAttributes.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/MathExtras.h"
26 #include <algorithm>
27 #include <cstddef>
28 #include <cstdint>
29 #include <memory>
30 #include <string>
31 #include <system_error>
32 #include <utility>
33
34 using namespace llvm;
35 using namespace object;
36
ELFObjectFileBase(unsigned int Type,MemoryBufferRef Source)37 ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
38 : ObjectFile(Type, Source) {}
39
40 template <class ELFT>
41 static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
createPtr(MemoryBufferRef Object)42 createPtr(MemoryBufferRef Object) {
43 auto Ret = ELFObjectFile<ELFT>::create(Object);
44 if (Error E = Ret.takeError())
45 return std::move(E);
46 return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
47 }
48
49 Expected<std::unique_ptr<ObjectFile>>
createELFObjectFile(MemoryBufferRef Obj)50 ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
51 std::pair<unsigned char, unsigned char> Ident =
52 getElfArchType(Obj.getBuffer());
53 std::size_t MaxAlignment =
54 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
55
56 if (MaxAlignment < 2)
57 return createError("Insufficient alignment");
58
59 if (Ident.first == ELF::ELFCLASS32) {
60 if (Ident.second == ELF::ELFDATA2LSB)
61 return createPtr<ELF32LE>(Obj);
62 else if (Ident.second == ELF::ELFDATA2MSB)
63 return createPtr<ELF32BE>(Obj);
64 else
65 return createError("Invalid ELF data");
66 } else if (Ident.first == ELF::ELFCLASS64) {
67 if (Ident.second == ELF::ELFDATA2LSB)
68 return createPtr<ELF64LE>(Obj);
69 else if (Ident.second == ELF::ELFDATA2MSB)
70 return createPtr<ELF64BE>(Obj);
71 else
72 return createError("Invalid ELF data");
73 }
74 return createError("Invalid ELF class");
75 }
76
getMIPSFeatures() const77 SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
78 SubtargetFeatures Features;
79 unsigned PlatformFlags = getPlatformFlags();
80
81 switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
82 case ELF::EF_MIPS_ARCH_1:
83 break;
84 case ELF::EF_MIPS_ARCH_2:
85 Features.AddFeature("mips2");
86 break;
87 case ELF::EF_MIPS_ARCH_3:
88 Features.AddFeature("mips3");
89 break;
90 case ELF::EF_MIPS_ARCH_4:
91 Features.AddFeature("mips4");
92 break;
93 case ELF::EF_MIPS_ARCH_5:
94 Features.AddFeature("mips5");
95 break;
96 case ELF::EF_MIPS_ARCH_32:
97 Features.AddFeature("mips32");
98 break;
99 case ELF::EF_MIPS_ARCH_64:
100 Features.AddFeature("mips64");
101 break;
102 case ELF::EF_MIPS_ARCH_32R2:
103 Features.AddFeature("mips32r2");
104 break;
105 case ELF::EF_MIPS_ARCH_64R2:
106 Features.AddFeature("mips64r2");
107 break;
108 case ELF::EF_MIPS_ARCH_32R6:
109 Features.AddFeature("mips32r6");
110 break;
111 case ELF::EF_MIPS_ARCH_64R6:
112 Features.AddFeature("mips64r6");
113 break;
114 default:
115 llvm_unreachable("Unknown EF_MIPS_ARCH value");
116 }
117
118 switch (PlatformFlags & ELF::EF_MIPS_MACH) {
119 case ELF::EF_MIPS_MACH_NONE:
120 // No feature associated with this value.
121 break;
122 case ELF::EF_MIPS_MACH_OCTEON:
123 Features.AddFeature("cnmips");
124 break;
125 default:
126 llvm_unreachable("Unknown EF_MIPS_ARCH value");
127 }
128
129 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
130 Features.AddFeature("mips16");
131 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
132 Features.AddFeature("micromips");
133
134 return Features;
135 }
136
getARMFeatures() const137 SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
138 SubtargetFeatures Features;
139 ARMAttributeParser Attributes;
140 std::error_code EC = getBuildAttributes(Attributes);
141 if (EC)
142 return SubtargetFeatures();
143
144 // both ARMv7-M and R have to support thumb hardware div
145 bool isV7 = false;
146 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
147 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
148 == ARMBuildAttrs::v7;
149
150 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
151 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
152 case ARMBuildAttrs::ApplicationProfile:
153 Features.AddFeature("aclass");
154 break;
155 case ARMBuildAttrs::RealTimeProfile:
156 Features.AddFeature("rclass");
157 if (isV7)
158 Features.AddFeature("hwdiv");
159 break;
160 case ARMBuildAttrs::MicroControllerProfile:
161 Features.AddFeature("mclass");
162 if (isV7)
163 Features.AddFeature("hwdiv");
164 break;
165 }
166 }
167
168 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
169 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
170 default:
171 break;
172 case ARMBuildAttrs::Not_Allowed:
173 Features.AddFeature("thumb", false);
174 Features.AddFeature("thumb2", false);
175 break;
176 case ARMBuildAttrs::AllowThumb32:
177 Features.AddFeature("thumb2");
178 break;
179 }
180 }
181
182 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
183 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
184 default:
185 break;
186 case ARMBuildAttrs::Not_Allowed:
187 Features.AddFeature("vfp2", false);
188 Features.AddFeature("vfp3", false);
189 Features.AddFeature("vfp4", false);
190 break;
191 case ARMBuildAttrs::AllowFPv2:
192 Features.AddFeature("vfp2");
193 break;
194 case ARMBuildAttrs::AllowFPv3A:
195 case ARMBuildAttrs::AllowFPv3B:
196 Features.AddFeature("vfp3");
197 break;
198 case ARMBuildAttrs::AllowFPv4A:
199 case ARMBuildAttrs::AllowFPv4B:
200 Features.AddFeature("vfp4");
201 break;
202 }
203 }
204
205 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
206 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
207 default:
208 break;
209 case ARMBuildAttrs::Not_Allowed:
210 Features.AddFeature("neon", false);
211 Features.AddFeature("fp16", false);
212 break;
213 case ARMBuildAttrs::AllowNeon:
214 Features.AddFeature("neon");
215 break;
216 case ARMBuildAttrs::AllowNeon2:
217 Features.AddFeature("neon");
218 Features.AddFeature("fp16");
219 break;
220 }
221 }
222
223 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
224 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
225 default:
226 break;
227 case ARMBuildAttrs::DisallowDIV:
228 Features.AddFeature("hwdiv", false);
229 Features.AddFeature("hwdiv-arm", false);
230 break;
231 case ARMBuildAttrs::AllowDIVExt:
232 Features.AddFeature("hwdiv");
233 Features.AddFeature("hwdiv-arm");
234 break;
235 }
236 }
237
238 return Features;
239 }
240
getRISCVFeatures() const241 SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
242 SubtargetFeatures Features;
243 unsigned PlatformFlags = getPlatformFlags();
244
245 if (PlatformFlags & ELF::EF_RISCV_RVC) {
246 Features.AddFeature("c");
247 }
248
249 return Features;
250 }
251
getFeatures() const252 SubtargetFeatures ELFObjectFileBase::getFeatures() const {
253 switch (getEMachine()) {
254 case ELF::EM_MIPS:
255 return getMIPSFeatures();
256 case ELF::EM_ARM:
257 return getARMFeatures();
258 case ELF::EM_RISCV:
259 return getRISCVFeatures();
260 default:
261 return SubtargetFeatures();
262 }
263 }
264
265 // FIXME Encode from a tablegen description or target parser.
setARMSubArch(Triple & TheTriple) const266 void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
267 if (TheTriple.getSubArch() != Triple::NoSubArch)
268 return;
269
270 ARMAttributeParser Attributes;
271 std::error_code EC = getBuildAttributes(Attributes);
272 if (EC)
273 return;
274
275 std::string Triple;
276 // Default to ARM, but use the triple if it's been set.
277 if (TheTriple.isThumb())
278 Triple = "thumb";
279 else
280 Triple = "arm";
281
282 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
283 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
284 case ARMBuildAttrs::v4:
285 Triple += "v4";
286 break;
287 case ARMBuildAttrs::v4T:
288 Triple += "v4t";
289 break;
290 case ARMBuildAttrs::v5T:
291 Triple += "v5t";
292 break;
293 case ARMBuildAttrs::v5TE:
294 Triple += "v5te";
295 break;
296 case ARMBuildAttrs::v5TEJ:
297 Triple += "v5tej";
298 break;
299 case ARMBuildAttrs::v6:
300 Triple += "v6";
301 break;
302 case ARMBuildAttrs::v6KZ:
303 Triple += "v6kz";
304 break;
305 case ARMBuildAttrs::v6T2:
306 Triple += "v6t2";
307 break;
308 case ARMBuildAttrs::v6K:
309 Triple += "v6k";
310 break;
311 case ARMBuildAttrs::v7:
312 Triple += "v7";
313 break;
314 case ARMBuildAttrs::v6_M:
315 Triple += "v6m";
316 break;
317 case ARMBuildAttrs::v6S_M:
318 Triple += "v6sm";
319 break;
320 case ARMBuildAttrs::v7E_M:
321 Triple += "v7em";
322 break;
323 }
324 }
325 if (!isLittleEndian())
326 Triple += "eb";
327
328 TheTriple.setArchName(Triple);
329 }
330