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