blob: 0f2f31faca6cffc8d1b62e441ce1408e70d81964 [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
Nick Kledzikabb69812012-05-31 22:34:00 +000016#include "lld/ReaderWriter/ReaderELF.h"
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +000017#include "lld/ReaderWriter/ReaderArchive.h"
Michael J. Spencer842885e2013-01-15 21:12:45 +000018#include "lld/Core/ErrorOr.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000019#include "lld/Core/File.h"
Sid Manning8caf4de2012-09-17 12:49:38 +000020#include "lld/Core/Reference.h"
Michael J. Spencer6344b322012-12-20 00:37:10 +000021
Sid Manning1a601412012-07-25 16:27:21 +000022#include "llvm/ADT/ArrayRef.h"
Sid Manning8caf4de2012-09-17 12:49:38 +000023#include "llvm/ADT/SmallString.h"
Sid Manning1a601412012-07-25 16:27:21 +000024#include "llvm/ADT/StringRef.h"
25#include "llvm/Object/ELF.h"
26#include "llvm/Object/ObjectFile.h"
27#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000028#include "llvm/Support/Casting.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000029#include "llvm/Support/Path.h"
Sid Manning1a601412012-07-25 16:27:21 +000030#include "llvm/Support/ELF.h"
31#include "llvm/Support/Endian.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000032#include "llvm/Support/ErrorHandling.h"
Sid Manning1a601412012-07-25 16:27:21 +000033#include "llvm/Support/MathExtras.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000034#include "llvm/Support/Memory.h"
35#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer6344b322012-12-20 00:37:10 +000036#include "llvm/Support/Path.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000037#include "llvm/Support/raw_ostream.h"
38#include "llvm/Support/system_error.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000039#include "AtomsELF.h"
Sid Manning1a601412012-07-25 16:27:21 +000040
Nick Kledzikabb69812012-05-31 22:34:00 +000041#include <map>
42#include <vector>
43
Sid Manning1a601412012-07-25 16:27:21 +000044using namespace lld;
Michael J. Spencer6344b322012-12-20 00:37:10 +000045using llvm::support::endianness;
Michael J. Spencera2c97272013-01-04 21:09:21 +000046using namespace llvm::object;
Sid Manning1a601412012-07-25 16:27:21 +000047
Michael J. Spencer6344b322012-12-20 00:37:10 +000048namespace {
Michael J. Spencer6344b322012-12-20 00:37:10 +000049// \brief Read a binary, find out based on the symbol table contents what kind
50// of symbol it is and create corresponding atoms for it
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000051template<class ELFT>
Sid Manning1a601412012-07-25 16:27:21 +000052class FileELF: public File {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000053 typedef Elf_Sym_Impl<ELFT> Elf_Sym;
54 typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
55 typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
56 typedef Elf_Rel_Impl<ELFT, true> Elf_Rela;
Sid Manning1a601412012-07-25 16:27:21 +000057
58public:
Michael J. Spencer6344b322012-12-20 00:37:10 +000059 FileELF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
60 : File(MB->getBufferIdentifier()) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000061 llvm::OwningPtr<Binary> binaryFile;
62 EC = createBinary(MB.release(), binaryFile);
Sid Manning1a601412012-07-25 16:27:21 +000063 if (EC)
64 return;
65
66 // Point Obj to correct class and bitwidth ELF object
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000067 _objFile.reset(llvm::dyn_cast<ELFObjectFile<ELFT>>(binaryFile.get()));
Sid Manning1a601412012-07-25 16:27:21 +000068
Sid Manning8caf4de2012-09-17 12:49:38 +000069 if (!_objFile) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000070 EC = make_error_code(object_error::invalid_file_type);
Sid Manning1a601412012-07-25 16:27:21 +000071 return;
72 }
73
Sid Manning8caf4de2012-09-17 12:49:38 +000074 binaryFile.take();
Sid Manning1a601412012-07-25 16:27:21 +000075
Sid Manning8caf4de2012-09-17 12:49:38 +000076 std::map< const Elf_Shdr *, std::vector<const Elf_Sym *>> sectionSymbols;
Sid Manning1a601412012-07-25 16:27:21 +000077
Michael J. Spencer6344b322012-12-20 00:37:10 +000078 // Handle: SHT_REL and SHT_RELA sections:
79 // Increment over the sections, when REL/RELA section types are found add
80 // the contents to the RelocationReferences map.
Michael J. Spencera2c97272013-01-04 21:09:21 +000081 section_iterator sit(_objFile->begin_sections());
82 section_iterator sie(_objFile->end_sections());
Sid Manning8caf4de2012-09-17 12:49:38 +000083 for (; sit != sie; sit.increment(EC)) {
84 if (EC)
85 return;
86
87 const Elf_Shdr *section = _objFile->getElfSection(sit);
88
89 if (section->sh_type == llvm::ELF::SHT_RELA) {
90 llvm::StringRef sectionName;
91 if ((EC = _objFile->getSectionName(section, sectionName)))
92 return;
93 // Get rid of the leading .rela so Atoms can use their own section
94 // name to find the relocs.
95 sectionName = sectionName.drop_front(5);
96
97 auto rai(_objFile->beginELFRela(section));
98 auto rae(_objFile->endELFRela(section));
99
100 auto &Ref = _relocationAddendRefences[sectionName];
101 for (; rai != rae; rai++) {
102 Ref.push_back(&*rai);
103 }
104 }
105
106 if (section->sh_type == llvm::ELF::SHT_REL) {
107 llvm::StringRef sectionName;
108 if ((EC = _objFile->getSectionName(section, sectionName)))
109 return;
110 // Get rid of the leading .rel so Atoms can use their own section
111 // name to find the relocs.
112 sectionName = sectionName.drop_front(4);
113
114 auto ri(_objFile->beginELFRel(section));
115 auto re(_objFile->endELFRel(section));
116
117 auto &Ref = _relocationReferences[sectionName];
118 for (; ri != re; ri++) {
119 Ref.push_back(&*ri);
120 }
121 }
122 }
123
Michael J. Spencer6344b322012-12-20 00:37:10 +0000124 // Increment over all the symbols collecting atoms and symbol names for
125 // later use.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000126 symbol_iterator it(_objFile->begin_symbols());
127 symbol_iterator ie(_objFile->end_symbols());
Sid Manning1a601412012-07-25 16:27:21 +0000128
Sid Manning429a4bc2012-07-27 14:52:18 +0000129 for (; it != ie; it.increment(EC)) {
Sid Manning1a601412012-07-25 16:27:21 +0000130 if (EC)
Sid Manning429a4bc2012-07-27 14:52:18 +0000131 return;
Sid Manning1a601412012-07-25 16:27:21 +0000132
Sid Manning8caf4de2012-09-17 12:49:38 +0000133 if ((EC = it->getSection(sit)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000134 return;
Sid Manning1a601412012-07-25 16:27:21 +0000135
Sid Manning8caf4de2012-09-17 12:49:38 +0000136 const Elf_Shdr *section = _objFile->getElfSection(sit);
137 const Elf_Sym *symbol = _objFile->getElfSymbol(it);
Sid Manning1a601412012-07-25 16:27:21 +0000138
Sid Manning8caf4de2012-09-17 12:49:38 +0000139 llvm::StringRef symbolName;
140 if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000141 return;
Sid Manning1a601412012-07-25 16:27:21 +0000142
Sid Manning8caf4de2012-09-17 12:49:38 +0000143 if (symbol->st_shndx == llvm::ELF::SHN_ABS) {
Sid Manning1a601412012-07-25 16:27:21 +0000144 // Create an absolute atom.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000145 auto *newAtom = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000146 ELFAbsoluteAtom<ELFT> > ())
147 ELFAbsoluteAtom<ELFT>(
Michael J. Spencera2c97272013-01-04 21:09:21 +0000148 *this, symbolName, symbol, symbol->st_value);
Sid Manning1a601412012-07-25 16:27:21 +0000149
Sid Manning8caf4de2012-09-17 12:49:38 +0000150 _absoluteAtoms._atoms.push_back(newAtom);
151 _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
Sid Manning8caf4de2012-09-17 12:49:38 +0000152 } else if (symbol->st_shndx == llvm::ELF::SHN_UNDEF) {
Sid Manning1a601412012-07-25 16:27:21 +0000153 // Create an undefined atom.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000154 auto *newAtom = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000155 ELFUndefinedAtom<ELFT> > ())
156 ELFUndefinedAtom<ELFT>(
Michael J. Spencera2c97272013-01-04 21:09:21 +0000157 *this, symbolName, symbol);
Sid Manning8caf4de2012-09-17 12:49:38 +0000158
159 _undefinedAtoms._atoms.push_back(newAtom);
160 _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
Sid Manning1a601412012-07-25 16:27:21 +0000161 } else {
162 // This is actually a defined symbol. Add it to its section's list of
163 // symbols.
Sid Manning8caf4de2012-09-17 12:49:38 +0000164 if (symbol->getType() == llvm::ELF::STT_NOTYPE
165 || symbol->getType() == llvm::ELF::STT_OBJECT
166 || symbol->getType() == llvm::ELF::STT_FUNC
Michael J. Spencer65f61132013-01-04 21:25:25 +0000167 || symbol->getType() == llvm::ELF::STT_GNU_IFUNC
Sid Manning8caf4de2012-09-17 12:49:38 +0000168 || symbol->getType() == llvm::ELF::STT_SECTION
169 || symbol->getType() == llvm::ELF::STT_FILE
170 || symbol->getType() == llvm::ELF::STT_TLS
171 || symbol->getType() == llvm::ELF::STT_COMMON
172 || symbol->st_shndx == llvm::ELF::SHN_COMMON) {
173 sectionSymbols[section].push_back(symbol);
Michael J. Spencer6344b322012-12-20 00:37:10 +0000174 } else {
Sid Manning8caf4de2012-09-17 12:49:38 +0000175 llvm::errs() << "Unable to create atom for: " << symbolName << "\n";
Michael J. Spencera2c97272013-01-04 21:09:21 +0000176 EC = object_error::parse_failed;
Sid Manning1a601412012-07-25 16:27:21 +0000177 return;
178 }
179 }
180 }
181
Sid Manning8caf4de2012-09-17 12:49:38 +0000182 for (auto &i : sectionSymbols) {
183 auto &symbols = i.second;
Sid Manning1a601412012-07-25 16:27:21 +0000184 // Sort symbols by position.
Sid Manning8caf4de2012-09-17 12:49:38 +0000185 std::stable_sort(symbols.begin(), symbols.end(),
Michael J. Spencer6344b322012-12-20 00:37:10 +0000186 [](const Elf_Sym *A, const Elf_Sym *B) {
Sid Manning1a601412012-07-25 16:27:21 +0000187 return A->st_value < B->st_value;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000188 });
Sid Manning1a601412012-07-25 16:27:21 +0000189
Michael J. Spencer842885e2013-01-15 21:12:45 +0000190 StringRef sectionContents;
191 if ((EC = _objFile->getSectionContents(i.first, sectionContents)))
192 return;
193
194 llvm::StringRef sectionName;
195 if ((EC = _objFile->getSectionName(i.first, sectionName)))
196 return;
197
Sid Manning1a601412012-07-25 16:27:21 +0000198 // i.first is the section the symbol lives in
Sid Manning8caf4de2012-09-17 12:49:38 +0000199 for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000200 llvm::StringRef symbolName;
Sid Manning8caf4de2012-09-17 12:49:38 +0000201 if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000202 return;
Sid Manning1a601412012-07-25 16:27:21 +0000203
Michael J. Spencer842885e2013-01-15 21:12:45 +0000204 bool isCommon = (*si)->getType() == llvm::ELF::STT_COMMON ||
205 (*si)->st_shndx == llvm::ELF::SHN_COMMON;
Sid Manning1a601412012-07-25 16:27:21 +0000206
207 // Get the symbol's content:
Sid Manning8caf4de2012-09-17 12:49:38 +0000208 uint64_t contentSize;
Sid Manning1a601412012-07-25 16:27:21 +0000209 if (si + 1 == se) {
210 // if this is the last symbol, take up the remaining data.
Michael J. Spencer6344b322012-12-20 00:37:10 +0000211 contentSize = (isCommon) ? 0
Sid Manning8caf4de2012-09-17 12:49:38 +0000212 : ((i.first)->sh_size - (*si)->st_value);
Michael J. Spencer842885e2013-01-15 21:12:45 +0000213 } else {
Michael J. Spencer6344b322012-12-20 00:37:10 +0000214 contentSize = (isCommon) ? 0
Sid Manning8caf4de2012-09-17 12:49:38 +0000215 : (*(si + 1))->st_value - (*si)->st_value;
Sid Manning1a601412012-07-25 16:27:21 +0000216 }
217
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000218
219 // Don't allocate content to a weak symbol, as they may be merged away.
220 // Create an anonymous atom to hold the data.
221 ELFDefinedAtom<ELFT> *anonAtom = nullptr;
222 if ((*si)->getBinding() == llvm::ELF::STB_WEAK && contentSize != 0) {
223 // Create a new non-weak ELF symbol.
224 auto sym = new (_readerStorage.Allocate<Elf_Sym>()) Elf_Sym;
225 *sym = **si;
226 sym->setBinding(llvm::ELF::STB_GLOBAL);
227 anonAtom = createDefinedAtomAndAssignRelocations(
228 "", sectionName, sym, i.first,
229 ArrayRef<uint8_t>(
230 (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize));
231 contentSize = 0;
232 }
233
Michael J. Spencer842885e2013-01-15 21:12:45 +0000234 ArrayRef<uint8_t> symbolData = ArrayRef<uint8_t>(
235 (uint8_t *)sectionContents.data() + (*si)->st_value, contentSize);
Sid Manning8caf4de2012-09-17 12:49:38 +0000236
Michael J. Spencer842885e2013-01-15 21:12:45 +0000237 auto newAtom = createDefinedAtomAndAssignRelocations(
238 symbolName, sectionName, *si, i.first, symbolData);
Sid Manning8caf4de2012-09-17 12:49:38 +0000239
240 _definedAtoms._atoms.push_back(newAtom);
241 _symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
Michael J. Spencer8b3898a2013-01-15 21:13:02 +0000242 if (anonAtom)
243 _definedAtoms._atoms.push_back(anonAtom);
Sid Manning1a601412012-07-25 16:27:21 +0000244 }
245 }
Sid Manning8caf4de2012-09-17 12:49:38 +0000246
Michael J. Spencer6344b322012-12-20 00:37:10 +0000247 // All the Atoms and References are created. Now update each Reference's
248 // target with the Atom pointer it refers to.
Sid Manning8caf4de2012-09-17 12:49:38 +0000249 for (auto &ri : _references) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000250 const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
251 ri->setTarget(findAtom(Symbol));
Sid Manning8caf4de2012-09-17 12:49:38 +0000252 }
Sid Manning1a601412012-07-25 16:27:21 +0000253 }
254
Sid Manning1a601412012-07-25 16:27:21 +0000255 virtual const atom_collection<DefinedAtom> &defined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000256 return _definedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000257 }
258
259 virtual const atom_collection<UndefinedAtom> &undefined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000260 return _undefinedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000261 }
262
263 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000264 return _sharedLibraryAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000265 }
266
267 virtual const atom_collection<AbsoluteAtom> &absolute() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000268 return _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000269 }
270
Michael J. Spencer842885e2013-01-15 21:12:45 +0000271 Atom *findAtom(const Elf_Sym *symbol) {
272 return _symbolToAtomMapping.lookup(symbol);
Sid Manning8caf4de2012-09-17 12:49:38 +0000273 }
274
Sid Manning1a601412012-07-25 16:27:21 +0000275private:
Michael J. Spencer842885e2013-01-15 21:12:45 +0000276 ELFDefinedAtom<ELFT> *
277 createDefinedAtomAndAssignRelocations(StringRef symbolName,
278 StringRef sectionName,
279 const Elf_Sym *symbol,
280 const Elf_Shdr *section,
281 ArrayRef<uint8_t> content) {
282 unsigned int referenceStart = _references.size();
283
284 // Only relocations that are inside the domain of the atom are added.
285
286 // Add Rela (those with r_addend) references:
287 for (auto &rai : _relocationAddendRefences[sectionName]) {
288 if (!((rai->r_offset >= symbol->st_value) &&
289 (rai->r_offset < symbol->st_value + content.size())))
290 continue;
291 auto *ERef = new (_readerStorage.Allocate<ELFReference<ELFT>> ())
292 ELFReference<ELFT>(rai, rai->r_offset - symbol->st_value, nullptr);
293 _references.push_back(ERef);
294 }
295
296 // Add Rel references.
297 for (auto &ri : _relocationReferences[sectionName]) {
298 if ((ri->r_offset >= symbol->st_value) &&
299 (ri->r_offset < symbol->st_value + content.size())) {
300 auto *ERef = new (_readerStorage.Allocate<ELFReference<ELFT>>())
301 ELFReference<ELFT>(ri, ri->r_offset - symbol->st_value, nullptr);
302 _references.push_back(ERef);
303 }
304 }
305
306 // Create the DefinedAtom and add it to the list of DefinedAtoms.
307 return new (_readerStorage.Allocate<ELFDefinedAtom<ELFT>>())
308 ELFDefinedAtom<ELFT>(*this,
309 symbolName,
310 sectionName,
311 symbol,
312 section,
313 content,
314 referenceStart,
315 _references.size(),
316 _references);
317 }
318
319 std::unique_ptr<ELFObjectFile<ELFT>> _objFile;
Sid Manning8caf4de2012-09-17 12:49:38 +0000320 atom_collection_vector<DefinedAtom> _definedAtoms;
321 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
322 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
323 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000324
Michael J. Spencer6344b322012-12-20 00:37:10 +0000325 /// \brief _relocationAddendRefences and _relocationReferences contain the
326 /// list of relocations references. In ELF, if a section named, ".text" has
327 /// relocations will also have a section named ".rel.text" or ".rela.text"
328 /// which will hold the entries. -- .rel or .rela is prepended to create
329 /// the SHT_REL(A) section name.
Michael J. Spencer842885e2013-01-15 21:12:45 +0000330 std::map<llvm::StringRef, std::vector<const Elf_Rela *>>
331 _relocationAddendRefences;
332 std::map<llvm::StringRef, std::vector<const Elf_Rel *>>
333 _relocationReferences;
334 std::vector<ELFReference<ELFT> *> _references;
Sid Manning8caf4de2012-09-17 12:49:38 +0000335 llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
Sid Manning8caf4de2012-09-17 12:49:38 +0000336 llvm::BumpPtrAllocator _readerStorage;
Sid Manning1a601412012-07-25 16:27:21 +0000337};
338
Michael J. Spencer6344b322012-12-20 00:37:10 +0000339// \brief A reader object that will instantiate correct FileELF by examining the
Michael J. Spencer842885e2013-01-15 21:12:45 +0000340// memory buffer for ELF class and bit width
Sid Manning1a601412012-07-25 16:27:21 +0000341class ReaderELF: public Reader {
342public:
Michael J. Spencera5d22812012-11-13 19:58:58 +0000343 ReaderELF(const ReaderOptionsELF &,
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000344 ReaderOptionsArchive &readerOptionsArchive)
Michael J. Spencera5d22812012-11-13 19:58:58 +0000345 : _readerOptionsArchive(readerOptionsArchive)
Michael J. Spencer6344b322012-12-20 00:37:10 +0000346 , _readerArchive(_readerOptionsArchive) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000347 _readerOptionsArchive.setReader(this);
348 }
349
Michael J. Spencer842885e2013-01-15 21:12:45 +0000350 error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
351 std::vector<std::unique_ptr<File>> &result) {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000352 using llvm::object::ELFType;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000353 llvm::sys::LLVMFileType fileType =
Michael J. Spencer842885e2013-01-15 21:12:45 +0000354 llvm::sys::IdentifyFileType(mb->getBufferStart(),
355 static_cast<unsigned>(mb->getBufferSize()));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000356
357 std::size_t MaxAlignment =
358 1ULL << llvm::CountTrailingZeros_64(uintptr_t(mb->getBufferStart()));
359
Michael J. Spencer842885e2013-01-15 21:12:45 +0000360 llvm::error_code ec;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000361 switch (fileType) {
Michael J. Spencer842885e2013-01-15 21:12:45 +0000362 case llvm::sys::ELF_Relocatable_FileType: {
363 std::pair<unsigned char, unsigned char> Ident = getElfArchType(&*mb);
364 std::unique_ptr<File> f;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000365 // Instantiate the correct FileELF template instance based on the Ident
366 // pair. Once the File is created we push the file to the vector of files
367 // already created during parser's life.
Michael J. Spencera5d22812012-11-13 19:58:58 +0000368 if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
369 == llvm::ELF::ELFDATA2LSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000370 if (MaxAlignment >= 4)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000371 f.reset(new FileELF<ELFType<llvm::support::little, 4, false>>(
372 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000373 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000374 f.reset(new FileELF<ELFType<llvm::support::little, 2, false>>(
375 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000376 else
377 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000378 } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
379 == llvm::ELF::ELFDATA2MSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000380 if (MaxAlignment >= 4)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000381 f.reset(new FileELF<ELFType<llvm::support::big, 4, false>>(
382 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000383 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000384 f.reset(new FileELF<ELFType<llvm::support::big, 2, false>>(
385 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000386 else
387 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000388 } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
389 == llvm::ELF::ELFDATA2MSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000390 if (MaxAlignment >= 8)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000391 f.reset(new FileELF<ELFType<llvm::support::big, 8, true>>(
392 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000393 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000394 f.reset(new FileELF<ELFType<llvm::support::big, 2, true>>(
395 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000396 else
397 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000398 } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
399 == llvm::ELF::ELFDATA2LSB) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000400 if (MaxAlignment >= 8)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000401 f.reset(new FileELF<ELFType<llvm::support::little, 8, true>>(
402 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000403 else if (MaxAlignment >= 2)
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000404 f.reset(new FileELF<ELFType<llvm::support::little, 2, true>>(
405 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000406 else
407 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000408 }
409 if (!ec)
410 result.push_back(std::move(f));
411 break;
Michael J. Spencer842885e2013-01-15 21:12:45 +0000412 }
Michael J. Spencera5d22812012-11-13 19:58:58 +0000413 case llvm::sys::Archive_FileType:
414 ec = _readerArchive.parseFile(std::move(mb), result);
415 break;
Michael J. Spencera5d22812012-11-13 19:58:58 +0000416 default:
417 llvm_unreachable("not supported format");
418 break;
Sid Manning1a601412012-07-25 16:27:21 +0000419 }
420
421 if (ec)
422 return ec;
423
Sid Manning1a601412012-07-25 16:27:21 +0000424 return error_code::success();
425 }
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000426
427private:
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000428 ReaderOptionsArchive &_readerOptionsArchive;
429 ReaderArchive _readerArchive;
Sid Manning1a601412012-07-25 16:27:21 +0000430};
Michael J. Spencer6344b322012-12-20 00:37:10 +0000431} // end anon namespace.
Nick Kledzikabb69812012-05-31 22:34:00 +0000432
433namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +0000434ReaderOptionsELF::ReaderOptionsELF() {
435}
436
437ReaderOptionsELF::~ReaderOptionsELF() {
438}
439
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000440Reader *createReaderELF(const ReaderOptionsELF &options,
441 ReaderOptionsArchive &optionsArchive) {
442 return new ReaderELF(options, optionsArchive);
Nick Kledzikabb69812012-05-31 22:34:00 +0000443}
Michael J. Spencer6344b322012-12-20 00:37:10 +0000444} // end namespace lld