blob: deaf66354c44216d7716cebf2631282a3b2f41dc [file] [log] [blame]
Michael J. Spencer6344b322012-12-20 00:37:10 +00001//===- lib/ReaderWriter/ELF/ReaderELF.cpp ---------------------------------===//
Nick Kledzikabb69812012-05-31 22:34:00 +00002//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Michael J. Spencer6344b322012-12-20 00:37:10 +00009///
10/// \file
11/// \brief Defines the ELF Reader and all helper sub classes to consume an ELF
12/// file and produces atoms out of it.
13///
Sid Manning1a601412012-07-25 16:27:21 +000014//===----------------------------------------------------------------------===//
Michael J. Spencer6344b322012-12-20 00:37:10 +000015
Michael J. Spencer64afcb42013-01-23 01:18:43 +000016#include "lld/ReaderWriter/Reader.h"
17
Nick Kledzikabb69812012-05-31 22:34:00 +000018#include "lld/Core/File.h"
Sid Manning8caf4de2012-09-17 12:49:38 +000019#include "lld/Core/Reference.h"
Michael J. Spencer64afcb42013-01-23 01:18:43 +000020#include "lld/ReaderWriter/ELFTargetInfo.h"
21#include "lld/ReaderWriter/ReaderArchive.h"
Michael J. Spencer6344b322012-12-20 00:37:10 +000022
Sid Manning1a601412012-07-25 16:27:21 +000023#include "llvm/ADT/ArrayRef.h"
Sid Manning8caf4de2012-09-17 12:49:38 +000024#include "llvm/ADT/SmallString.h"
Sid Manning1a601412012-07-25 16:27:21 +000025#include "llvm/ADT/StringRef.h"
26#include "llvm/Object/ELF.h"
27#include "llvm/Object/ObjectFile.h"
28#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000029#include "llvm/Support/Casting.h"
Michael J. Spencer8af48f32013-01-20 21:27:05 +000030#include "llvm/Support/ErrorOr.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000031#include "llvm/Support/Path.h"
Sid Manning1a601412012-07-25 16:27:21 +000032#include "llvm/Support/ELF.h"
33#include "llvm/Support/Endian.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000034#include "llvm/Support/ErrorHandling.h"
Sid Manning1a601412012-07-25 16:27:21 +000035#include "llvm/Support/MathExtras.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000036#include "llvm/Support/Memory.h"
37#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer6344b322012-12-20 00:37:10 +000038#include "llvm/Support/Path.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000039#include "llvm/Support/raw_ostream.h"
40#include "llvm/Support/system_error.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000041#include "AtomsELF.h"
Sid Manning1a601412012-07-25 16:27:21 +000042
Nick Kledzikabb69812012-05-31 22:34:00 +000043#include <map>
44#include <vector>
45
Sid Manning1a601412012-07-25 16:27:21 +000046using namespace lld;
Michael J. Spencer6344b322012-12-20 00:37:10 +000047using llvm::support::endianness;
Michael J. Spencera2c97272013-01-04 21:09:21 +000048using namespace llvm::object;
Sid Manning1a601412012-07-25 16:27:21 +000049
Michael J. Spencer6344b322012-12-20 00:37:10 +000050namespace {
Michael J. Spencer84d3b012013-01-16 23:34:32 +000051/// \brief Read a binary, find out based on the symbol table contents what kind
52/// of symbol it is and create corresponding atoms for it
53template <class ELFT> class FileELF : public File {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000054 typedef Elf_Sym_Impl<ELFT> Elf_Sym;
55 typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
56 typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
57 typedef Elf_Rel_Impl<ELFT, true> Elf_Rela;
Sid Manning1a601412012-07-25 16:27:21 +000058
59public:
Michael J. Spencer6344b322012-12-20 00:37:10 +000060 FileELF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
Michael J. Spencer84d3b012013-01-16 23:34:32 +000061 : File(MB->getBufferIdentifier()) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000062 llvm::OwningPtr<Binary> binaryFile;
63 EC = createBinary(MB.release(), binaryFile);
Sid Manning1a601412012-07-25 16:27:21 +000064 if (EC)
65 return;
66
67 // Point Obj to correct class and bitwidth ELF object
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000068 _objFile.reset(llvm::dyn_cast<ELFObjectFile<ELFT>>(binaryFile.get()));
Sid Manning1a601412012-07-25 16:27:21 +000069
Sid Manning8caf4de2012-09-17 12:49:38 +000070 if (!_objFile) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000071 EC = make_error_code(object_error::invalid_file_type);
Sid Manning1a601412012-07-25 16:27:21 +000072 return;
73 }
74
Sid Manning8caf4de2012-09-17 12:49:38 +000075 binaryFile.take();
Sid Manning1a601412012-07-25 16:27:21 +000076
Michael J. Spencer84d3b012013-01-16 23:34:32 +000077 std::map<const Elf_Shdr *, std::vector<const Elf_Sym *>> sectionSymbols;
Sid Manning1a601412012-07-25 16:27:21 +000078
Michael J. Spencer6344b322012-12-20 00:37:10 +000079 // Handle: SHT_REL and SHT_RELA sections:
80 // Increment over the sections, when REL/RELA section types are found add
81 // the contents to the RelocationReferences map.
Michael J. Spencera2c97272013-01-04 21:09:21 +000082 section_iterator sit(_objFile->begin_sections());
83 section_iterator sie(_objFile->end_sections());
Sid Manning8caf4de2012-09-17 12:49:38 +000084 for (; sit != sie; sit.increment(EC)) {
85 if (EC)
86 return;
87
88 const Elf_Shdr *section = _objFile->getElfSection(sit);
89
90 if (section->sh_type == llvm::ELF::SHT_RELA) {
91 llvm::StringRef sectionName;
92 if ((EC = _objFile->getSectionName(section, sectionName)))
93 return;
94 // Get rid of the leading .rela so Atoms can use their own section
95 // name to find the relocs.
96 sectionName = sectionName.drop_front(5);
97
98 auto rai(_objFile->beginELFRela(section));
99 auto rae(_objFile->endELFRela(section));
100
101 auto &Ref = _relocationAddendRefences[sectionName];
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000102 for (; rai != rae; ++rai) {
Sid Manning8caf4de2012-09-17 12:49:38 +0000103 Ref.push_back(&*rai);
104 }
105 }
106
107 if (section->sh_type == llvm::ELF::SHT_REL) {
108 llvm::StringRef sectionName;
109 if ((EC = _objFile->getSectionName(section, sectionName)))
110 return;
111 // Get rid of the leading .rel so Atoms can use their own section
112 // name to find the relocs.
113 sectionName = sectionName.drop_front(4);
114
115 auto ri(_objFile->beginELFRel(section));
116 auto re(_objFile->endELFRel(section));
117
118 auto &Ref = _relocationReferences[sectionName];
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000119 for (; ri != re; ++ri) {
Sid Manning8caf4de2012-09-17 12:49:38 +0000120 Ref.push_back(&*ri);
121 }
122 }
123 }
124
Michael J. Spencer6344b322012-12-20 00:37:10 +0000125 // Increment over all the symbols collecting atoms and symbol names for
126 // later use.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000127 symbol_iterator it(_objFile->begin_symbols());
128 symbol_iterator ie(_objFile->end_symbols());
Sid Manning1a601412012-07-25 16:27:21 +0000129
Sid Manning429a4bc2012-07-27 14:52:18 +0000130 for (; it != ie; it.increment(EC)) {
Sid Manning1a601412012-07-25 16:27:21 +0000131 if (EC)
Sid Manning429a4bc2012-07-27 14:52:18 +0000132 return;
Sid Manning1a601412012-07-25 16:27:21 +0000133
Sid Manning8caf4de2012-09-17 12:49:38 +0000134 if ((EC = it->getSection(sit)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000135 return;
Sid Manning1a601412012-07-25 16:27:21 +0000136
Sid Manning8caf4de2012-09-17 12:49:38 +0000137 const Elf_Shdr *section = _objFile->getElfSection(sit);
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000138 const Elf_Sym *symbol = _objFile->getElfSymbol(it);
Sid Manning1a601412012-07-25 16:27:21 +0000139
Sid Manning8caf4de2012-09-17 12:49:38 +0000140 llvm::StringRef symbolName;
141 if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000142 return;
Sid Manning1a601412012-07-25 16:27:21 +0000143
Sid Manning8caf4de2012-09-17 12:49:38 +0000144 if (symbol->st_shndx == llvm::ELF::SHN_ABS) {
Sid Manning1a601412012-07-25 16:27:21 +0000145 // Create an absolute atom.
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000146 auto *newAtom = new (_readerStorage)
147 ELFAbsoluteAtom<ELFT>(*this, symbolName, symbol, symbol->st_value);
Sid Manning1a601412012-07-25 16:27:21 +0000148
Sid Manning8caf4de2012-09-17 12:49:38 +0000149 _absoluteAtoms._atoms.push_back(newAtom);
150 _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
Sid Manning8caf4de2012-09-17 12:49:38 +0000151 } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) {
Sid Manning1a601412012-07-25 16:27:21 +0000152 // Create an undefined atom.
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000153 auto *newAtom = new (_readerStorage)
154 ELFUndefinedAtom<ELFT>(*this, symbolName, symbol);
Sid Manning8caf4de2012-09-17 12:49:38 +0000155
156 _undefinedAtoms._atoms.push_back(newAtom);
157 _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
Sid Manning1a601412012-07-25 16:27:21 +0000158 } else {
159 // This is actually a defined symbol. Add it to its section's list of
160 // symbols.
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000161 if (symbol->getType() == llvm::ELF::STT_NOTYPE ||
162 symbol->getType() == llvm::ELF::STT_OBJECT ||
163 symbol->getType() == llvm::ELF::STT_FUNC ||
164 symbol->getType() == llvm::ELF::STT_GNU_IFUNC ||
165 symbol->getType() == llvm::ELF::STT_SECTION ||
166 symbol->getType() == llvm::ELF::STT_FILE ||
167 symbol->getType() == llvm::ELF::STT_TLS ||
168 symbol->getType() == llvm::ELF::STT_COMMON ||
169 symbol->st_shndx == llvm::ELF::SHN_COMMON) {
Sid Manning8caf4de2012-09-17 12:49:38 +0000170 sectionSymbols[section].push_back(symbol);
Michael J. Spencer6344b322012-12-20 00:37:10 +0000171 } else {
Sid Manning8caf4de2012-09-17 12:49:38 +0000172 llvm::errs() << "Unable to create atom for: " << symbolName << "\n";
Michael J. Spencera2c97272013-01-04 21:09:21 +0000173 EC = object_error::parse_failed;
Sid Manning1a601412012-07-25 16:27:21 +0000174 return;
175 }
176 }
177 }
178
Sid Manning8caf4de2012-09-17 12:49:38 +0000179 for (auto &i : sectionSymbols) {
180 auto &symbols = i.second;
Sid Manning1a601412012-07-25 16:27:21 +0000181 // Sort symbols by position.
Sid Manning8caf4de2012-09-17 12:49:38 +0000182 std::stable_sort(symbols.begin(), symbols.end(),
Michael J. Spencer6344b322012-12-20 00:37:10 +0000183 [](const Elf_Sym *A, const Elf_Sym *B) {
Sid Manning1a601412012-07-25 16:27:21 +0000184 return A->st_value < B->st_value;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000185 });
Sid Manning1a601412012-07-25 16:27:21 +0000186
Michael J. Spencer842885e2013-01-15 21:12:45 +0000187 StringRef sectionContents;
188 if ((EC = _objFile->getSectionContents(i.first, sectionContents)))
189 return;
190
191 llvm::StringRef sectionName;
192 if ((EC = _objFile->getSectionName(i.first, sectionName)))
193 return;
194
Sid Manning1a601412012-07-25 16:27:21 +0000195 // i.first is the section the symbol lives in
Sid Manning8caf4de2012-09-17 12:49:38 +0000196 for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000197 llvm::StringRef symbolName;
Sid Manning8caf4de2012-09-17 12:49:38 +0000198 if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000199 return;
Sid Manning1a601412012-07-25 16:27:21 +0000200
Michael J. Spencer842885e2013-01-15 21:12:45 +0000201 bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON ||
202 (*si)->st_shndx == llvm::ELF::SHN_COMMON;
Sid Manning1a601412012-07-25 16:27:21 +0000203
204 // Get the symbol's content:
Sid Manning8caf4de2012-09-17 12:49:38 +0000205 uint64_t contentSize;
Sid Manning1a601412012-07-25 16:27:21 +0000206 if (si + 1 == se) {
207 // if this is the last symbol, take up the remaining data.
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000208 contentSize = isCommon ? 0
209 : i.first->sh_size - (*si)->st_value;
Michael J. Spencer842885e2013-01-15 21:12:45 +0000210 } else {
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000211 contentSize = isCommon ? 0
212 : (*(si + 1))->st_value - (*si)->st_value;
Sid Manning1a601412012-07-25 16:27:21 +0000213 }
214
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000215 // Don't allocate content to a weak symbol, as they may be merged away.
216 // Create an anonymous atom to hold the data.
217 ELFDefinedAtom<ELFT> *anonAtom = nullptr;
218 if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) {
219 // Create a new non-weak ELF symbol.
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000220 auto sym = new (_readerStorage) Elf_Sym;
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000221 *sym = **si;
222 sym->setBinding(llvm::ELF::STB_GLOBAL);
223 anonAtom = createDefinedAtomAndAssignRelocations(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000224 "", sectionName, sym, i.first,
225 ArrayRef<uint8_t>((uint8_t *)sectionContents.data() +
226 (*si)->st_value, contentSize));
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000227 contentSize = 0;
228 }
229
Michael J. Spencer842885e2013-01-15 21:12:45 +0000230 ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000231 (uint8_t *)sectionContents.data() +
232 (*si)->st_value, contentSize);
Sid Manning8caf4de2012-09-17 12:49:38 +0000233
Michael J. Spencer842885e2013-01-15 21:12:45 +0000234 auto newAtom = createDefinedAtomAndAssignRelocations(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000235 symbolName, sectionName, *si, i.first, symbolData);
Sid Manning8caf4de2012-09-17 12:49:38 +0000236
237 _definedAtoms._atoms.push_back(newAtom);
238 _symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000239 if (anonAtom)
240 _definedAtoms._atoms.push_back(anonAtom);
Sid Manning1a601412012-07-25 16:27:21 +0000241 }
242 }
Sid Manning8caf4de2012-09-17 12:49:38 +0000243
Michael J. Spencer6344b322012-12-20 00:37:10 +0000244 // All the Atoms and References are created. Now update each Reference's
245 // target with the Atom pointer it refers to.
Sid Manning8caf4de2012-09-17 12:49:38 +0000246 for (auto &ri : _references) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000247 const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
248 ri->setTarget(findAtom(Symbol));
Sid Manning8caf4de2012-09-17 12:49:38 +0000249 }
Sid Manning1a601412012-07-25 16:27:21 +0000250 }
251
Sid Manning1a601412012-07-25 16:27:21 +0000252 virtual const atom_collection<DefinedAtom> &defined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000253 return _definedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000254 }
255
256 virtual const atom_collection<UndefinedAtom> &undefined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000257 return _undefinedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000258 }
259
260 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000261 return _sharedLibraryAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000262 }
263
264 virtual const atom_collection<AbsoluteAtom> &absolute() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000265 return _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000266 }
267
Michael J. Spencer842885e2013-01-15 21:12:45 +0000268 Atom *findAtom(const Elf_Sym *symbol) {
269 return _symbolToAtomMapping.lookup(symbol);
Sid Manning8caf4de2012-09-17 12:49:38 +0000270 }
271
Sid Manning1a601412012-07-25 16:27:21 +0000272private:
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000273 ELFDefinedAtom<ELFT> *createDefinedAtomAndAssignRelocations(
274 StringRef symbolName, StringRef sectionName, const Elf_Sym *symbol,
275 const Elf_Shdr *section, ArrayRef<uint8_t> content) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000276 unsigned int referenceStart = _references.size();
277
278 // Only relocations that are inside the domain of the atom are added.
279
280 // Add Rela (those with r_addend) references:
281 for (auto &rai : _relocationAddendRefences[sectionName]) {
282 if (!((rai->r_offset >= symbol->st_value) &&
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000283 (rai->r_offset < symbol->st_value + content.size())))
Michael J. Spencer842885e2013-01-15 21:12:45 +0000284 continue;
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000285 auto *ERef = new (_readerStorage)
286 ELFReference<ELFT>(rai, rai->r_offset - symbol->st_value, nullptr);
Michael J. Spencer842885e2013-01-15 21:12:45 +0000287 _references.push_back(ERef);
288 }
289
290 // Add Rel references.
291 for (auto &ri : _relocationReferences[sectionName]) {
292 if ((ri->r_offset >= symbol->st_value) &&
293 (ri->r_offset < symbol->st_value + content.size())) {
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000294 auto *ERef = new (_readerStorage)
295 ELFReference<ELFT>(ri, ri->r_offset - symbol->st_value, nullptr);
Michael J. Spencer842885e2013-01-15 21:12:45 +0000296 _references.push_back(ERef);
297 }
298 }
299
300 // Create the DefinedAtom and add it to the list of DefinedAtoms.
Michael J. Spencer71c00f42013-01-16 23:34:45 +0000301 return new (_readerStorage)
302 ELFDefinedAtom<ELFT>(*this, symbolName, sectionName, symbol, section,
303 content, referenceStart, _references.size(),
304 _references);
Michael J. Spencer842885e2013-01-15 21:12:45 +0000305 }
306
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000307 std::unique_ptr<ELFObjectFile<ELFT>> _objFile;
308 atom_collection_vector<DefinedAtom> _definedAtoms;
309 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
Sid Manning8caf4de2012-09-17 12:49:38 +0000310 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000311 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000312
Michael J. Spencer6344b322012-12-20 00:37:10 +0000313 /// \brief _relocationAddendRefences and _relocationReferences contain the
314 /// list of relocations references. In ELF, if a section named, ".text" has
315 /// relocations will also have a section named ".rel.text" or ".rela.text"
316 /// which will hold the entries. -- .rel or .rela is prepended to create
317 /// the SHT_REL(A) section name.
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000318 std::map<llvm::StringRef,
319 std::vector<const Elf_Rela *>> _relocationAddendRefences;
320 std::map<llvm::StringRef,
321 std::vector<const Elf_Rel *>> _relocationReferences;
Michael J. Spencer842885e2013-01-15 21:12:45 +0000322 std::vector<ELFReference<ELFT> *> _references;
Sid Manning8caf4de2012-09-17 12:49:38 +0000323 llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
Sid Manning8caf4de2012-09-17 12:49:38 +0000324 llvm::BumpPtrAllocator _readerStorage;
Sid Manning1a601412012-07-25 16:27:21 +0000325};
326
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000327/// \brief A reader object that will instantiate correct FileELF by examining the
328/// memory buffer for ELF class and bit width
329class ReaderELF : public Reader {
Sid Manning1a601412012-07-25 16:27:21 +0000330public:
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000331 ReaderELF(const TargetInfo & ti, std::function<ReaderFunc> read)
332 : Reader(ti),
333 _readerArchive(ti, read) {}
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000334
Michael J. Spencer842885e2013-01-15 21:12:45 +0000335 error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
336 std::vector<std::unique_ptr<File>> &result) {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000337 using llvm::object::ELFType;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000338 llvm::sys::LLVMFileType fileType =
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000339 llvm::sys::IdentifyFileType(mb->getBufferStart(),
340 static_cast<unsigned>(mb->getBufferSize()));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000341
342 std::size_t MaxAlignment =
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000343 1ULL << llvm::CountTrailingZeros_64(uintptr_t(mb->getBufferStart()));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000344
Michael J. Spencer842885e2013-01-15 21:12:45 +0000345 llvm::error_code ec;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000346 switch (fileType) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000347 case llvm::sys::ELF_Relocatable_FileType: {
348 std::pair<unsigned char, unsigned char> Ident = getElfArchType(&*mb);
349 std::unique_ptr<File> f;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000350 // Instantiate the correct FileELF template instance based on the Ident
351 // pair. Once the File is created we push the file to the vector of files
352 // already created during parser's life.
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000353 if (Ident.first == llvm::ELF::ELFCLASS32 &&
354 Ident.second == llvm::ELF::ELFDATA2LSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000355 if (MaxAlignment >= 4)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000356 f.reset(new FileELF<ELFType<llvm::support::little, 4, false>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000357 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000358 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000359 f.reset(new FileELF<ELFType<llvm::support::little, 2, false>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000360 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000361 else
362 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000363 } else if (Ident.first == llvm::ELF::ELFCLASS32 &&
364 Ident.second == llvm::ELF::ELFDATA2MSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000365 if (MaxAlignment >= 4)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000366 f.reset(new FileELF<ELFType<llvm::support::big, 4, false>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000367 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000368 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000369 f.reset(new FileELF<ELFType<llvm::support::big, 2, false>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000370 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000371 else
372 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000373 } else if (Ident.first == llvm::ELF::ELFCLASS64 &&
374 Ident.second == llvm::ELF::ELFDATA2MSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000375 if (MaxAlignment >= 8)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000376 f.reset(new FileELF<ELFType<llvm::support::big, 8, true>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000377 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000378 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000379 f.reset(new FileELF<ELFType<llvm::support::big, 2, true>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000380 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000381 else
382 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000383 } else if (Ident.first == llvm::ELF::ELFCLASS64 &&
384 Ident.second == llvm::ELF::ELFDATA2LSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000385 if (MaxAlignment >= 8)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000386 f.reset(new FileELF<ELFType<llvm::support::little, 8, true>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000387 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000388 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000389 f.reset(new FileELF<ELFType<llvm::support::little, 2, true>>(
Michael J. Spencer84d3b012013-01-16 23:34:32 +0000390 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000391 else
392 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000393 }
394 if (!ec)
395 result.push_back(std::move(f));
396 break;
Michael J. Spencer842885e2013-01-15 21:12:45 +0000397 }
Michael J. Spencera5d22812012-11-13 19:58:58 +0000398 case llvm::sys::Archive_FileType:
399 ec = _readerArchive.parseFile(std::move(mb), result);
400 break;
Michael J. Spencera5d22812012-11-13 19:58:58 +0000401 default:
402 llvm_unreachable("not supported format");
403 break;
Sid Manning1a601412012-07-25 16:27:21 +0000404 }
405
406 if (ec)
407 return ec;
408
Sid Manning1a601412012-07-25 16:27:21 +0000409 return error_code::success();
410 }
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000411
412private:
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000413 ReaderArchive _readerArchive;
Sid Manning1a601412012-07-25 16:27:21 +0000414};
Michael J. Spencer6344b322012-12-20 00:37:10 +0000415} // end anon namespace.
Nick Kledzikabb69812012-05-31 22:34:00 +0000416
417namespace lld {
Michael J. Spencer64afcb42013-01-23 01:18:43 +0000418std::unique_ptr<Reader> createReaderELF(const TargetInfo & ti,
419 std::function<ReaderFunc> read) {
420 return std::unique_ptr<Reader>(new ReaderELF(ti, std::move(read)));
Nick Kledzikabb69812012-05-31 22:34:00 +0000421}
Michael J. Spencer6344b322012-12-20 00:37:10 +0000422} // end namespace lld