blob: a6fa7edfe3f456c1bc9b85a634bd8d3f49e343c7 [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"
17
18using namespace llvm;
19
20using namespace lld;
21using namespace lld::elf2;
22
23namespace lld {
24namespace elf2 {
25Configuration *Config;
26LinkerDriver *Driver;
27
28void link(ArrayRef<const char *> Args) {
29 auto C = make_unique<Configuration>();
30 Config = C.get();
31 auto D = make_unique<LinkerDriver>();
32 Driver = D.get();
33 Driver->link(Args.slice(1));
34}
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 Espindolaaefd5c12015-08-04 15:45:54 +000051 std::pair<unsigned char, unsigned char> Type =
52 object::getElfArchType(MB.getBuffer());
53 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
54 error("Invalid data encoding");
55
56 if (Type.first == ELF::ELFCLASS32) {
57 if (Type.second == ELF::ELFDATA2LSB)
58 return make_unique<ObjectFile<object::ELF32LE>>(MB);
59 return make_unique<ObjectFile<object::ELF32BE>>(MB);
60 }
61 if (Type.first == ELF::ELFCLASS64) {
62 if (Type.second == ELF::ELFDATA2LSB)
63 return make_unique<ObjectFile<object::ELF64LE>>(MB);
64 return make_unique<ObjectFile<object::ELF64BE>>(MB);
65 }
66 error("Invalid file class");
Michael J. Spencer84487f12015-07-24 21:03:07 +000067}
68
69void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
70 // Parse command line options.
71 opt::InputArgList Args = Parser.parse(ArgsArr);
72
73 // Handle -o
74 if (auto *Arg = Args.getLastArg(OPT_output))
75 Config->OutputFile = Arg->getValue();
76 if (Config->OutputFile.empty())
77 error("-o must be specified.");
78
79 // Create a list of input files.
80 std::vector<MemoryBufferRef> Inputs;
81
82 for (auto *Arg : Args.filtered(OPT_INPUT)) {
83 StringRef Path = Arg->getValue();
84 Inputs.push_back(openFile(Path));
85 }
86
87 if (Inputs.empty())
88 error("no input files.");
89
90 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +000091 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +000092
93 // Parse all input files and put all symbols to the symbol table.
94 // The symbol table will take care of name resolution.
95 for (MemoryBufferRef MB : Inputs) {
96 std::unique_ptr<InputFile> File = createFile(MB);
97 Symtab.addFile(std::move(File));
98 }
99
100 // Make sure we have resolved all symbols.
101 Symtab.reportRemainingUndefines();
102
103 // Write the result.
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000104 ObjectFileBase &FirstObj = *Symtab.ObjectFiles[0];
105 switch (FirstObj.kind()) {
Rui Ueyamaafff74e22015-08-05 23:24:46 +0000106 case InputFile::Object32LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000107 writeResult<object::ELF32LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000108 return;
Rui Ueyamaafff74e22015-08-05 23:24:46 +0000109 case InputFile::Object32BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000110 writeResult<object::ELF32BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000111 return;
Rui Ueyamaafff74e22015-08-05 23:24:46 +0000112 case InputFile::Object64LEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000113 writeResult<object::ELF64LE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000114 return;
Rui Ueyamaafff74e22015-08-05 23:24:46 +0000115 case InputFile::Object64BEKind:
Rui Ueyamacb8474ed2015-08-05 23:51:50 +0000116 writeResult<object::ELF64BE>(&Symtab);
Rafael Espindola4b7c2fc2015-08-05 15:08:40 +0000117 return;
118 }
Michael J. Spencer84487f12015-07-24 21:03:07 +0000119}