xref: /llvm-project-15.0.7/lld/ELF/Driver.cpp (revision 614c7ef8)
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 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/Support/FileSystem.h"
19 
20 using namespace llvm;
21 
22 using namespace lld;
23 using namespace lld::elf2;
24 
25 namespace lld {
26 namespace elf2 {
27 Configuration *Config;
28 
29 void link(ArrayRef<const char *> Args) {
30   Configuration C;
31   Config = &C;
32   LinkerDriver().link(Args.slice(1));
33 }
34 
35 }
36 }
37 
38 // Opens a file. Path has to be resolved already.
39 // Newly created memory buffers are owned by this driver.
40 MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
41   ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
42   error(MBOrErr, Twine("cannot open ") + Path);
43   std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
44   MemoryBufferRef MBRef = MB->getMemBufferRef();
45   OwningMBs.push_back(std::move(MB)); // take ownership
46   return MBRef;
47 }
48 
49 static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
50   using namespace llvm::sys::fs;
51   file_magic Magic = identify_magic(MB.getBuffer());
52 
53   if (Magic == file_magic::archive)
54     return make_unique<ArchiveFile>(MB);
55 
56   if (Magic == file_magic::elf_shared_object)
57     return createELFFile<SharedFile>(MB);
58 
59   return createELFFile<ObjectFile>(MB);
60 }
61 
62 void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
63   // Parse command line options.
64   opt::InputArgList Args = Parser.parse(ArgsArr);
65 
66   // Handle -o
67   if (auto *Arg = Args.getLastArg(OPT_output))
68     Config->OutputFile = Arg->getValue();
69   if (Config->OutputFile.empty())
70     error("-o must be specified.");
71 
72   // Handle -dynamic-linker
73   if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
74     Config->DynamicLinker = Arg->getValue();
75 
76   std::vector<StringRef> RPaths;
77   for (auto *Arg : Args.filtered(OPT_rpath))
78     RPaths.push_back(Arg->getValue());
79   if (!RPaths.empty())
80     Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
81 
82   if (Args.hasArg(OPT_shared))
83     Config->Shared = true;
84 
85   if (Args.hasArg(OPT_discard_all))
86     Config->DiscardAll = true;
87 
88   if (Args.hasArg(OPT_discard_locals))
89     Config->DiscardLocals = true;
90 
91   // Create a list of input files.
92   std::vector<MemoryBufferRef> Inputs;
93 
94   for (auto *Arg : Args.filtered(OPT_INPUT)) {
95     StringRef Path = Arg->getValue();
96     Inputs.push_back(openFile(Path));
97   }
98 
99   if (Inputs.empty())
100     error("no input files.");
101 
102   // Create a symbol table.
103   SymbolTable Symtab;
104 
105   // Parse all input files and put all symbols to the symbol table.
106   // The symbol table will take care of name resolution.
107   for (MemoryBufferRef MB : Inputs) {
108     std::unique_ptr<InputFile> File = createFile(MB);
109     Symtab.addFile(std::move(File));
110   }
111 
112   // Write the result.
113   const ELFFileBase *FirstObj = Symtab.getFirstELF();
114   switch (FirstObj->getELFKind()) {
115   case ELF32LEKind:
116     writeResult<object::ELF32LE>(&Symtab);
117     return;
118   case ELF32BEKind:
119     writeResult<object::ELF32BE>(&Symtab);
120     return;
121   case ELF64LEKind:
122     writeResult<object::ELF64LE>(&Symtab);
123     return;
124   case ELF64BEKind:
125     writeResult<object::ELF64BE>(&Symtab);
126     return;
127   }
128 }
129