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