1//===- ELFObjectFile.cpp - ELF object file implementation -------*- C++ -*-===//
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/Support/MathExtras.h"
16
17namespace llvm {
18using namespace object;
19
20ErrorOr<ObjectFile *>
21ObjectFile::createELFObjectFile(std::unique_ptr<MemoryBuffer> &Obj) {
22  std::pair<unsigned char, unsigned char> Ident =
23      getElfArchType(Obj->getBuffer());
24  std::size_t MaxAlignment =
25    1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart()));
26
27  std::error_code EC;
28  std::unique_ptr<ObjectFile> R;
29  if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB)
30#if !LLVM_IS_UNALIGNED_ACCESS_FAST
31    if (MaxAlignment >= 4)
32      R.reset(new ELFObjectFile<ELFType<support::little, 4, false>>(
33          std::move(Obj), EC));
34    else
35#endif
36    if (MaxAlignment >= 2)
37      R.reset(new ELFObjectFile<ELFType<support::little, 2, false>>(
38          std::move(Obj), EC));
39    else
40      return object_error::parse_failed;
41  else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB)
42#if !LLVM_IS_UNALIGNED_ACCESS_FAST
43    if (MaxAlignment >= 4)
44      R.reset(new ELFObjectFile<ELFType<support::big, 4, false>>(std::move(Obj),
45                                                                 EC));
46    else
47#endif
48    if (MaxAlignment >= 2)
49      R.reset(new ELFObjectFile<ELFType<support::big, 2, false>>(std::move(Obj),
50                                                                 EC));
51    else
52      return object_error::parse_failed;
53  else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB)
54#if !LLVM_IS_UNALIGNED_ACCESS_FAST
55    if (MaxAlignment >= 8)
56      R.reset(new ELFObjectFile<ELFType<support::big, 8, true>>(std::move(Obj),
57                                                                EC));
58    else
59#endif
60    if (MaxAlignment >= 2)
61      R.reset(new ELFObjectFile<ELFType<support::big, 2, true>>(std::move(Obj),
62                                                                EC));
63    else
64      return object_error::parse_failed;
65  else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
66#if !LLVM_IS_UNALIGNED_ACCESS_FAST
67    if (MaxAlignment >= 8)
68      R.reset(new ELFObjectFile<ELFType<support::little, 8, true>>(
69          std::move(Obj), EC));
70    else
71#endif
72    if (MaxAlignment >= 2)
73      R.reset(new ELFObjectFile<ELFType<support::little, 2, true>>(
74          std::move(Obj), EC));
75    else
76      return object_error::parse_failed;
77  }
78  else
79    llvm_unreachable("Buffer is not an ELF object file!");
80
81  if (EC)
82    return EC;
83  return R.release();
84}
85
86} // end namespace llvm
87