blob: 5c65fb76dbfe32c71dbf421f27d6cff12e2dadd1 [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 {
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000028
Michael J. Spencer84487f12015-07-24 21:03:07 +000029Configuration *Config;
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000030std::vector<std::unique_ptr<MemoryBuffer>> *MemoryBufferPool;
Michael J. Spencer84487f12015-07-24 21:03:07 +000031
32void link(ArrayRef<const char *> Args) {
Rui Ueyama570752c2015-08-18 09:13:25 +000033 Configuration C;
34 Config = &C;
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000035 std::vector<std::unique_ptr<MemoryBuffer>> V;
36 MemoryBufferPool = &V;
Rui Ueyama880632c2015-08-11 21:45:55 +000037 LinkerDriver().link(Args.slice(1));
Michael J. Spencer84487f12015-07-24 21:03:07 +000038}
39
Michael J. Spencer84487f12015-07-24 21:03:07 +000040// Opens a file. Path has to be resolved already.
41// Newly created memory buffers are owned by this driver.
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000042MemoryBufferRef openFile(StringRef Path) {
Michael J. Spencer84487f12015-07-24 21:03:07 +000043 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
44 error(MBOrErr, Twine("cannot open ") + Path);
45 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
46 MemoryBufferRef MBRef = MB->getMemBufferRef();
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000047 MemoryBufferPool->push_back(std::move(MB)); // transfer ownership
Michael J. Spencer84487f12015-07-24 21:03:07 +000048 return MBRef;
49}
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000050}
Michael J. Spencer84487f12015-07-24 21:03:07 +000051}
52
Igor Kudrin1309fc02015-09-28 15:01:59 +000053// Makes a path by concatenating Dir and File.
Igor Kudrinf03d2b42015-09-30 10:39:37 +000054// If Dir starts with '=' the result will be preceded by Sysroot,
Igor Kudrin1309fc02015-09-28 15:01:59 +000055// which can be set with --sysroot command line switch.
56static std::string buildSysrootedPath(StringRef Dir, StringRef File) {
57 SmallString<128> Path;
Igor Kudrinf03d2b42015-09-30 10:39:37 +000058 if (Dir.startswith("="))
59 sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
60 else
61 sys::path::append(Path, Dir, File);
Igor Kudrin1309fc02015-09-28 15:01:59 +000062 return Path.str().str();
63}
64
Rafael Espindolaabb7b282015-09-28 12:52:21 +000065// Searches a given library from input search paths, which are filled
66// from -L command line switches. Returns a path to an existent library file.
67static std::string searchLibrary(StringRef Path) {
68 std::vector<std::string> Names;
69 if (Path[0] == ':') {
70 Names.push_back(Path.drop_front().str());
71 } else {
72 Names.push_back((Twine("lib") + Path + ".so").str());
73 Names.push_back((Twine("lib") + Path + ".a").str());
74 }
Rafael Espindolaabb7b282015-09-28 12:52:21 +000075 for (StringRef Dir : Config->InputSearchPaths) {
76 for (const std::string &Name : Names) {
Igor Kudrin1309fc02015-09-28 15:01:59 +000077 std::string FullPath = buildSysrootedPath(Dir, Name);
78 if (sys::fs::exists(FullPath))
79 return FullPath;
Rafael Espindolaabb7b282015-09-28 12:52:21 +000080 }
81 }
82 error(Twine("Unable to find library -l") + Path);
83}
84
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +000085// Returns true if MB looks like a linker script.
86static bool isLinkerScript(MemoryBufferRef MB) {
87 using namespace llvm::sys::fs;
88 return identify_magic(MB.getBuffer()) == file_magic::unknown;
89}
90
Michael J. Spencer84487f12015-07-24 21:03:07 +000091void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
92 // Parse command line options.
93 opt::InputArgList Args = Parser.parse(ArgsArr);
94
Michael J. Spencer84487f12015-07-24 21:03:07 +000095 if (auto *Arg = Args.getLastArg(OPT_output))
96 Config->OutputFile = Arg->getValue();
Michael J. Spencer84487f12015-07-24 21:03:07 +000097
Rafael Espindola70107762015-09-11 18:49:42 +000098 if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
99 Config->DynamicLinker = Arg->getValue();
100
Igor Kudrin1309fc02015-09-28 15:01:59 +0000101 if (auto *Arg = Args.getLastArg(OPT_sysroot))
102 Config->Sysroot = Arg->getValue();
103
Rafael Espindola2e9eac12015-09-11 21:18:56 +0000104 std::vector<StringRef> RPaths;
105 for (auto *Arg : Args.filtered(OPT_rpath))
106 RPaths.push_back(Arg->getValue());
107 if (!RPaths.empty())
108 Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
109
Rafael Espindolaabb7b282015-09-28 12:52:21 +0000110 for (auto *Arg : Args.filtered(OPT_L))
111 Config->InputSearchPaths.push_back(Arg->getValue());
112
Rui Ueyama9d4c6d72015-09-29 16:40:13 +0000113 if (auto *Arg = Args.getLastArg(OPT_entry))
114 Config->Entry = Arg->getValue();
115
Rui Ueyamad7c417c2015-09-29 22:33:18 +0000116 Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
117 Config->DiscardAll = Args.hasArg(OPT_discard_all);
118 Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
119 Config->DiscardNone = Args.hasArg(OPT_discard_none);
120 Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
121 Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
122 Config->Shared = Args.hasArg(OPT_shared);
123
Michael J. Spencer84487f12015-07-24 21:03:07 +0000124 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +0000125 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000126
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +0000127 for (auto *Arg : Args.filtered(OPT_l, OPT_INPUT)) {
128 std::string Path = Arg->getValue();
129 if (Arg->getOption().getID() == OPT_l)
130 Path = searchLibrary(Path);
131 MemoryBufferRef MB = openFile(Path);
132 if (isLinkerScript(MB)) {
133 // readLinkerScript may add files to the symbol table.
134 readLinkerScript(&Symtab, MB);
135 continue;
136 }
137 Symtab.addFile(createFile(MB));
Michael J. Spencer84487f12015-07-24 21:03:07 +0000138 }
139
Rui Ueyamaf5c4aca2015-09-30 17:06:09 +0000140 if (Symtab.getObjectFiles().empty())
141 error("no input files.");
142
Michael J. Spencer84487f12015-07-24 21:03:07 +0000143 // Write the result.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000144 const ELFFileBase *FirstObj = Symtab.getFirstELF();
145 switch (FirstObj->getELFKind()) {
Rafael Espindola905ad342015-09-02 20:43:43 +0000146 case ELF32LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000147 writeResult<object::ELF32LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000148 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000149 case ELF32BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000150 writeResult<object::ELF32BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000151 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000152 case ELF64LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000153 writeResult<object::ELF64LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000154 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000155 case ELF64BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000156 writeResult<object::ELF64BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000157 return;
158 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000159}