blob: 4582b286e473aaa227aa5c2937d7d252a3c5e742 [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
10#include "Driver.h"
11#include "Config.h"
12#include "Writer.h"
13#include "llvm/ADT/STLExtras.h"
14
15using namespace llvm;
16
17using namespace lld;
18using namespace lld::elf2;
19
20namespace lld {
21namespace elf2 {
22Configuration *Config;
23LinkerDriver *Driver;
24
25void link(ArrayRef<const char *> Args) {
26 auto C = make_unique<Configuration>();
27 Config = C.get();
28 auto D = make_unique<LinkerDriver>();
29 Driver = D.get();
30 Driver->link(Args.slice(1));
31}
32
33void error(Twine Msg) {
34 errs() << Msg << "\n";
35 exit(1);
36}
37
38void error(std::error_code EC, Twine Prefix) {
39 if (!EC)
40 return;
41 error(Prefix + ": " + EC.message());
42}
43
44void error(std::error_code EC) {
45 if (!EC)
46 return;
47 error(EC.message());
48}
49}
50}
51
52// Opens a file. Path has to be resolved already.
53// Newly created memory buffers are owned by this driver.
54MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
55 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
56 error(MBOrErr, Twine("cannot open ") + Path);
57 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
58 MemoryBufferRef MBRef = MB->getMemBufferRef();
59 OwningMBs.push_back(std::move(MB)); // take ownership
60 return MBRef;
61}
62
63static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
Rafael Espindolaaefd5c12015-08-04 15:45:54 +000064 std::pair<unsigned char, unsigned char> Type =
65 object::getElfArchType(MB.getBuffer());
66 if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB)
67 error("Invalid data encoding");
68
69 if (Type.first == ELF::ELFCLASS32) {
70 if (Type.second == ELF::ELFDATA2LSB)
71 return make_unique<ObjectFile<object::ELF32LE>>(MB);
72 return make_unique<ObjectFile<object::ELF32BE>>(MB);
73 }
74 if (Type.first == ELF::ELFCLASS64) {
75 if (Type.second == ELF::ELFDATA2LSB)
76 return make_unique<ObjectFile<object::ELF64LE>>(MB);
77 return make_unique<ObjectFile<object::ELF64BE>>(MB);
78 }
79 error("Invalid file class");
Michael J. Spencer84487f12015-07-24 21:03:07 +000080}
81
82void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
83 // Parse command line options.
84 opt::InputArgList Args = Parser.parse(ArgsArr);
85
86 // Handle -o
87 if (auto *Arg = Args.getLastArg(OPT_output))
88 Config->OutputFile = Arg->getValue();
89 if (Config->OutputFile.empty())
90 error("-o must be specified.");
91
92 // Create a list of input files.
93 std::vector<MemoryBufferRef> Inputs;
94
95 for (auto *Arg : Args.filtered(OPT_INPUT)) {
96 StringRef Path = Arg->getValue();
97 Inputs.push_back(openFile(Path));
98 }
99
100 if (Inputs.empty())
101 error("no input files.");
102
103 // Create a symbol table.
Rafael Espindola2ffdd4d2015-08-04 14:29:01 +0000104 SymbolTable Symtab;
Michael J. Spencer84487f12015-07-24 21:03:07 +0000105
106 // Parse all input files and put all symbols to the symbol table.
107 // The symbol table will take care of name resolution.
108 for (MemoryBufferRef MB : Inputs) {
109 std::unique_ptr<InputFile> File = createFile(MB);
110 Symtab.addFile(std::move(File));
111 }
112
113 // Make sure we have resolved all symbols.
114 Symtab.reportRemainingUndefines();
115
116 // Write the result.
117 Writer<object::ELF64LE> Out(&Symtab);
118 Out.write(Config->OutputFile);
119}