blob: 7da02a0a3bfe8572627045878878f1186402925f [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 Espindolaf98d6d82015-09-03 20:03:54 +000017#include "llvm/Support/FileSystem.h"
Michael J. Spencer84487f12015-07-24 21:03:07 +000018
19using namespace llvm;
20
21using namespace lld;
22using namespace lld::elf2;
23
24namespace lld {
25namespace elf2 {
26Configuration *Config;
Michael J. Spencer84487f12015-07-24 21:03:07 +000027
28void link(ArrayRef<const char *> Args) {
Rui Ueyama570752c2015-08-18 09:13:25 +000029 Configuration C;
30 Config = &C;
Rui Ueyama880632c2015-08-11 21:45:55 +000031 LinkerDriver().link(Args.slice(1));
Michael J. Spencer84487f12015-07-24 21:03:07 +000032}
33
Michael J. Spencer84487f12015-07-24 21:03:07 +000034}
35}
36
37// Opens a file. Path has to be resolved already.
38// Newly created memory buffers are owned by this driver.
39MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
40 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
41 error(MBOrErr, Twine("cannot open ") + Path);
42 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
43 MemoryBufferRef MBRef = MB->getMemBufferRef();
44 OwningMBs.push_back(std::move(MB)); // take ownership
45 return MBRef;
46}
47
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000048template <class ELFT>
49static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB,
50 bool IsShared) {
51 if (IsShared)
52 return make_unique<SharedFile<ELFT>>(MB);
53 return make_unique<ObjectFile<ELFT>>(MB);
54}
55
Michael J. Spencer84487f12015-07-24 21:03:07 +000056static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000057 using namespace llvm::sys::fs;
58 file_magic Magic = identify_magic(MB.getBuffer());
59
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000060 std::pair<unsigned char, unsigned char> Type =
61 object::getElfArchType(MB.getBuffer());
62 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
63 error("Invalid data encoding");
64
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000065 bool IsShared = Magic == file_magic::elf_shared_object;
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000066 if (Type.first == ELF::ELFCLASS32) {
67 if (Type.second == ELF::ELFDATA2LSB)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000068 return createFile<object::ELF32LE>(MB, IsShared);
69 return createFile<object::ELF32BE>(MB, IsShared);
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000070 }
71 if (Type.first == ELF::ELFCLASS64) {
72 if (Type.second == ELF::ELFDATA2LSB)
Rafael Espindolaf98d6d82015-09-03 20:03:54 +000073 return createFile<object::ELF64LE>(MB, IsShared);
74 return createFile<object::ELF64BE>(MB, IsShared);
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000075 }
76 error("Invalid file class");
Michael J. Spencer84487f12015-07-24 21:03:07 +000077}
78
79void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
80 // Parse command line options.
81 opt::InputArgList Args = Parser.parse(ArgsArr);
82
83 // Handle -o
84 if (auto *Arg = Args.getLastArg(OPT_output))
85 Config->OutputFile = Arg->getValue();
86 if (Config->OutputFile.empty())
87 error("-o must be specified.");
88
89 // Create a list of input files.
90 std::vector<MemoryBufferRef> Inputs;
91
92 for (auto *Arg : Args.filtered(OPT_INPUT)) {
93 StringRef Path = Arg->getValue();
94 Inputs.push_back(openFile(Path));
95 }
96
97 if (Inputs.empty())
98 error("no input files.");
99
100 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +0000101 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000102
103 // Parse all input files and put all symbols to the symbol table.
104 // The symbol table will take care of name resolution.
105 for (MemoryBufferRef MB : Inputs) {
106 std::unique_ptr<InputFile> File = createFile(MB);
107 Symtab.addFile(std::move(File));
108 }
109
110 // Make sure we have resolved all symbols.
111 Symtab.reportRemainingUndefines();
112
113 // Write the result.
Rafael Espindolaf98d6d82015-09-03 20:03:54 +0000114 const ELFFileBase *FirstObj = Symtab.getFirstELF();
115 switch (FirstObj->getELFKind()) {
Rafael Espindola905ad342015-09-02 20:43:43 +0000116 case ELF32LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000117 writeResult<object::ELF32LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000118 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000119 case ELF32BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000120 writeResult<object::ELF32BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000121 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000122 case ELF64LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000123 writeResult<object::ELF64LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000124 return;
Rafael Espindola905ad342015-09-02 20:43:43 +0000125 case ELF64BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000126 writeResult<object::ELF64BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000127 return;
128 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000129}