xref: /llvm-project-15.0.7/lld/ELF/Driver.cpp (revision 522b1d14)
1 //===- 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 
15 using namespace llvm;
16 
17 using namespace lld;
18 using namespace lld::elf2;
19 
20 namespace lld {
21 namespace elf2 {
22 Configuration *Config;
23 LinkerDriver *Driver;
24 
25 void 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 
33 void error(Twine Msg) {
34   errs() << Msg << "\n";
35   exit(1);
36 }
37 
38 void error(std::error_code EC, Twine Prefix) {
39   if (!EC)
40     return;
41   error(Prefix + ": " + EC.message());
42 }
43 
44 void 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.
54 MemoryBufferRef 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 
63 static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
64   return std::unique_ptr<InputFile>(new ObjectFile<object::ELF64LE>(MB));
65 }
66 
67 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
68   // Parse command line options.
69   opt::InputArgList Args = Parser.parse(ArgsArr);
70 
71   // Handle -o
72   if (auto *Arg = Args.getLastArg(OPT_output))
73     Config->OutputFile = Arg->getValue();
74   if (Config->OutputFile.empty())
75     error("-o must be specified.");
76 
77   // Create a list of input files.
78   std::vector<MemoryBufferRef> Inputs;
79 
80   for (auto *Arg : Args.filtered(OPT_INPUT)) {
81     StringRef Path = Arg->getValue();
82     Inputs.push_back(openFile(Path));
83   }
84 
85   if (Inputs.empty())
86     error("no input files.");
87 
88   // Create a symbol table.
89   SymbolTable<object::ELF64LE> Symtab;
90 
91   // Parse all input files and put all symbols to the symbol table.
92   // The symbol table will take care of name resolution.
93   for (MemoryBufferRef MB : Inputs) {
94     std::unique_ptr<InputFile> File = createFile(MB);
95     Symtab.addFile(std::move(File));
96   }
97 
98   // Make sure we have resolved all symbols.
99   Symtab.reportRemainingUndefines();
100 
101   // Write the result.
102   Writer<object::ELF64LE> Out(&Symtab);
103   Out.write(Config->OutputFile);
104 }
105