]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/ReaderWriter/ELF/ELFLinkingContext.cpp
Vendor import of lld trunk r233088:
[FreeBSD/FreeBSD.git] / lib / ReaderWriter / ELF / ELFLinkingContext.cpp
1 //===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
2 //
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 //===----------------------------------------------------------------------===//
9
10 #include "lld/ReaderWriter/ELFLinkingContext.h"
11 #include "ELFFile.h"
12 #include "OrderPass.h"
13 #include "TargetHandler.h"
14 #include "lld/Core/Instrumentation.h"
15 #include "lld/Core/SharedLibraryFile.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/Triple.h"
18 #include "llvm/Config/config.h"
19 #include "llvm/Support/ELF.h"
20 #include "llvm/Support/Errc.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/Path.h"
23
24 #if defined(HAVE_CXXABI_H)
25 #include <cxxabi.h>
26 #endif
27
28 namespace lld {
29
30 class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
31 public:
32   CommandLineUndefinedAtom(const File &f, StringRef name)
33       : SimpleUndefinedAtom(f, name) {}
34
35   CanBeNull canBeNull() const override {
36     return CanBeNull::canBeNullAtBuildtime;
37   }
38 };
39
40 ELFLinkingContext::ELFLinkingContext(
41     llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
42     : _outputELFType(llvm::ELF::ET_EXEC), _triple(triple),
43       _targetHandler(std::move(targetHandler)), _baseAddress(0),
44       _isStaticExecutable(false), _noInhibitExec(false), _exportDynamic(false),
45       _mergeCommonStrings(false), _useShlibUndefines(true),
46       _dynamicLinkerArg(false), _noAllowDynamicLibraries(false),
47       _mergeRODataToTextSegment(true), _demangle(true),
48       _stripSymbols(false), _alignSegments(true), _collectStats(false),
49       _outputMagic(OutputMagic::DEFAULT), _initFunction("_init"),
50       _finiFunction("_fini"), _sysrootPath(""), _linkerScriptSema() {}
51
52 void ELFLinkingContext::addPasses(PassManager &pm) {
53   pm.add(llvm::make_unique<elf::OrderPass>());
54 }
55
56 uint16_t ELFLinkingContext::getOutputMachine() const {
57   switch (getTriple().getArch()) {
58   case llvm::Triple::x86:
59     return llvm::ELF::EM_386;
60   case llvm::Triple::x86_64:
61     return llvm::ELF::EM_X86_64;
62   case llvm::Triple::hexagon:
63     return llvm::ELF::EM_HEXAGON;
64   case llvm::Triple::mipsel:
65   case llvm::Triple::mips64el:
66     return llvm::ELF::EM_MIPS;
67   case llvm::Triple::aarch64:
68     return llvm::ELF::EM_AARCH64;
69   case llvm::Triple::arm:
70     return llvm::ELF::EM_ARM;
71   default:
72     llvm_unreachable("Unhandled arch");
73   }
74 }
75
76 StringRef ELFLinkingContext::entrySymbolName() const {
77   if (_outputELFType == llvm::ELF::ET_EXEC && _entrySymbolName.empty())
78     return "_start";
79   return _entrySymbolName;
80 }
81
82 bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
83   switch (outputFileType()) {
84   case LinkingContext::OutputFileType::YAML:
85     _writer = createWriterYAML(*this);
86     break;
87   case LinkingContext::OutputFileType::Native:
88     llvm_unreachable("Unimplemented");
89     break;
90   default:
91     _writer = createWriterELF(this->targetHandler());
92     break;
93   }
94
95   // If -dead_strip, set up initial live symbols.
96   if (deadStrip())
97     addDeadStripRoot(entrySymbolName());
98   return true;
99 }
100
101 bool ELFLinkingContext::isDynamic() const {
102   switch (_outputELFType) {
103   case llvm::ELF::ET_EXEC:
104     return !_isStaticExecutable;
105   case llvm::ELF::ET_DYN:
106     return true;
107   }
108   return false;
109 }
110
111 bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
112   return false;
113 }
114
115 Writer &ELFLinkingContext::writer() const { return *_writer; }
116
117 static void buildSearchPath(SmallString<128> &path, StringRef dir,
118                             StringRef sysRoot) {
119   if (!dir.startswith("=/"))
120     path.assign(dir);
121   else {
122     path.assign(sysRoot);
123     path.append(dir.substr(1));
124   }
125 }
126
127 ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
128   bool hasColonPrefix = libName[0] == ':';
129   SmallString<128> path;
130   for (StringRef dir : _inputSearchPaths) {
131     // Search for dynamic library
132     if (!_isStaticExecutable) {
133       buildSearchPath(path, dir, _sysrootPath);
134       llvm::sys::path::append(path, hasColonPrefix
135                                         ? libName.drop_front()
136                                         : Twine("lib", libName) + ".so");
137       if (llvm::sys::fs::exists(path.str()))
138         return StringRef(*new (_allocator) std::string(path.str()));
139     }
140     // Search for static libraries too
141     buildSearchPath(path, dir, _sysrootPath);
142     llvm::sys::path::append(path, hasColonPrefix
143                                       ? libName.drop_front()
144                                       : Twine("lib", libName) + ".a");
145     if (llvm::sys::fs::exists(path.str()))
146       return StringRef(*new (_allocator) std::string(path.str()));
147   }
148   if (hasColonPrefix && llvm::sys::fs::exists(libName.drop_front()))
149       return libName.drop_front();
150
151   return make_error_code(llvm::errc::no_such_file_or_directory);
152 }
153
154 ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName,
155                                                  bool isSysRooted) const {
156   SmallString<128> path;
157   if (llvm::sys::path::is_absolute(fileName) && isSysRooted) {
158     path.assign(_sysrootPath);
159     path.append(fileName);
160     if (llvm::sys::fs::exists(path.str()))
161       return StringRef(*new (_allocator) std::string(path.str()));
162   } else if (llvm::sys::fs::exists(fileName))
163     return fileName;
164
165   if (llvm::sys::path::is_absolute(fileName))
166     return make_error_code(llvm::errc::no_such_file_or_directory);
167
168   for (StringRef dir : _inputSearchPaths) {
169     buildSearchPath(path, dir, _sysrootPath);
170     llvm::sys::path::append(path, fileName);
171     if (llvm::sys::fs::exists(path.str()))
172       return StringRef(*new (_allocator) std::string(path.str()));
173   }
174   return make_error_code(llvm::errc::no_such_file_or_directory);
175 }
176
177 void ELFLinkingContext::createInternalFiles(
178     std::vector<std::unique_ptr<File>> &files) const {
179   std::unique_ptr<SimpleFile> file(
180       new SimpleFile("<internal file for --defsym>"));
181   for (auto &i : getAbsoluteSymbols()) {
182     StringRef sym = i.first;
183     uint64_t val = i.second;
184     file->addAtom(*(new (_allocator) SimpleAbsoluteAtom(
185         *file, sym, Atom::scopeGlobal, val)));
186   }
187   files.push_back(std::move(file));
188   LinkingContext::createInternalFiles(files);
189 }
190
191 void ELFLinkingContext::finalizeInputFiles() {
192   // Add virtual archive that resolves undefined symbols.
193   if (_resolver)
194     getNodes().push_back(llvm::make_unique<FileNode>(std::move(_resolver)));
195 }
196
197 std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() const {
198   if (_initialUndefinedSymbols.empty())
199     return nullptr;
200   std::unique_ptr<SimpleFile> undefinedSymFile(
201       new SimpleFile("command line option -u"));
202   for (auto undefSymStr : _initialUndefinedSymbols)
203     undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom(
204         *undefinedSymFile, undefSymStr)));
205   return std::move(undefinedSymFile);
206 }
207
208 void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom,
209                                                   const Atom *newAtom,
210                                                   bool &useNew) {
211   // First suppose that the `existingAtom` is defined
212   // and the `newAtom` is undefined.
213   auto *da = dyn_cast<DefinedAtom>(existingAtom);
214   auto *ua = dyn_cast<UndefinedAtom>(newAtom);
215   if (!da && !ua) {
216     // Then try to reverse the assumption.
217     da = dyn_cast<DefinedAtom>(newAtom);
218     ua = dyn_cast<UndefinedAtom>(existingAtom);
219   }
220
221   if (da && ua && da->scope() == Atom::scopeGlobal &&
222       isa<SharedLibraryFile>(ua->file()))
223     // If strong defined atom coalesces away an atom declared
224     // in the shared object the strong atom needs to be dynamically exported.
225     // Save its name.
226     _dynamicallyExportedSymbols.insert(ua->name());
227 }
228
229 std::string ELFLinkingContext::demangle(StringRef symbolName) const {
230   if (!demangleSymbols())
231     return symbolName;
232
233   // Only try to demangle symbols that look like C++ symbols
234   if (!symbolName.startswith("_Z"))
235     return symbolName;
236
237 #if defined(HAVE_CXXABI_H)
238   SmallString<256> symBuff;
239   StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
240   const char *cstr = nullTermSym.data();
241   int status;
242   char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
243   if (demangled != NULL) {
244     std::string result(demangled);
245     // __cxa_demangle() always uses a malloc'ed buffer to return the result.
246     free(demangled);
247     return result;
248   }
249 #endif
250
251   return symbolName;
252 }
253
254 void ELFLinkingContext::setUndefinesResolver(std::unique_ptr<File> resolver) {
255   assert(isa<ArchiveLibraryFile>(resolver.get()) && "Wrong resolver type");
256   _resolver = std::move(resolver);
257 }
258
259 } // end namespace lld