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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
//===- lib/ReaderWriter/ELF/Reader.cpp ------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Defines the ELF Reader and all helper sub classes to consume an ELF
/// file and produces atoms out of it.
///
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/Reader.h"
#include "Atoms.h"
#include "CreateELF.h"
#include "DynamicFile.h"
#include "File.h"
#include "X86/X86TargetHandler.h"
#include "X86_64/X86_64TargetHandler.h"
#include "Hexagon/HexagonTargetHandler.h"
#include "lld/Core/Reference.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "lld/ReaderWriter/Reader.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/ELF.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Memory.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include <map>
#include <vector>
using llvm::support::endianness;
using namespace llvm::object;
namespace lld {
namespace {
struct DynamicFileCreateELFTraits {
typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
template <class ELFT>
static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
bool useUndefines) {
return lld::elf::DynamicFile<ELFT>::create(std::move(mb), useUndefines);
}
};
struct ELFFileCreateELFTraits {
typedef std::unique_ptr<lld::File> result_type;
template <class ELFT>
static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
bool atomizeStrings, TargetHandlerBase *handler,
lld::error_code &ec) {
return std::unique_ptr<lld::File>(new lld::elf::ELFFile<ELFT>(
std::move(mb), atomizeStrings, handler, ec));
}
};
class ELFObjectReader : public Reader {
public:
ELFObjectReader(bool atomizeStrings, TargetHandlerBase *handler)
: _atomizeStrings(atomizeStrings), _handler(handler) {}
virtual bool canParse(file_magic magic, StringRef,
const MemoryBuffer &) const {
return (magic == llvm::sys::fs::file_magic::elf_relocatable);
}
virtual error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
std::vector<std::unique_ptr<File>> &result) const {
error_code ec;
std::size_t maxAlignment =
1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
std::unique_ptr<File> f(createELF<ELFFileCreateELFTraits>(
getElfArchType(&*mb), maxAlignment, std::move(mb), _atomizeStrings,
_handler, ec));
if (ec)
return ec;
result.push_back(std::move(f));
return error_code::success();
}
private:
bool _atomizeStrings;
TargetHandlerBase *_handler;
};
class ELFDSOReader : public Reader {
public:
ELFDSOReader(bool useUndefines) : _useUndefines(useUndefines) {}
virtual bool canParse(file_magic magic, StringRef,
const MemoryBuffer &) const {
return (magic == llvm::sys::fs::file_magic::elf_shared_object);
}
virtual error_code
parseFile(std::unique_ptr<MemoryBuffer> &mb, const class Registry &,
std::vector<std::unique_ptr<File>> &result) const {
std::size_t maxAlignment =
1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
auto f = createELF<DynamicFileCreateELFTraits>(
getElfArchType(&*mb), maxAlignment, std::move(mb), _useUndefines);
if (!f)
return f;
result.push_back(std::move(*f));
return error_code::success();
}
private:
bool _useUndefines;
};
} // anonymous
// This dynamic registration of a handler causes support for all ELF
// architectures to be pulled into the linker. If we want to support making a
// linker that only supports one ELF architecture, we'd need to change this
// to have a different registration method for each architecture.
void Registry::addSupportELFObjects(bool atomizeStrings,
TargetHandlerBase *handler) {
// Tell registry about the ELF object file parser.
add(std::unique_ptr<Reader>(new ELFObjectReader(atomizeStrings, handler)));
// Tell registry about the relocation name to number mapping for this arch.
handler->registerRelocationNames(*this);
}
void Registry::addSupportELFDynamicSharedObjects(bool useShlibUndefines) {
add(std::unique_ptr<Reader>(new ELFDSOReader(useShlibUndefines)));
}
} // end namespace lld
|