summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
blob: 776676e92b4a2ae66242327598023028a99e09ca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//===- lib/ReaderWriter/ELF/ELFTargetInfo.cpp -----------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/ReaderWriter/ELFTargetInfo.h"

#include "TargetHandler.h"
#include "Targets.h"

#include "lld/Core/LinkerOptions.h"
#include "lld/Passes/LayoutPass.h"
#include "lld/ReaderWriter/ReaderLinkerScript.h"

#include "llvm/ADT/Triple.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"

namespace lld {
ELFTargetInfo::ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}

uint16_t ELFTargetInfo::getOutputType() const {
  switch (_options._outputKind) {
  case OutputKind::StaticExecutable:
  case OutputKind::DynamicExecutable:
    return llvm::ELF::ET_EXEC;
  case OutputKind::Relocatable:
    return llvm::ELF::ET_REL;
  case OutputKind::Shared:
    return llvm::ELF::ET_DYN;
  case OutputKind::Core:
    return llvm::ELF::ET_CORE;
  case OutputKind::SharedStubs:
  case OutputKind::DebugSymbols:
  case OutputKind::Bundle:
  case OutputKind::Preload:
    break;
  case OutputKind::Invalid:
    llvm_unreachable("Invalid output kind!");
  }
  llvm_unreachable("Unhandled OutputKind");
}

void ELFTargetInfo::addPasses(PassManager &pm) const {
  pm.add(std::unique_ptr<Pass>(new LayoutPass()));
}

uint16_t ELFTargetInfo::getOutputMachine() const {
  switch (getTriple().getArch()) {
  case llvm::Triple::x86:
    return llvm::ELF::EM_386;
  case llvm::Triple::x86_64:
    return llvm::ELF::EM_X86_64;
  case llvm::Triple::hexagon:
    return llvm::ELF::EM_HEXAGON;
  case llvm::Triple::ppc:
    return llvm::ELF::EM_PPC;
  default:
    llvm_unreachable("Unhandled arch");
  }
}

ErrorOr<Reader &> ELFTargetInfo::getReader(const LinkerInput &input) const {
  auto buffer = input.getBuffer();
  if (!buffer)
    return error_code(buffer);
  auto magic = llvm::sys::fs::identify_magic(buffer->getBuffer());
  // Assume unknown file types are linker scripts.
  if (magic == llvm::sys::fs::file_magic::unknown) {
    if (!_linkerScriptReader)
      _linkerScriptReader.reset(new ReaderLinkerScript(
          *this,
          std::bind(&ELFTargetInfo::getReader, this, std::placeholders::_1)));
    return *_linkerScriptReader;
  }

  // Assume anything else is an ELF file.
  if (!_elfReader)
    _elfReader = createReaderELF(*this, std::bind(&ELFTargetInfo::getReader,
                                                  this, std::placeholders::_1));
  return *_elfReader;
}

ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
  if (!_writer) {
    if (_options._outputYAML)
      _writer = createWriterYAML(*this);
    else
      _writer = createWriterELF(*this);
  }
  return *_writer;
}

std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
  switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
  case llvm::Triple::x86:
    return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(lo));
  case llvm::Triple::x86_64:
    return std::unique_ptr<
        ELFTargetInfo>(new lld::elf::X86_64TargetInfo(lo));
  case llvm::Triple::hexagon:
    return std::unique_ptr<
        ELFTargetInfo>(new lld::elf::HexagonTargetInfo(lo));
  case llvm::Triple::ppc:
    return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(lo));
  default:
    return std::unique_ptr<ELFTargetInfo>();
  }
}

StringRef ELFTargetInfo::getEntry() const {
  if (!_options._entrySymbol.empty())
    return _options._entrySymbol;
  return "_start";
}

} // end namespace lld
OpenPOWER on IntegriCloud