blob: 9cee71eac880c6cdc3919ce4d66f22127d375340 [file] [log] [blame]
Michael J. Spencer84487f12015-07-24 21:03:07 +00001//===- Driver.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
Rui Ueyamaafff74e22015-08-05 23:24:46 +000010#include "Driver.h"
Rafael Espindola192e1fa2015-08-06 15:08:23 +000011#include "Config.h"
12#include "Error.h"
Rui Ueyamaafff74e22015-08-05 23:24:46 +000013#include "InputFiles.h"
14#include "SymbolTable.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000015#include "Writer.h"
16#include "llvm/ADT/STLExtras.h"
Rafael Espindola2e9eac12015-09-11 21:18:56 +000017#include "llvm/ADT/StringExtras.h"
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000018#include "llvm/Support/FileSystem.h"
Rafael Espindolaabb7b282015-09-28 12:52:21 +000019#include "llvm/Support/Path.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000020
21using namespace llvm;
22
23using namespace lld;
24using namespace lld::elf2;
25
26namespace lld {
27namespace elf2 {
28Configuration *Config;
Michael J. Spencer84487f12015-07-24 21:03:07 +000029
30void link(ArrayRef<const char *> Args) {
Rui Ueyama570752c2015-08-18 09:13:25 +000031 Configuration C;
32 Config = &C;
Rui Ueyama880632c2015-08-11 21:45:55 +000033 LinkerDriver().link(Args.slice(1));
Michael J. Spencer84487f12015-07-24 21:03:07 +000034}
35
Michael J. Spencer84487f12015-07-24 21:03:07 +000036}
37}
38
39// Opens a file. Path has to be resolved already.
40// Newly created memory buffers are owned by this driver.
41MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
42 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
43 error(MBOrErr, Twine("cannot open ") + Path);
44 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
45 MemoryBufferRef MBRef = MB->getMemBufferRef();
46 OwningMBs.push_back(std::move(MB)); // take ownership
47 return MBRef;
48}
49
50static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000051 using namespace llvm::sys::fs;
52 file_magic Magic = identify_magic(MB.getBuffer());
53
Michael J. Spencer1b348a62015-09-04 22:28:10 +000054 if (Magic == file_magic::archive)
55 return make_unique<ArchiveFile>(MB);
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000056
Michael J. Spencer1b348a62015-09-04 22:28:10 +000057 if (Magic == file_magic::elf_shared_object)
58 return createELFFile<SharedFile>(MB);
59
60 return createELFFile<ObjectFile>(MB);
Michael J. Spencer84487f12015-07-24 21:03:07 +000061}
62
Igor Kudrin1309fc02015-09-28 15:01:59 +000063// Makes a path by concatenating Dir and File.
64// If Dir starts with "=" the result will be preceded by SysRoot,
65// which can be set with --sysroot command line switch.
66static std::string buildSysrootedPath(StringRef Dir, StringRef File) {
67 SmallString<128> Path;
68 if (Dir.startswith("=")) {
69 Path.assign(Config->Sysroot);
70 sys::path::append(Path, Dir.substr(1), File);
71 } else {
72 Path.assign(Dir);
73 sys::path::append(Path, File);
74 }
75 return Path.str().str();
76}
77
Rafael Espindolaabb7b282015-09-28 12:52:21 +000078// Searches a given library from input search paths, which are filled
79// from -L command line switches. Returns a path to an existent library file.
80static std::string searchLibrary(StringRef Path) {
81 std::vector<std::string> Names;
82 if (Path[0] == ':') {
83 Names.push_back(Path.drop_front().str());
84 } else {
85 Names.push_back((Twine("lib") + Path + ".so").str());
86 Names.push_back((Twine("lib") + Path + ".a").str());
87 }
Rafael Espindolaabb7b282015-09-28 12:52:21 +000088 for (StringRef Dir : Config->InputSearchPaths) {
89 for (const std::string &Name : Names) {
Igor Kudrin1309fc02015-09-28 15:01:59 +000090 std::string FullPath = buildSysrootedPath(Dir, Name);
91 if (sys::fs::exists(FullPath))
92 return FullPath;
Rafael Espindolaabb7b282015-09-28 12:52:21 +000093 }
94 }
95 error(Twine("Unable to find library -l") + Path);
96}
97
Michael J. Spencer84487f12015-07-24 21:03:07 +000098void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
99 // Parse command line options.
100 opt::InputArgList Args = Parser.parse(ArgsArr);
101
Michael J. Spencer84487f12015-07-24 21:03:07 +0000102 if (auto *Arg = Args.getLastArg(OPT_output))
103 Config->OutputFile = Arg->getValue();
Michael J. Spencer84487f12015-07-24 21:03:07 +0000104
Rafael Espindola70107762015-09-11 18:49:42 +0000105 if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
106 Config->DynamicLinker = Arg->getValue();
107
Igor Kudrin1309fc02015-09-28 15:01:59 +0000108 if (auto *Arg = Args.getLastArg(OPT_sysroot))
109 Config->Sysroot = Arg->getValue();
110
Rafael Espindola2e9eac12015-09-11 21:18:56 +0000111 std::vector<StringRef> RPaths;
112 for (auto *Arg : Args.filtered(OPT_rpath))
113 RPaths.push_back(Arg->getValue());
114 if (!RPaths.empty())
115 Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
116
Rafael Espindolaabb7b282015-09-28 12:52:21 +0000117 for (auto *Arg : Args.filtered(OPT_L))
118 Config->InputSearchPaths.push_back(Arg->getValue());
119
Rafael Espindola4340aad2015-09-11 22:42:45 +0000120 if (Args.hasArg(OPT_shared))
121 Config->Shared = true;
122
Davide Italiano6d328d32015-09-16 20:45:57 +0000123 if (Args.hasArg(OPT_discard_all))
124 Config->DiscardAll = true;
125
Davide Italiano5445b2de2015-09-20 21:58:12 +0000126 if (Args.hasArg(OPT_discard_locals))
127 Config->DiscardLocals = true;
128
Davide Italianod75d3b92015-09-24 15:08:23 +0000129 if (Args.hasArg(OPT_discard_none))
130 Config->DiscardNone = true;
131
Rafael Espindola05a3dd22015-09-22 23:38:23 +0000132 if (Args.hasArg(OPT_export_dynamic))
133 Config->ExportDynamic = true;
134
Rafael Espindola551dfd82015-09-25 19:24:57 +0000135 if (Args.hasArg(OPT_noinhibit_exec))
136 Config->NoInhibitExec = true;
137
Rafael Espindola4b2ca852015-09-28 20:30:11 +0000138 if (Args.hasArg(OPT_allow_multiple_definition))
139 Config->AllowMultipleDefinition = true;
140
Rui Ueyama9d4c6d72015-09-29 16:40:13 +0000141 if (auto *Arg = Args.getLastArg(OPT_entry))
142 Config->Entry = Arg->getValue();
143
Michael J. Spencer84487f12015-07-24 21:03:07 +0000144 // Create a list of input files.
145 std::vector<MemoryBufferRef> Inputs;
146
Rafael Espindolaabb7b282015-09-28 12:52:21 +0000147 for (auto *Arg : Args.filtered(OPT_l, OPT_INPUT)) {
Michael J. Spencer84487f12015-07-24 21:03:07 +0000148 StringRef Path = Arg->getValue();
Rafael Espindolaabb7b282015-09-28 12:52:21 +0000149 if (Arg->getOption().getID() == OPT_l) {
150 Inputs.push_back(openFile(searchLibrary(Path)));
151 continue;
152 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000153 Inputs.push_back(openFile(Path));
154 }
155
156 if (Inputs.empty())
157 error("no input files.");
158
159 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +0000160 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000161
162 // Parse all input files and put all symbols to the symbol table.
163 // The symbol table will take care of name resolution.
164 for (MemoryBufferRef MB : Inputs) {
165 std::unique_ptr<InputFile> File = createFile(MB);
166 Symtab.addFile(std::move(File));
167 }
168
Michael J. Spencer84487f12015-07-24 21:03:07 +0000169 // Write the result.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000170 const ELFFileBase *FirstObj = Symtab.getFirstELF();
171 switch (FirstObj->getELFKind()) {
Rafael Espindola905ad342015-09-02 20:43:43 +0000172 case ELF32LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000173 writeResult<object::ELF32LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000174 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000175 case ELF32BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000176 writeResult<object::ELF32BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000177 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000178 case ELF64LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000179 writeResult<object::ELF64LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000180 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000181 case ELF64BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000182 writeResult<object::ELF64BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000183 return;
184 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000185}