blob: 6537e13da99120a29449efceaa6875a514ec4103 [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"
Michael J. Spencer84487f12015-07-24 21:03:07 +000019
20using namespace llvm;
21
22using namespace lld;
23using namespace lld::elf2;
24
25namespace lld {
26namespace elf2 {
27Configuration *Config;
Michael J. Spencer84487f12015-07-24 21:03:07 +000028
29void link(ArrayRef<const char *> Args) {
Rui Ueyama570752c2015-08-18 09:13:25 +000030 Configuration C;
31 Config = &C;
Rui Ueyama880632c2015-08-11 21:45:55 +000032 LinkerDriver().link(Args.slice(1));
Michael J. Spencer84487f12015-07-24 21:03:07 +000033}
34
Michael J. Spencer84487f12015-07-24 21:03:07 +000035}
36}
37
38// Opens a file. Path has to be resolved already.
39// Newly created memory buffers are owned by this driver.
40MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
41 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
42 error(MBOrErr, Twine("cannot open ") + Path);
43 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
44 MemoryBufferRef MBRef = MB->getMemBufferRef();
45 OwningMBs.push_back(std::move(MB)); // take ownership
46 return MBRef;
47}
48
49static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000050 using namespace llvm::sys::fs;
51 file_magic Magic = identify_magic(MB.getBuffer());
52
Michael J. Spencer1b348a62015-09-04 22:28:10 +000053 if (Magic == file_magic::archive)
54 return make_unique<ArchiveFile>(MB);
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000055
Michael J. Spencer1b348a62015-09-04 22:28:10 +000056 if (Magic == file_magic::elf_shared_object)
57 return createELFFile<SharedFile>(MB);
58
59 return createELFFile<ObjectFile>(MB);
Michael J. Spencer84487f12015-07-24 21:03:07 +000060}
61
62void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
63 // Parse command line options.
64 opt::InputArgList Args = Parser.parse(ArgsArr);
65
66 // Handle -o
67 if (auto *Arg = Args.getLastArg(OPT_output))
68 Config->OutputFile = Arg->getValue();
69 if (Config->OutputFile.empty())
70 error("-o must be specified.");
71
Rafael Espindola70107762015-09-11 18:49:42 +000072 // Handle -dynamic-linker
73 if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
74 Config->DynamicLinker = Arg->getValue();
75
Rafael Espindola2e9eac12015-09-11 21:18:56 +000076 std::vector<StringRef> RPaths;
77 for (auto *Arg : Args.filtered(OPT_rpath))
78 RPaths.push_back(Arg->getValue());
79 if (!RPaths.empty())
80 Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
81
Rafael Espindola4340aad2015-09-11 22:42:45 +000082 if (Args.hasArg(OPT_shared))
83 Config->Shared = true;
84
Davide Italiano6d328d32015-09-16 20:45:57 +000085 if (Args.hasArg(OPT_discard_all))
86 Config->DiscardAll = true;
87
Davide Italiano5445b2de2015-09-20 21:58:12 +000088 if (Args.hasArg(OPT_discard_locals))
89 Config->DiscardLocals = true;
90
Michael J. Spencer84487f12015-07-24 21:03:07 +000091 // Create a list of input files.
92 std::vector<MemoryBufferRef> Inputs;
93
94 for (auto *Arg : Args.filtered(OPT_INPUT)) {
95 StringRef Path = Arg->getValue();
96 Inputs.push_back(openFile(Path));
97 }
98
99 if (Inputs.empty())
100 error("no input files.");
101
102 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +0000103 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000104
105 // Parse all input files and put all symbols to the symbol table.
106 // The symbol table will take care of name resolution.
107 for (MemoryBufferRef MB : Inputs) {
108 std::unique_ptr<InputFile> File = createFile(MB);
109 Symtab.addFile(std::move(File));
110 }
111
Michael J. Spencer84487f12015-07-24 21:03:07 +0000112 // Write the result.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000113 const ELFFileBase *FirstObj = Symtab.getFirstELF();
114 switch (FirstObj->getELFKind()) {
Rafael Espindola905ad342015-09-02 20:43:43 +0000115 case ELF32LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000116 writeResult<object::ELF32LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000117 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000118 case ELF32BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000119 writeResult<object::ELF32BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000120 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000121 case ELF64LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000122 writeResult<object::ELF64LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000123 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000124 case ELF64BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000125 writeResult<object::ELF64BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000126 return;
127 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000128}