blob: 9fb3a55ac7b1855d531316489d366c1d4753e45c [file] [log] [blame]
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +00001//===- ELFObjectFile.cpp - ELF object file implementation -----------------===//
Michael J. Spencerb84551a2011-01-20 06:38:47 +00002//
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//
Eli Benderskyf4eff4b2012-02-12 06:12:10 +000010// Part of the ELFObjectFile class implementation.
Michael J. Spencerb84551a2011-01-20 06:38:47 +000011//
12//===----------------------------------------------------------------------===//
13
Chandler Carruthe3e43d92017-06-06 11:49:48 +000014#include "llvm/Object/ELFObjectFile.h"
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000015#include "llvm/ADT/Triple.h"
Zachary Turner19ca2b02017-06-07 03:48:56 +000016#include "llvm/BinaryFormat/ELF.h"
Joel Galenson77a17af2018-08-24 15:21:56 +000017#include "llvm/MC/MCInstrAnalysis.h"
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000018#include "llvm/MC/SubtargetFeature.h"
19#include "llvm/Object/ELF.h"
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000020#include "llvm/Object/ELFTypes.h"
21#include "llvm/Object/Error.h"
Sam Parker56e5bde2017-01-18 15:52:11 +000022#include "llvm/Support/ARMAttributeParser.h"
Chandler Carruthe3e43d92017-06-06 11:49:48 +000023#include "llvm/Support/ARMBuildAttributes.h"
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000024#include "llvm/Support/Endian.h"
25#include "llvm/Support/ErrorHandling.h"
Michael J. Spencer4d9c5392013-01-04 20:36:28 +000026#include "llvm/Support/MathExtras.h"
Joel Galenson77a17af2018-08-24 15:21:56 +000027#include "llvm/Support/TargetRegistry.h"
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000028#include <algorithm>
29#include <cstddef>
30#include <cstdint>
31#include <memory>
32#include <string>
33#include <system_error>
34#include <utility>
Eli Bendersky24973c12012-01-22 09:01:03 +000035
Eugene Zelenkoc581c4f2017-04-24 23:21:38 +000036using namespace llvm;
Eli Benderskyf4eff4b2012-02-12 06:12:10 +000037using namespace object;
Eli Bendersky24973c12012-01-22 09:01:03 +000038
Rafael Espindola548f2b62014-08-19 18:44:46 +000039ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source)
40 : ObjectFile(Type, Source) {}
Rafael Espindoladb7cdc82014-08-17 17:52:10 +000041
Rafael Espindola5c1b4432017-10-10 21:21:16 +000042template <class ELFT>
43static Expected<std::unique_ptr<ELFObjectFile<ELFT>>>
44createPtr(MemoryBufferRef Object) {
45 auto Ret = ELFObjectFile<ELFT>::create(Object);
46 if (Error E = Ret.takeError())
47 return std::move(E);
48 return make_unique<ELFObjectFile<ELFT>>(std::move(*Ret));
49}
50
Rafael Espindolae2d20cb2017-10-10 20:00:07 +000051Expected<std::unique_ptr<ObjectFile>>
Rafael Espindola548f2b62014-08-19 18:44:46 +000052ObjectFile::createELFObjectFile(MemoryBufferRef Obj) {
Rafael Espindoladb8cb222014-07-05 11:38:52 +000053 std::pair<unsigned char, unsigned char> Ident =
Rafael Espindola548f2b62014-08-19 18:44:46 +000054 getElfArchType(Obj.getBuffer());
Michael J. Spencer4d9c5392013-01-04 20:36:28 +000055 std::size_t MaxAlignment =
Rafael Espindola548f2b62014-08-19 18:44:46 +000056 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart()));
Michael J. Spencer4d9c5392013-01-04 20:36:28 +000057
Rafael Espindola9751e352015-06-02 12:05:27 +000058 if (MaxAlignment < 2)
Rafael Espindolae2d20cb2017-10-10 20:00:07 +000059 return createError("Insufficient alignment");
Rafael Espindola9751e352015-06-02 12:05:27 +000060
Rafael Espindola9751e352015-06-02 12:05:27 +000061 if (Ident.first == ELF::ELFCLASS32) {
62 if (Ident.second == ELF::ELFDATA2LSB)
Rafael Espindola5c1b4432017-10-10 21:21:16 +000063 return createPtr<ELF32LE>(Obj);
Rafael Espindola9751e352015-06-02 12:05:27 +000064 else if (Ident.second == ELF::ELFDATA2MSB)
Rafael Espindola5c1b4432017-10-10 21:21:16 +000065 return createPtr<ELF32BE>(Obj);
Michael J. Spencerd9d2f182013-02-03 10:48:31 +000066 else
Rafael Espindolae2d20cb2017-10-10 20:00:07 +000067 return createError("Invalid ELF data");
Alexey Samsonov196340c2015-06-04 23:14:43 +000068 } else if (Ident.first == ELF::ELFCLASS64) {
Rafael Espindola9751e352015-06-02 12:05:27 +000069 if (Ident.second == ELF::ELFDATA2LSB)
Rafael Espindola5c1b4432017-10-10 21:21:16 +000070 return createPtr<ELF64LE>(Obj);
Rafael Espindola9751e352015-06-02 12:05:27 +000071 else if (Ident.second == ELF::ELFDATA2MSB)
Rafael Espindola5c1b4432017-10-10 21:21:16 +000072 return createPtr<ELF64BE>(Obj);
Michael J. Spencer4d9c5392013-01-04 20:36:28 +000073 else
Rafael Espindolae2d20cb2017-10-10 20:00:07 +000074 return createError("Invalid ELF data");
Eli Benderskyf4eff4b2012-02-12 06:12:10 +000075 }
Rafael Espindola5c1b4432017-10-10 21:21:16 +000076 return createError("Invalid ELF class");
Eli Benderskyf4eff4b2012-02-12 06:12:10 +000077}
Michael J. Spencerb84551a2011-01-20 06:38:47 +000078
Sam Parker56e5bde2017-01-18 15:52:11 +000079SubtargetFeatures ELFObjectFileBase::getMIPSFeatures() const {
80 SubtargetFeatures Features;
Rafael Espindolaf1e44df2018-01-29 18:27:30 +000081 unsigned PlatformFlags = getPlatformFlags();
Sam Parker56e5bde2017-01-18 15:52:11 +000082
83 switch (PlatformFlags & ELF::EF_MIPS_ARCH) {
84 case ELF::EF_MIPS_ARCH_1:
85 break;
86 case ELF::EF_MIPS_ARCH_2:
87 Features.AddFeature("mips2");
88 break;
89 case ELF::EF_MIPS_ARCH_3:
90 Features.AddFeature("mips3");
91 break;
92 case ELF::EF_MIPS_ARCH_4:
93 Features.AddFeature("mips4");
94 break;
95 case ELF::EF_MIPS_ARCH_5:
96 Features.AddFeature("mips5");
97 break;
98 case ELF::EF_MIPS_ARCH_32:
99 Features.AddFeature("mips32");
100 break;
101 case ELF::EF_MIPS_ARCH_64:
102 Features.AddFeature("mips64");
103 break;
104 case ELF::EF_MIPS_ARCH_32R2:
105 Features.AddFeature("mips32r2");
106 break;
107 case ELF::EF_MIPS_ARCH_64R2:
108 Features.AddFeature("mips64r2");
109 break;
110 case ELF::EF_MIPS_ARCH_32R6:
111 Features.AddFeature("mips32r6");
112 break;
113 case ELF::EF_MIPS_ARCH_64R6:
114 Features.AddFeature("mips64r6");
115 break;
116 default:
117 llvm_unreachable("Unknown EF_MIPS_ARCH value");
118 }
119
120 switch (PlatformFlags & ELF::EF_MIPS_MACH) {
121 case ELF::EF_MIPS_MACH_NONE:
122 // No feature associated with this value.
123 break;
124 case ELF::EF_MIPS_MACH_OCTEON:
125 Features.AddFeature("cnmips");
126 break;
127 default:
128 llvm_unreachable("Unknown EF_MIPS_ARCH value");
129 }
130
131 if (PlatformFlags & ELF::EF_MIPS_ARCH_ASE_M16)
132 Features.AddFeature("mips16");
133 if (PlatformFlags & ELF::EF_MIPS_MICROMIPS)
134 Features.AddFeature("micromips");
135
136 return Features;
137}
138
139SubtargetFeatures ELFObjectFileBase::getARMFeatures() const {
140 SubtargetFeatures Features;
141 ARMAttributeParser Attributes;
142 std::error_code EC = getBuildAttributes(Attributes);
143 if (EC)
144 return SubtargetFeatures();
145
146 // both ARMv7-M and R have to support thumb hardware div
147 bool isV7 = false;
148 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
149 isV7 = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)
150 == ARMBuildAttrs::v7;
151
152 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch_profile)) {
153 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch_profile)) {
154 case ARMBuildAttrs::ApplicationProfile:
155 Features.AddFeature("aclass");
156 break;
157 case ARMBuildAttrs::RealTimeProfile:
158 Features.AddFeature("rclass");
159 if (isV7)
160 Features.AddFeature("hwdiv");
161 break;
162 case ARMBuildAttrs::MicroControllerProfile:
163 Features.AddFeature("mclass");
164 if (isV7)
165 Features.AddFeature("hwdiv");
166 break;
167 }
168 }
169
170 if (Attributes.hasAttribute(ARMBuildAttrs::THUMB_ISA_use)) {
171 switch(Attributes.getAttributeValue(ARMBuildAttrs::THUMB_ISA_use)) {
172 default:
173 break;
174 case ARMBuildAttrs::Not_Allowed:
175 Features.AddFeature("thumb", false);
176 Features.AddFeature("thumb2", false);
177 break;
178 case ARMBuildAttrs::AllowThumb32:
179 Features.AddFeature("thumb2");
180 break;
181 }
182 }
183
184 if (Attributes.hasAttribute(ARMBuildAttrs::FP_arch)) {
185 switch(Attributes.getAttributeValue(ARMBuildAttrs::FP_arch)) {
186 default:
187 break;
188 case ARMBuildAttrs::Not_Allowed:
189 Features.AddFeature("vfp2", false);
190 Features.AddFeature("vfp3", false);
191 Features.AddFeature("vfp4", false);
192 break;
193 case ARMBuildAttrs::AllowFPv2:
194 Features.AddFeature("vfp2");
195 break;
196 case ARMBuildAttrs::AllowFPv3A:
197 case ARMBuildAttrs::AllowFPv3B:
198 Features.AddFeature("vfp3");
199 break;
200 case ARMBuildAttrs::AllowFPv4A:
201 case ARMBuildAttrs::AllowFPv4B:
202 Features.AddFeature("vfp4");
203 break;
204 }
205 }
206
207 if (Attributes.hasAttribute(ARMBuildAttrs::Advanced_SIMD_arch)) {
208 switch(Attributes.getAttributeValue(ARMBuildAttrs::Advanced_SIMD_arch)) {
209 default:
210 break;
211 case ARMBuildAttrs::Not_Allowed:
212 Features.AddFeature("neon", false);
213 Features.AddFeature("fp16", false);
214 break;
215 case ARMBuildAttrs::AllowNeon:
216 Features.AddFeature("neon");
217 break;
218 case ARMBuildAttrs::AllowNeon2:
219 Features.AddFeature("neon");
220 Features.AddFeature("fp16");
221 break;
222 }
223 }
224
225 if (Attributes.hasAttribute(ARMBuildAttrs::DIV_use)) {
226 switch(Attributes.getAttributeValue(ARMBuildAttrs::DIV_use)) {
227 default:
228 break;
229 case ARMBuildAttrs::DisallowDIV:
230 Features.AddFeature("hwdiv", false);
231 Features.AddFeature("hwdiv-arm", false);
232 break;
233 case ARMBuildAttrs::AllowDIVExt:
234 Features.AddFeature("hwdiv");
235 Features.AddFeature("hwdiv-arm");
236 break;
237 }
238 }
239
240 return Features;
241}
242
Shiva Chen10bc2942018-02-02 06:01:02 +0000243SubtargetFeatures ELFObjectFileBase::getRISCVFeatures() const {
244 SubtargetFeatures Features;
245 unsigned PlatformFlags = getPlatformFlags();
246
247 if (PlatformFlags & ELF::EF_RISCV_RVC) {
248 Features.AddFeature("c");
249 }
250
251 return Features;
252}
253
Daniel Sanders0b8fc772016-06-16 09:17:03 +0000254SubtargetFeatures ELFObjectFileBase::getFeatures() const {
255 switch (getEMachine()) {
Sam Parker56e5bde2017-01-18 15:52:11 +0000256 case ELF::EM_MIPS:
257 return getMIPSFeatures();
258 case ELF::EM_ARM:
259 return getARMFeatures();
Shiva Chen10bc2942018-02-02 06:01:02 +0000260 case ELF::EM_RISCV:
261 return getRISCVFeatures();
Daniel Sanders0b8fc772016-06-16 09:17:03 +0000262 default:
263 return SubtargetFeatures();
264 }
265}
266
Sam Parkeraa967632017-01-18 13:52:12 +0000267// FIXME Encode from a tablegen description or target parser.
268void ELFObjectFileBase::setARMSubArch(Triple &TheTriple) const {
269 if (TheTriple.getSubArch() != Triple::NoSubArch)
270 return;
271
272 ARMAttributeParser Attributes;
273 std::error_code EC = getBuildAttributes(Attributes);
274 if (EC)
275 return;
276
277 std::string Triple;
278 // Default to ARM, but use the triple if it's been set.
Florian Hahnace970e2017-08-12 17:40:18 +0000279 if (TheTriple.isThumb())
Sam Parkeraa967632017-01-18 13:52:12 +0000280 Triple = "thumb";
281 else
282 Triple = "arm";
283
284 if (Attributes.hasAttribute(ARMBuildAttrs::CPU_arch)) {
285 switch(Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch)) {
286 case ARMBuildAttrs::v4:
287 Triple += "v4";
288 break;
289 case ARMBuildAttrs::v4T:
290 Triple += "v4t";
291 break;
292 case ARMBuildAttrs::v5T:
293 Triple += "v5t";
294 break;
295 case ARMBuildAttrs::v5TE:
296 Triple += "v5te";
297 break;
298 case ARMBuildAttrs::v5TEJ:
299 Triple += "v5tej";
300 break;
301 case ARMBuildAttrs::v6:
302 Triple += "v6";
303 break;
304 case ARMBuildAttrs::v6KZ:
305 Triple += "v6kz";
306 break;
307 case ARMBuildAttrs::v6T2:
308 Triple += "v6t2";
309 break;
310 case ARMBuildAttrs::v6K:
311 Triple += "v6k";
312 break;
313 case ARMBuildAttrs::v7:
314 Triple += "v7";
315 break;
316 case ARMBuildAttrs::v6_M:
317 Triple += "v6m";
318 break;
319 case ARMBuildAttrs::v6S_M:
320 Triple += "v6sm";
321 break;
322 case ARMBuildAttrs::v7E_M:
323 Triple += "v7em";
324 break;
325 }
326 }
327 if (!isLittleEndian())
328 Triple += "eb";
329
330 TheTriple.setArchName(Triple);
331}
Joel Galenson77a17af2018-08-24 15:21:56 +0000332
333std::vector<std::pair<DataRefImpl, uint64_t>>
334ELFObjectFileBase::getPltAddresses() const {
335 std::string Err;
336 const auto Triple = makeTriple();
337 const auto *T = TargetRegistry::lookupTarget(Triple.str(), Err);
338 if (!T)
339 return {};
340 uint64_t JumpSlotReloc = 0;
341 switch (Triple.getArch()) {
342 case Triple::x86:
343 JumpSlotReloc = ELF::R_386_JUMP_SLOT;
344 break;
345 case Triple::x86_64:
346 JumpSlotReloc = ELF::R_X86_64_JUMP_SLOT;
347 break;
348 case Triple::aarch64:
349 JumpSlotReloc = ELF::R_AARCH64_JUMP_SLOT;
350 break;
351 default:
352 return {};
353 }
Vitaly Bukaa4da4372018-08-24 21:03:35 +0000354 std::unique_ptr<const MCInstrInfo> MII(T->createMCInstrInfo());
Joel Galensonddf08922018-08-24 19:40:35 +0000355 std::unique_ptr<const MCInstrAnalysis> MIA(
Vitaly Bukaa4da4372018-08-24 21:03:35 +0000356 T->createMCInstrAnalysis(MII.get()));
Joel Galenson77a17af2018-08-24 15:21:56 +0000357 if (!MIA)
358 return {};
359 Optional<SectionRef> Plt = None, RelaPlt = None, GotPlt = None;
360 for (const SectionRef &Section : sections()) {
361 StringRef Name;
362 if (Section.getName(Name))
363 continue;
364 if (Name == ".plt")
365 Plt = Section;
366 else if (Name == ".rela.plt" || Name == ".rel.plt")
367 RelaPlt = Section;
368 else if (Name == ".got.plt")
369 GotPlt = Section;
370 }
371 if (!Plt || !RelaPlt || !GotPlt)
372 return {};
373 StringRef PltContents;
374 if (Plt->getContents(PltContents))
375 return {};
376 ArrayRef<uint8_t> PltBytes((const uint8_t *)PltContents.data(),
377 Plt->getSize());
378 auto PltEntries = MIA->findPltEntries(Plt->getAddress(), PltBytes,
379 GotPlt->getAddress(), Triple);
380 // Build a map from GOT entry virtual address to PLT entry virtual address.
381 DenseMap<uint64_t, uint64_t> GotToPlt;
382 for (const auto &Entry : PltEntries)
383 GotToPlt.insert(std::make_pair(Entry.second, Entry.first));
384 // Find the relocations in the dynamic relocation table that point to
385 // locations in the GOT for which we know the corresponding PLT entry.
386 std::vector<std::pair<DataRefImpl, uint64_t>> Result;
387 for (const auto &Relocation : RelaPlt->relocations()) {
388 if (Relocation.getType() != JumpSlotReloc)
389 continue;
390 auto PltEntryIter = GotToPlt.find(Relocation.getOffset());
391 if (PltEntryIter != GotToPlt.end())
392 Result.push_back(std::make_pair(
393 Relocation.getSymbol()->getRawDataRefImpl(), PltEntryIter->second));
394 }
395 return Result;
396}