blob: 53871a9bff8f73c12b25ea361f7666f4eaedc1a9 [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"
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. Spencer6344b322012-12-20 00:37:10 +000020
Sid Manning1a601412012-07-25 16:27:21 +000021#include "llvm/ADT/ArrayRef.h"
Sid Manning8caf4de2012-09-17 12:49:38 +000022#include "llvm/ADT/SmallString.h"
Sid Manning1a601412012-07-25 16:27:21 +000023#include "llvm/ADT/StringRef.h"
24#include "llvm/Object/ELF.h"
25#include "llvm/Object/ObjectFile.h"
26#include "llvm/Support/Allocator.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000027#include "llvm/Support/Casting.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000028#include "llvm/Support/Path.h"
Sid Manning1a601412012-07-25 16:27:21 +000029#include "llvm/Support/ELF.h"
30#include "llvm/Support/Endian.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000031#include "llvm/Support/ErrorHandling.h"
Sid Manning1a601412012-07-25 16:27:21 +000032#include "llvm/Support/MathExtras.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000033#include "llvm/Support/Memory.h"
34#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer6344b322012-12-20 00:37:10 +000035#include "llvm/Support/Path.h"
Nick Kledzikabb69812012-05-31 22:34:00 +000036#include "llvm/Support/raw_ostream.h"
37#include "llvm/Support/system_error.h"
Shankar Easwaranbbf9ddd2012-12-27 01:40:08 +000038#include "AtomsELF.h"
Sid Manning1a601412012-07-25 16:27:21 +000039
Nick Kledzikabb69812012-05-31 22:34:00 +000040#include <map>
41#include <vector>
42
Sid Manning1a601412012-07-25 16:27:21 +000043using namespace lld;
Michael J. Spencer6344b322012-12-20 00:37:10 +000044using llvm::support::endianness;
Michael J. Spencera2c97272013-01-04 21:09:21 +000045using namespace llvm::object;
Sid Manning1a601412012-07-25 16:27:21 +000046
Michael J. Spencer6344b322012-12-20 00:37:10 +000047namespace {
Michael J. Spencer6344b322012-12-20 00:37:10 +000048// \brief Read a binary, find out based on the symbol table contents what kind
49// of symbol it is and create corresponding atoms for it
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000050template<class ELFT>
Sid Manning1a601412012-07-25 16:27:21 +000051class FileELF: public File {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000052 typedef Elf_Sym_Impl<ELFT> Elf_Sym;
53 typedef Elf_Shdr_Impl<ELFT> Elf_Shdr;
54 typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
55 typedef Elf_Rel_Impl<ELFT, true> Elf_Rela;
Sid Manning1a601412012-07-25 16:27:21 +000056
57public:
Michael J. Spencer6344b322012-12-20 00:37:10 +000058 FileELF(std::unique_ptr<llvm::MemoryBuffer> MB, llvm::error_code &EC)
59 : File(MB->getBufferIdentifier()) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000060 llvm::OwningPtr<Binary> binaryFile;
61 EC = createBinary(MB.release(), binaryFile);
Sid Manning1a601412012-07-25 16:27:21 +000062 if (EC)
63 return;
64
65 // Point Obj to correct class and bitwidth ELF object
Michael J. Spencerb03f6c42013-01-15 07:53:22 +000066 _objFile.reset(llvm::dyn_cast<ELFObjectFile<ELFT>>(binaryFile.get()));
Sid Manning1a601412012-07-25 16:27:21 +000067
Sid Manning8caf4de2012-09-17 12:49:38 +000068 if (!_objFile) {
Michael J. Spencera2c97272013-01-04 21:09:21 +000069 EC = make_error_code(object_error::invalid_file_type);
Sid Manning1a601412012-07-25 16:27:21 +000070 return;
71 }
72
Sid Manning8caf4de2012-09-17 12:49:38 +000073 binaryFile.take();
Sid Manning1a601412012-07-25 16:27:21 +000074
Sid Manning8caf4de2012-09-17 12:49:38 +000075 std::map< const Elf_Shdr *, std::vector<const Elf_Sym *>> sectionSymbols;
Sid Manning1a601412012-07-25 16:27:21 +000076
Michael J. Spencer6344b322012-12-20 00:37:10 +000077 // Handle: SHT_REL and SHT_RELA sections:
78 // Increment over the sections, when REL/RELA section types are found add
79 // the contents to the RelocationReferences map.
Michael J. Spencera2c97272013-01-04 21:09:21 +000080 section_iterator sit(_objFile->begin_sections());
81 section_iterator sie(_objFile->end_sections());
Sid Manning8caf4de2012-09-17 12:49:38 +000082 for (; sit != sie; sit.increment(EC)) {
83 if (EC)
84 return;
85
86 const Elf_Shdr *section = _objFile->getElfSection(sit);
87
88 if (section->sh_type == llvm::ELF::SHT_RELA) {
89 llvm::StringRef sectionName;
90 if ((EC = _objFile->getSectionName(section, sectionName)))
91 return;
92 // Get rid of the leading .rela so Atoms can use their own section
93 // name to find the relocs.
94 sectionName = sectionName.drop_front(5);
95
96 auto rai(_objFile->beginELFRela(section));
97 auto rae(_objFile->endELFRela(section));
98
99 auto &Ref = _relocationAddendRefences[sectionName];
100 for (; rai != rae; rai++) {
101 Ref.push_back(&*rai);
102 }
103 }
104
105 if (section->sh_type == llvm::ELF::SHT_REL) {
106 llvm::StringRef sectionName;
107 if ((EC = _objFile->getSectionName(section, sectionName)))
108 return;
109 // Get rid of the leading .rel so Atoms can use their own section
110 // name to find the relocs.
111 sectionName = sectionName.drop_front(4);
112
113 auto ri(_objFile->beginELFRel(section));
114 auto re(_objFile->endELFRel(section));
115
116 auto &Ref = _relocationReferences[sectionName];
117 for (; ri != re; ri++) {
118 Ref.push_back(&*ri);
119 }
120 }
121 }
122
Michael J. Spencer6344b322012-12-20 00:37:10 +0000123 // Increment over all the symbols collecting atoms and symbol names for
124 // later use.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000125 symbol_iterator it(_objFile->begin_symbols());
126 symbol_iterator ie(_objFile->end_symbols());
Sid Manning1a601412012-07-25 16:27:21 +0000127
Sid Manning429a4bc2012-07-27 14:52:18 +0000128 for (; it != ie; it.increment(EC)) {
Sid Manning1a601412012-07-25 16:27:21 +0000129 if (EC)
Sid Manning429a4bc2012-07-27 14:52:18 +0000130 return;
Sid Manning1a601412012-07-25 16:27:21 +0000131
Sid Manning8caf4de2012-09-17 12:49:38 +0000132 if ((EC = it->getSection(sit)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000133 return;
Sid Manning1a601412012-07-25 16:27:21 +0000134
Sid Manning8caf4de2012-09-17 12:49:38 +0000135 const Elf_Shdr *section = _objFile->getElfSection(sit);
136 const Elf_Sym *symbol = _objFile->getElfSymbol(it);
Sid Manning1a601412012-07-25 16:27:21 +0000137
Sid Manning8caf4de2012-09-17 12:49:38 +0000138 llvm::StringRef symbolName;
139 if ((EC = _objFile->getSymbolName(section, symbol, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000140 return;
Sid Manning1a601412012-07-25 16:27:21 +0000141
Sid Manning8caf4de2012-09-17 12:49:38 +0000142 if (symbol->st_shndx == llvm::ELF::SHN_ABS) {
Sid Manning1a601412012-07-25 16:27:21 +0000143 // Create an absolute atom.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000144 auto *newAtom = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000145 ELFAbsoluteAtom<ELFT> > ())
146 ELFAbsoluteAtom<ELFT>(
Michael J. Spencera2c97272013-01-04 21:09:21 +0000147 *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. Spencera2c97272013-01-04 21:09:21 +0000153 auto *newAtom = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000154 ELFUndefinedAtom<ELFT> > ())
155 ELFUndefinedAtom<ELFT>(
Michael J. Spencera2c97272013-01-04 21:09:21 +0000156 *this, symbolName, symbol);
Sid Manning8caf4de2012-09-17 12:49:38 +0000157
158 _undefinedAtoms._atoms.push_back(newAtom);
159 _symbolToAtomMapping.insert(std::make_pair(symbol, newAtom));
Sid Manning1a601412012-07-25 16:27:21 +0000160 } else {
161 // This is actually a defined symbol. Add it to its section's list of
162 // symbols.
Sid Manning8caf4de2012-09-17 12:49:38 +0000163 if (symbol->getType() == llvm::ELF::STT_NOTYPE
164 || symbol->getType() == llvm::ELF::STT_OBJECT
165 || symbol->getType() == llvm::ELF::STT_FUNC
Michael J. Spencer65f61132013-01-04 21:25:25 +0000166 || symbol->getType() == llvm::ELF::STT_GNU_IFUNC
Sid Manning8caf4de2012-09-17 12:49:38 +0000167 || symbol->getType() == llvm::ELF::STT_SECTION
168 || symbol->getType() == llvm::ELF::STT_FILE
169 || symbol->getType() == llvm::ELF::STT_TLS
170 || symbol->getType() == llvm::ELF::STT_COMMON
171 || symbol->st_shndx == llvm::ELF::SHN_COMMON) {
172 sectionSymbols[section].push_back(symbol);
Michael J. Spencer6344b322012-12-20 00:37:10 +0000173 } else {
Sid Manning8caf4de2012-09-17 12:49:38 +0000174 llvm::errs() << "Unable to create atom for: " << symbolName << "\n";
Michael J. Spencera2c97272013-01-04 21:09:21 +0000175 EC = object_error::parse_failed;
Sid Manning1a601412012-07-25 16:27:21 +0000176 return;
177 }
178 }
179 }
180
Sid Manning8caf4de2012-09-17 12:49:38 +0000181 for (auto &i : sectionSymbols) {
182 auto &symbols = i.second;
183 llvm::StringRef symbolName;
184 llvm::StringRef sectionName;
Sid Manning1a601412012-07-25 16:27:21 +0000185 // Sort symbols by position.
Sid Manning8caf4de2012-09-17 12:49:38 +0000186 std::stable_sort(symbols.begin(), symbols.end(),
Michael J. Spencer6344b322012-12-20 00:37:10 +0000187 [](const Elf_Sym *A, const Elf_Sym *B) {
Sid Manning1a601412012-07-25 16:27:21 +0000188 return A->st_value < B->st_value;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000189 });
Sid Manning1a601412012-07-25 16:27:21 +0000190
191 // i.first is the section the symbol lives in
Sid Manning8caf4de2012-09-17 12:49:38 +0000192 for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
Sid Manning1a601412012-07-25 16:27:21 +0000193 StringRef symbolContents;
Sid Manning8caf4de2012-09-17 12:49:38 +0000194 if ((EC = _objFile->getSectionContents(i.first, symbolContents)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000195 return;
Sid Manning1a601412012-07-25 16:27:21 +0000196
Sid Manning8caf4de2012-09-17 12:49:38 +0000197 if ((EC = _objFile->getSymbolName(i.first, *si, symbolName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000198 return;
Sid Manning1a601412012-07-25 16:27:21 +0000199
Sid Manning8caf4de2012-09-17 12:49:38 +0000200 if ((EC = _objFile->getSectionName(i.first, sectionName)))
Sid Manning429a4bc2012-07-27 14:52:18 +0000201 return;
Sid Manning1a601412012-07-25 16:27:21 +0000202
Sid Manning8caf4de2012-09-17 12:49:38 +0000203 bool isCommon = false;
Sid Manning1a601412012-07-25 16:27:21 +0000204 if (((*si)->getType() == llvm::ELF::STT_COMMON)
Sid Manning8caf4de2012-09-17 12:49:38 +0000205 || (*si)->st_shndx == llvm::ELF::SHN_COMMON)
206 isCommon = true;
Sid Manning1a601412012-07-25 16:27:21 +0000207
208 // Get the symbol's content:
Sid Manning8caf4de2012-09-17 12:49:38 +0000209 llvm::ArrayRef<uint8_t> symbolData;
210 uint64_t contentSize;
Michael J. Spencer57752dc2013-01-12 02:45:54 +0000211
212 // If the next symbol is at the same location
213
Sid Manning1a601412012-07-25 16:27:21 +0000214 if (si + 1 == se) {
215 // if this is the last symbol, take up the remaining data.
Michael J. Spencer6344b322012-12-20 00:37:10 +0000216 contentSize = (isCommon) ? 0
Sid Manning8caf4de2012-09-17 12:49:38 +0000217 : ((i.first)->sh_size - (*si)->st_value);
Sid Manning1a601412012-07-25 16:27:21 +0000218 }
219 else {
Michael J. Spencer6344b322012-12-20 00:37:10 +0000220 contentSize = (isCommon) ? 0
Sid Manning8caf4de2012-09-17 12:49:38 +0000221 : (*(si + 1))->st_value - (*si)->st_value;
Sid Manning1a601412012-07-25 16:27:21 +0000222 }
223
Sid Manning8caf4de2012-09-17 12:49:38 +0000224 symbolData = llvm::ArrayRef<uint8_t>((uint8_t *)symbolContents.data()
225 + (*si)->st_value, contentSize);
226
Sid Manning8caf4de2012-09-17 12:49:38 +0000227 unsigned int referenceStart = _references.size();
228
Michael J. Spencer6344b322012-12-20 00:37:10 +0000229 // Only relocations that are inside the domain of the atom are added.
Sid Manning8caf4de2012-09-17 12:49:38 +0000230
231 // Add Rela (those with r_addend) references:
232 for (auto &rai : _relocationAddendRefences[sectionName]) {
233 if ((rai->r_offset >= (*si)->st_value) &&
234 (rai->r_offset < (*si)->st_value+contentSize)) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000235 auto *ERef = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000236 ELFReference<ELFT> > ())
237 ELFReference<ELFT> (
Michael J. Spencera2c97272013-01-04 21:09:21 +0000238 rai, rai->r_offset-(*si)->st_value, nullptr);
Sid Manning8caf4de2012-09-17 12:49:38 +0000239
240 _references.push_back(ERef);
241 }
242 }
243
Michael J. Spencer6344b322012-12-20 00:37:10 +0000244 // Add Rel references.
Sid Manning8caf4de2012-09-17 12:49:38 +0000245 for (auto &ri : _relocationReferences[sectionName]) {
246 if (((ri)->r_offset >= (*si)->st_value) &&
247 ((ri)->r_offset < (*si)->st_value+contentSize)) {
Michael J. Spencera2c97272013-01-04 21:09:21 +0000248 auto *ERef = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000249 ELFReference<ELFT> > ())
250 ELFReference<ELFT> (
Michael J. Spencera2c97272013-01-04 21:09:21 +0000251 (ri), (ri)->r_offset-(*si)->st_value, nullptr);
Sid Manning8caf4de2012-09-17 12:49:38 +0000252
253 _references.push_back(ERef);
254 }
255 }
256
257 // Create the DefinedAtom and add it to the list of DefinedAtoms.
Michael J. Spencera2c97272013-01-04 21:09:21 +0000258 auto *newAtom = new (_readerStorage.Allocate<
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000259 ELFDefinedAtom<ELFT> > ())
260 ELFDefinedAtom<ELFT>(
Michael J. Spencera2c97272013-01-04 21:09:21 +0000261 *this, symbolName, sectionName, *si, i.first, symbolData,
262 referenceStart, _references.size(), _references);
Sid Manning8caf4de2012-09-17 12:49:38 +0000263
264 _definedAtoms._atoms.push_back(newAtom);
265 _symbolToAtomMapping.insert(std::make_pair((*si), newAtom));
Sid Manning1a601412012-07-25 16:27:21 +0000266 }
267 }
Sid Manning8caf4de2012-09-17 12:49:38 +0000268
Michael J. Spencer6344b322012-12-20 00:37:10 +0000269 // All the Atoms and References are created. Now update each Reference's
270 // target with the Atom pointer it refers to.
Sid Manning8caf4de2012-09-17 12:49:38 +0000271 for (auto &ri : _references) {
272 const Elf_Sym *Symbol = _objFile->getElfSymbol(ri->targetSymbolIndex());
273 ri->setTarget(findAtom (Symbol));
274 }
Sid Manning1a601412012-07-25 16:27:21 +0000275 }
276
Sid Manning1a601412012-07-25 16:27:21 +0000277 virtual const atom_collection<DefinedAtom> &defined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000278 return _definedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000279 }
280
281 virtual const atom_collection<UndefinedAtom> &undefined() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000282 return _undefinedAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000283 }
284
285 virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000286 return _sharedLibraryAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000287 }
288
289 virtual const atom_collection<AbsoluteAtom> &absolute() const {
Sid Manning8caf4de2012-09-17 12:49:38 +0000290 return _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000291 }
292
Sid Manning8caf4de2012-09-17 12:49:38 +0000293 Atom *findAtom(const Elf_Sym *symbol) {
294 return (_symbolToAtomMapping.lookup(symbol));
295 }
296
Sid Manning1a601412012-07-25 16:27:21 +0000297private:
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000298 std::unique_ptr<ELFObjectFile<ELFT> >
Sid Manning8caf4de2012-09-17 12:49:38 +0000299 _objFile;
300 atom_collection_vector<DefinedAtom> _definedAtoms;
301 atom_collection_vector<UndefinedAtom> _undefinedAtoms;
302 atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
303 atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
Sid Manning1a601412012-07-25 16:27:21 +0000304
Michael J. Spencer6344b322012-12-20 00:37:10 +0000305 /// \brief _relocationAddendRefences and _relocationReferences contain the
306 /// list of relocations references. In ELF, if a section named, ".text" has
307 /// relocations will also have a section named ".rel.text" or ".rela.text"
308 /// which will hold the entries. -- .rel or .rela is prepended to create
309 /// the SHT_REL(A) section name.
Sid Manning8caf4de2012-09-17 12:49:38 +0000310 std::map<llvm::StringRef, std::vector<const Elf_Rela *> >
311 _relocationAddendRefences;
312 std::map<llvm::StringRef, std::vector<const Elf_Rel *> >
313 _relocationReferences;
314
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000315 std::vector<ELFReference<ELFT> *>
Michael J. Spencera2c97272013-01-04 21:09:21 +0000316 _references;
Sid Manning8caf4de2012-09-17 12:49:38 +0000317 llvm::DenseMap<const Elf_Sym *, Atom *> _symbolToAtomMapping;
318
319 llvm::BumpPtrAllocator _readerStorage;
Sid Manning1a601412012-07-25 16:27:21 +0000320};
321
Michael J. Spencer6344b322012-12-20 00:37:10 +0000322// \brief A reader object that will instantiate correct FileELF by examining the
323// memory buffer for ELF class and bitwidth
Sid Manning1a601412012-07-25 16:27:21 +0000324class ReaderELF: public Reader {
325public:
Michael J. Spencera5d22812012-11-13 19:58:58 +0000326 ReaderELF(const ReaderOptionsELF &,
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000327 ReaderOptionsArchive &readerOptionsArchive)
Michael J. Spencera5d22812012-11-13 19:58:58 +0000328 : _readerOptionsArchive(readerOptionsArchive)
Michael J. Spencer6344b322012-12-20 00:37:10 +0000329 , _readerArchive(_readerOptionsArchive) {
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000330 _readerOptionsArchive.setReader(this);
331 }
332
Sid Manning1a601412012-07-25 16:27:21 +0000333 error_code parseFile(std::unique_ptr<MemoryBuffer> mb, std::vector<
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000334 std::unique_ptr<File> > &result) {
Michael J. Spencerb03f6c42013-01-15 07:53:22 +0000335 using llvm::object::ELFType;
Michael J. Spencer6344b322012-12-20 00:37:10 +0000336 llvm::error_code ec;
Sid Manning1a601412012-07-25 16:27:21 +0000337 std::unique_ptr<File> f;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000338 std::pair<unsigned char, unsigned char> Ident;
Sid Manning1a601412012-07-25 16:27:21 +0000339
Michael J. Spencer6344b322012-12-20 00:37:10 +0000340 llvm::sys::LLVMFileType fileType =
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000341 llvm::sys::IdentifyFileType(mb->getBufferStart(),
342 static_cast<unsigned>(mb->getBufferSize()));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000343
344 std::size_t MaxAlignment =
345 1ULL << llvm::CountTrailingZeros_64(uintptr_t(mb->getBufferStart()));
346
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000347 switch (fileType) {
Michael J. Spencera5d22812012-11-13 19:58:58 +0000348 case llvm::sys::ELF_Relocatable_FileType:
Michael J. Spencera2c97272013-01-04 21:09:21 +0000349 Ident = getElfArchType(&*mb);
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. Spencera5d22812012-11-13 19:58:58 +0000353 if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
354 == 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>>(
357 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>>(
360 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000361 else
362 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000363 } else if (Ident.first == llvm::ELF::ELFCLASS32 && Ident.second
364 == 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>>(
367 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>>(
370 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000371 else
372 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000373 } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
374 == 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>>(
377 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>>(
380 std::move(mb), ec));
Michael J. Spencera2c97272013-01-04 21:09:21 +0000381 else
382 llvm_unreachable("Invalid alignment for ELF file!");
Michael J. Spencera5d22812012-11-13 19:58:58 +0000383 } else if (Ident.first == llvm::ELF::ELFCLASS64 && Ident.second
384 == 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>>(
387 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>>(
390 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;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +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;
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000401
Michael J. Spencera5d22812012-11-13 19:58:58 +0000402 default:
403 llvm_unreachable("not supported format");
404 break;
Sid Manning1a601412012-07-25 16:27:21 +0000405 }
406
407 if (ec)
408 return ec;
409
Sid Manning1a601412012-07-25 16:27:21 +0000410 return error_code::success();
411 }
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000412
413private:
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000414 ReaderOptionsArchive &_readerOptionsArchive;
415 ReaderArchive _readerArchive;
Sid Manning1a601412012-07-25 16:27:21 +0000416};
Michael J. Spencer6344b322012-12-20 00:37:10 +0000417} // end anon namespace.
Nick Kledzikabb69812012-05-31 22:34:00 +0000418
419namespace lld {
Nick Kledzikabb69812012-05-31 22:34:00 +0000420ReaderOptionsELF::ReaderOptionsELF() {
421}
422
423ReaderOptionsELF::~ReaderOptionsELF() {
424}
425
Shankar Easwaran70b4dcf2012-11-13 18:39:10 +0000426Reader *createReaderELF(const ReaderOptionsELF &options,
427 ReaderOptionsArchive &optionsArchive) {
428 return new ReaderELF(options, optionsArchive);
Nick Kledzikabb69812012-05-31 22:34:00 +0000429}
Michael J. Spencer6344b322012-12-20 00:37:10 +0000430} // end namespace lld